diff --git a/packages/opencode/src/acp/agent.ts b/packages/opencode/src/acp/agent.ts index 8ac09e4bb31e..103da4081b03 100644 --- a/packages/opencode/src/acp/agent.ts +++ b/packages/opencode/src/acp/agent.ts @@ -461,6 +461,27 @@ export namespace ACP { return } + case "file.edited": + const props = event.properties + const session = this.sessionManager.tryGet(props.sessionID) + if (!session) return + const sessionId = session.id + + if (this.config.clientCapabilities?.fs?.writeTextFile) { + const filepath = event.properties.file + try { + const content = await Bun.file(filepath).text() + await this.connection.writeTextFile({ + sessionId, + path: filepath, + content, + }) + log.info("synced file edit to ACP client", { filepath, sessionId}) + } catch (err) { + log.error("failed to sync file edit to ACP client", { error: err, filepath, sessionId }) + } + } + break case "message.part.delta": { const props = event.properties @@ -530,7 +551,9 @@ export namespace ACP { } async initialize(params: InitializeRequest): Promise { - log.info("initialize", { protocolVersion: params.protocolVersion }) + log.info("initialize", { protocolVersion: params.protocolVersion, clientCapabilities: params.clientCapabilities }) + + this.config.clientCapabilities = params.clientCapabilities const authMethod: AuthMethod = { description: "Run `opencode auth login` in the terminal", diff --git a/packages/opencode/src/acp/types.ts b/packages/opencode/src/acp/types.ts index 2c3e886bc185..27da7255bea7 100644 --- a/packages/opencode/src/acp/types.ts +++ b/packages/opencode/src/acp/types.ts @@ -1,4 +1,4 @@ -import type { McpServer } from "@agentclientprotocol/sdk" +import type { McpServer, ClientCapabilities } from "@agentclientprotocol/sdk" import type { OpencodeClient } from "@opencode-ai/sdk/v2" import type { ProviderID, ModelID } from "../provider/schema" @@ -21,4 +21,5 @@ export interface ACPConfig { providerID: ProviderID modelID: ModelID } + clientCapabilities?: ClientCapabilities } diff --git a/packages/opencode/src/file/index.ts b/packages/opencode/src/file/index.ts index 113dc59096b5..cfba136f1ddd 100644 --- a/packages/opencode/src/file/index.ts +++ b/packages/opencode/src/file/index.ts @@ -79,6 +79,7 @@ export namespace File { "file.edited", z.object({ file: z.string(), + sessionID: z.string(), }), ), } diff --git a/packages/opencode/src/tool/apply_patch.ts b/packages/opencode/src/tool/apply_patch.ts index b9877d8fec8b..99eb755e6c83 100644 --- a/packages/opencode/src/tool/apply_patch.ts +++ b/packages/opencode/src/tool/apply_patch.ts @@ -227,7 +227,7 @@ export const ApplyPatchTool = Tool.define( if (edited) { yield* format.file(edited) - yield* bus.publish(File.Event.Edited, { file: edited }) + yield* bus.publish(File.Event.Edited, { file: edited, sessionID: ctx.sessionID }) } } diff --git a/packages/opencode/src/tool/edit.ts b/packages/opencode/src/tool/edit.ts index bc8478e39f89..da65e888ac8f 100644 --- a/packages/opencode/src/tool/edit.ts +++ b/packages/opencode/src/tool/edit.ts @@ -88,7 +88,7 @@ export const EditTool = Tool.define( }) yield* afs.writeWithDirs(filePath, params.newString) yield* format.file(filePath) - yield* bus.publish(File.Event.Edited, { file: filePath }) + yield* bus.publish(File.Event.Edited, { file: filePath, sessionID: ctx.sessionID }) yield* bus.publish(FileWatcher.Event.Updated, { file: filePath, event: existed ? "change" : "add", @@ -129,7 +129,7 @@ export const EditTool = Tool.define( yield* afs.writeWithDirs(filePath, contentNew) yield* format.file(filePath) - yield* bus.publish(File.Event.Edited, { file: filePath }) + yield* bus.publish(File.Event.Edited, { file: filePath, sessionID: ctx.sessionID }) yield* bus.publish(FileWatcher.Event.Updated, { file: filePath, event: "change", diff --git a/packages/opencode/src/tool/write.ts b/packages/opencode/src/tool/write.ts index 337c2708c9e3..ddc0c48f11e2 100644 --- a/packages/opencode/src/tool/write.ts +++ b/packages/opencode/src/tool/write.ts @@ -56,7 +56,7 @@ export const WriteTool = Tool.define( yield* fs.writeWithDirs(filepath, params.content) yield* format.file(filepath) - yield* bus.publish(File.Event.Edited, { file: filepath }) + yield* bus.publish(File.Event.Edited, { file: filepath, sessionID: ctx.sessionID }) yield* bus.publish(FileWatcher.Event.Updated, { file: filepath, event: exists ? "change" : "add", diff --git a/packages/sdk/js/src/gen/types.gen.ts b/packages/sdk/js/src/gen/types.gen.ts index 8eefe5bfe985..9b29b89ba564 100644 --- a/packages/sdk/js/src/gen/types.gen.ts +++ b/packages/sdk/js/src/gen/types.gen.ts @@ -490,6 +490,7 @@ export type EventFileEdited = { type: "file.edited" properties: { file: string + sessionID?: string } } diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 24c1d53bf749..97847c7319e1 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -72,6 +72,7 @@ export type EventFileEdited = { type: "file.edited" properties: { file: string + sessionID: string } }