mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-22 18:24:21 +01:00
ACP: update package, fix slash command bug (#3906)
This commit is contained in:
4
bun.lock
4
bun.lock
@@ -173,7 +173,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "1.11.1",
|
"@actions/core": "1.11.1",
|
||||||
"@actions/github": "6.0.1",
|
"@actions/github": "6.0.1",
|
||||||
"@agentclientprotocol/sdk": "0.4.9",
|
"@agentclientprotocol/sdk": "0.5.1",
|
||||||
"@clack/prompts": "1.0.0-alpha.1",
|
"@clack/prompts": "1.0.0-alpha.1",
|
||||||
"@hono/standard-validator": "0.1.5",
|
"@hono/standard-validator": "0.1.5",
|
||||||
"@hono/zod-validator": "catalog:",
|
"@hono/zod-validator": "catalog:",
|
||||||
@@ -401,7 +401,7 @@
|
|||||||
|
|
||||||
"@adobe/css-tools": ["@adobe/css-tools@4.4.4", "", {}, "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg=="],
|
"@adobe/css-tools": ["@adobe/css-tools@4.4.4", "", {}, "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg=="],
|
||||||
|
|
||||||
"@agentclientprotocol/sdk": ["@agentclientprotocol/sdk@0.4.9", "", { "dependencies": { "zod": "^3.0.0" } }, "sha512-ExwH828LaTGoTTjxuw49l+fwOLA+Yx0+qkWn1TcHMOsY5mVI9CUfkj7ZDhv2klgZ7mJeT+lxX/Dn/KINv1AkNQ=="],
|
"@agentclientprotocol/sdk": ["@agentclientprotocol/sdk@0.5.1", "", { "dependencies": { "zod": "^3.0.0" } }, "sha512-9bq2TgjhLBSUSC5jE04MEe+Hqw8YePzKghhYZ9QcjOyonY3q2oJfX6GoSO83hURpEnsqEPIrex6VZN3+61fBJg=="],
|
||||||
|
|
||||||
"@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@2.2.10", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-icLGO7Q0NinnHIPgT+y1QjHVwH4HwV+brWbvM+FfCG2Afpa89PyKa3Ret91kGjZpBgM/xnj1B7K5eM+rRlsXQA=="],
|
"@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@2.2.10", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.0.0" } }, "sha512-icLGO7Q0NinnHIPgT+y1QjHVwH4HwV+brWbvM+FfCG2Afpa89PyKa3Ret91kGjZpBgM/xnj1B7K5eM+rRlsXQA=="],
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "1.11.1",
|
"@actions/core": "1.11.1",
|
||||||
"@actions/github": "6.0.1",
|
"@actions/github": "6.0.1",
|
||||||
"@agentclientprotocol/sdk": "0.4.9",
|
"@agentclientprotocol/sdk": "0.5.1",
|
||||||
"@clack/prompts": "1.0.0-alpha.1",
|
"@clack/prompts": "1.0.0-alpha.1",
|
||||||
"@hono/standard-validator": "0.1.5",
|
"@hono/standard-validator": "0.1.5",
|
||||||
"@hono/zod-validator": "catalog:",
|
"@hono/zod-validator": "catalog:",
|
||||||
@@ -57,8 +57,8 @@
|
|||||||
"@opentui/core": "0.1.33",
|
"@opentui/core": "0.1.33",
|
||||||
"@opentui/solid": "0.1.33",
|
"@opentui/solid": "0.1.33",
|
||||||
"@parcel/watcher": "2.5.1",
|
"@parcel/watcher": "2.5.1",
|
||||||
"@solid-primitives/event-bus": "1.1.2",
|
|
||||||
"@pierre/precision-diffs": "catalog:",
|
"@pierre/precision-diffs": "catalog:",
|
||||||
|
"@solid-primitives/event-bus": "1.1.2",
|
||||||
"@standard-schema/spec": "1.0.0",
|
"@standard-schema/spec": "1.0.0",
|
||||||
"@zip.js/zip.js": "2.7.62",
|
"@zip.js/zip.js": "2.7.62",
|
||||||
"ai": "catalog:",
|
"ai": "catalog:",
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
|
RequestError,
|
||||||
type Agent as ACPAgent,
|
type Agent as ACPAgent,
|
||||||
type AgentSideConnection,
|
type AgentSideConnection,
|
||||||
type AuthenticateRequest,
|
type AuthenticateRequest,
|
||||||
|
type AuthMethod,
|
||||||
type CancelNotification,
|
type CancelNotification,
|
||||||
type InitializeRequest,
|
type InitializeRequest,
|
||||||
|
type InitializeResponse,
|
||||||
type LoadSessionRequest,
|
type LoadSessionRequest,
|
||||||
type NewSessionRequest,
|
type NewSessionRequest,
|
||||||
type PermissionOption,
|
type PermissionOption,
|
||||||
@@ -33,6 +36,7 @@ import type { Config } from "@/config/config"
|
|||||||
import { MCP } from "@/mcp"
|
import { MCP } from "@/mcp"
|
||||||
import { Todo } from "@/session/todo"
|
import { Todo } from "@/session/todo"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
import { LoadAPIKeyError } from "ai"
|
||||||
|
|
||||||
export namespace ACP {
|
export namespace ACP {
|
||||||
const log = Log.create({ service: "acp-agent" })
|
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 })
|
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 {
|
return {
|
||||||
protocolVersion: 1,
|
protocolVersion: 1,
|
||||||
agentCapabilities: {
|
agentCapabilities: {
|
||||||
@@ -325,10 +346,9 @@ export namespace ACP {
|
|||||||
id: "opencode-login",
|
id: "opencode-login",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
_meta: {
|
agentInfo: {
|
||||||
opencode: {
|
name: "OpenCode",
|
||||||
version: Installation.VERSION,
|
version: Installation.VERSION,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,21 +358,31 @@ export namespace ACP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async newSession(params: NewSessionRequest) {
|
async newSession(params: NewSessionRequest) {
|
||||||
const model = await defaultModel(this.config)
|
try {
|
||||||
const session = await this.sessionManager.create(params.cwd, params.mcpServers, model)
|
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 })
|
log.info("creating_session", { mcpServers: params.mcpServers.length })
|
||||||
const load = await this.loadSession({
|
const load = await this.loadSession({
|
||||||
cwd: params.cwd,
|
cwd: params.cwd,
|
||||||
mcpServers: params.mcpServers,
|
mcpServers: params.mcpServers,
|
||||||
sessionId: session.id,
|
sessionId: session.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sessionId: session.id,
|
sessionId: session.id,
|
||||||
models: load.models,
|
models: load.models,
|
||||||
modes: load.modes,
|
modes: load.modes,
|
||||||
_meta: {},
|
_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",
|
description: "compact the session",
|
||||||
})
|
})
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.connection.sessionUpdate({
|
|
||||||
sessionId,
|
|
||||||
update: {
|
|
||||||
sessionUpdate: "available_commands_update",
|
|
||||||
availableCommands,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}, 0)
|
|
||||||
|
|
||||||
const availableModes = (await Agents.list())
|
const availableModes = (await Agents.list())
|
||||||
.filter((agent) => agent.mode !== "subagent")
|
.filter((agent) => agent.mode !== "subagent")
|
||||||
.map((agent) => ({
|
.map((agent) => ({
|
||||||
@@ -437,6 +457,16 @@ export namespace ACP {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.connection.sessionUpdate({
|
||||||
|
sessionId,
|
||||||
|
update: {
|
||||||
|
sessionUpdate: "available_commands_update",
|
||||||
|
availableCommands,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}, 0)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sessionId,
|
sessionId,
|
||||||
models: {
|
models: {
|
||||||
|
|||||||
@@ -6,13 +6,18 @@ import type { ACPSessionState } from "./types"
|
|||||||
export class ACPSessionManager {
|
export class ACPSessionManager {
|
||||||
private sessions = new Map<string, ACPSessionState>()
|
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 session = await Session.create({ title: `ACP Session ${crypto.randomUUID()}` })
|
||||||
const sessionId = session.id
|
const sessionId = session.id
|
||||||
const resolvedModel = model ?? (await Provider.defaultModel())
|
const resolvedModel = model ?? (await Provider.defaultModel())
|
||||||
|
|
||||||
const state: ACPSessionState = {
|
const state: ACPSessionState = {
|
||||||
id: sessionId,
|
id: sessionId,
|
||||||
|
parentId: session.parentID,
|
||||||
cwd,
|
cwd,
|
||||||
mcpServers,
|
mcpServers,
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { McpServer } from "@agentclientprotocol/sdk"
|
|||||||
|
|
||||||
export interface ACPSessionState {
|
export interface ACPSessionState {
|
||||||
id: string
|
id: string
|
||||||
|
parentId?: string
|
||||||
cwd: string
|
cwd: string
|
||||||
mcpServers: McpServer[]
|
mcpServers: McpServer[]
|
||||||
createdAt: Date
|
createdAt: Date
|
||||||
|
|||||||
@@ -77,7 +77,15 @@ export namespace MCP {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async (state) => {
|
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(() => {})
|
const result = await withTimeout(mcpClient.tools(), mcp.timeout ?? 5000).catch(() => {})
|
||||||
if (!result) {
|
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 {
|
return {
|
||||||
mcpClient: undefined,
|
mcpClient: undefined,
|
||||||
status: {
|
status: {
|
||||||
|
|||||||
Reference in New Issue
Block a user