ACP: update package, fix slash command bug (#3906)

This commit is contained in:
Aiden Cline
2025-11-05 00:50:48 -06:00
committed by GitHub
parent 3ebec2435a
commit 1e0596bc46
6 changed files with 87 additions and 35 deletions

View File

@@ -43,7 +43,7 @@
"dependencies": {
"@actions/core": "1.11.1",
"@actions/github": "6.0.1",
"@agentclientprotocol/sdk": "0.4.9",
"@agentclientprotocol/sdk": "0.5.1",
"@clack/prompts": "1.0.0-alpha.1",
"@hono/standard-validator": "0.1.5",
"@hono/zod-validator": "catalog:",
@@ -57,8 +57,8 @@
"@opentui/core": "0.1.33",
"@opentui/solid": "0.1.33",
"@parcel/watcher": "2.5.1",
"@solid-primitives/event-bus": "1.1.2",
"@pierre/precision-diffs": "catalog:",
"@solid-primitives/event-bus": "1.1.2",
"@standard-schema/spec": "1.0.0",
"@zip.js/zip.js": "2.7.62",
"ai": "catalog:",

View File

@@ -1,9 +1,12 @@
import {
RequestError,
type Agent as ACPAgent,
type AgentSideConnection,
type AuthenticateRequest,
type AuthMethod,
type CancelNotification,
type InitializeRequest,
type InitializeResponse,
type LoadSessionRequest,
type NewSessionRequest,
type PermissionOption,
@@ -33,6 +36,7 @@ import type { Config } from "@/config/config"
import { MCP } from "@/mcp"
import { Todo } from "@/session/todo"
import { z } from "zod"
import { LoadAPIKeyError } from "ai"
export namespace ACP {
const log = Log.create({ service: "acp-agent" })
@@ -302,9 +306,26 @@ export namespace ACP {
})
}
async initialize(params: InitializeRequest) {
async initialize(params: InitializeRequest): Promise<InitializeResponse> {
log.info("initialize", { protocolVersion: params.protocolVersion })
const authMethod: AuthMethod = {
description: "Run `opencode auth login` in the terminal",
name: "Login with opencode",
id: "opencode-login",
}
// If client supports terminal-auth capability, use that instead.
if (params.clientCapabilities?._meta?.["terminal-auth"] === true) {
authMethod._meta = {
"terminal-auth": {
command: "opencode",
args: ["auth", "login"],
label: "OpenCode Login",
},
}
}
return {
protocolVersion: 1,
agentCapabilities: {
@@ -325,10 +346,9 @@ export namespace ACP {
id: "opencode-login",
},
],
_meta: {
opencode: {
version: Installation.VERSION,
},
agentInfo: {
name: "OpenCode",
version: Installation.VERSION,
},
}
}
@@ -338,21 +358,31 @@ export namespace ACP {
}
async newSession(params: NewSessionRequest) {
const model = await defaultModel(this.config)
const session = await this.sessionManager.create(params.cwd, params.mcpServers, model)
try {
const model = await defaultModel(this.config)
const session = await this.sessionManager.create(params.cwd, params.mcpServers, model)
log.info("creating_session", { mcpServers: params.mcpServers.length })
const load = await this.loadSession({
cwd: params.cwd,
mcpServers: params.mcpServers,
sessionId: session.id,
})
log.info("creating_session", { mcpServers: params.mcpServers.length })
const load = await this.loadSession({
cwd: params.cwd,
mcpServers: params.mcpServers,
sessionId: session.id,
})
return {
sessionId: session.id,
models: load.models,
modes: load.modes,
_meta: {},
return {
sessionId: session.id,
models: load.models,
modes: load.modes,
_meta: {},
}
} catch (e) {
const error = MessageV2.fromError(e, {
providerID: this.config.defaultModel?.providerID ?? "unknown",
})
if (LoadAPIKeyError.isInstance(error)) {
throw RequestError.authRequired()
}
throw e
}
}
@@ -387,16 +417,6 @@ export namespace ACP {
description: "compact the session",
})
setTimeout(() => {
this.connection.sessionUpdate({
sessionId,
update: {
sessionUpdate: "available_commands_update",
availableCommands,
},
})
}, 0)
const availableModes = (await Agents.list())
.filter((agent) => agent.mode !== "subagent")
.map((agent) => ({
@@ -437,6 +457,16 @@ export namespace ACP {
}),
)
setTimeout(() => {
this.connection.sessionUpdate({
sessionId,
update: {
sessionUpdate: "available_commands_update",
availableCommands,
},
})
}, 0)
return {
sessionId,
models: {

View File

@@ -6,13 +6,18 @@ import type { ACPSessionState } from "./types"
export class ACPSessionManager {
private sessions = new Map<string, ACPSessionState>()
async create(cwd: string, mcpServers: McpServer[], model?: ACPSessionState["model"]): Promise<ACPSessionState> {
async create(
cwd: string,
mcpServers: McpServer[],
model?: ACPSessionState["model"],
): Promise<ACPSessionState> {
const session = await Session.create({ title: `ACP Session ${crypto.randomUUID()}` })
const sessionId = session.id
const resolvedModel = model ?? (await Provider.defaultModel())
const state: ACPSessionState = {
id: sessionId,
parentId: session.parentID,
cwd,
mcpServers,
createdAt: new Date(),

View File

@@ -2,6 +2,7 @@ import type { McpServer } from "@agentclientprotocol/sdk"
export interface ACPSessionState {
id: string
parentId?: string
cwd: string
mcpServers: McpServer[]
createdAt: Date

View File

@@ -77,7 +77,15 @@ export namespace MCP {
}
},
async (state) => {
await Promise.all(Object.values(state.clients).map((client) => client.close()))
await Promise.all(
Object.values(state.clients).map((client) =>
client.close().catch((error) => {
log.error("Failed to close MCP client", {
error,
})
}),
),
)
},
)
@@ -201,7 +209,15 @@ export namespace MCP {
const result = await withTimeout(mcpClient.tools(), mcp.timeout ?? 5000).catch(() => {})
if (!result) {
await mcpClient.close()
await mcpClient.close().catch((error) => {
log.error("Failed to close MCP client", {
error,
})
})
status = {
status: "failed",
error: "Failed to get tools",
}
return {
mcpClient: undefined,
status: {