From d24536c71020094754fd5ebeb1484a5cdc6c8527 Mon Sep 17 00:00:00 2001 From: Ben Brandt Date: Mon, 18 May 2026 12:50:52 +0200 Subject: [PATCH] feat: Support experimental additionalDirectories field --- src/acp-agent.ts | 16 +++++++++++++--- src/tests/additional-roots.test.ts | 29 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/acp-agent.ts b/src/acp-agent.ts index 5c3f19b1..4902f1a7 100644 --- a/src/acp-agent.ts +++ b/src/acp-agent.ts @@ -628,11 +628,12 @@ export class ClaudeAcpAgent implements Agent { }, loadSession: true, sessionCapabilities: { + additionalDirectories: {}, + close: {}, + delete: {}, fork: {}, list: {}, resume: {}, - close: {}, - delete: {}, }, }, agentInfo: { @@ -664,6 +665,7 @@ export class ClaudeAcpAgent implements Agent { { cwd: params.cwd, mcpServers: params.mcpServers ?? [], + additionalDirectories: params.additionalDirectories, _meta: params._meta, }, { @@ -1775,6 +1777,7 @@ export class ClaudeAcpAgent implements Agent { sessionId: string; cwd: string; mcpServers?: NewSessionRequest["mcpServers"]; + additionalDirectories?: NewSessionRequest["additionalDirectories"]; _meta?: NewSessionRequest["_meta"]; }): Promise { const existingSession = this.sessions[params.sessionId]; @@ -1799,6 +1802,7 @@ export class ClaudeAcpAgent implements Agent { { cwd: params.cwd, mcpServers: params.mcpServers ?? [], + additionalDirectories: params.additionalDirectories, _meta: params._meta, }, { @@ -2020,9 +2024,15 @@ export class ClaudeAcpAgent implements Agent { abortController, }; + // Prefer the official ACP `additionalDirectories` field. Fall back to the + // legacy `_meta.additionalRoots` extension for clients that haven't been + // updated yet. Either source is merged with directories supplied via + // `_meta.claudeCode.options.additionalDirectories` (SDK pass-through). + const acpAdditionalDirectories = + params.additionalDirectories ?? sessionMeta?.additionalRoots ?? []; options.additionalDirectories = [ ...(userProvidedOptions?.additionalDirectories ?? []), - ...(sessionMeta?.additionalRoots ?? []), + ...acpAdditionalDirectories, ]; if (creationOpts?.resume === undefined || creationOpts?.forkSession) { diff --git a/src/tests/additional-roots.test.ts b/src/tests/additional-roots.test.ts index 9fe7066d..f410f690 100644 --- a/src/tests/additional-roots.test.ts +++ b/src/tests/additional-roots.test.ts @@ -76,4 +76,33 @@ describe("additionalRoots", () => { }); expect(capturedOptions!.additionalDirectories).toEqual(["/workspace/shared", "", root]); }); + + it("prefers the official ACP additionalDirectories field over _meta.additionalRoots", async () => { + await agent.newSession({ + cwd: "/test", + mcpServers: [], + additionalDirectories: ["/from/official"], + _meta: { additionalRoots: ["/from/meta"] }, + }); + expect(capturedOptions!.additionalDirectories).toEqual(["/from/official"]); + }); + + it("merges official ACP additionalDirectories with claudeCode SDK additionalDirectories", async () => { + await agent.newSession({ + cwd: "/test", + mcpServers: [], + additionalDirectories: ["/from/official"], + _meta: { claudeCode: { options: { additionalDirectories: ["/from/sdk"] } } }, + }); + expect(capturedOptions!.additionalDirectories).toEqual(["/from/sdk", "/from/official"]); + }); + + it("falls back to _meta.additionalRoots when the official field is omitted", async () => { + await agent.newSession({ + cwd: "/test", + mcpServers: [], + _meta: { additionalRoots: ["/from/meta"] }, + }); + expect(capturedOptions!.additionalDirectories).toEqual(["/from/meta"]); + }); });