@agentclientprotocol/claude-agent-acp 0.34.1 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/acp-agent.d.ts +8 -1
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +126 -9
- package/dist/index.js +8 -5
- package/dist/lib.d.ts +2 -2
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +2 -2
- package/dist/settings.d.ts +14 -56
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +40 -114
- package/dist/tools.d.ts +38 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +143 -0
- package/dist/utils.d.ts +0 -3
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +0 -17
- package/package.json +9 -9
package/dist/acp-agent.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Agent, AgentSideConnection, AuthenticateRequest, CancelNotification, ClientCapabilities, ForkSessionRequest, ForkSessionResponse, InitializeRequest, InitializeResponse, ListSessionsRequest, ListSessionsResponse, LoadSessionRequest, LoadSessionResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, ReadTextFileRequest, ReadTextFileResponse, ResumeSessionRequest, ResumeSessionResponse, SessionConfigOption, SessionModelState, SessionModeState, SessionNotification, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, SetSessionModelRequest, SetSessionModelResponse, SetSessionModeRequest, SetSessionModeResponse, CloseSessionRequest, CloseSessionResponse, TerminalHandle, TerminalOutputResponse, WriteTextFileRequest, WriteTextFileResponse } from "@agentclientprotocol/sdk";
|
|
1
|
+
import { Agent, AgentSideConnection, AuthenticateRequest, CancelNotification, ClientCapabilities, ForkSessionRequest, ForkSessionResponse, InitializeRequest, InitializeResponse, ListSessionsRequest, ListSessionsResponse, LoadSessionRequest, LoadSessionResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, ReadTextFileRequest, ReadTextFileResponse, ResumeSessionRequest, ResumeSessionResponse, SessionConfigOption, SessionModelState, SessionModeState, SessionNotification, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse, SetSessionModelRequest, SetSessionModelResponse, SetSessionModeRequest, SetSessionModeResponse, CloseSessionRequest, CloseSessionResponse, DeleteSessionRequest, DeleteSessionResponse, TerminalHandle, TerminalOutputResponse, WriteTextFileRequest, WriteTextFileResponse } from "@agentclientprotocol/sdk";
|
|
2
2
|
import { CanUseTool, ModelInfo, Options, PermissionMode, PermissionUpdate, Query, SDKMessageOrigin, SDKPartialAssistantMessage, SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
|
|
3
3
|
import { ContentBlockParam } from "@anthropic-ai/sdk/resources";
|
|
4
4
|
import { BetaContentBlock, BetaRawContentBlockDelta } from "@anthropic-ai/sdk/resources/beta.mjs";
|
|
5
5
|
import { SettingsManager } from "./settings.js";
|
|
6
|
+
import { TaskState } from "./tools.js";
|
|
6
7
|
import { Pushable } from "./utils.js";
|
|
7
8
|
export declare const CLAUDE_CONFIG_DIR: string;
|
|
8
9
|
/**
|
|
@@ -46,6 +47,9 @@ type Session = {
|
|
|
46
47
|
* DEFAULT_CONTEXT_WINDOW, refreshed from each result's modelUsage, and
|
|
47
48
|
* invalidated when the user switches the session's model. */
|
|
48
49
|
contextWindowSize: number;
|
|
50
|
+
/** Accumulated task list for the session, keyed by task ID. Task IDs are
|
|
51
|
+
* per-session, so this state must not be shared across sessions. */
|
|
52
|
+
taskState: TaskState;
|
|
49
53
|
};
|
|
50
54
|
type BackgroundTerminal = {
|
|
51
55
|
handle: TerminalHandle;
|
|
@@ -184,6 +188,7 @@ export declare class ClaudeAcpAgent implements Agent {
|
|
|
184
188
|
/** Tear down all active sessions. Called when the ACP connection closes. */
|
|
185
189
|
dispose(): Promise<void>;
|
|
186
190
|
closeSession(params: CloseSessionRequest): Promise<CloseSessionResponse>;
|
|
191
|
+
unstable_deleteSession(params: DeleteSessionRequest): Promise<DeleteSessionResponse>;
|
|
187
192
|
unstable_setSessionModel(params: SetSessionModelRequest): Promise<SetSessionModelResponse | void>;
|
|
188
193
|
setSessionMode(params: SetSessionModeRequest): Promise<SetSessionModeResponse>;
|
|
189
194
|
setSessionConfigOption(params: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse>;
|
|
@@ -208,10 +213,12 @@ export declare function toAcpNotifications(content: string | ContentBlockParam[]
|
|
|
208
213
|
clientCapabilities?: ClientCapabilities;
|
|
209
214
|
parentToolUseId?: string | null;
|
|
210
215
|
cwd?: string;
|
|
216
|
+
taskState?: TaskState;
|
|
211
217
|
}): SessionNotification[];
|
|
212
218
|
export declare function streamEventToAcpNotifications(message: SDKPartialAssistantMessage, sessionId: string, toolUseCache: ToolUseCache, client: AgentSideConnection, logger: Logger, options?: {
|
|
213
219
|
clientCapabilities?: ClientCapabilities;
|
|
214
220
|
cwd?: string;
|
|
221
|
+
taskState?: TaskState;
|
|
215
222
|
}): SessionNotification[];
|
|
216
223
|
export declare function runAcp(): {
|
|
217
224
|
connection: AgentSideConnection;
|
package/dist/acp-agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,mBAAmB,EACnB,mBAAmB,EAGnB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EAEnB,iBAAiB,EACjB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../src/acp-agent.ts"],"names":[],"mappings":"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"}
|
package/dist/acp-agent.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { AgentSideConnection, ndJsonStream, RequestError, } from "@agentclientprotocol/sdk";
|
|
2
|
-
import { getSessionMessages, listSessions, query, } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import { deleteSession, getSessionMessages, listSessions, query, } from "@anthropic-ai/claude-agent-sdk";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import * as os from "node:os";
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import packageJson from "../package.json" with { type: "json" };
|
|
7
7
|
import { SettingsManager } from "./settings.js";
|
|
8
|
-
import { createPostToolUseHook, planEntries, registerHookCallback, toolInfoFromToolUse, toolUpdateFromDiffToolResponse, toolUpdateFromToolResult, } from "./tools.js";
|
|
8
|
+
import { applyTaskCreate, applyTaskUpdate, createPostToolUseHook, createTaskHook, parseTaskCreateOutput, planEntries, registerHookCallback, taskStateToPlanEntries, toolInfoFromToolUse, toolUpdateFromDiffToolResponse, toolUpdateFromToolResult, } from "./tools.js";
|
|
9
9
|
import { nodeToWebReadable, nodeToWebWritable, Pushable, unreachable } from "./utils.js";
|
|
10
10
|
export const CLAUDE_CONFIG_DIR = process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
|
|
11
11
|
const MAX_TITLE_LENGTH = 256;
|
|
@@ -324,10 +324,12 @@ export class ClaudeAcpAgent {
|
|
|
324
324
|
},
|
|
325
325
|
loadSession: true,
|
|
326
326
|
sessionCapabilities: {
|
|
327
|
+
additionalDirectories: {},
|
|
328
|
+
close: {},
|
|
329
|
+
delete: {},
|
|
327
330
|
fork: {},
|
|
328
331
|
list: {},
|
|
329
332
|
resume: {},
|
|
330
|
-
close: {},
|
|
331
333
|
},
|
|
332
334
|
},
|
|
333
335
|
agentInfo: {
|
|
@@ -356,6 +358,7 @@ export class ClaudeAcpAgent {
|
|
|
356
358
|
const response = await this.createSession({
|
|
357
359
|
cwd: params.cwd,
|
|
358
360
|
mcpServers: params.mcpServers ?? [],
|
|
361
|
+
additionalDirectories: params.additionalDirectories,
|
|
359
362
|
_meta: params._meta,
|
|
360
363
|
}, {
|
|
361
364
|
resume: params.sessionId,
|
|
@@ -548,6 +551,7 @@ export class ClaudeAcpAgent {
|
|
|
548
551
|
case "notification":
|
|
549
552
|
case "api_retry":
|
|
550
553
|
case "mirror_error":
|
|
554
|
+
case "permission_denied":
|
|
551
555
|
// Todo: process via status api: https://docs.claude.com/en/docs/claude-code/hooks#hook-output
|
|
552
556
|
break;
|
|
553
557
|
default:
|
|
@@ -707,6 +711,7 @@ export class ClaudeAcpAgent {
|
|
|
707
711
|
for (const notification of streamEventToAcpNotifications(message, params.sessionId, this.toolUseCache, this.client, this.logger, {
|
|
708
712
|
clientCapabilities: this.clientCapabilities,
|
|
709
713
|
cwd: session.cwd,
|
|
714
|
+
taskState: session.taskState,
|
|
710
715
|
})) {
|
|
711
716
|
await this.client.sessionUpdate(notification);
|
|
712
717
|
}
|
|
@@ -750,11 +755,27 @@ export class ClaudeAcpAgent {
|
|
|
750
755
|
lastAssistantError = message.error;
|
|
751
756
|
}
|
|
752
757
|
}
|
|
753
|
-
//
|
|
754
|
-
//
|
|
758
|
+
// Strip <command-*>/<local-command-stdout> markers and render any
|
|
759
|
+
// remaining prose. Skill bodies and built-in slash commands (e.g.
|
|
760
|
+
// /usage, /status, /model) arrive wrapped in these tags; pure-marker
|
|
761
|
+
// payloads (e.g. /compact's malformed output) strip to null and are
|
|
762
|
+
// skipped. Mirrors the replay path at replaySessionHistory.
|
|
755
763
|
if (typeof message.message.content === "string" &&
|
|
756
764
|
message.message.content.includes("<local-command-stdout>")) {
|
|
757
|
-
|
|
765
|
+
const stripped = stripLocalCommandMetadata(message.message.content);
|
|
766
|
+
if (typeof stripped === "string") {
|
|
767
|
+
for (const notification of toAcpNotifications(stripped, message.message.role, params.sessionId, this.toolUseCache, this.client, this.logger, {
|
|
768
|
+
clientCapabilities: this.clientCapabilities,
|
|
769
|
+
parentToolUseId: message.parent_tool_use_id,
|
|
770
|
+
cwd: session.cwd,
|
|
771
|
+
taskState: session.taskState,
|
|
772
|
+
})) {
|
|
773
|
+
await this.client.sessionUpdate(notification);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
this.logger.log(message.message.content);
|
|
778
|
+
}
|
|
758
779
|
break;
|
|
759
780
|
}
|
|
760
781
|
if (typeof message.message.content === "string" &&
|
|
@@ -786,6 +807,7 @@ export class ClaudeAcpAgent {
|
|
|
786
807
|
clientCapabilities: this.clientCapabilities,
|
|
787
808
|
parentToolUseId: message.parent_tool_use_id,
|
|
788
809
|
cwd: session.cwd,
|
|
810
|
+
taskState: session.taskState,
|
|
789
811
|
})) {
|
|
790
812
|
await this.client.sessionUpdate(notification);
|
|
791
813
|
}
|
|
@@ -874,6 +896,15 @@ export class ClaudeAcpAgent {
|
|
|
874
896
|
await this.teardownSession(params.sessionId);
|
|
875
897
|
return {};
|
|
876
898
|
}
|
|
899
|
+
async unstable_deleteSession(params) {
|
|
900
|
+
// Tear down any active in-memory state first so the on-disk file isn't
|
|
901
|
+
// recreated by an outstanding query writing to it.
|
|
902
|
+
if (this.sessions[params.sessionId]) {
|
|
903
|
+
await this.teardownSession(params.sessionId);
|
|
904
|
+
}
|
|
905
|
+
await deleteSession(params.sessionId);
|
|
906
|
+
return {};
|
|
907
|
+
}
|
|
877
908
|
async unstable_setSessionModel(params) {
|
|
878
909
|
const session = this.sessions[params.sessionId];
|
|
879
910
|
if (!session) {
|
|
@@ -1005,6 +1036,7 @@ export class ClaudeAcpAgent {
|
|
|
1005
1036
|
registerHooks: false,
|
|
1006
1037
|
clientCapabilities: this.clientCapabilities,
|
|
1007
1038
|
cwd: this.sessions[sessionId]?.cwd,
|
|
1039
|
+
taskState: this.sessions[sessionId]?.taskState,
|
|
1008
1040
|
})) {
|
|
1009
1041
|
await this.client.sessionUpdate(notification);
|
|
1010
1042
|
}
|
|
@@ -1280,6 +1312,7 @@ export class ClaudeAcpAgent {
|
|
|
1280
1312
|
const response = await this.createSession({
|
|
1281
1313
|
cwd: params.cwd,
|
|
1282
1314
|
mcpServers: params.mcpServers ?? [],
|
|
1315
|
+
additionalDirectories: params.additionalDirectories,
|
|
1283
1316
|
_meta: params._meta,
|
|
1284
1317
|
}, {
|
|
1285
1318
|
resume: params.sessionId,
|
|
@@ -1322,7 +1355,7 @@ export class ClaudeAcpAgent {
|
|
|
1322
1355
|
: undefined,
|
|
1323
1356
|
};
|
|
1324
1357
|
}
|
|
1325
|
-
else {
|
|
1358
|
+
else if (!("type" in server)) {
|
|
1326
1359
|
// Stdio type MCP server (with or without explicit type field)
|
|
1327
1360
|
mcpServers[server.name] = {
|
|
1328
1361
|
type: "stdio",
|
|
@@ -1372,6 +1405,10 @@ export class ClaudeAcpAgent {
|
|
|
1372
1405
|
const tools = userProvidedOptions?.tools ??
|
|
1373
1406
|
(params._meta?.disableBuiltInTools === true ? [] : { type: "preset", preset: "claude_code" });
|
|
1374
1407
|
const abortController = userProvidedOptions?.abortController || new AbortController();
|
|
1408
|
+
// Per-session task state. Created here (rather than in the session record
|
|
1409
|
+
// below) so the TaskCreated/TaskCompleted hook callbacks can close over
|
|
1410
|
+
// the same Map that the streaming message handler will read from.
|
|
1411
|
+
const taskState = new Map();
|
|
1375
1412
|
const options = {
|
|
1376
1413
|
systemPrompt,
|
|
1377
1414
|
settingSources: ["user", "project", "local"],
|
|
@@ -1432,13 +1469,56 @@ export class ClaudeAcpAgent {
|
|
|
1432
1469
|
],
|
|
1433
1470
|
},
|
|
1434
1471
|
],
|
|
1472
|
+
TaskCreated: [
|
|
1473
|
+
...(userProvidedOptions?.hooks?.TaskCreated || []),
|
|
1474
|
+
{
|
|
1475
|
+
hooks: [
|
|
1476
|
+
createTaskHook({
|
|
1477
|
+
taskState,
|
|
1478
|
+
onChange: async () => {
|
|
1479
|
+
await this.client.sessionUpdate({
|
|
1480
|
+
sessionId,
|
|
1481
|
+
update: {
|
|
1482
|
+
sessionUpdate: "plan",
|
|
1483
|
+
entries: taskStateToPlanEntries(taskState),
|
|
1484
|
+
},
|
|
1485
|
+
});
|
|
1486
|
+
},
|
|
1487
|
+
}),
|
|
1488
|
+
],
|
|
1489
|
+
},
|
|
1490
|
+
],
|
|
1491
|
+
TaskCompleted: [
|
|
1492
|
+
...(userProvidedOptions?.hooks?.TaskCompleted || []),
|
|
1493
|
+
{
|
|
1494
|
+
hooks: [
|
|
1495
|
+
createTaskHook({
|
|
1496
|
+
taskState,
|
|
1497
|
+
onChange: async () => {
|
|
1498
|
+
await this.client.sessionUpdate({
|
|
1499
|
+
sessionId,
|
|
1500
|
+
update: {
|
|
1501
|
+
sessionUpdate: "plan",
|
|
1502
|
+
entries: taskStateToPlanEntries(taskState),
|
|
1503
|
+
},
|
|
1504
|
+
});
|
|
1505
|
+
},
|
|
1506
|
+
}),
|
|
1507
|
+
],
|
|
1508
|
+
},
|
|
1509
|
+
],
|
|
1435
1510
|
},
|
|
1436
1511
|
...creationOpts,
|
|
1437
1512
|
abortController,
|
|
1438
1513
|
};
|
|
1514
|
+
// Prefer the official ACP `additionalDirectories` field. Fall back to the
|
|
1515
|
+
// legacy `_meta.additionalRoots` extension for clients that haven't been
|
|
1516
|
+
// updated yet. Either source is merged with directories supplied via
|
|
1517
|
+
// `_meta.claudeCode.options.additionalDirectories` (SDK pass-through).
|
|
1518
|
+
const acpAdditionalDirectories = params.additionalDirectories ?? sessionMeta?.additionalRoots ?? [];
|
|
1439
1519
|
options.additionalDirectories = [
|
|
1440
1520
|
...(userProvidedOptions?.additionalDirectories ?? []),
|
|
1441
|
-
...
|
|
1521
|
+
...acpAdditionalDirectories,
|
|
1442
1522
|
];
|
|
1443
1523
|
if (creationOpts?.resume === undefined || creationOpts?.forkSession) {
|
|
1444
1524
|
// Set our own session id if not resuming an existing session.
|
|
@@ -1546,6 +1626,7 @@ export class ClaudeAcpAgent {
|
|
|
1546
1626
|
abortController,
|
|
1547
1627
|
emitRawSDKMessages: sessionMeta?.claudeCode?.emitRawSDKMessages ?? false,
|
|
1548
1628
|
contextWindowSize: inferContextWindowFromModel(models.currentModelId) ?? DEFAULT_CONTEXT_WINDOW,
|
|
1629
|
+
taskState,
|
|
1549
1630
|
};
|
|
1550
1631
|
return {
|
|
1551
1632
|
sessionId,
|
|
@@ -2019,6 +2100,7 @@ export function promptToClaude(prompt) {
|
|
|
2019
2100
|
* Only handles text, image, and thinking chunks for now.
|
|
2020
2101
|
*/
|
|
2021
2102
|
export function toAcpNotifications(content, role, sessionId, toolUseCache, client, logger, options) {
|
|
2103
|
+
const taskState = options?.taskState ?? new Map();
|
|
2022
2104
|
const registerHooks = options?.registerHooks !== false;
|
|
2023
2105
|
const supportsTerminalOutput = options?.clientCapabilities?._meta?.["terminal_output"] === true;
|
|
2024
2106
|
if (typeof content === "string") {
|
|
@@ -2090,6 +2172,14 @@ export function toAcpNotifications(content, role, sessionId, toolUseCache, clien
|
|
|
2090
2172
|
};
|
|
2091
2173
|
}
|
|
2092
2174
|
}
|
|
2175
|
+
else if (chunk.name === "TaskCreate" ||
|
|
2176
|
+
chunk.name === "TaskUpdate" ||
|
|
2177
|
+
chunk.name === "TaskList" ||
|
|
2178
|
+
chunk.name === "TaskGet") {
|
|
2179
|
+
// Task* tool_use is suppressed; the plan update is emitted at
|
|
2180
|
+
// tool_result time once we have the task ID (for TaskCreate) and
|
|
2181
|
+
// confirmation that the change took effect.
|
|
2182
|
+
}
|
|
2093
2183
|
else {
|
|
2094
2184
|
// Only register hooks on first encounter to avoid double-firing
|
|
2095
2185
|
if (registerHooks && !alreadyCached) {
|
|
@@ -2188,7 +2278,32 @@ export function toAcpNotifications(content, role, sessionId, toolUseCache, clien
|
|
|
2188
2278
|
logger.error(`[claude-agent-acp] Got a tool result for tool use that wasn't tracked: ${chunk.tool_use_id}`);
|
|
2189
2279
|
break;
|
|
2190
2280
|
}
|
|
2191
|
-
if (toolUse.name
|
|
2281
|
+
if (toolUse.name === "TaskCreate" ||
|
|
2282
|
+
toolUse.name === "TaskUpdate" ||
|
|
2283
|
+
toolUse.name === "TaskList" ||
|
|
2284
|
+
toolUse.name === "TaskGet") {
|
|
2285
|
+
// Headless/SDK sessions emit Task* tools instead of TodoWrite.
|
|
2286
|
+
// TaskCreate / TaskUpdate mutate the accumulated task list; TaskList
|
|
2287
|
+
// and TaskGet are read-only so we just suppress their tool_call /
|
|
2288
|
+
// tool_result events. The plan update is emitted as a snapshot of
|
|
2289
|
+
// the accumulated state, mirroring the legacy TodoWrite behavior.
|
|
2290
|
+
const isError = "is_error" in chunk && chunk.is_error;
|
|
2291
|
+
if (!isError) {
|
|
2292
|
+
if (toolUse.name === "TaskCreate") {
|
|
2293
|
+
applyTaskCreate(taskState, toolUse.input, parseTaskCreateOutput(chunk.content));
|
|
2294
|
+
}
|
|
2295
|
+
else if (toolUse.name === "TaskUpdate") {
|
|
2296
|
+
applyTaskUpdate(taskState, toolUse.input);
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
if (!isError && (toolUse.name === "TaskCreate" || toolUse.name === "TaskUpdate")) {
|
|
2300
|
+
update = {
|
|
2301
|
+
sessionUpdate: "plan",
|
|
2302
|
+
entries: taskStateToPlanEntries(taskState),
|
|
2303
|
+
};
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
else if (toolUse.name !== "TodoWrite") {
|
|
2192
2307
|
const { _meta: toolMeta, ...toolUpdate } = toolUpdateFromToolResult(chunk, toolUseCache[chunk.tool_use_id], supportsTerminalOutput);
|
|
2193
2308
|
// When terminal output is supported, send terminal_output as a
|
|
2194
2309
|
// separate notification to match codex-acp's streaming lifecycle:
|
|
@@ -2264,12 +2379,14 @@ export function streamEventToAcpNotifications(message, sessionId, toolUseCache,
|
|
|
2264
2379
|
clientCapabilities: options?.clientCapabilities,
|
|
2265
2380
|
parentToolUseId: message.parent_tool_use_id,
|
|
2266
2381
|
cwd: options?.cwd,
|
|
2382
|
+
taskState: options?.taskState,
|
|
2267
2383
|
});
|
|
2268
2384
|
case "content_block_delta":
|
|
2269
2385
|
return toAcpNotifications([event.delta], "assistant", sessionId, toolUseCache, client, logger, {
|
|
2270
2386
|
clientCapabilities: options?.clientCapabilities,
|
|
2271
2387
|
parentToolUseId: message.parent_tool_use_id,
|
|
2272
2388
|
cwd: options?.cwd,
|
|
2389
|
+
taskState: options?.taskState,
|
|
2273
2390
|
});
|
|
2274
2391
|
// No content
|
|
2275
2392
|
case "message_start":
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { loadManagedSettings, applyEnvironmentSettings } from "./utils.js";
|
|
2
|
+
import { resolveSettings } from "@anthropic-ai/claude-agent-sdk";
|
|
4
3
|
import { claudeCliPath, runAcp } from "./acp-agent.js";
|
|
5
4
|
if (process.argv.includes("--cli")) {
|
|
6
5
|
const { spawn } = await import("node:child_process");
|
|
@@ -33,9 +32,13 @@ if (process.argv.includes("--cli")) {
|
|
|
33
32
|
});
|
|
34
33
|
}
|
|
35
34
|
else {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
// Apply env vars from the managed-policy tier before any SDK call so the
|
|
36
|
+
// SDK subprocess inherits them. Going through resolveSettings (vs. a raw
|
|
37
|
+
// read of managed-settings.json) also picks up MDM sources on macOS and
|
|
38
|
+
// HKLM/HKCU on Windows.
|
|
39
|
+
const policy = await resolveSettings({ settingSources: [] });
|
|
40
|
+
for (const [key, value] of Object.entries(policy.effective.env ?? {})) {
|
|
41
|
+
process.env[key] = value;
|
|
39
42
|
}
|
|
40
43
|
// stdout is used to send messages to the client
|
|
41
44
|
// we redirect everything else to stderr to make sure it doesn't interfere with ACP
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { ClaudeAcpAgent, isLocalCommandMetadata, stripLocalCommandMetadata, runAcp, toAcpNotifications, streamEventToAcpNotifications, type ToolUpdateMeta, type NewSessionMeta, type SDKMessageFilter, } from "./acp-agent.js";
|
|
2
|
-
export {
|
|
2
|
+
export { nodeToWebReadable, nodeToWebWritable, Pushable, unreachable } from "./utils.js";
|
|
3
3
|
export { toolInfoFromToolUse, toDisplayPath, planEntries, toolUpdateFromToolResult, } from "./tools.js";
|
|
4
|
-
export { SettingsManager, type
|
|
4
|
+
export { SettingsManager, type SettingsManagerOptions } from "./settings.js";
|
|
5
5
|
export type { ClaudePlanEntry } from "./tools.js";
|
|
6
6
|
//# sourceMappingURL=lib.d.ts.map
|
package/dist/lib.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EACzB,MAAM,EACN,kBAAkB,EAClB,6BAA6B,EAC7B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EACzB,MAAM,EACN,kBAAkB,EAClB,6BAA6B,EAC7B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,wBAAwB,GACzB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAG7E,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/lib.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Export the main agent class and utilities for library usage
|
|
2
2
|
export { ClaudeAcpAgent, isLocalCommandMetadata, stripLocalCommandMetadata, runAcp, toAcpNotifications, streamEventToAcpNotifications, } from "./acp-agent.js";
|
|
3
|
-
export {
|
|
3
|
+
export { nodeToWebReadable, nodeToWebWritable, Pushable, unreachable } from "./utils.js";
|
|
4
4
|
export { toolInfoFromToolUse, toDisplayPath, planEntries, toolUpdateFromToolResult, } from "./tools.js";
|
|
5
|
-
export { SettingsManager
|
|
5
|
+
export { SettingsManager } from "./settings.js";
|
package/dist/settings.d.ts
CHANGED
|
@@ -1,28 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Permission rule format examples:
|
|
3
|
-
* - "Read" - matches all Read tool calls
|
|
4
|
-
* - "Read(./.env)" - matches specific path
|
|
5
|
-
* - "Read(./.env.*)" - glob pattern
|
|
6
|
-
* - "Read(./secrets/**)" - recursive glob
|
|
7
|
-
* - "Bash(npm run lint)" - exact command prefix
|
|
8
|
-
* - "Bash(npm run:*)" - command prefix with wildcard
|
|
9
|
-
*
|
|
10
|
-
* Docs: https://code.claude.com/docs/en/iam#tool-specific-permission-rules
|
|
11
|
-
*/
|
|
12
|
-
export interface PermissionSettings {
|
|
13
|
-
defaultMode?: string;
|
|
14
|
-
}
|
|
15
|
-
export interface ClaudeCodeSettings {
|
|
16
|
-
permissions?: PermissionSettings;
|
|
17
|
-
env?: Record<string, string>;
|
|
18
|
-
model?: string;
|
|
19
|
-
effortLevel?: string;
|
|
20
|
-
availableModels?: string[];
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Gets the enterprise settings path based on the current platform
|
|
24
|
-
*/
|
|
25
|
-
export declare function getManagedSettingsPath(): string;
|
|
1
|
+
import { type Settings } from "@anthropic-ai/claude-agent-sdk";
|
|
26
2
|
export interface SettingsManagerOptions {
|
|
27
3
|
onChange?: () => void;
|
|
28
4
|
logger?: {
|
|
@@ -31,23 +7,17 @@ export interface SettingsManagerOptions {
|
|
|
31
7
|
};
|
|
32
8
|
}
|
|
33
9
|
/**
|
|
34
|
-
* Manages Claude Code settings
|
|
10
|
+
* Manages Claude Code settings using the SDK's `resolveSettings` merge engine
|
|
11
|
+
* so the values we see match what `query()` would observe.
|
|
35
12
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* 4. Enterprise managed settings (platform-specific path)
|
|
41
|
-
*
|
|
42
|
-
* The manager watches all settings files for changes and automatically reloads.
|
|
13
|
+
* Watches the user/project/local/managed settings files for changes and
|
|
14
|
+
* re-resolves through the SDK on update. Escalating `permissions.defaultMode`
|
|
15
|
+
* values from repo-committed sources are filtered out via
|
|
16
|
+
* `filterEscalatingDefaultMode`, matching the CLI's trust policy.
|
|
43
17
|
*/
|
|
44
18
|
export declare class SettingsManager {
|
|
45
19
|
private cwd;
|
|
46
|
-
private
|
|
47
|
-
private projectSettings;
|
|
48
|
-
private localSettings;
|
|
49
|
-
private enterpriseSettings;
|
|
50
|
-
private mergedSettings;
|
|
20
|
+
private effective;
|
|
51
21
|
private watchers;
|
|
52
22
|
private onChange?;
|
|
53
23
|
private logger;
|
|
@@ -61,27 +31,15 @@ export declare class SettingsManager {
|
|
|
61
31
|
*/
|
|
62
32
|
initialize(): Promise<void>;
|
|
63
33
|
/**
|
|
64
|
-
*
|
|
65
|
-
|
|
66
|
-
private getUserSettingsPath;
|
|
67
|
-
/**
|
|
68
|
-
* Returns the path to the project settings file
|
|
34
|
+
* Paths the SDK reads when resolving settings for this cwd. Watching the
|
|
35
|
+
* containing directories means we pick up file creation as well as edits.
|
|
69
36
|
*/
|
|
70
|
-
private
|
|
37
|
+
private getWatchedPaths;
|
|
71
38
|
/**
|
|
72
|
-
*
|
|
73
|
-
|
|
74
|
-
private getLocalSettingsPath;
|
|
75
|
-
/**
|
|
76
|
-
* Loads settings from all sources
|
|
39
|
+
* Resolves the effective settings via the SDK and applies the CLI's trust
|
|
40
|
+
* filter for escalating `permissions.defaultMode` values.
|
|
77
41
|
*/
|
|
78
42
|
private loadAllSettings;
|
|
79
|
-
/**
|
|
80
|
-
* Merges all settings sources with proper precedence.
|
|
81
|
-
* For permissions, rules from all sources are combined.
|
|
82
|
-
* Deny rules always take precedence during permission checks.
|
|
83
|
-
*/
|
|
84
|
-
private mergeSettings;
|
|
85
43
|
/**
|
|
86
44
|
* Sets up file watchers for all settings files
|
|
87
45
|
*/
|
|
@@ -93,7 +51,7 @@ export declare class SettingsManager {
|
|
|
93
51
|
/**
|
|
94
52
|
* Returns the current merged settings
|
|
95
53
|
*/
|
|
96
|
-
getSettings():
|
|
54
|
+
getSettings(): Settings;
|
|
97
55
|
/**
|
|
98
56
|
* Returns the current working directory
|
|
99
57
|
*/
|
package/dist/settings.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,QAAQ,EACd,MAAM,gCAAgC,CAAC;AA0BxC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7E;AAED;;;;;;;;GAQG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,QAAQ,CAAC,CAAa;IAC9B,OAAO,CAAC,MAAM,CAAqE;IACnF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,WAAW,CAA8B;gBAErC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB;IAMzD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBjC;;;OAGG;IACH,OAAO,CAAC,eAAe;IASvB;;;OAGG;YACW,eAAe;IAU7B;;OAEG;IACH,OAAO,CAAC,aAAa;IAyBrB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,WAAW,IAAI,QAAQ;IAIvB;;OAEG;IACH,MAAM,IAAI,MAAM;IAIhB;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxC;;OAEG;IACH,OAAO,IAAI,IAAI;CAehB"}
|
package/dist/settings.js
CHANGED
|
@@ -1,36 +1,24 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
// resolveSettings and filterEscalatingDefaultMode are marked @alpha in the
|
|
4
|
+
// SDK; API may shift in a future release.
|
|
5
|
+
import { filterEscalatingDefaultMode, resolveSettings, } from "@anthropic-ai/claude-agent-sdk";
|
|
3
6
|
import { CLAUDE_CONFIG_DIR } from "./acp-agent.js";
|
|
4
7
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const content = await fs.promises.readFile(filePath, "utf-8");
|
|
15
|
-
return JSON.parse(content);
|
|
16
|
-
}
|
|
17
|
-
catch (error) {
|
|
18
|
-
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
19
|
-
return {};
|
|
20
|
-
}
|
|
21
|
-
logger?.error(`Failed to load settings from ${filePath}:`, error);
|
|
22
|
-
return {};
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Gets the enterprise settings path based on the current platform
|
|
8
|
+
* Permission rule format examples:
|
|
9
|
+
* - "Read" - matches all Read tool calls
|
|
10
|
+
* - "Read(./.env)" - matches specific path
|
|
11
|
+
* - "Read(./.env.*)" - glob pattern
|
|
12
|
+
* - "Read(./secrets/**)" - recursive glob
|
|
13
|
+
* - "Bash(npm run lint)" - exact command prefix
|
|
14
|
+
* - "Bash(npm run:*)" - command prefix with wildcard
|
|
15
|
+
*
|
|
16
|
+
* Docs: https://code.claude.com/docs/en/iam#tool-specific-permission-rules
|
|
27
17
|
*/
|
|
28
|
-
|
|
18
|
+
function getManagedSettingsPath() {
|
|
29
19
|
switch (process.platform) {
|
|
30
20
|
case "darwin":
|
|
31
21
|
return "/Library/Application Support/ClaudeCode/managed-settings.json";
|
|
32
|
-
case "linux":
|
|
33
|
-
return "/etc/claude-code/managed-settings.json";
|
|
34
22
|
case "win32":
|
|
35
23
|
return "C:\\Program Files\\ClaudeCode\\managed-settings.json";
|
|
36
24
|
default:
|
|
@@ -38,23 +26,17 @@ export function getManagedSettingsPath() {
|
|
|
38
26
|
}
|
|
39
27
|
}
|
|
40
28
|
/**
|
|
41
|
-
* Manages Claude Code settings
|
|
42
|
-
*
|
|
43
|
-
* Settings are loaded from (in order of increasing precedence):
|
|
44
|
-
* 1. User settings (~/.claude/settings.json)
|
|
45
|
-
* 2. Project settings (<cwd>/.claude/settings.json)
|
|
46
|
-
* 3. Local project settings (<cwd>/.claude/settings.local.json)
|
|
47
|
-
* 4. Enterprise managed settings (platform-specific path)
|
|
29
|
+
* Manages Claude Code settings using the SDK's `resolveSettings` merge engine
|
|
30
|
+
* so the values we see match what `query()` would observe.
|
|
48
31
|
*
|
|
49
|
-
*
|
|
32
|
+
* Watches the user/project/local/managed settings files for changes and
|
|
33
|
+
* re-resolves through the SDK on update. Escalating `permissions.defaultMode`
|
|
34
|
+
* values from repo-committed sources are filtered out via
|
|
35
|
+
* `filterEscalatingDefaultMode`, matching the CLI's trust policy.
|
|
50
36
|
*/
|
|
51
37
|
export class SettingsManager {
|
|
52
38
|
constructor(cwd, options) {
|
|
53
|
-
this.
|
|
54
|
-
this.projectSettings = {};
|
|
55
|
-
this.localSettings = {};
|
|
56
|
-
this.enterpriseSettings = {};
|
|
57
|
-
this.mergedSettings = {};
|
|
39
|
+
this.effective = {};
|
|
58
40
|
this.watchers = [];
|
|
59
41
|
this.initialized = false;
|
|
60
42
|
this.disposed = false;
|
|
@@ -85,92 +67,36 @@ export class SettingsManager {
|
|
|
85
67
|
return this.initPromise;
|
|
86
68
|
}
|
|
87
69
|
/**
|
|
88
|
-
*
|
|
89
|
-
|
|
90
|
-
getUserSettingsPath() {
|
|
91
|
-
return path.join(CLAUDE_CONFIG_DIR, "settings.json");
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Returns the path to the project settings file
|
|
95
|
-
*/
|
|
96
|
-
getProjectSettingsPath() {
|
|
97
|
-
return path.join(this.cwd, ".claude", "settings.json");
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Returns the path to the local project settings file
|
|
70
|
+
* Paths the SDK reads when resolving settings for this cwd. Watching the
|
|
71
|
+
* containing directories means we pick up file creation as well as edits.
|
|
101
72
|
*/
|
|
102
|
-
|
|
103
|
-
return
|
|
73
|
+
getWatchedPaths() {
|
|
74
|
+
return [
|
|
75
|
+
path.join(CLAUDE_CONFIG_DIR, "settings.json"),
|
|
76
|
+
path.join(this.cwd, ".claude", "settings.json"),
|
|
77
|
+
path.join(this.cwd, ".claude", "settings.local.json"),
|
|
78
|
+
getManagedSettingsPath(),
|
|
79
|
+
];
|
|
104
80
|
}
|
|
105
81
|
/**
|
|
106
|
-
*
|
|
82
|
+
* Resolves the effective settings via the SDK and applies the CLI's trust
|
|
83
|
+
* filter for escalating `permissions.defaultMode` values.
|
|
107
84
|
*/
|
|
108
85
|
async loadAllSettings() {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
this.projectSettings = projectSettings;
|
|
117
|
-
this.localSettings = localSettings;
|
|
118
|
-
this.enterpriseSettings = enterpriseSettings;
|
|
119
|
-
this.mergeSettings();
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Merges all settings sources with proper precedence.
|
|
123
|
-
* For permissions, rules from all sources are combined.
|
|
124
|
-
* Deny rules always take precedence during permission checks.
|
|
125
|
-
*/
|
|
126
|
-
mergeSettings() {
|
|
127
|
-
const allSettings = [
|
|
128
|
-
this.userSettings,
|
|
129
|
-
this.projectSettings,
|
|
130
|
-
this.localSettings,
|
|
131
|
-
this.enterpriseSettings,
|
|
132
|
-
];
|
|
133
|
-
const merged = {};
|
|
134
|
-
for (const settings of allSettings) {
|
|
135
|
-
if (settings.env) {
|
|
136
|
-
merged.env = { ...merged.env, ...settings.env };
|
|
137
|
-
}
|
|
138
|
-
if (settings.model) {
|
|
139
|
-
merged.model = settings.model;
|
|
140
|
-
}
|
|
141
|
-
if (settings.effortLevel !== undefined) {
|
|
142
|
-
merged.effortLevel = settings.effortLevel;
|
|
143
|
-
}
|
|
144
|
-
if (settings.availableModels !== undefined) {
|
|
145
|
-
// Per Claude Code docs: "When `availableModels` is set at multiple
|
|
146
|
-
// levels, such as user settings and project settings, arrays are
|
|
147
|
-
// merged and deduplicated."
|
|
148
|
-
// https://code.claude.com/docs/en/model-config#merge-behavior
|
|
149
|
-
const combined = [...(merged.availableModels ?? []), ...settings.availableModels];
|
|
150
|
-
merged.availableModels = Array.from(new Set(combined));
|
|
151
|
-
}
|
|
152
|
-
if (settings.permissions?.defaultMode !== undefined) {
|
|
153
|
-
merged.permissions = {
|
|
154
|
-
...merged.permissions,
|
|
155
|
-
defaultMode: settings.permissions.defaultMode,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
86
|
+
try {
|
|
87
|
+
const resolved = await resolveSettings({ cwd: this.cwd });
|
|
88
|
+
this.effective = filterEscalatingDefaultMode(resolved);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
this.logger.error("Failed to resolve settings:", error);
|
|
92
|
+
this.effective = {};
|
|
158
93
|
}
|
|
159
|
-
this.mergedSettings = merged;
|
|
160
94
|
}
|
|
161
95
|
/**
|
|
162
96
|
* Sets up file watchers for all settings files
|
|
163
97
|
*/
|
|
164
98
|
setupWatchers() {
|
|
165
|
-
const
|
|
166
|
-
this.getUserSettingsPath(),
|
|
167
|
-
this.getProjectSettingsPath(),
|
|
168
|
-
this.getLocalSettingsPath(),
|
|
169
|
-
getManagedSettingsPath(),
|
|
170
|
-
];
|
|
171
|
-
for (const filePath of paths) {
|
|
172
|
-
if (!filePath)
|
|
173
|
-
continue;
|
|
99
|
+
for (const filePath of this.getWatchedPaths()) {
|
|
174
100
|
try {
|
|
175
101
|
const dir = path.dirname(filePath);
|
|
176
102
|
const filename = path.basename(filePath);
|
|
@@ -218,7 +144,7 @@ export class SettingsManager {
|
|
|
218
144
|
* Returns the current merged settings
|
|
219
145
|
*/
|
|
220
146
|
getSettings() {
|
|
221
|
-
return this.
|
|
147
|
+
return this.effective;
|
|
222
148
|
}
|
|
223
149
|
/**
|
|
224
150
|
* Returns the current working directory
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PlanEntry, ToolCallContent, ToolCallLocation, ToolKind } from "@agentclientprotocol/sdk";
|
|
2
2
|
import { HookCallback } from "@anthropic-ai/claude-agent-sdk";
|
|
3
|
+
import { TaskCreateInput, TaskCreateOutput, TaskUpdateInput } from "@anthropic-ai/claude-agent-sdk/sdk-tools.js";
|
|
3
4
|
import { ToolResultBlockParam, WebSearchToolResultBlockParam } from "@anthropic-ai/sdk/resources";
|
|
4
5
|
import { BetaBashCodeExecutionToolResultBlockParam, BetaCodeExecutionToolResultBlockParam, BetaRequestMCPToolResultBlockParam, BetaTextEditorCodeExecutionToolResultBlockParam, BetaToolResultBlockParam, BetaToolSearchToolResultBlockParam, BetaWebFetchToolResultBlockParam, BetaWebSearchToolResultBlockParam } from "@anthropic-ai/sdk/resources/beta.mjs";
|
|
5
6
|
import { Logger } from "./acp-agent.js";
|
|
@@ -43,6 +44,29 @@ export type ClaudePlanEntry = {
|
|
|
43
44
|
export declare function planEntries(input: {
|
|
44
45
|
todos: ClaudePlanEntry[];
|
|
45
46
|
} | undefined): PlanEntry[];
|
|
47
|
+
/**
|
|
48
|
+
* Per-session task list accumulated from Task* tool calls (TaskCreate /
|
|
49
|
+
* TaskUpdate). The headless/SDK session emits these as incremental tool
|
|
50
|
+
* calls keyed by task ID, replacing the snapshot-style TodoWrite tool.
|
|
51
|
+
* Iteration order is insertion order (Map semantics), matching the order
|
|
52
|
+
* tasks are created.
|
|
53
|
+
*/
|
|
54
|
+
export type TaskEntry = {
|
|
55
|
+
subject: string;
|
|
56
|
+
status: "pending" | "in_progress" | "completed";
|
|
57
|
+
activeForm?: string;
|
|
58
|
+
description?: string;
|
|
59
|
+
};
|
|
60
|
+
export type TaskState = Map<string, TaskEntry>;
|
|
61
|
+
/**
|
|
62
|
+
* Best-effort parse of a TaskCreate tool_result content into the structured
|
|
63
|
+
* TaskCreateOutput. The SDK delivers tool outputs either as a string or as
|
|
64
|
+
* an array of TextBlockParam-like blocks containing JSON text; try both.
|
|
65
|
+
*/
|
|
66
|
+
export declare function parseTaskCreateOutput(content: unknown): TaskCreateOutput | undefined;
|
|
67
|
+
export declare function applyTaskCreate(state: TaskState, input: TaskCreateInput | undefined, output: TaskCreateOutput | undefined): void;
|
|
68
|
+
export declare function applyTaskUpdate(state: TaskState, input: TaskUpdateInput | undefined): void;
|
|
69
|
+
export declare function taskStateToPlanEntries(state: TaskState): PlanEntry[];
|
|
46
70
|
export declare function markdownEscape(text: string): string;
|
|
47
71
|
/**
|
|
48
72
|
* Builds diff ToolUpdate content from the structured toolResponse provided by
|
|
@@ -61,5 +85,19 @@ export declare const registerHookCallback: (toolUseID: string, { onPostToolUseHo
|
|
|
61
85
|
export declare const createPostToolUseHook: (logger?: Logger, options?: {
|
|
62
86
|
onEnterPlanMode?: () => Promise<void>;
|
|
63
87
|
}) => HookCallback;
|
|
88
|
+
/**
|
|
89
|
+
* Hook callback for `TaskCreated` / `TaskCompleted` events. The SDK fires
|
|
90
|
+
* these for both user-facing TaskCreate tool calls and subagent task
|
|
91
|
+
* creation, giving us `task_id` + `task_subject` without having to parse
|
|
92
|
+
* tool_result payloads.
|
|
93
|
+
*
|
|
94
|
+
* Populating `taskState` from the hook means a later `TaskUpdate` (which
|
|
95
|
+
* typically only carries `taskId` + `status`) finds an existing entry with
|
|
96
|
+
* a real subject, instead of synthesizing a placeholder with empty content.
|
|
97
|
+
*/
|
|
98
|
+
export declare const createTaskHook: (options: {
|
|
99
|
+
taskState: TaskState;
|
|
100
|
+
onChange?: () => Promise<void>;
|
|
101
|
+
}) => HookCallback;
|
|
64
102
|
export {};
|
|
65
103
|
//# sourceMappingURL=tools.d.ts.map
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.js
CHANGED
|
@@ -234,6 +234,36 @@ export function toolInfoFromToolUse(toolUse, supportsTerminalOutput = false, cwd
|
|
|
234
234
|
content: [],
|
|
235
235
|
};
|
|
236
236
|
}
|
|
237
|
+
case "TaskCreate": {
|
|
238
|
+
const input = toolUse.input;
|
|
239
|
+
return {
|
|
240
|
+
title: input?.subject ? `Create task: ${input.subject}` : "Create task",
|
|
241
|
+
kind: "think",
|
|
242
|
+
content: [],
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
case "TaskUpdate": {
|
|
246
|
+
const input = toolUse.input;
|
|
247
|
+
return {
|
|
248
|
+
title: input?.subject ? `Update task: ${input.subject}` : "Update task",
|
|
249
|
+
kind: "think",
|
|
250
|
+
content: [],
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
case "TaskList": {
|
|
254
|
+
return {
|
|
255
|
+
title: "List tasks",
|
|
256
|
+
kind: "think",
|
|
257
|
+
content: [],
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
case "TaskGet": {
|
|
261
|
+
return {
|
|
262
|
+
title: "Get task",
|
|
263
|
+
kind: "think",
|
|
264
|
+
content: [],
|
|
265
|
+
};
|
|
266
|
+
}
|
|
237
267
|
case "ExitPlanMode": {
|
|
238
268
|
const planInput = toolUse.input;
|
|
239
269
|
return {
|
|
@@ -483,6 +513,82 @@ export function planEntries(input) {
|
|
|
483
513
|
priority: "medium",
|
|
484
514
|
}));
|
|
485
515
|
}
|
|
516
|
+
/**
|
|
517
|
+
* Best-effort parse of a TaskCreate tool_result content into the structured
|
|
518
|
+
* TaskCreateOutput. The SDK delivers tool outputs either as a string or as
|
|
519
|
+
* an array of TextBlockParam-like blocks containing JSON text; try both.
|
|
520
|
+
*/
|
|
521
|
+
export function parseTaskCreateOutput(content) {
|
|
522
|
+
const tryParse = (text) => {
|
|
523
|
+
try {
|
|
524
|
+
const parsed = JSON.parse(text);
|
|
525
|
+
if (parsed &&
|
|
526
|
+
typeof parsed === "object" &&
|
|
527
|
+
parsed.task &&
|
|
528
|
+
typeof parsed.task.id === "string") {
|
|
529
|
+
return parsed;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
catch {
|
|
533
|
+
// ignore
|
|
534
|
+
}
|
|
535
|
+
return undefined;
|
|
536
|
+
};
|
|
537
|
+
if (typeof content === "string") {
|
|
538
|
+
return tryParse(content);
|
|
539
|
+
}
|
|
540
|
+
if (Array.isArray(content)) {
|
|
541
|
+
for (const block of content) {
|
|
542
|
+
if (block && typeof block === "object" && "type" in block && block.type === "text") {
|
|
543
|
+
const text = block.text;
|
|
544
|
+
if (typeof text === "string") {
|
|
545
|
+
const parsed = tryParse(text);
|
|
546
|
+
if (parsed)
|
|
547
|
+
return parsed;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
return undefined;
|
|
553
|
+
}
|
|
554
|
+
export function applyTaskCreate(state, input, output) {
|
|
555
|
+
const taskId = output?.task?.id;
|
|
556
|
+
if (!taskId || !input)
|
|
557
|
+
return;
|
|
558
|
+
state.set(taskId, {
|
|
559
|
+
subject: input.subject,
|
|
560
|
+
status: "pending",
|
|
561
|
+
activeForm: input.activeForm,
|
|
562
|
+
description: input.description,
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
export function applyTaskUpdate(state, input) {
|
|
566
|
+
if (!input?.taskId)
|
|
567
|
+
return;
|
|
568
|
+
if (input.status === "deleted") {
|
|
569
|
+
state.delete(input.taskId);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
const existing = state.get(input.taskId);
|
|
573
|
+
// Without a subject from either the existing entry or the update payload,
|
|
574
|
+
// we'd produce a plan entry with empty `content` — drop the update.
|
|
575
|
+
const subject = input.subject ?? existing?.subject;
|
|
576
|
+
if (!subject)
|
|
577
|
+
return;
|
|
578
|
+
state.set(input.taskId, {
|
|
579
|
+
subject,
|
|
580
|
+
status: input.status ?? existing?.status ?? "pending",
|
|
581
|
+
activeForm: input.activeForm ?? existing?.activeForm,
|
|
582
|
+
description: input.description ?? existing?.description,
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
export function taskStateToPlanEntries(state) {
|
|
586
|
+
return Array.from(state.values()).map((task) => ({
|
|
587
|
+
content: task.subject,
|
|
588
|
+
status: task.status,
|
|
589
|
+
priority: "medium",
|
|
590
|
+
}));
|
|
591
|
+
}
|
|
486
592
|
export function markdownEscape(text) {
|
|
487
593
|
let escape = "```";
|
|
488
594
|
for (const [m] of text.matchAll(/^```+/gm)) {
|
|
@@ -568,3 +674,40 @@ export const createPostToolUseHook = (logger = console, options) => async (input
|
|
|
568
674
|
}
|
|
569
675
|
return { continue: true };
|
|
570
676
|
};
|
|
677
|
+
/**
|
|
678
|
+
* Hook callback for `TaskCreated` / `TaskCompleted` events. The SDK fires
|
|
679
|
+
* these for both user-facing TaskCreate tool calls and subagent task
|
|
680
|
+
* creation, giving us `task_id` + `task_subject` without having to parse
|
|
681
|
+
* tool_result payloads.
|
|
682
|
+
*
|
|
683
|
+
* Populating `taskState` from the hook means a later `TaskUpdate` (which
|
|
684
|
+
* typically only carries `taskId` + `status`) finds an existing entry with
|
|
685
|
+
* a real subject, instead of synthesizing a placeholder with empty content.
|
|
686
|
+
*/
|
|
687
|
+
export const createTaskHook = (options) => async (input) => {
|
|
688
|
+
const taskId = "task_id" in input && typeof input.task_id === "string" ? input.task_id : undefined;
|
|
689
|
+
if (!taskId)
|
|
690
|
+
return { continue: true };
|
|
691
|
+
if (input.hook_event_name === "TaskCreated") {
|
|
692
|
+
if (!input.task_subject)
|
|
693
|
+
return { continue: true };
|
|
694
|
+
if (options.taskState.has(taskId))
|
|
695
|
+
return { continue: true };
|
|
696
|
+
options.taskState.set(taskId, {
|
|
697
|
+
subject: input.task_subject,
|
|
698
|
+
status: "pending",
|
|
699
|
+
description: input.task_description,
|
|
700
|
+
});
|
|
701
|
+
if (options.onChange)
|
|
702
|
+
await options.onChange();
|
|
703
|
+
}
|
|
704
|
+
else if (input.hook_event_name === "TaskCompleted") {
|
|
705
|
+
const existing = options.taskState.get(taskId);
|
|
706
|
+
if (!existing || existing.status === "completed")
|
|
707
|
+
return { continue: true };
|
|
708
|
+
options.taskState.set(taskId, { ...existing, status: "completed" });
|
|
709
|
+
if (options.onChange)
|
|
710
|
+
await options.onChange();
|
|
711
|
+
}
|
|
712
|
+
return { continue: true };
|
|
713
|
+
};
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Readable, Writable } from "node:stream";
|
|
2
2
|
import { WritableStream, ReadableStream } from "node:stream/web";
|
|
3
3
|
import { Logger } from "./acp-agent.js";
|
|
4
|
-
import { ClaudeCodeSettings } from "./settings.js";
|
|
5
4
|
export declare class Pushable<T> implements AsyncIterable<T> {
|
|
6
5
|
private queue;
|
|
7
6
|
private resolvers;
|
|
@@ -14,6 +13,4 @@ export declare function nodeToWebWritable(nodeStream: Writable): WritableStream<
|
|
|
14
13
|
export declare function nodeToWebReadable(nodeStream: Readable): ReadableStream<Uint8Array>;
|
|
15
14
|
export declare function unreachable(value: never, logger?: Logger): void;
|
|
16
15
|
export declare function sleep(time: number): Promise<void>;
|
|
17
|
-
export declare function loadManagedSettings(): ClaudeCodeSettings | null;
|
|
18
|
-
export declare function applyEnvironmentSettings(settings: ClaudeCodeSettings): void;
|
|
19
16
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGxC,qBAAa,QAAQ,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,IAAI,CAAS;IAErB,IAAI,CAAC,IAAI,EAAE,CAAC;IASZ,GAAG;IAQH,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC;CAgB3C;AAGD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CAclF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CAUlF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,GAAE,MAAgB,QAQjE;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjD"}
|
package/dist/utils.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
// A pushable async iterable: allows you to push items and consume them with for-await.
|
|
2
2
|
import { WritableStream, ReadableStream } from "node:stream/web";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { getManagedSettingsPath } from "./settings.js";
|
|
5
3
|
// Useful for bridging push-based and async-iterator-based code.
|
|
6
4
|
export class Pushable {
|
|
7
5
|
constructor() {
|
|
@@ -83,18 +81,3 @@ export function unreachable(value, logger = console) {
|
|
|
83
81
|
export function sleep(time) {
|
|
84
82
|
return new Promise((resolve) => setTimeout(resolve, time));
|
|
85
83
|
}
|
|
86
|
-
export function loadManagedSettings() {
|
|
87
|
-
try {
|
|
88
|
-
return JSON.parse(readFileSync(getManagedSettingsPath(), "utf8"));
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
export function applyEnvironmentSettings(settings) {
|
|
95
|
-
if (settings.env) {
|
|
96
|
-
for (const [key, value] of Object.entries(settings.env)) {
|
|
97
|
-
process.env[key] = value;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.36.0",
|
|
7
7
|
"description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
|
|
8
8
|
"main": "dist/lib.js",
|
|
9
9
|
"types": "dist/lib.d.ts",
|
|
@@ -60,22 +60,22 @@
|
|
|
60
60
|
"author": "Zed Industries",
|
|
61
61
|
"license": "Apache-2.0",
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@agentclientprotocol/sdk": "0.
|
|
64
|
-
"@anthropic-ai/claude-agent-sdk": "0.
|
|
63
|
+
"@agentclientprotocol/sdk": "0.22.0",
|
|
64
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.143",
|
|
65
65
|
"zod": "^3.25.0 || ^4.0.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@anthropic-ai/sdk": "0.
|
|
68
|
+
"@anthropic-ai/sdk": "0.96.0",
|
|
69
69
|
"@eslint/js": "10.0.1",
|
|
70
|
-
"@types/node": "25.
|
|
71
|
-
"@typescript-eslint/eslint-plugin": "8.59.
|
|
72
|
-
"@typescript-eslint/parser": "8.59.
|
|
73
|
-
"eslint": "10.
|
|
70
|
+
"@types/node": "25.8.0",
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "8.59.3",
|
|
72
|
+
"@typescript-eslint/parser": "8.59.3",
|
|
73
|
+
"eslint": "10.4.0",
|
|
74
74
|
"eslint-config-prettier": "10.1.8",
|
|
75
75
|
"globals": "17.6.0",
|
|
76
76
|
"prettier": "3.8.3",
|
|
77
77
|
"ts-node": "10.9.2",
|
|
78
78
|
"typescript": "6.0.3",
|
|
79
|
-
"vitest": "4.1.
|
|
79
|
+
"vitest": "4.1.6"
|
|
80
80
|
}
|
|
81
81
|
}
|