chore(cli): upgrade acp sdk (#38316)
This commit is contained in:
parent
5b1321a8ca
commit
bbe985b4d0
9 changed files with 8 additions and 33 deletions
4
bun.lock
4
bun.lock
|
|
@ -124,7 +124,7 @@
|
||||||
"opencode2": "./bin/opencode2.cjs",
|
"opencode2": "./bin/opencode2.cjs",
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@agentclientprotocol/sdk": "0.21.0",
|
"@agentclientprotocol/sdk": "1.2.1",
|
||||||
"@effect/platform-node": "catalog:",
|
"@effect/platform-node": "catalog:",
|
||||||
"@opencode-ai/client": "workspace:*",
|
"@opencode-ai/client": "workspace:*",
|
||||||
"@opencode-ai/plugin": "workspace:*",
|
"@opencode-ai/plugin": "workspace:*",
|
||||||
|
|
@ -1173,7 +1173,7 @@
|
||||||
|
|
||||||
"@adobe/css-tools": ["@adobe/css-tools@4.5.0", "", {}, "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q=="],
|
"@adobe/css-tools": ["@adobe/css-tools@4.5.0", "", {}, "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q=="],
|
||||||
|
|
||||||
"@agentclientprotocol/sdk": ["@agentclientprotocol/sdk@0.21.0", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-ONj+Q8qOdNQp5XbH5jnMwzT9IKZJsSN0p0lkceS4GtUtNOPVLpNzSS8gqQdGMKfBvA0ESbkL8BTaSN1Rc9miEw=="],
|
"@agentclientprotocol/sdk": ["@agentclientprotocol/sdk@1.2.1", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-jwYUdOQR7tc+Zfch53VL4JJyUNK/46q03uUTYb+PjECsmnNl94XFXOfYLJ8RBpMNidXd1rpOAVgb0vqD98xImA=="],
|
||||||
|
|
||||||
"@ai-sdk/alibaba": ["@ai-sdk/alibaba@1.0.17", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZbE+U5bWz2JBc5DERLowx5+TKbjGBE93LqKZAWvuEn7HOSQMraxFMZuc0ST335QZJAyfBOzh7m1mPQ+y7EaaoA=="],
|
"@ai-sdk/alibaba": ["@ai-sdk/alibaba@1.0.17", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.41", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZbE+U5bWz2JBc5DERLowx5+TKbjGBE93LqKZAWvuEn7HOSQMraxFMZuc0ST335QZJAyfBOzh7m1mPQ+y7EaaoA=="],
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
"typecheck": "tsgo --noEmit"
|
"typecheck": "tsgo --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@agentclientprotocol/sdk": "0.21.0",
|
"@agentclientprotocol/sdk": "1.2.1",
|
||||||
"@effect/platform-node": "catalog:",
|
"@effect/platform-node": "catalog:",
|
||||||
"@opencode-ai/client": "workspace:*",
|
"@opencode-ai/client": "workspace:*",
|
||||||
"@opencode-ai/plugin": "workspace:*",
|
"@opencode-ai/plugin": "workspace:*",
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import {
|
||||||
type PromptRequest,
|
type PromptRequest,
|
||||||
type ResumeSessionRequest,
|
type ResumeSessionRequest,
|
||||||
type SetSessionConfigOptionRequest,
|
type SetSessionConfigOptionRequest,
|
||||||
type SetSessionModelRequest,
|
|
||||||
type SetSessionModeRequest,
|
type SetSessionModeRequest,
|
||||||
} from "@agentclientprotocol/sdk"
|
} from "@agentclientprotocol/sdk"
|
||||||
import type { OpenCodeClient } from "@opencode-ai/client/promise"
|
import type { OpenCodeClient } from "@opencode-ai/client/promise"
|
||||||
|
|
@ -33,7 +32,6 @@ export function create(client: OpenCodeClient, connection: AgentSideConnection)
|
||||||
unstable_forkSession: (params: ForkSessionRequest) => run(service.forkSession(params)),
|
unstable_forkSession: (params: ForkSessionRequest) => run(service.forkSession(params)),
|
||||||
setSessionConfigOption: (params: SetSessionConfigOptionRequest) => run(service.setSessionConfigOption(params)),
|
setSessionConfigOption: (params: SetSessionConfigOptionRequest) => run(service.setSessionConfigOption(params)),
|
||||||
setSessionMode: (params: SetSessionModeRequest) => run(service.setSessionMode(params)),
|
setSessionMode: (params: SetSessionModeRequest) => run(service.setSessionMode(params)),
|
||||||
unstable_setSessionModel: (params: SetSessionModelRequest) => run(service.setSessionModel(params)),
|
|
||||||
prompt: (params: PromptRequest) => run(service.prompt(params)),
|
prompt: (params: PromptRequest) => run(service.prompt(params)),
|
||||||
cancel: (params: CancelNotification) => run(service.cancel(params)),
|
cancel: (params: CancelNotification) => run(service.cancel(params)),
|
||||||
} satisfies Agent
|
} satisfies Agent
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ export async function streamTurn(input: {
|
||||||
readonly sessionID: string
|
readonly sessionID: string
|
||||||
readonly cwd: string
|
readonly cwd: string
|
||||||
readonly start: TurnStart
|
readonly start: TurnStart
|
||||||
readonly userMessageID?: string | null
|
|
||||||
readonly submit: (signal: AbortSignal) => Promise<unknown>
|
readonly submit: (signal: AbortSignal) => Promise<unknown>
|
||||||
readonly control: TurnControl
|
readonly control: TurnControl
|
||||||
}): Promise<PromptResponse> {
|
}): Promise<PromptResponse> {
|
||||||
|
|
@ -231,7 +230,7 @@ export async function streamTurn(input: {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
streamController.abort()
|
streamController.abort()
|
||||||
await completed.catch(() => {})
|
await completed.catch(() => {})
|
||||||
return response(undefined, undefined, "interrupted", true, undefined, input.userMessageID)
|
return response(undefined, undefined, "interrupted", true, undefined)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const terminal = await completed
|
const terminal = await completed
|
||||||
|
|
@ -246,7 +245,6 @@ export async function streamTurn(input: {
|
||||||
terminal,
|
terminal,
|
||||||
control.cancelled,
|
control.cancelled,
|
||||||
finish,
|
finish,
|
||||||
input.userMessageID,
|
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
streamController.abort()
|
streamController.abort()
|
||||||
|
|
@ -400,7 +398,6 @@ function response(
|
||||||
terminal: "succeeded" | "failed" | "interrupted",
|
terminal: "succeeded" | "failed" | "interrupted",
|
||||||
cancelled: boolean,
|
cancelled: boolean,
|
||||||
finish: SessionMessageAssistant["finish"],
|
finish: SessionMessageAssistant["finish"],
|
||||||
messageID: string | null | undefined,
|
|
||||||
): PromptResponse {
|
): PromptResponse {
|
||||||
const error = assistant?.error ?? executionError
|
const error = assistant?.error ?? executionError
|
||||||
if (error?.type === "provider.auth") throw new ACPError.AuthRequiredError()
|
if (error?.type === "provider.auth") throw new ACPError.AuthRequiredError()
|
||||||
|
|
@ -423,7 +420,7 @@ function response(
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
const stopReason = resolveStopReason({ terminal, cancelled, finish, error: error?.type })
|
const stopReason = resolveStopReason({ terminal, cancelled, finish, error: error?.type })
|
||||||
return { stopReason, ...(usage ? { usage } : {}), ...(messageID ? { userMessageId: messageID } : {}), _meta: {} }
|
return { stopReason, ...(usage ? { usage } : {}), _meta: {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveStopReason(input: {
|
function resolveStopReason(input: {
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,6 @@ import type {
|
||||||
ResumeSessionResponse,
|
ResumeSessionResponse,
|
||||||
SetSessionConfigOptionRequest,
|
SetSessionConfigOptionRequest,
|
||||||
SetSessionConfigOptionResponse,
|
SetSessionConfigOptionResponse,
|
||||||
SetSessionModelRequest,
|
|
||||||
SetSessionModelResponse,
|
|
||||||
SetSessionModeRequest,
|
SetSessionModeRequest,
|
||||||
SetSessionModeResponse,
|
SetSessionModeResponse,
|
||||||
} from "@agentclientprotocol/sdk"
|
} from "@agentclientprotocol/sdk"
|
||||||
|
|
@ -88,7 +86,6 @@ export interface Interface {
|
||||||
forkSession(input: ForkSessionRequest): Promise<ForkSessionResponse>
|
forkSession(input: ForkSessionRequest): Promise<ForkSessionResponse>
|
||||||
setSessionConfigOption(input: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse>
|
setSessionConfigOption(input: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse>
|
||||||
setSessionMode(input: SetSessionModeRequest): Promise<SetSessionModeResponse>
|
setSessionMode(input: SetSessionModeRequest): Promise<SetSessionModeResponse>
|
||||||
setSessionModel(input: SetSessionModelRequest): Promise<SetSessionModelResponse>
|
|
||||||
prompt(input: PromptRequest): Promise<PromptResponse>
|
prompt(input: PromptRequest): Promise<PromptResponse>
|
||||||
cancel(input: CancelNotification): Promise<void>
|
cancel(input: CancelNotification): Promise<void>
|
||||||
}
|
}
|
||||||
|
|
@ -270,13 +267,6 @@ export function make(input: { readonly client: OpenCodeClient; readonly connecti
|
||||||
await selectMode(input.client, await requireSession(params.sessionId), params.modeId)
|
await selectMode(input.client, await requireSession(params.sessionId), params.modeId)
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
setSessionModel: async (params) => {
|
|
||||||
const state = await requireSession(params.sessionId)
|
|
||||||
const selected = requireModel(state.catalog, params.modelId)
|
|
||||||
state.model = selected
|
|
||||||
await input.client.session.switchModel({ sessionID: state.id, model: selected })
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
prompt: async (params) => {
|
prompt: async (params) => {
|
||||||
const state = await requireSession(params.sessionId)
|
const state = await requireSession(params.sessionId)
|
||||||
if (active.has(state.id)) {
|
if (active.has(state.id)) {
|
||||||
|
|
@ -295,7 +285,6 @@ export function make(input: { readonly client: OpenCodeClient; readonly connecti
|
||||||
sessionID: state.id,
|
sessionID: state.id,
|
||||||
cwd: state.cwd,
|
cwd: state.cwd,
|
||||||
start: prepared.start,
|
start: prepared.start,
|
||||||
userMessageID: params.messageId,
|
|
||||||
control,
|
control,
|
||||||
submit: (signal) => submitPrompt(input.client, state, prepared, signal),
|
submit: (signal) => submitPrompt(input.client, state, prepared, signal),
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
|
@ -479,6 +468,7 @@ async function registerMcpServers(
|
||||||
|
|
||||||
function mcpConfig(server: McpServer) {
|
function mcpConfig(server: McpServer) {
|
||||||
if ("type" in server) {
|
if ("type" in server) {
|
||||||
|
if (server.type === "acp") throw new Error("MCP-over-ACP is not supported")
|
||||||
return {
|
return {
|
||||||
type: "remote" as const,
|
type: "remote" as const,
|
||||||
url: server.url,
|
url: server.url,
|
||||||
|
|
|
||||||
|
|
@ -566,7 +566,6 @@ function turn(input: {
|
||||||
sessionID: input.sessionID,
|
sessionID: input.sessionID,
|
||||||
cwd: "/workspace",
|
cwd: "/workspace",
|
||||||
start: { type: "input", id: input.inputID },
|
start: { type: "input", id: input.inputID },
|
||||||
userMessageID: `client_${input.inputID}`,
|
|
||||||
control: { cancelled: false, admission: new AbortController() },
|
control: { cancelled: false, admission: new AbortController() },
|
||||||
submit: (signal) =>
|
submit: (signal) =>
|
||||||
input.fixture.client.session.prompt({ sessionID: input.sessionID, id: input.inputID, text: "hello" }, { signal }),
|
input.fixture.client.session.prompt({ sessionID: input.sessionID, id: input.inputID, text: "hello" }, { signal }),
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,6 @@ test("acp prompt resolves after ordered turn updates", async () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const id = "msg_prompt"
|
const id = "msg_prompt"
|
||||||
const userMessageID = "client-message"
|
|
||||||
const response = await streamTurn({
|
const response = await streamTurn({
|
||||||
client,
|
client,
|
||||||
connection: {
|
connection: {
|
||||||
|
|
@ -97,7 +96,6 @@ test("acp prompt resolves after ordered turn updates", async () => {
|
||||||
sessionID: "ses_test",
|
sessionID: "ses_test",
|
||||||
cwd: "/workspace",
|
cwd: "/workspace",
|
||||||
start: { type: "input", id },
|
start: { type: "input", id },
|
||||||
userMessageID,
|
|
||||||
control: { cancelled: false, admission: new AbortController() },
|
control: { cancelled: false, admission: new AbortController() },
|
||||||
submit: () => client.session.prompt({ sessionID: "ses_test", id, text: "hi" }),
|
submit: () => client.session.prompt({ sessionID: "ses_test", id, text: "hi" }),
|
||||||
})
|
})
|
||||||
|
|
@ -112,7 +110,7 @@ test("acp prompt resolves after ordered turn updates", async () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
expect(response).toMatchObject({ stopReason: "end_turn", userMessageId: userMessageID, usage: { totalTokens: 2 } })
|
expect(response).toMatchObject({ stopReason: "end_turn", usage: { totalTokens: 2 } })
|
||||||
} finally {
|
} finally {
|
||||||
events?.close()
|
events?.close()
|
||||||
await server.stop(true)
|
await server.stop(true)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, expect, test } from "bun:test"
|
import { describe, expect, test } from "bun:test"
|
||||||
import type { McpServer, SessionConfigOption } from "@agentclientprotocol/sdk"
|
import type { McpServer, SessionConfigOption } from "@agentclientprotocol/sdk"
|
||||||
import { makeACPFixture, makeSession, secondModel, testModel } from "./service-fixture"
|
import { makeACPFixture, makeSession, secondModel } from "./service-fixture"
|
||||||
|
|
||||||
describe("acp service directory behavior", () => {
|
describe("acp service directory behavior", () => {
|
||||||
test("creates sessions from a catalog shared by concurrent callers in the same cwd", async () => {
|
test("creates sessions from a catalog shared by concurrent callers in the same cwd", async () => {
|
||||||
|
|
@ -134,7 +134,6 @@ describe("acp service directory behavior", () => {
|
||||||
configId: "mode",
|
configId: "mode",
|
||||||
value: "plan",
|
value: "plan",
|
||||||
})
|
})
|
||||||
await fixture.service.setSessionModel({ sessionId: session.sessionId, modelId: "test/test-model/high" })
|
|
||||||
await fixture.service.setSessionMode({ sessionId: session.sessionId, modeId: "build" })
|
await fixture.service.setSessionMode({ sessionId: session.sessionId, modeId: "build" })
|
||||||
|
|
||||||
expect(currentValue(selectedModel, "model")).toBe("test/second-model")
|
expect(currentValue(selectedModel, "model")).toBe("test/second-model")
|
||||||
|
|
@ -148,7 +147,6 @@ describe("acp service directory behavior", () => {
|
||||||
).toEqual([
|
).toEqual([
|
||||||
{ model: { providerID: "test", id: secondModel.id } },
|
{ model: { providerID: "test", id: secondModel.id } },
|
||||||
{ model: { providerID: "test", id: secondModel.id, variant: "medium" } },
|
{ model: { providerID: "test", id: secondModel.id, variant: "medium" } },
|
||||||
{ model: { providerID: "test", id: testModel.id, variant: "high" } },
|
|
||||||
])
|
])
|
||||||
expect(
|
expect(
|
||||||
fixture.requests
|
fixture.requests
|
||||||
|
|
|
||||||
|
|
@ -45,17 +45,14 @@ describe("acp service prompt routing and usage", () => {
|
||||||
|
|
||||||
const commandResult = await fixture.service.prompt({
|
const commandResult = await fixture.service.prompt({
|
||||||
sessionId: session.sessionId,
|
sessionId: session.sessionId,
|
||||||
messageId: "client-command",
|
|
||||||
prompt: [{ type: "text", text: "/review now" }],
|
prompt: [{ type: "text", text: "/review now" }],
|
||||||
})
|
})
|
||||||
const skillResult = await fixture.service.prompt({
|
const skillResult = await fixture.service.prompt({
|
||||||
sessionId: session.sessionId,
|
sessionId: session.sessionId,
|
||||||
messageId: "client-skill",
|
|
||||||
prompt: [{ type: "text", text: "/verify" }],
|
prompt: [{ type: "text", text: "/verify" }],
|
||||||
})
|
})
|
||||||
const compactResult = await fixture.service.prompt({
|
const compactResult = await fixture.service.prompt({
|
||||||
sessionId: session.sessionId,
|
sessionId: session.sessionId,
|
||||||
messageId: "client-compact",
|
|
||||||
prompt: [{ type: "text", text: "/compact" }],
|
prompt: [{ type: "text", text: "/compact" }],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -154,13 +151,11 @@ describe("acp service prompt routing and usage", () => {
|
||||||
|
|
||||||
const response = await fixture.service.prompt({
|
const response = await fixture.service.prompt({
|
||||||
sessionId: session.sessionId,
|
sessionId: session.sessionId,
|
||||||
messageId: "client-message",
|
|
||||||
prompt: [{ type: "text", text: "hello" }],
|
prompt: [{ type: "text", text: "hello" }],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(response).toEqual({
|
expect(response).toEqual({
|
||||||
stopReason: "end_turn",
|
stopReason: "end_turn",
|
||||||
userMessageId: "client-message",
|
|
||||||
usage: {
|
usage: {
|
||||||
inputTokens: 100,
|
inputTokens: 100,
|
||||||
outputTokens: 40,
|
outputTokens: 40,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue