@zed-industries/claude-code-acp
Advanced tools
@@ -47,2 +47,3 @@ import { Agent, AgentSideConnection, AuthenticateRequest, CancelNotification, ClientCapabilities, ForkSessionRequest, ForkSessionResponse, InitializeRequest, InitializeResponse, LoadSessionRequest, LoadSessionResponse, ListSessionsRequest, ListSessionsResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, ReadTextFileRequest, ReadTextFileResponse, ResumeSessionRequest, ResumeSessionResponse, SessionNotification, SetSessionModelRequest, SetSessionModelResponse, SetSessionModeRequest, SetSessionModeResponse, TerminalHandle, TerminalOutputResponse, WriteTextFileRequest, WriteTextFileResponse } from "@agentclientprotocol/sdk"; | ||
| * - mcpServers (merged with ACP's mcpServers) | ||
| * - disallowedTools (merged with ACP's disallowedTools) | ||
| */ | ||
@@ -85,2 +86,8 @@ options?: Options; | ||
| unstable_resumeSession(params: ResumeSessionRequest): Promise<ResumeSessionResponse>; | ||
| /** | ||
| * Find a session file by ID, first checking the given cwd's project directory, | ||
| * then falling back to scanning all project directories. | ||
| * Returns the absolute file path if found, or null if not found. | ||
| */ | ||
| private findSessionFile; | ||
| loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse>; | ||
@@ -102,2 +109,3 @@ /** | ||
| canUseTool(sessionId: string): CanUseTool; | ||
| private sendAvailableCommandsUpdate; | ||
| private createSession; | ||
@@ -104,0 +112,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"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"} |
+111
-52
@@ -16,20 +16,2 @@ import { AgentSideConnection, ndJsonStream, RequestError, } from "@agentclientprotocol/sdk"; | ||
| export const CLAUDE_CONFIG_DIR = process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude"); | ||
| /** | ||
| * Decode a Claude project path encoding back to the original filesystem path. | ||
| * Claude encodes paths by replacing path separators with dashes: | ||
| * - Unix: "/Users/morse/project" -> "-Users-morse-project" | ||
| * - Windows: "C:\Users\morse\project" -> "C-Users-morse-project" | ||
| */ | ||
| function decodeProjectPath(encodedPath) { | ||
| // Check if this looks like a Windows path (starts with drive letter pattern like "C-") | ||
| const windowsDriveMatch = encodedPath.match(/^([A-Za-z])-/); | ||
| if (windowsDriveMatch) { | ||
| // Windows path: "C-Users-morse-project" -> "C:\Users\morse\project" | ||
| const driveLetter = windowsDriveMatch[1]; | ||
| const rest = encodedPath.slice(2); // Skip "C-" | ||
| return `${driveLetter}:\\${rest.replace(/-/g, "\\")}`; | ||
| } | ||
| // Unix path: "-Users-morse-project" -> "/Users/morse/project" | ||
| return encodedPath.replace(/-/g, "/"); | ||
| } | ||
| function sessionFilePath(cwd, sessionId) { | ||
@@ -112,9 +94,14 @@ return path.join(CLAUDE_CONFIG_DIR, "projects", encodeProjectPath(cwd), `${sessionId}.jsonl`); | ||
| } | ||
| return await this.createSession(params, { | ||
| const response = await this.createSession(params, { | ||
| // Revisit these meta values once we support resume | ||
| resume: params._meta?.claudeCode?.options?.resume, | ||
| }); | ||
| // Needs to happen after we return the session | ||
| setTimeout(() => { | ||
| this.sendAvailableCommandsUpdate(response.sessionId); | ||
| }, 0); | ||
| return response; | ||
| } | ||
| async unstable_forkSession(params) { | ||
| return await this.createSession({ | ||
| const response = await this.createSession({ | ||
| cwd: params.cwd, | ||
@@ -127,2 +114,7 @@ mcpServers: params.mcpServers ?? [], | ||
| }); | ||
| // Needs to happen after we return the session | ||
| setTimeout(() => { | ||
| this.sendAvailableCommandsUpdate(response.sessionId); | ||
| }, 0); | ||
| return response; | ||
| } | ||
@@ -137,9 +129,50 @@ async unstable_resumeSession(params) { | ||
| }); | ||
| // Needs to happen after we return the session | ||
| setTimeout(() => { | ||
| this.sendAvailableCommandsUpdate(response.sessionId); | ||
| }, 0); | ||
| return response; | ||
| } | ||
| async loadSession(params) { | ||
| /** | ||
| * Find a session file by ID, first checking the given cwd's project directory, | ||
| * then falling back to scanning all project directories. | ||
| * Returns the absolute file path if found, or null if not found. | ||
| */ | ||
| async findSessionFile(sessionId, cwd) { | ||
| const fileName = `${sessionId}.jsonl`; | ||
| // Fast path: check the expected location based on cwd | ||
| const expectedPath = sessionFilePath(cwd, sessionId); | ||
| try { | ||
| await fs.promises.access(sessionFilePath(params.cwd, params.sessionId)); | ||
| await fs.promises.access(expectedPath); | ||
| return expectedPath; | ||
| } | ||
| catch { | ||
| // Not found at expected path, scan all project directories | ||
| } | ||
| const claudeDir = path.join(CLAUDE_CONFIG_DIR, "projects"); | ||
| try { | ||
| const projectDirs = await fs.promises.readdir(claudeDir); | ||
| for (const encodedPath of projectDirs) { | ||
| const projectDir = path.join(claudeDir, encodedPath); | ||
| const stat = await fs.promises.stat(projectDir); | ||
| if (!stat.isDirectory()) | ||
| continue; | ||
| const candidatePath = path.join(projectDir, fileName); | ||
| try { | ||
| await fs.promises.access(candidatePath); | ||
| return candidatePath; | ||
| } | ||
| catch { | ||
| continue; | ||
| } | ||
| } | ||
| } | ||
| catch { | ||
| // projects directory doesn't exist or isn't readable | ||
| } | ||
| return null; | ||
| } | ||
| async loadSession(params) { | ||
| const filePath = await this.findSessionFile(params.sessionId, params.cwd); | ||
| if (!filePath) { | ||
| throw new Error("Session not found"); | ||
@@ -154,3 +187,7 @@ } | ||
| }); | ||
| await this.replaySessionHistory(params.sessionId, params.cwd); | ||
| await this.replaySessionHistory(params.sessionId, filePath); | ||
| // Send available commands after replay so it doesn't interleave with history | ||
| setTimeout(() => { | ||
| this.sendAvailableCommandsUpdate(params.sessionId); | ||
| }, 0); | ||
| return { | ||
@@ -179,2 +216,3 @@ modes: response.modes, | ||
| const allSessions = []; | ||
| const encodedCwdFilter = params.cwd ? encodeProjectPath(params.cwd) : null; | ||
| try { | ||
@@ -187,8 +225,5 @@ const projectDirs = await fs.promises.readdir(claudeDir); | ||
| continue; | ||
| // Decode the path based on platform: | ||
| // - Unix: "-Users-morse-project" -> "/Users/morse/project" | ||
| // - Windows: "C-Users-morse-project" -> "C:\Users\morse\project" | ||
| const decodedCwd = decodeProjectPath(encodedPath); | ||
| // Skip if filtering by cwd and this doesn't match | ||
| if (params.cwd && decodedCwd !== params.cwd) | ||
| // Path encoding is not always reversible (hyphens can be separators or literals), | ||
| // so only use encoded value as a coarse pre-filter. | ||
| if (encodedCwdFilter && encodedPath !== encodedCwdFilter) | ||
| continue; | ||
@@ -204,8 +239,5 @@ const files = await fs.promises.readdir(projectDir); | ||
| const lines = content.trim().split("\n").filter(Boolean); | ||
| const firstLine = lines[0]; | ||
| if (!firstLine) | ||
| continue; | ||
| // Parse first line to get session info | ||
| const firstEntry = JSON.parse(firstLine); | ||
| const sessionId = firstEntry.sessionId || file.replace(".jsonl", ""); | ||
| const sessionId = file.replace(".jsonl", ""); | ||
| let parsedAnyEntry = false; | ||
| let sessionCwd; | ||
| // Find first user message for title | ||
@@ -216,7 +248,17 @@ let title; | ||
| const entry = JSON.parse(line); | ||
| if (entry.type === "user" && entry.message?.content) { | ||
| parsedAnyEntry = true; | ||
| if (entry.isSidechain === true) { | ||
| continue; | ||
| } | ||
| const entrySessionId = typeof entry.sessionId === "string" ? entry.sessionId : undefined; | ||
| if (typeof entry.sessionId === "string" && entry.sessionId !== entrySessionId) { | ||
| continue; | ||
| } | ||
| if (typeof entry.cwd === "string") { | ||
| sessionCwd = entry.cwd; | ||
| } | ||
| if (!title && entry.type === "user" && entry.message?.content) { | ||
| const msgContent = entry.message.content; | ||
| if (typeof msgContent === "string") { | ||
| title = sanitizeTitle(msgContent); | ||
| break; | ||
| } | ||
@@ -232,6 +274,10 @@ if (Array.isArray(msgContent) && msgContent.length > 0) { | ||
| title = sanitizeTitle(text); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| // Continue scanning until we have both fields, since cwd can appear | ||
| // in later entries even after the first user title-bearing message. | ||
| if (title && sessionCwd) { | ||
| break; | ||
| } | ||
| } | ||
@@ -242,2 +288,13 @@ catch { | ||
| } | ||
| if (!parsedAnyEntry) | ||
| continue; | ||
| // SessionInfo.cwd is currently required. For entries that do not | ||
| // include an explicit cwd in the session JSONL (typically metadata-only files), | ||
| // we skip them instead of decoding folder names because path encoding is lossy. | ||
| if (!sessionCwd) | ||
| continue; | ||
| // Even after encoded-path pre-filtering, verify per-entry cwd to disambiguate | ||
| // collisions such as "/a-b" and "/a/b" that map to the same encoded folder name. | ||
| if (params.cwd && sessionCwd !== params.cwd) | ||
| continue; | ||
| // Get file modification time as updatedAt | ||
@@ -248,3 +305,3 @@ const fileStat = await fs.promises.stat(filePath); | ||
| sessionId, | ||
| cwd: decodedCwd, | ||
| cwd: sessionCwd, | ||
| title: title ?? null, | ||
@@ -466,4 +523,3 @@ updatedAt, | ||
| } | ||
| async replaySessionHistory(sessionId, cwd) { | ||
| const filePath = sessionFilePath(cwd, sessionId); | ||
| async replaySessionHistory(sessionId, filePath) { | ||
| const toolUseCache = {}; | ||
@@ -641,2 +697,15 @@ const stream = fs.createReadStream(filePath, { encoding: "utf-8" }); | ||
| } | ||
| async sendAvailableCommandsUpdate(sessionId) { | ||
| const session = this.sessions[sessionId]; | ||
| if (!session) | ||
| return; | ||
| const commands = await session.query.supportedCommands(); | ||
| await this.client.sessionUpdate({ | ||
| sessionId, | ||
| update: { | ||
| sessionUpdate: "available_commands_update", | ||
| availableCommands: getAvailableSlashCommands(commands), | ||
| }, | ||
| }); | ||
| } | ||
| async createSession(params, creationOpts = {}) { | ||
@@ -797,3 +866,3 @@ // We want to create a new session id unless it is resume, | ||
| if (disallowedTools.length > 0) { | ||
| options.disallowedTools = disallowedTools; | ||
| options.disallowedTools = [...(options.disallowedTools || []), ...disallowedTools]; | ||
| } | ||
@@ -818,12 +887,2 @@ // Handle abort controller from meta options | ||
| const models = await getAvailableModels(q, initializationResult.models, settingsManager); | ||
| // Needs to happen after we return the session | ||
| setTimeout(() => { | ||
| this.client.sessionUpdate({ | ||
| sessionId, | ||
| update: { | ||
| sessionUpdate: "available_commands_update", | ||
| availableCommands: getAvailableSlashCommands(initializationResult.commands), | ||
| }, | ||
| }); | ||
| }, 0); | ||
| const availableModes = [ | ||
@@ -830,0 +889,0 @@ { |
+6
-6
@@ -6,3 +6,3 @@ { | ||
| }, | ||
| "version": "0.16.0", | ||
| "version": "0.16.1", | ||
| "description": "An ACP-compatible coding agent powered by the Claude Code SDK (TypeScript)", | ||
@@ -65,3 +65,3 @@ "main": "dist/lib.js", | ||
| "@agentclientprotocol/sdk": "0.14.1", | ||
| "@anthropic-ai/claude-agent-sdk": "0.2.34", | ||
| "@anthropic-ai/claude-agent-sdk": "0.2.38", | ||
| "@modelcontextprotocol/sdk": "1.26.0", | ||
@@ -72,6 +72,6 @@ "diff": "8.0.3", | ||
| "devDependencies": { | ||
| "@anthropic-ai/sdk": "0.73.0", | ||
| "@types/node": "25.2.1", | ||
| "@typescript-eslint/eslint-plugin": "8.54.0", | ||
| "@typescript-eslint/parser": "8.54.0", | ||
| "@anthropic-ai/sdk": "0.74.0", | ||
| "@types/node": "25.2.3", | ||
| "@typescript-eslint/eslint-plugin": "8.55.0", | ||
| "@typescript-eslint/parser": "8.55.0", | ||
| "eslint": "9.39.2", | ||
@@ -78,0 +78,0 @@ "eslint-config-prettier": "10.1.8", |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
173703
1.92%3659
1.87%20
33.33%+ Added
- Removed