upgrade goose sdk and tui to be compatible with the latest agentclientprotocol/sdk package (#8667)
This commit is contained in:
@@ -313,7 +313,9 @@ export default function AppsView() {
|
|||||||
)}
|
)}
|
||||||
{app.mcpServers && app.mcpServers.length > 0 && (
|
{app.mcpServers && app.mcpServers.length > 0 && (
|
||||||
<span className="inline-block px-2 py-1 text-xs bg-background-secondary text-text-secondary rounded">
|
<span className="inline-block px-2 py-1 text-xs bg-background-secondary text-text-secondary rounded">
|
||||||
{isCustomApp ? intl.formatMessage(i18n.customApp) : app.mcpServers.join(', ')}
|
{isCustomApp
|
||||||
|
? intl.formatMessage(i18n.customApp)
|
||||||
|
: app.mcpServers.join(', ')}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type {
|
|||||||
NewSessionResponse,
|
NewSessionResponse,
|
||||||
LoadSessionResponse,
|
LoadSessionResponse,
|
||||||
PromptResponse,
|
PromptResponse,
|
||||||
|
SessionInfo,
|
||||||
} from "@agentclientprotocol/sdk";
|
} from "@agentclientprotocol/sdk";
|
||||||
import { getClient } from "./acpConnection";
|
import { getClient } from "./acpConnection";
|
||||||
import { perfLog } from "@/shared/lib/perfLog";
|
import { perfLog } from "@/shared/lib/perfLog";
|
||||||
@@ -43,24 +44,13 @@ export async function listProviders(): Promise<AcpProvider[]> {
|
|||||||
|
|
||||||
export async function listSessions(): Promise<AcpSessionInfo[]> {
|
export async function listSessions(): Promise<AcpSessionInfo[]> {
|
||||||
const client = await getClient();
|
const client = await getClient();
|
||||||
// GooseClient.unstable_listSessions doesn't work with SDK 0.19 (renamed to listSessions).
|
const response = await client.listSessions({});
|
||||||
// Bypass GooseClient and call the connection directly. Fix when ui/acp is updated.
|
return response.sessions.map((info: SessionInfo) => ({
|
||||||
// biome-ignore lint/suspicious/noExplicitAny: SDK doesn't expose conn property
|
sessionId: info.sessionId,
|
||||||
const conn = (client as any).conn;
|
title: info.title ?? null,
|
||||||
const response = await conn.listSessions({});
|
updatedAt: info.updatedAt ?? null,
|
||||||
return response.sessions.map(
|
messageCount: (info._meta?.messageCount as number) ?? 0,
|
||||||
(info: {
|
}));
|
||||||
sessionId: string;
|
|
||||||
title?: string;
|
|
||||||
updatedAt?: string;
|
|
||||||
_meta?: Record<string, unknown>;
|
|
||||||
}) => ({
|
|
||||||
sessionId: info.sessionId,
|
|
||||||
title: info.title ?? null,
|
|
||||||
updatedAt: info.updatedAt ?? null,
|
|
||||||
messageCount: (info._meta?.messageCount as number) ?? 0,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function exportSession(sessionId: string): Promise<string> {
|
export async function exportSession(sessionId: string): Promise<string> {
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
export class GooseClient {
|
|
||||||
closed = Promise.resolve();
|
|
||||||
|
|
||||||
async initialize(..._args: unknown[]): Promise<void> {}
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ export default defineConfig({
|
|||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"@": resolve(__dirname, "./src"),
|
"@": resolve(__dirname, "./src"),
|
||||||
"@aaif/goose-sdk": resolve(__dirname, "./src/test/mocks/goose-sdk.ts"),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
|
|||||||
Generated
+5
-14
@@ -653,8 +653,8 @@ importers:
|
|||||||
version: 3.25.76
|
version: 3.25.76
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@agentclientprotocol/sdk':
|
'@agentclientprotocol/sdk':
|
||||||
specifier: ^0.14.1
|
specifier: ^0.19.0
|
||||||
version: 0.14.1(zod@3.25.76)
|
version: 0.19.0(zod@3.25.76)
|
||||||
'@hey-api/openapi-ts':
|
'@hey-api/openapi-ts':
|
||||||
specifier: ^0.92.3
|
specifier: ^0.92.3
|
||||||
version: 0.92.4(magicast@0.5.2)(typescript@5.9.3)
|
version: 0.92.4(magicast@0.5.2)(typescript@5.9.3)
|
||||||
@@ -693,8 +693,8 @@ importers:
|
|||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../sdk
|
version: link:../sdk
|
||||||
'@agentclientprotocol/sdk':
|
'@agentclientprotocol/sdk':
|
||||||
specifier: ^0.14.1
|
specifier: ^0.19.0
|
||||||
version: 0.14.1(zod@4.3.6)
|
version: 0.19.0(zod@4.3.6)
|
||||||
'@inkjs/ui':
|
'@inkjs/ui':
|
||||||
specifier: ^2.0.0
|
specifier: ^2.0.0
|
||||||
version: 2.0.0(ink@6.8.0(@types/react@19.2.14)(react@19.2.4))
|
version: 2.0.0(ink@6.8.0(@types/react@19.2.14)(react@19.2.4))
|
||||||
@@ -744,11 +744,6 @@ packages:
|
|||||||
'@adobe/css-tools@4.4.4':
|
'@adobe/css-tools@4.4.4':
|
||||||
resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==}
|
resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==}
|
||||||
|
|
||||||
'@agentclientprotocol/sdk@0.14.1':
|
|
||||||
resolution: {integrity: sha512-b6r3PS3Nly+Wyw9U+0nOr47bV8tfS476EgyEMhoKvJCZLbgqoDFN7DJwkxL88RR0aiOqOYV1ZnESHqb+RmdH8w==}
|
|
||||||
peerDependencies:
|
|
||||||
zod: ^3.25.0 || ^4.0.0
|
|
||||||
|
|
||||||
'@agentclientprotocol/sdk@0.19.0':
|
'@agentclientprotocol/sdk@0.19.0':
|
||||||
resolution: {integrity: sha512-U9I8ws9WTOk6jCBAWpXefGSDgVXn14/kV6HFzwWGcstQ02mOQgClMAROHmoIn9GqZbDBDEOkdIbP4P4TEMQdug==}
|
resolution: {integrity: sha512-U9I8ws9WTOk6jCBAWpXefGSDgVXn14/kV6HFzwWGcstQ02mOQgClMAROHmoIn9GqZbDBDEOkdIbP4P4TEMQdug==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -8859,14 +8854,10 @@ snapshots:
|
|||||||
|
|
||||||
'@adobe/css-tools@4.4.4': {}
|
'@adobe/css-tools@4.4.4': {}
|
||||||
|
|
||||||
'@agentclientprotocol/sdk@0.14.1(zod@3.25.76)':
|
'@agentclientprotocol/sdk@0.19.0(zod@3.25.76)':
|
||||||
dependencies:
|
dependencies:
|
||||||
zod: 3.25.76
|
zod: 3.25.76
|
||||||
|
|
||||||
'@agentclientprotocol/sdk@0.14.1(zod@4.3.6)':
|
|
||||||
dependencies:
|
|
||||||
zod: 4.3.6
|
|
||||||
|
|
||||||
'@agentclientprotocol/sdk@0.19.0(zod@4.3.6)':
|
'@agentclientprotocol/sdk@0.19.0(zod@4.3.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
zod: 4.3.6
|
zod: 4.3.6
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@aaif/goose-sdk",
|
"name": "@aaif/goose-sdk",
|
||||||
"version": "0.17.0",
|
"version": "0.18.0",
|
||||||
"description": "Agent Client Protocol (ACP) SDK for Goose AI agent",
|
"description": "Agent Client Protocol (ACP) SDK for Goose AI agent",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
"zod": "^3.25.76"
|
"zod": "^3.25.76"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@agentclientprotocol/sdk": "*"
|
"@agentclientprotocol/sdk": "^0.19.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@aaif/goose-binary-darwin-arm64": "workspace:*",
|
"@aaif/goose-binary-darwin-arm64": "workspace:*",
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"@aaif/goose-binary-win32-x64": "workspace:*"
|
"@aaif/goose-binary-win32-x64": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@agentclientprotocol/sdk": "^0.14.1",
|
"@agentclientprotocol/sdk": "^0.19.0",
|
||||||
"@hey-api/openapi-ts": "^0.92.3",
|
"@hey-api/openapi-ts": "^0.92.3",
|
||||||
"@types/node": "^20.0.0",
|
"@types/node": "^20.0.0",
|
||||||
"prettier": "^3.8.1",
|
"prettier": "^3.8.1",
|
||||||
|
|||||||
@@ -92,10 +92,8 @@ export class GooseClient {
|
|||||||
return this.conn.unstable_forkSession(params);
|
return this.conn.unstable_forkSession(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
unstable_listSessions(
|
listSessions(params: ListSessionsRequest): Promise<ListSessionsResponse> {
|
||||||
params: ListSessionsRequest,
|
return this.conn.listSessions(params);
|
||||||
): Promise<ListSessionsResponse> {
|
|
||||||
return this.conn.unstable_listSessions(params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unstable_resumeSession(
|
unstable_resumeSession(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@aaif/goose",
|
"name": "@aaif/goose",
|
||||||
"version": "0.17.0",
|
"version": "0.18.0",
|
||||||
"description": "Goose - an open-source AI agent",
|
"description": "Goose - an open-source AI agent",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aaif/goose-sdk": "workspace:*",
|
"@aaif/goose-sdk": "workspace:*",
|
||||||
"@agentclientprotocol/sdk": "^0.14.1",
|
"@agentclientprotocol/sdk": "^0.19.0",
|
||||||
"@inkjs/ui": "^2.0.0",
|
"@inkjs/ui": "^2.0.0",
|
||||||
"ink": "^6.8.0",
|
"ink": "^6.8.0",
|
||||||
"ink-multiline-input": "^0.1.0",
|
"ink-multiline-input": "^0.1.0",
|
||||||
|
|||||||
+19
-46
@@ -37,7 +37,6 @@ interface ConfigureProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ModelSelectorProps {
|
interface ModelSelectorProps {
|
||||||
client: GooseClient;
|
|
||||||
provider: ProviderInventoryEntryDto;
|
provider: ProviderInventoryEntryDto;
|
||||||
height: number;
|
height: number;
|
||||||
onSelect: (model: string) => void;
|
onSelect: (model: string) => void;
|
||||||
@@ -45,7 +44,6 @@ interface ModelSelectorProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ModelSelector = React.memo(function ModelSelector({
|
const ModelSelector = React.memo(function ModelSelector({
|
||||||
client,
|
|
||||||
provider,
|
provider,
|
||||||
height,
|
height,
|
||||||
onSelect,
|
onSelect,
|
||||||
@@ -53,7 +51,6 @@ const ModelSelector = React.memo(function ModelSelector({
|
|||||||
}: ModelSelectorProps) {
|
}: ModelSelectorProps) {
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [models, setModels] = useState<string[]>([]);
|
const [models, setModels] = useState<string[]>([]);
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
const [selectedIdx, setSelectedIdx] = useState(0);
|
const [selectedIdx, setSelectedIdx] = useState(0);
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
const [manualEntry, setManualEntry] = useState(false);
|
const [manualEntry, setManualEntry] = useState(false);
|
||||||
@@ -61,42 +58,12 @@ const ModelSelector = React.memo(function ModelSelector({
|
|||||||
const columns = stdout?.columns ?? 80;
|
const columns = stdout?.columns ?? 80;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false;
|
const availableModels = provider.models.map((model) => model.id);
|
||||||
const timeoutId = setTimeout(() => {
|
setModels(availableModels);
|
||||||
if (!cancelled) {
|
const defaultIdx = availableModels.findIndex((model) => model === provider.defaultModel);
|
||||||
setError("Request timed out. The provider may be slow to respond.");
|
setSelectedIdx(defaultIdx >= 0 ? defaultIdx : 0);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}, [provider.models, provider.defaultModel]);
|
||||||
}, LOAD_MODELS_TIMEOUT_MS);
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
setError(null);
|
|
||||||
const resp = await client.goose.GooseProvidersModels({
|
|
||||||
providerName: provider.providerId,
|
|
||||||
});
|
|
||||||
if (!cancelled) {
|
|
||||||
setModels(resp.models);
|
|
||||||
const defaultIdx = resp.models.findIndex((m) => m === provider.defaultModel);
|
|
||||||
setSelectedIdx(defaultIdx >= 0 ? defaultIdx : 0);
|
|
||||||
setLoading(false);
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}
|
|
||||||
} catch (e: unknown) {
|
|
||||||
if (!cancelled) {
|
|
||||||
setError(e instanceof Error ? e.message : String(e));
|
|
||||||
setLoading(false);
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
cancelled = true;
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
};
|
|
||||||
}, [client, provider.providerId, provider.defaultModel]);
|
|
||||||
|
|
||||||
const filtered = (() => {
|
const filtered = (() => {
|
||||||
if (!searchQuery) return models;
|
if (!searchQuery) return models;
|
||||||
@@ -199,7 +166,7 @@ const ModelSelector = React.memo(function ModelSelector({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (models.length === 0) {
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="column" height={height} width={columns} paddingX={2}>
|
<Box flexDirection="column" height={height} width={columns} paddingX={2}>
|
||||||
<Box marginTop={1} />
|
<Box marginTop={1} />
|
||||||
@@ -207,11 +174,13 @@ const ModelSelector = React.memo(function ModelSelector({
|
|||||||
<Text color={TEXT_PRIMARY} bold>◆ Select model ◆</Text>
|
<Text color={TEXT_PRIMARY} bold>◆ Select model ◆</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box justifyContent="center" marginBottom={2}>
|
<Box justifyContent="center" marginBottom={2}>
|
||||||
<Text color={GOLD}>⚠ Failed to load models</Text>
|
<Text color={GOLD}>⚠ No models available</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box justifyContent="center">
|
<Box justifyContent="center">
|
||||||
<Box width={maxWidth}>
|
<Box width={maxWidth}>
|
||||||
<Text color={TEXT_DIM} wrap="wrap">{error}</Text>
|
<Text color={TEXT_DIM} wrap="wrap">
|
||||||
|
This provider does not currently expose any models in inventory.
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Box justifyContent="center" marginTop={2}>
|
<Box justifyContent="center" marginTop={2}>
|
||||||
@@ -439,10 +408,15 @@ export default function ConfigureScreen({
|
|||||||
value: provider.providerId,
|
value: provider.providerId,
|
||||||
});
|
});
|
||||||
await client.goose.GooseConfigUpsert({ key: "GOOSE_MODEL", value: model });
|
await client.goose.GooseConfigUpsert({ key: "GOOSE_MODEL", value: model });
|
||||||
await client.goose.GooseSessionProviderUpdate({
|
await client.setSessionConfigOption({
|
||||||
sessionId,
|
sessionId,
|
||||||
provider: provider.providerId,
|
configId: "provider",
|
||||||
model,
|
value: provider.providerId,
|
||||||
|
});
|
||||||
|
await client.setSessionConfigOption({
|
||||||
|
sessionId,
|
||||||
|
configId: "model",
|
||||||
|
value: model,
|
||||||
});
|
});
|
||||||
onComplete();
|
onComplete();
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
@@ -544,7 +518,6 @@ export default function ConfigureScreen({
|
|||||||
if (phase === "select_model" && selectedProvider) {
|
if (phase === "select_model" && selectedProvider) {
|
||||||
return (
|
return (
|
||||||
<ModelSelector
|
<ModelSelector
|
||||||
client={client}
|
|
||||||
provider={selectedProvider}
|
provider={selectedProvider}
|
||||||
height={height}
|
height={height}
|
||||||
onSelect={handleModelSelected}
|
onSelect={handleModelSelected}
|
||||||
|
|||||||
+27
-3
@@ -11,8 +11,10 @@ import type {
|
|||||||
ContentChunk,
|
ContentChunk,
|
||||||
ToolCall,
|
ToolCall,
|
||||||
ToolCallUpdate,
|
ToolCallUpdate,
|
||||||
|
RequestPermissionRequest,
|
||||||
|
RequestPermissionResponse,
|
||||||
} from "@agentclientprotocol/sdk";
|
} from "@agentclientprotocol/sdk";
|
||||||
import { ndJsonStream } from "@agentclientprotocol/sdk";
|
import { PROTOCOL_VERSION, ndJsonStream } from "@agentclientprotocol/sdk";
|
||||||
import { GooseClient } from "@aaif/goose-sdk";
|
import { GooseClient } from "@aaif/goose-sdk";
|
||||||
import { resolveGooseBinary } from "@aaif/goose-sdk/node";
|
import { resolveGooseBinary } from "@aaif/goose-sdk/node";
|
||||||
import Onboarding from "./onboarding.js";
|
import Onboarding from "./onboarding.js";
|
||||||
@@ -741,6 +743,17 @@ function App({
|
|||||||
|
|
||||||
const client = new GooseClient(
|
const client = new GooseClient(
|
||||||
() => ({
|
() => ({
|
||||||
|
requestPermission: async (
|
||||||
|
params: RequestPermissionRequest,
|
||||||
|
): Promise<RequestPermissionResponse> => {
|
||||||
|
const optionId = params.options?.[0]?.optionId ?? "approve";
|
||||||
|
return {
|
||||||
|
outcome: {
|
||||||
|
outcome: "selected",
|
||||||
|
optionId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
sessionUpdate: async (params: SessionNotification) => {
|
sessionUpdate: async (params: SessionNotification) => {
|
||||||
const update = params.update;
|
const update = params.update;
|
||||||
if (update.sessionUpdate === "agent_message_chunk") {
|
if (update.sessionUpdate === "agent_message_chunk") {
|
||||||
@@ -763,7 +776,7 @@ function App({
|
|||||||
|
|
||||||
setStatus("handshaking…");
|
setStatus("handshaking…");
|
||||||
await client.initialize({
|
await client.initialize({
|
||||||
protocolVersion: 0,
|
protocolVersion: PROTOCOL_VERSION,
|
||||||
clientInfo: { name: "goose-text", version: "0.1.0" },
|
clientInfo: { name: "goose-text", version: "0.1.0" },
|
||||||
clientCapabilities: {},
|
clientCapabilities: {},
|
||||||
});
|
});
|
||||||
@@ -1218,6 +1231,17 @@ async function runTextMode(serverConnection: Stream | string, prompt: string) {
|
|||||||
try {
|
try {
|
||||||
const client = new GooseClient(
|
const client = new GooseClient(
|
||||||
() => ({
|
() => ({
|
||||||
|
requestPermission: async (
|
||||||
|
params: RequestPermissionRequest,
|
||||||
|
): Promise<RequestPermissionResponse> => {
|
||||||
|
const optionId = params.options?.[0]?.optionId ?? "approve";
|
||||||
|
return {
|
||||||
|
outcome: {
|
||||||
|
outcome: "selected",
|
||||||
|
optionId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
sessionUpdate: async (params: SessionNotification) => {
|
sessionUpdate: async (params: SessionNotification) => {
|
||||||
const update = params.update;
|
const update = params.update;
|
||||||
if (update.sessionUpdate === "agent_message_chunk") {
|
if (update.sessionUpdate === "agent_message_chunk") {
|
||||||
@@ -1231,7 +1255,7 @@ async function runTextMode(serverConnection: Stream | string, prompt: string) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await client.initialize({
|
await client.initialize({
|
||||||
protocolVersion: 0,
|
protocolVersion: PROTOCOL_VERSION,
|
||||||
clientInfo: { name: "goose-text", version: "0.1.0" },
|
clientInfo: { name: "goose-text", version: "0.1.0" },
|
||||||
clientCapabilities: {},
|
clientCapabilities: {},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user