Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
eed4bfa
init
haoxiangliew Nov 6, 2025
c368e74
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 6, 2025
f14d314
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 6, 2025
e4f4bbe
refactor ACP tools
haoxiangliew Nov 6, 2025
e0e9072
revert changes to readme
haoxiangliew Nov 6, 2025
8408d94
refactor ACP tools
haoxiangliew Nov 6, 2025
949e6b0
we don't need ACP for "does a file exist"
haoxiangliew Nov 6, 2025
e1b0ab8
remove unused import
haoxiangliew Nov 6, 2025
c10f3f8
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 6, 2025
8e86d9c
assure both capabilities are there
haoxiangliew Nov 6, 2025
a799496
Merge branch 'dev' into zed-acp-fixes
rekram1-node Nov 6, 2025
1b78db4
Merge branch 'dev' into zed-acp-fixes
rekram1-node Nov 6, 2025
399b0cf
address PR
haoxiangliew Nov 6, 2025
b011b6b
address PR
haoxiangliew Nov 6, 2025
07de79e
cleanup
haoxiangliew Nov 6, 2025
c246889
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 6, 2025
70efa29
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 6, 2025
268dd07
cleanup
haoxiangliew Nov 6, 2025
6b0c042
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 6, 2025
c08e60c
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 7, 2025
32524f3
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 7, 2025
425f56f
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 8, 2025
63e85c3
refactor merge after 'dev'
haoxiangliew Nov 8, 2025
c95d2f7
update
haoxiangliew Nov 8, 2025
f076d39
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 9, 2025
cd602ca
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 10, 2025
47a99f6
cleanup
haoxiangliew Nov 10, 2025
cb7923c
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 10, 2025
5e244ce
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 11, 2025
12e3774
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 12, 2025
4e5b577
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 13, 2025
71bb163
chore: format code
actions-user Nov 13, 2025
c93c8f3
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 14, 2025
563e619
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 16, 2025
5a2779c
fix after merge
haoxiangliew Nov 16, 2025
ef2a6de
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 17, 2025
bd1c93c
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 17, 2025
854af11
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 18, 2025
1ff6c62
rework for domain
haoxiangliew Nov 18, 2025
8bdc7fa
chore: format code
actions-user Nov 18, 2025
0761b3a
update
haoxiangliew Nov 18, 2025
054907d
chore: format code
actions-user Nov 18, 2025
8d3b326
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 18, 2025
94c2a58
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 19, 2025
5cc19f0
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 21, 2025
a29e72f
chore: format code
actions-user Nov 21, 2025
e52f502
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 21, 2025
fb691cc
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 23, 2025
8db3929
Update Nix flake.lock and hashes
actions-user Nov 23, 2025
e282fcf
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Nov 24, 2025
ae57cb8
Update Nix flake.lock and hashes
actions-user Nov 24, 2025
21739b6
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Dec 1, 2025
e23f92d
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Dec 3, 2025
650f80b
bump
haoxiangliew Dec 3, 2025
8fa8d50
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Dec 7, 2025
28d0755
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Dec 8, 2025
e94ccd8
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Dec 9, 2025
ae5ba82
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Dec 9, 2025
fa2f417
Merge branch 'dev' into zed-acp-fixes
haoxiangliew Dec 10, 2025
300e4f5
update
haoxiangliew Dec 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/opencode/src/acp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ The implementation follows a clean separation of concerns:
- Sets up JSON-RPC over stdio using the official library
- Manages graceful shutdown on SIGTERM/SIGINT
- Provides Instance context for the agent

- **`tools.ts`** - ACP-aware tools for client file operation delegation
- Provides `acp_read`, `acp_edit`, and `acp_write` tools
- These tools delegate file operations to the ACP client (e.g., Zed)
- Registered automatically when client has `writeTextFile` capability
- Enables proper edit accumulation and undo/redo in supporting clients


- **`types.ts`** - Type definitions for internal use

Expand Down
50 changes: 47 additions & 3 deletions packages/opencode/src/acp/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@ import {
type AuthenticateRequest,
type AuthMethod,
type CancelNotification,
type ClientCapabilities,
type InitializeRequest,
type InitializeResponse,
type LoadSessionRequest,
type NewSessionRequest,
type PermissionOption,
type PlanEntry,
type PromptRequest,
type ReadTextFileRequest,
type ReadTextFileResponse,
type SetSessionModelRequest,
type SetSessionModeRequest,
type SetSessionModeResponse,
type ToolCallContent,
type ToolKind,
type WriteTextFileRequest,
type WriteTextFileResponse,
} from "@agentclientprotocol/sdk"
import { Log } from "../util/log"
import { ACPSessionManager } from "./session"
Expand All @@ -37,6 +42,8 @@ import { MCP } from "@/mcp"
import { Todo } from "@/session/todo"
import { z } from "zod"
import { LoadAPIKeyError } from "ai"
import { createACPTools } from "./tools"
import { ToolRegistry } from "../tool/registry"

export namespace ACP {
const log = Log.create({ service: "acp-agent" })
Expand All @@ -45,6 +52,7 @@ export namespace ACP {
private sessionManager = new ACPSessionManager()
private connection: AgentSideConnection
private config: ACPConfig
private clientCapabilities?: ClientCapabilities

constructor(connection: AgentSideConnection, config: ACPConfig = {}) {
this.connection = connection
Expand Down Expand Up @@ -315,6 +323,7 @@ export namespace ACP {

async initialize(params: InitializeRequest): Promise<InitializeResponse> {
log.info("initialize", { protocolVersion: params.protocolVersion })
this.clientCapabilities = params.clientCapabilities

const authMethod: AuthMethod = {
description: "Run `opencode auth login` in the terminal",
Expand Down Expand Up @@ -361,9 +370,18 @@ export namespace ACP {
async newSession(params: NewSessionRequest) {
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 hasACPTools = !!this.clientCapabilities?.fs?.writeTextFile
const session = await this.sessionManager.create(
params.cwd,
params.mcpServers,
model,
hasACPTools,
)

log.info("creating_session", {
mcpServers: params.mcpServers.length,
hasACPTools,
})
const load = await this.loadSession({
cwd: params.cwd,
mcpServers: params.mcpServers,
Expand Down Expand Up @@ -452,6 +470,14 @@ export namespace ACP {
}
}

if (this.clientCapabilities?.fs?.writeTextFile) {
log.info("Client has writeTextFile capability, registering ACP tools")
const acpTools = createACPTools(this, sessionId)
for (const tool of acpTools) {
await ToolRegistry.register(tool)
}
}

await Promise.all(
Object.entries(mcpServers).map(async ([key, mcp]) => {
await MCP.add(key, mcp)
Expand Down Expand Up @@ -593,6 +619,13 @@ export namespace ACP {
}

if (!cmd) {
const tools = acpSession.hasACPTools
? {
edit: false,
write: false,
read: false,
}
: undefined
await SessionPrompt.prompt({
sessionID,
model: {
Expand All @@ -601,6 +634,7 @@ export namespace ACP {
},
parts,
agent,
tools,
})
return done
}
Expand Down Expand Up @@ -633,6 +667,16 @@ export namespace ACP {
async cancel(params: CancelNotification) {
SessionLock.abort(params.sessionId)
}

async readTextFile(params: ReadTextFileRequest): Promise<ReadTextFileResponse> {
log.debug("readTextFile", { path: params.path, sessionId: params.sessionId })
return await this.connection.readTextFile(params)
}

async writeTextFile(params: WriteTextFileRequest): Promise<WriteTextFileResponse> {
log.debug("writeTextFile", { path: params.path, sessionId: params.sessionId })
return await this.connection.writeTextFile(params)
}
}

function toToolKind(toolName: string): ToolKind {
Expand Down
2 changes: 2 additions & 0 deletions packages/opencode/src/acp/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class ACPSessionManager {
cwd: string,
mcpServers: McpServer[],
model?: ACPSessionState["model"],
hasACPTools?: boolean,
): Promise<ACPSessionState> {
const session = await Session.create({ title: `ACP Session ${crypto.randomUUID()}` })
const sessionId = session.id
Expand All @@ -22,6 +23,7 @@ export class ACPSessionManager {
mcpServers,
createdAt: new Date(),
model: resolvedModel,
hasACPTools,
}

this.sessions.set(sessionId, state)
Expand Down
Loading