@posthog/agent 2.3.735 → 2.3.736
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/adapters/claude/conversion/tool-use-to-acp.d.ts +2 -10
- package/dist/adapters/claude/conversion/tool-use-to-acp.js +24 -10
- package/dist/adapters/claude/conversion/tool-use-to-acp.js.map +1 -1
- package/dist/adapters/claude/permissions/permission-options.js +6 -4
- package/dist/adapters/claude/permissions/permission-options.js.map +1 -1
- package/dist/adapters/claude/session/jsonl-hydration.js +1 -0
- package/dist/adapters/claude/session/jsonl-hydration.js.map +1 -1
- package/dist/adapters/claude/session/models.js +20 -1
- package/dist/adapters/claude/session/models.js.map +1 -1
- package/dist/adapters/claude/tools.js +4 -2
- package/dist/adapters/claude/tools.js.map +1 -1
- package/dist/adapters/reasoning-effort.js +3 -1
- package/dist/adapters/reasoning-effort.js.map +1 -1
- package/dist/agent.js +524 -72
- package/dist/agent.js.map +1 -1
- package/dist/posthog-api.js +4 -4
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.js +524 -72
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +524 -72
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +6 -6
- package/src/adapters/claude/UPSTREAM.md +80 -3
- package/src/adapters/claude/claude-agent.ts +201 -18
- package/src/adapters/claude/conversion/sdk-to-acp.ts +182 -16
- package/src/adapters/claude/conversion/task-state.test.ts +338 -0
- package/src/adapters/claude/conversion/task-state.ts +178 -0
- package/src/adapters/claude/conversion/tool-use-to-acp.ts +29 -19
- package/src/adapters/claude/hooks.test.ts +162 -0
- package/src/adapters/claude/hooks.ts +44 -3
- package/src/adapters/claude/permissions/permission-options.ts +7 -2
- package/src/adapters/claude/session/commands.ts +1 -0
- package/src/adapters/claude/session/mcp-config.ts +23 -7
- package/src/adapters/claude/session/model-config.test.ts +60 -0
- package/src/adapters/claude/session/model-config.ts +56 -0
- package/src/adapters/claude/session/models.test.ts +119 -0
- package/src/adapters/claude/session/models.ts +31 -0
- package/src/adapters/claude/session/options.test.ts +1 -0
- package/src/adapters/claude/session/options.ts +29 -1
- package/src/adapters/claude/session/settings.test.ts +102 -1
- package/src/adapters/claude/session/settings.ts +33 -6
- package/src/adapters/claude/tools.ts +4 -2
- package/src/adapters/claude/types.ts +8 -0
- package/src/adapters/codex/codex-agent.ts +2 -2
- package/src/server/agent-server.test.ts +173 -0
- package/src/test/mocks/claude-sdk.ts +4 -0
- package/src/test/native-binary.test.ts +27 -0
- package/dist/claude-cli/cli.js +0 -18412
- package/dist/claude-cli/vendor/audio-capture/arm64-darwin/audio-capture.node +0 -0
- package/dist/claude-cli/vendor/audio-capture/arm64-linux/audio-capture.node +0 -0
- package/dist/claude-cli/vendor/audio-capture/arm64-win32/audio-capture.node +0 -0
- package/dist/claude-cli/vendor/audio-capture/x64-darwin/audio-capture.node +0 -0
- package/dist/claude-cli/vendor/audio-capture/x64-linux/audio-capture.node +0 -0
- package/dist/claude-cli/vendor/audio-capture/x64-win32/audio-capture.node +0 -0
- package/dist/claude-cli/vendor/ripgrep/COPYING +0 -3
- package/dist/claude-cli/vendor/ripgrep/arm64-darwin/rg +0 -0
- package/dist/claude-cli/vendor/ripgrep/arm64-linux/rg +0 -0
- package/dist/claude-cli/vendor/ripgrep/arm64-win32/rg.exe +0 -0
- package/dist/claude-cli/vendor/ripgrep/x64-darwin/rg +0 -0
- package/dist/claude-cli/vendor/ripgrep/x64-linux/rg +0 -0
- package/dist/claude-cli/vendor/ripgrep/x64-win32/rg.exe +0 -0
- package/dist/claude-cli/yoga.wasm +0 -0
package/dist/agent.js
CHANGED
|
@@ -4674,7 +4674,7 @@ import { v7 as uuidv7 } from "uuid";
|
|
|
4674
4674
|
// package.json
|
|
4675
4675
|
var package_default = {
|
|
4676
4676
|
name: "@posthog/agent",
|
|
4677
|
-
version: "2.3.
|
|
4677
|
+
version: "2.3.736",
|
|
4678
4678
|
repository: "https://github.com/PostHog/code",
|
|
4679
4679
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
4680
4680
|
exports: {
|
|
@@ -4794,9 +4794,9 @@ var package_default = {
|
|
|
4794
4794
|
vitest: "^2.1.8"
|
|
4795
4795
|
},
|
|
4796
4796
|
dependencies: {
|
|
4797
|
-
"@agentclientprotocol/sdk": "0.
|
|
4798
|
-
"@anthropic-ai/claude-agent-sdk": "0.
|
|
4799
|
-
"@anthropic-ai/sdk": "0.
|
|
4797
|
+
"@agentclientprotocol/sdk": "0.22.1",
|
|
4798
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.154",
|
|
4799
|
+
"@anthropic-ai/sdk": "0.100.0",
|
|
4800
4800
|
"@hono/node-server": "^1.19.9",
|
|
4801
4801
|
"@opentelemetry/api-logs": "^0.208.0",
|
|
4802
4802
|
"@opentelemetry/exporter-logs-otlp-http": "^0.208.0",
|
|
@@ -10183,6 +10183,30 @@ var registerHookCallback = (toolUseID, {
|
|
|
10183
10183
|
onPostToolUseHook
|
|
10184
10184
|
};
|
|
10185
10185
|
};
|
|
10186
|
+
var createTaskHook = (taskState, onChange) => async (input) => {
|
|
10187
|
+
const taskId = "task_id" in input && typeof input.task_id === "string" ? input.task_id : void 0;
|
|
10188
|
+
if (!taskId) return { continue: true };
|
|
10189
|
+
let mutated = false;
|
|
10190
|
+
if (input.hook_event_name === "TaskCreated") {
|
|
10191
|
+
if (!input.task_subject) return { continue: true };
|
|
10192
|
+
if (taskState.has(taskId)) return { continue: true };
|
|
10193
|
+
taskState.set(taskId, {
|
|
10194
|
+
subject: input.task_subject,
|
|
10195
|
+
status: "pending",
|
|
10196
|
+
description: input.task_description
|
|
10197
|
+
});
|
|
10198
|
+
mutated = true;
|
|
10199
|
+
} else if (input.hook_event_name === "TaskCompleted") {
|
|
10200
|
+
const existing = taskState.get(taskId);
|
|
10201
|
+
if (!existing || existing.status === "completed") {
|
|
10202
|
+
return { continue: true };
|
|
10203
|
+
}
|
|
10204
|
+
taskState.set(taskId, { ...existing, status: "completed" });
|
|
10205
|
+
mutated = true;
|
|
10206
|
+
}
|
|
10207
|
+
if (mutated && onChange) await onChange();
|
|
10208
|
+
return { continue: true };
|
|
10209
|
+
};
|
|
10186
10210
|
var createPostToolUseHook = ({ onModeChange }) => async (input, toolUseID) => {
|
|
10187
10211
|
if (input.hook_event_name === "PostToolUse") {
|
|
10188
10212
|
const toolName = input.tool_name;
|
|
@@ -10197,10 +10221,8 @@ var createPostToolUseHook = ({ onModeChange }) => async (input, toolUseID) => {
|
|
|
10197
10221
|
input.tool_input,
|
|
10198
10222
|
input.tool_response
|
|
10199
10223
|
);
|
|
10200
|
-
delete toolUseCallbacks[toolUseID];
|
|
10201
|
-
} else {
|
|
10202
|
-
delete toolUseCallbacks[toolUseID];
|
|
10203
10224
|
}
|
|
10225
|
+
delete toolUseCallbacks[toolUseID];
|
|
10204
10226
|
}
|
|
10205
10227
|
}
|
|
10206
10228
|
return { continue: true };
|
|
@@ -10347,6 +10369,104 @@ var createPreToolUseHook = (settingsManager, logger) => async (input, _toolUseID
|
|
|
10347
10369
|
}
|
|
10348
10370
|
};
|
|
10349
10371
|
|
|
10372
|
+
// src/adapters/claude/conversion/task-state.ts
|
|
10373
|
+
function parseTaskCreateOutput(content) {
|
|
10374
|
+
const tryParse = (text2) => {
|
|
10375
|
+
try {
|
|
10376
|
+
const parsed = JSON.parse(text2);
|
|
10377
|
+
if (parsed && typeof parsed === "object" && parsed.task && typeof parsed.task.id === "string") {
|
|
10378
|
+
return parsed;
|
|
10379
|
+
}
|
|
10380
|
+
} catch {
|
|
10381
|
+
}
|
|
10382
|
+
return void 0;
|
|
10383
|
+
};
|
|
10384
|
+
if (typeof content === "string") {
|
|
10385
|
+
return tryParse(content);
|
|
10386
|
+
}
|
|
10387
|
+
if (Array.isArray(content)) {
|
|
10388
|
+
for (const block of content) {
|
|
10389
|
+
if (block && typeof block === "object" && "type" in block && block.type === "text") {
|
|
10390
|
+
const text2 = block.text;
|
|
10391
|
+
if (typeof text2 === "string") {
|
|
10392
|
+
const parsed = tryParse(text2);
|
|
10393
|
+
if (parsed) return parsed;
|
|
10394
|
+
}
|
|
10395
|
+
}
|
|
10396
|
+
}
|
|
10397
|
+
}
|
|
10398
|
+
return void 0;
|
|
10399
|
+
}
|
|
10400
|
+
function applyTaskCreate(state, input, output) {
|
|
10401
|
+
const taskId = output?.task?.id;
|
|
10402
|
+
if (!taskId || !input) return;
|
|
10403
|
+
state.set(taskId, {
|
|
10404
|
+
subject: input.subject,
|
|
10405
|
+
status: "pending",
|
|
10406
|
+
activeForm: input.activeForm,
|
|
10407
|
+
description: input.description
|
|
10408
|
+
});
|
|
10409
|
+
}
|
|
10410
|
+
function applyTaskUpdate(state, input) {
|
|
10411
|
+
if (!input?.taskId) return;
|
|
10412
|
+
if (input.status === "deleted") {
|
|
10413
|
+
state.delete(input.taskId);
|
|
10414
|
+
return;
|
|
10415
|
+
}
|
|
10416
|
+
const existing = state.get(input.taskId);
|
|
10417
|
+
const subject = input.subject ?? existing?.subject;
|
|
10418
|
+
if (!subject) return;
|
|
10419
|
+
state.set(input.taskId, {
|
|
10420
|
+
subject,
|
|
10421
|
+
status: input.status ?? existing?.status ?? "pending",
|
|
10422
|
+
activeForm: input.activeForm ?? existing?.activeForm,
|
|
10423
|
+
description: input.description ?? existing?.description
|
|
10424
|
+
});
|
|
10425
|
+
}
|
|
10426
|
+
function taskStateToPlanEntries(state) {
|
|
10427
|
+
return Array.from(state.values()).map((task) => ({
|
|
10428
|
+
content: task.subject,
|
|
10429
|
+
status: task.status,
|
|
10430
|
+
priority: "medium"
|
|
10431
|
+
}));
|
|
10432
|
+
}
|
|
10433
|
+
function isToolUseBlock(block) {
|
|
10434
|
+
return !!block && typeof block === "object" && block.type === "tool_use" && typeof block.id === "string" && typeof block.name === "string";
|
|
10435
|
+
}
|
|
10436
|
+
function isToolResultBlock(block) {
|
|
10437
|
+
return !!block && typeof block === "object" && block.type === "tool_result" && typeof block.tool_use_id === "string";
|
|
10438
|
+
}
|
|
10439
|
+
function rehydrateTaskState(messages, state) {
|
|
10440
|
+
const pendingInputs = /* @__PURE__ */ new Map();
|
|
10441
|
+
for (const msg of messages) {
|
|
10442
|
+
const content = msg.message?.content;
|
|
10443
|
+
if (!Array.isArray(content)) continue;
|
|
10444
|
+
if (msg.type === "assistant") {
|
|
10445
|
+
for (const block of content) {
|
|
10446
|
+
if (isToolUseBlock(block) && (block.name === "TaskCreate" || block.name === "TaskUpdate")) {
|
|
10447
|
+
pendingInputs.set(block.id, { name: block.name, input: block.input });
|
|
10448
|
+
}
|
|
10449
|
+
}
|
|
10450
|
+
} else if (msg.type === "user") {
|
|
10451
|
+
for (const block of content) {
|
|
10452
|
+
if (!isToolResultBlock(block) || block.is_error) continue;
|
|
10453
|
+
const cached = pendingInputs.get(block.tool_use_id);
|
|
10454
|
+
if (!cached) continue;
|
|
10455
|
+
if (cached.name === "TaskCreate") {
|
|
10456
|
+
applyTaskCreate(
|
|
10457
|
+
state,
|
|
10458
|
+
cached.input,
|
|
10459
|
+
parseTaskCreateOutput(block.content)
|
|
10460
|
+
);
|
|
10461
|
+
} else if (cached.name === "TaskUpdate") {
|
|
10462
|
+
applyTaskUpdate(state, cached.input);
|
|
10463
|
+
}
|
|
10464
|
+
pendingInputs.delete(block.tool_use_id);
|
|
10465
|
+
}
|
|
10466
|
+
}
|
|
10467
|
+
}
|
|
10468
|
+
}
|
|
10469
|
+
|
|
10350
10470
|
// src/adapters/claude/conversion/tool-use-to-acp.ts
|
|
10351
10471
|
import fs4 from "fs";
|
|
10352
10472
|
import path7 from "path";
|
|
@@ -10698,9 +10818,31 @@ function toolInfoFromToolUse(toolUse, options) {
|
|
|
10698
10818
|
content: []
|
|
10699
10819
|
};
|
|
10700
10820
|
}
|
|
10701
|
-
case "
|
|
10821
|
+
case "TaskCreate": {
|
|
10822
|
+
const subject = typeof input?.subject === "string" ? input.subject : void 0;
|
|
10823
|
+
return {
|
|
10824
|
+
title: subject ? `Create task: ${subject}` : "Create task",
|
|
10825
|
+
kind: "think",
|
|
10826
|
+
content: []
|
|
10827
|
+
};
|
|
10828
|
+
}
|
|
10829
|
+
case "TaskUpdate": {
|
|
10830
|
+
const subject = typeof input?.subject === "string" ? input.subject : void 0;
|
|
10831
|
+
return {
|
|
10832
|
+
title: subject ? `Update task: ${subject}` : "Update task",
|
|
10833
|
+
kind: "think",
|
|
10834
|
+
content: []
|
|
10835
|
+
};
|
|
10836
|
+
}
|
|
10837
|
+
case "TaskList":
|
|
10838
|
+
return {
|
|
10839
|
+
title: "List tasks",
|
|
10840
|
+
kind: "think",
|
|
10841
|
+
content: []
|
|
10842
|
+
};
|
|
10843
|
+
case "TaskGet":
|
|
10702
10844
|
return {
|
|
10703
|
-
title:
|
|
10845
|
+
title: "Get task",
|
|
10704
10846
|
kind: "think",
|
|
10705
10847
|
content: []
|
|
10706
10848
|
};
|
|
@@ -10984,13 +11126,6 @@ ${content}
|
|
|
10984
11126
|
}
|
|
10985
11127
|
return {};
|
|
10986
11128
|
}
|
|
10987
|
-
function planEntries(input) {
|
|
10988
|
-
return input.todos.map((input2) => ({
|
|
10989
|
-
content: input2.content,
|
|
10990
|
-
status: input2.status,
|
|
10991
|
-
priority: "medium"
|
|
10992
|
-
}));
|
|
10993
|
-
}
|
|
10994
11129
|
function resolveFileContent(filePath, oldText, cachedFileContent) {
|
|
10995
11130
|
if (cachedFileContent && filePath in cachedFileContent) {
|
|
10996
11131
|
const cached = cachedFileContent[filePath];
|
|
@@ -11076,14 +11211,7 @@ function handleThinkingChunk(chunk, parentToolCallId) {
|
|
|
11076
11211
|
function handleToolUseChunk(chunk, ctx) {
|
|
11077
11212
|
const alreadyCached = chunk.id in ctx.toolUseCache;
|
|
11078
11213
|
ctx.toolUseCache[chunk.id] = chunk;
|
|
11079
|
-
if (chunk.name === "
|
|
11080
|
-
const input = chunk.input;
|
|
11081
|
-
if (Array.isArray(input.todos)) {
|
|
11082
|
-
return {
|
|
11083
|
-
sessionUpdate: "plan",
|
|
11084
|
-
entries: planEntries(chunk.input)
|
|
11085
|
-
};
|
|
11086
|
-
}
|
|
11214
|
+
if (chunk.name === "TaskCreate" || chunk.name === "TaskUpdate" || chunk.name === "TaskList" || chunk.name === "TaskGet") {
|
|
11087
11215
|
return null;
|
|
11088
11216
|
}
|
|
11089
11217
|
if (!alreadyCached && ctx.registerHooks !== false) {
|
|
@@ -11091,7 +11219,7 @@ function handleToolUseChunk(chunk, ctx) {
|
|
|
11091
11219
|
onPostToolUseHook: async (toolUseId, _toolInput, toolResponse) => {
|
|
11092
11220
|
const toolUse = ctx.toolUseCache[toolUseId];
|
|
11093
11221
|
if (toolUse) {
|
|
11094
|
-
const editUpdate = toolUse.name === "Edit" ? toolUpdateFromEditToolResponse(toolResponse) : null;
|
|
11222
|
+
const editUpdate = toolUse.name === "Edit" || toolUse.name === "Write" ? toolUpdateFromEditToolResponse(toolResponse) : null;
|
|
11095
11223
|
await ctx.client.sessionUpdate({
|
|
11096
11224
|
sessionId: ctx.sessionId,
|
|
11097
11225
|
update: {
|
|
@@ -11203,7 +11331,28 @@ function handleToolResultChunk(chunk, ctx) {
|
|
|
11203
11331
|
);
|
|
11204
11332
|
return [];
|
|
11205
11333
|
}
|
|
11206
|
-
if (toolUse.name === "
|
|
11334
|
+
if (toolUse.name === "TaskCreate" || toolUse.name === "TaskUpdate" || toolUse.name === "TaskList" || toolUse.name === "TaskGet") {
|
|
11335
|
+
if (chunk.is_error || !ctx.taskState) return [];
|
|
11336
|
+
if (toolUse.name === "TaskCreate") {
|
|
11337
|
+
applyTaskCreate(
|
|
11338
|
+
ctx.taskState,
|
|
11339
|
+
toolUse.input,
|
|
11340
|
+
parseTaskCreateOutput(chunk.content)
|
|
11341
|
+
);
|
|
11342
|
+
} else if (toolUse.name === "TaskUpdate") {
|
|
11343
|
+
applyTaskUpdate(
|
|
11344
|
+
ctx.taskState,
|
|
11345
|
+
toolUse.input
|
|
11346
|
+
);
|
|
11347
|
+
}
|
|
11348
|
+
if (toolUse.name === "TaskCreate" || toolUse.name === "TaskUpdate") {
|
|
11349
|
+
return [
|
|
11350
|
+
{
|
|
11351
|
+
sessionUpdate: "plan",
|
|
11352
|
+
entries: taskStateToPlanEntries(ctx.taskState)
|
|
11353
|
+
}
|
|
11354
|
+
];
|
|
11355
|
+
}
|
|
11207
11356
|
return [];
|
|
11208
11357
|
}
|
|
11209
11358
|
if (!chunk.is_error) {
|
|
@@ -11300,13 +11449,15 @@ function processContentChunk(chunk, role, ctx) {
|
|
|
11300
11449
|
case "container_upload":
|
|
11301
11450
|
case "compaction":
|
|
11302
11451
|
case "compaction_delta":
|
|
11452
|
+
case "advisor_tool_result":
|
|
11453
|
+
case "mid_conv_system":
|
|
11303
11454
|
return [];
|
|
11304
11455
|
default:
|
|
11305
11456
|
unreachable(chunk, ctx.logger);
|
|
11306
11457
|
return [];
|
|
11307
11458
|
}
|
|
11308
11459
|
}
|
|
11309
|
-
function toAcpNotifications(content, role, sessionId, toolUseCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, mcpToolUseResult, enrichedReadCache) {
|
|
11460
|
+
function toAcpNotifications(content, role, sessionId, toolUseCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, mcpToolUseResult, enrichedReadCache, taskState) {
|
|
11310
11461
|
if (typeof content === "string") {
|
|
11311
11462
|
const update = {
|
|
11312
11463
|
sessionUpdate: messageUpdateType(role),
|
|
@@ -11332,7 +11483,8 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, fileContentC
|
|
|
11332
11483
|
registerHooks,
|
|
11333
11484
|
supportsTerminalOutput,
|
|
11334
11485
|
cwd,
|
|
11335
|
-
mcpToolUseResult
|
|
11486
|
+
mcpToolUseResult,
|
|
11487
|
+
taskState
|
|
11336
11488
|
};
|
|
11337
11489
|
const output = [];
|
|
11338
11490
|
for (const chunk of content) {
|
|
@@ -11342,7 +11494,7 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, fileContentC
|
|
|
11342
11494
|
}
|
|
11343
11495
|
return output;
|
|
11344
11496
|
}
|
|
11345
|
-
function streamEventToAcpNotifications(message, sessionId, toolUseCache, toolUseStreamCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, enrichedReadCache) {
|
|
11497
|
+
function streamEventToAcpNotifications(message, sessionId, toolUseCache, toolUseStreamCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, enrichedReadCache, taskState) {
|
|
11346
11498
|
const event = message.event;
|
|
11347
11499
|
switch (event.type) {
|
|
11348
11500
|
case "content_block_start": {
|
|
@@ -11366,7 +11518,8 @@ function streamEventToAcpNotifications(message, sessionId, toolUseCache, toolUse
|
|
|
11366
11518
|
supportsTerminalOutput,
|
|
11367
11519
|
cwd,
|
|
11368
11520
|
void 0,
|
|
11369
|
-
enrichedReadCache
|
|
11521
|
+
enrichedReadCache,
|
|
11522
|
+
taskState
|
|
11370
11523
|
);
|
|
11371
11524
|
}
|
|
11372
11525
|
case "content_block_delta": {
|
|
@@ -11391,12 +11544,18 @@ function streamEventToAcpNotifications(message, sessionId, toolUseCache, toolUse
|
|
|
11391
11544
|
supportsTerminalOutput,
|
|
11392
11545
|
cwd,
|
|
11393
11546
|
void 0,
|
|
11394
|
-
enrichedReadCache
|
|
11547
|
+
enrichedReadCache,
|
|
11548
|
+
taskState
|
|
11395
11549
|
);
|
|
11396
11550
|
}
|
|
11397
11551
|
case "content_block_stop":
|
|
11398
11552
|
toolUseStreamCache.delete(event.index);
|
|
11399
11553
|
return [];
|
|
11554
|
+
// `ping` is a Messages-API keep-alive event that the SDK's
|
|
11555
|
+
// `BetaRawMessageStreamEvent` union doesn't include even though the
|
|
11556
|
+
// wire format emits it; the `as never` cast lets us no-op it here
|
|
11557
|
+
// instead of falling through to `unreachable`.
|
|
11558
|
+
case "ping":
|
|
11400
11559
|
case "message_start":
|
|
11401
11560
|
case "message_delta":
|
|
11402
11561
|
case "message_stop":
|
|
@@ -11467,6 +11626,38 @@ async function handleSystemMessage(message, context) {
|
|
|
11467
11626
|
});
|
|
11468
11627
|
break;
|
|
11469
11628
|
}
|
|
11629
|
+
case "memory_recall": {
|
|
11630
|
+
const isSynthesis = message.mode === "synthesize";
|
|
11631
|
+
if (!isSynthesis && message.memories.length === 0) break;
|
|
11632
|
+
const locations = isSynthesis ? [] : message.memories.map((m) => ({ path: m.path }));
|
|
11633
|
+
const content = isSynthesis ? message.memories.filter(
|
|
11634
|
+
(m) => typeof m.content === "string"
|
|
11635
|
+
).map((m) => ({
|
|
11636
|
+
type: "content",
|
|
11637
|
+
content: { type: "text", text: m.content }
|
|
11638
|
+
})) : [];
|
|
11639
|
+
const count = message.memories.length;
|
|
11640
|
+
const title = isSynthesis ? "Recalled synthesized memory" : `Recalled ${count} ${count === 1 ? "memory" : "memories"}`;
|
|
11641
|
+
await client.sessionUpdate({
|
|
11642
|
+
sessionId: message.session_id,
|
|
11643
|
+
update: {
|
|
11644
|
+
sessionUpdate: "tool_call",
|
|
11645
|
+
toolCallId: message.uuid,
|
|
11646
|
+
title,
|
|
11647
|
+
kind: "read",
|
|
11648
|
+
status: "completed",
|
|
11649
|
+
...locations.length > 0 && { locations },
|
|
11650
|
+
...content.length > 0 && { content },
|
|
11651
|
+
_meta: {
|
|
11652
|
+
claudeCode: {
|
|
11653
|
+
toolName: "memory_recall",
|
|
11654
|
+
toolResponse: { mode: message.mode }
|
|
11655
|
+
}
|
|
11656
|
+
}
|
|
11657
|
+
}
|
|
11658
|
+
});
|
|
11659
|
+
break;
|
|
11660
|
+
}
|
|
11470
11661
|
default:
|
|
11471
11662
|
break;
|
|
11472
11663
|
}
|
|
@@ -11576,7 +11767,8 @@ async function handleStreamEvent(message, context) {
|
|
|
11576
11767
|
context.registerHooks,
|
|
11577
11768
|
context.supportsTerminalOutput,
|
|
11578
11769
|
context.session.cwd,
|
|
11579
|
-
context.enrichedReadCache
|
|
11770
|
+
context.enrichedReadCache,
|
|
11771
|
+
context.session.taskState
|
|
11580
11772
|
)) {
|
|
11581
11773
|
await client.sessionUpdate(notification);
|
|
11582
11774
|
context.session.notificationHistory.push(notification);
|
|
@@ -11588,6 +11780,17 @@ function hasLocalCommandStdout(content) {
|
|
|
11588
11780
|
function hasLocalCommandStderr(content) {
|
|
11589
11781
|
return typeof content === "string" && content.includes("<local-command-stderr>");
|
|
11590
11782
|
}
|
|
11783
|
+
function isSdkLocalCommandMessage(content) {
|
|
11784
|
+
return typeof content === "string" && content.includes("<command-name>") && (content.includes("<local-command-stdout>") || content.includes("<local-command-stderr>"));
|
|
11785
|
+
}
|
|
11786
|
+
var LOCAL_COMMAND_TAG_PATTERN = /<(command-name|command-message|command-args|local-command-stdout|local-command-stderr)>[\s\S]*?<\/\1>/g;
|
|
11787
|
+
function stripMarkerTags(text2) {
|
|
11788
|
+
return text2.replace(LOCAL_COMMAND_TAG_PATTERN, "");
|
|
11789
|
+
}
|
|
11790
|
+
function stripLocalCommandMetadata(content) {
|
|
11791
|
+
const stripped = stripMarkerTags(content);
|
|
11792
|
+
return stripped.trim() === "" ? null : stripped;
|
|
11793
|
+
}
|
|
11591
11794
|
function isLoginRequiredMessage(message) {
|
|
11592
11795
|
return message.type === "assistant" && message.message.model === "<synthetic>" && Array.isArray(message.message.content) && message.message.content.length === 1 && message.message.content[0].type === "text" && message.message.content[0].text?.includes("Please run /login") === true;
|
|
11593
11796
|
}
|
|
@@ -11596,7 +11799,7 @@ function isPlainTextUserMessage(message) {
|
|
|
11596
11799
|
return message.type === "user" && (typeof content === "string" || Array.isArray(content) && content.length === 1 && content[0].type === "text");
|
|
11597
11800
|
}
|
|
11598
11801
|
function shouldSkipUserAssistantMessage(message) {
|
|
11599
|
-
return
|
|
11802
|
+
return isSdkLocalCommandMessage(message.message.content) || isLoginRequiredMessage(message);
|
|
11600
11803
|
}
|
|
11601
11804
|
function logSpecialMessages(message, logger) {
|
|
11602
11805
|
const content = message.message.content;
|
|
@@ -11617,11 +11820,39 @@ function filterMessageContent(content) {
|
|
|
11617
11820
|
}
|
|
11618
11821
|
async function handleUserAssistantMessage(message, context) {
|
|
11619
11822
|
const { session, sessionId, client, toolUseCache, fileContentCache, logger } = context;
|
|
11823
|
+
if (message.message.role === "system") {
|
|
11824
|
+
return {};
|
|
11825
|
+
}
|
|
11620
11826
|
if (shouldSkipUserAssistantMessage(message)) {
|
|
11621
11827
|
logSpecialMessages(message, logger);
|
|
11622
11828
|
if (isLoginRequiredMessage(message)) {
|
|
11623
11829
|
return { shouldStop: true, error: RequestError.authRequired() };
|
|
11624
11830
|
}
|
|
11831
|
+
const rawContent = message.message.content;
|
|
11832
|
+
if (typeof rawContent === "string") {
|
|
11833
|
+
const stripped = stripLocalCommandMetadata(rawContent);
|
|
11834
|
+
if (stripped !== null) {
|
|
11835
|
+
for (const notification of toAcpNotifications(
|
|
11836
|
+
stripped,
|
|
11837
|
+
message.message.role,
|
|
11838
|
+
sessionId,
|
|
11839
|
+
toolUseCache,
|
|
11840
|
+
fileContentCache,
|
|
11841
|
+
client,
|
|
11842
|
+
logger,
|
|
11843
|
+
void 0,
|
|
11844
|
+
context.registerHooks,
|
|
11845
|
+
context.supportsTerminalOutput,
|
|
11846
|
+
session.cwd,
|
|
11847
|
+
void 0,
|
|
11848
|
+
context.enrichedReadCache,
|
|
11849
|
+
session.taskState
|
|
11850
|
+
)) {
|
|
11851
|
+
await client.sessionUpdate(notification);
|
|
11852
|
+
session.notificationHistory.push(notification);
|
|
11853
|
+
}
|
|
11854
|
+
}
|
|
11855
|
+
}
|
|
11625
11856
|
return {};
|
|
11626
11857
|
}
|
|
11627
11858
|
if (isPlainTextUserMessage(message)) {
|
|
@@ -11644,7 +11875,8 @@ async function handleUserAssistantMessage(message, context) {
|
|
|
11644
11875
|
context.supportsTerminalOutput,
|
|
11645
11876
|
session.cwd,
|
|
11646
11877
|
mcpToolUseResult,
|
|
11647
|
-
context.enrichedReadCache
|
|
11878
|
+
context.enrichedReadCache,
|
|
11879
|
+
session.taskState
|
|
11648
11880
|
)) {
|
|
11649
11881
|
await client.sessionUpdate(notification);
|
|
11650
11882
|
session.notificationHistory.push(notification);
|
|
@@ -11840,8 +12072,10 @@ var WEB_TOOLS = /* @__PURE__ */ new Set(["WebSearch", "WebFetch"]);
|
|
|
11840
12072
|
var AGENT_TOOLS = /* @__PURE__ */ new Set([
|
|
11841
12073
|
"Task",
|
|
11842
12074
|
"Agent",
|
|
11843
|
-
"
|
|
11844
|
-
"
|
|
12075
|
+
"TaskCreate",
|
|
12076
|
+
"TaskUpdate",
|
|
12077
|
+
"TaskGet",
|
|
12078
|
+
"TaskList"
|
|
11845
12079
|
]);
|
|
11846
12080
|
var BASE_ALLOWED_TOOLS = [
|
|
11847
12081
|
...READ_TOOLS,
|
|
@@ -11925,8 +12159,8 @@ function buildPermissionOptions(toolName, toolInput, repoRoot, suggestions) {
|
|
|
11925
12159
|
if (toolName === "Task") {
|
|
11926
12160
|
return permissionOptions("Yes, allow all sub-tasks");
|
|
11927
12161
|
}
|
|
11928
|
-
if (toolName === "
|
|
11929
|
-
return permissionOptions("Yes, allow all
|
|
12162
|
+
if (toolName === "TaskCreate" || toolName === "TaskUpdate" || toolName === "TaskGet" || toolName === "TaskList") {
|
|
12163
|
+
return permissionOptions("Yes, allow all task updates");
|
|
11930
12164
|
}
|
|
11931
12165
|
return permissionOptions("Yes, always allow");
|
|
11932
12166
|
}
|
|
@@ -12478,6 +12712,7 @@ async function canUseTool(context) {
|
|
|
12478
12712
|
|
|
12479
12713
|
// src/adapters/claude/session/commands.ts
|
|
12480
12714
|
var UNSUPPORTED_COMMANDS = [
|
|
12715
|
+
"clear",
|
|
12481
12716
|
"context",
|
|
12482
12717
|
"cost",
|
|
12483
12718
|
"keybindings-help",
|
|
@@ -12532,18 +12767,30 @@ function loadUserClaudeJsonMcpServers(cwd, logger, homeDir = os3.homedir()) {
|
|
|
12532
12767
|
const projectScoped = project?.mcpServers && typeof project.mcpServers === "object" ? project.mcpServers : {};
|
|
12533
12768
|
return { ...topLevel, ...projectScoped };
|
|
12534
12769
|
}
|
|
12535
|
-
function parseMcpServers(params) {
|
|
12770
|
+
function parseMcpServers(params, logger) {
|
|
12536
12771
|
const mcpServers = {};
|
|
12537
12772
|
if (!Array.isArray(params.mcpServers)) {
|
|
12538
12773
|
return mcpServers;
|
|
12539
12774
|
}
|
|
12540
12775
|
for (const server of params.mcpServers) {
|
|
12541
12776
|
if ("type" in server) {
|
|
12542
|
-
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
|
|
12777
|
+
if (server.type === "http" || server.type === "sse") {
|
|
12778
|
+
mcpServers[server.name] = {
|
|
12779
|
+
type: server.type,
|
|
12780
|
+
url: server.url,
|
|
12781
|
+
headers: server.headers ? Object.fromEntries(
|
|
12782
|
+
server.headers.map((e) => [
|
|
12783
|
+
e.name,
|
|
12784
|
+
e.value
|
|
12785
|
+
])
|
|
12786
|
+
) : void 0
|
|
12787
|
+
};
|
|
12788
|
+
} else {
|
|
12789
|
+
logger?.warn("parseMcpServers: dropping unsupported MCP server type", {
|
|
12790
|
+
name: server.name,
|
|
12791
|
+
type: server.type
|
|
12792
|
+
});
|
|
12793
|
+
}
|
|
12547
12794
|
} else {
|
|
12548
12795
|
mcpServers[server.name] = {
|
|
12549
12796
|
type: "stdio",
|
|
@@ -12556,12 +12803,43 @@ function parseMcpServers(params) {
|
|
|
12556
12803
|
return mcpServers;
|
|
12557
12804
|
}
|
|
12558
12805
|
|
|
12806
|
+
// src/adapters/claude/session/model-config.ts
|
|
12807
|
+
function applyAvailableModelsAllowlist(modelOptions, allowlist) {
|
|
12808
|
+
const filtered = [];
|
|
12809
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12810
|
+
for (const entry of allowlist) {
|
|
12811
|
+
const trimmed2 = entry.trim();
|
|
12812
|
+
if (!trimmed2 || seen.has(trimmed2)) continue;
|
|
12813
|
+
const match = modelOptions.options.find((o) => o.value === trimmed2);
|
|
12814
|
+
if (match) {
|
|
12815
|
+
filtered.push(match);
|
|
12816
|
+
seen.add(trimmed2);
|
|
12817
|
+
}
|
|
12818
|
+
}
|
|
12819
|
+
if (filtered.length === 0) return modelOptions;
|
|
12820
|
+
const currentModelId = filtered.some(
|
|
12821
|
+
(o) => o.value === modelOptions.currentModelId
|
|
12822
|
+
) ? modelOptions.currentModelId : filtered[0].value;
|
|
12823
|
+
return { currentModelId, options: filtered };
|
|
12824
|
+
}
|
|
12825
|
+
function resolveInitialModelId(modelOptions, preferredModelIds) {
|
|
12826
|
+
const allowedModelIds = new Set(modelOptions.options.map((opt) => opt.value));
|
|
12827
|
+
for (const candidate of preferredModelIds) {
|
|
12828
|
+
const trimmed2 = candidate?.trim();
|
|
12829
|
+
if (trimmed2 && allowedModelIds.has(trimmed2)) {
|
|
12830
|
+
return trimmed2;
|
|
12831
|
+
}
|
|
12832
|
+
}
|
|
12833
|
+
return modelOptions.currentModelId;
|
|
12834
|
+
}
|
|
12835
|
+
|
|
12559
12836
|
// src/adapters/claude/session/models.ts
|
|
12560
12837
|
var DEFAULT_MODEL = "opus";
|
|
12561
12838
|
var GATEWAY_TO_SDK_MODEL = {
|
|
12562
12839
|
"claude-opus-4-5": "opus",
|
|
12563
12840
|
"claude-opus-4-6": "opus",
|
|
12564
12841
|
"claude-opus-4-7": "opus",
|
|
12842
|
+
"claude-opus-4-8": "opus",
|
|
12565
12843
|
"claude-sonnet-4-5": "sonnet",
|
|
12566
12844
|
"claude-sonnet-4-6": "sonnet",
|
|
12567
12845
|
"claude-haiku-4-5": "haiku"
|
|
@@ -12572,6 +12850,7 @@ function toSdkModelId(modelId) {
|
|
|
12572
12850
|
var MODELS_WITH_1M_CONTEXT = /* @__PURE__ */ new Set([
|
|
12573
12851
|
"claude-opus-4-6",
|
|
12574
12852
|
"claude-opus-4-7",
|
|
12853
|
+
"claude-opus-4-8",
|
|
12575
12854
|
"claude-sonnet-4-6"
|
|
12576
12855
|
]);
|
|
12577
12856
|
function supports1MContext(modelId) {
|
|
@@ -12581,11 +12860,13 @@ var MODELS_WITH_EFFORT = /* @__PURE__ */ new Set([
|
|
|
12581
12860
|
"claude-opus-4-5",
|
|
12582
12861
|
"claude-opus-4-6",
|
|
12583
12862
|
"claude-opus-4-7",
|
|
12863
|
+
"claude-opus-4-8",
|
|
12584
12864
|
"claude-sonnet-4-6"
|
|
12585
12865
|
]);
|
|
12586
12866
|
var MODELS_WITH_XHIGH_EFFORT = /* @__PURE__ */ new Set([
|
|
12587
12867
|
"claude-opus-4-6",
|
|
12588
|
-
"claude-opus-4-7"
|
|
12868
|
+
"claude-opus-4-7",
|
|
12869
|
+
"claude-opus-4-8"
|
|
12589
12870
|
]);
|
|
12590
12871
|
function supportsEffort(modelId) {
|
|
12591
12872
|
return MODELS_WITH_EFFORT.has(modelId);
|
|
@@ -12625,6 +12906,19 @@ function tokenizeModelPreference(model) {
|
|
|
12625
12906
|
}).filter((token) => token && token !== "claude").filter((token) => /[a-z]/.test(token) || token.endsWith("m"));
|
|
12626
12907
|
return { tokens, contextHint };
|
|
12627
12908
|
}
|
|
12909
|
+
var MODEL_FAMILY_VERSION_PATTERN = /\b(\d+)[-.](\d+)\b/;
|
|
12910
|
+
function extractModelFamilyVersion(s) {
|
|
12911
|
+
if (!s) return null;
|
|
12912
|
+
const match = s.match(MODEL_FAMILY_VERSION_PATTERN);
|
|
12913
|
+
return match ? `${match[1]}.${match[2]}` : null;
|
|
12914
|
+
}
|
|
12915
|
+
function modelVersionsCompatible(preference, candidate) {
|
|
12916
|
+
const preferred = extractModelFamilyVersion(preference);
|
|
12917
|
+
if (!preferred) return true;
|
|
12918
|
+
const candidateVersion = extractModelFamilyVersion(candidate.value) ?? extractModelFamilyVersion(candidate.name) ?? extractModelFamilyVersion(candidate.description);
|
|
12919
|
+
if (!candidateVersion) return true;
|
|
12920
|
+
return preferred === candidateVersion;
|
|
12921
|
+
}
|
|
12628
12922
|
function scoreModelMatch(model, tokens, contextHint) {
|
|
12629
12923
|
const haystack = `${model.value} ${model.name ?? ""}`.toLowerCase();
|
|
12630
12924
|
let score = 0;
|
|
@@ -12644,6 +12938,7 @@ function resolveModelPreference(preference, options) {
|
|
|
12644
12938
|
);
|
|
12645
12939
|
if (directMatch) return directMatch.value;
|
|
12646
12940
|
const includesMatch = options.find((o) => {
|
|
12941
|
+
if (!modelVersionsCompatible(trimmed2, o)) return false;
|
|
12647
12942
|
const value = o.value.toLowerCase();
|
|
12648
12943
|
const display = (o.name ?? "").toLowerCase();
|
|
12649
12944
|
return value.includes(lower) || display.includes(lower) || lower.includes(value);
|
|
@@ -12654,6 +12949,7 @@ function resolveModelPreference(preference, options) {
|
|
|
12654
12949
|
let bestMatch = null;
|
|
12655
12950
|
let bestScore = 0;
|
|
12656
12951
|
for (const model of options) {
|
|
12952
|
+
if (!modelVersionsCompatible(trimmed2, model)) continue;
|
|
12657
12953
|
const score = scoreModelMatch(model, tokens, contextHint);
|
|
12658
12954
|
if (0 < score && (!bestMatch || bestScore < score)) {
|
|
12659
12955
|
bestMatch = model;
|
|
@@ -12730,6 +13026,7 @@ function buildEnvironment() {
|
|
|
12730
13026
|
const existingCustomHeaders = process.env.ANTHROPIC_CUSTOM_HEADERS;
|
|
12731
13027
|
const customHeaders = existingCustomHeaders ? `${existingCustomHeaders}
|
|
12732
13028
|
${bedrockFallbackHeader}` : bedrockFallbackHeader;
|
|
13029
|
+
const mcpNonblocking = process.env.MCP_CONNECTION_NONBLOCKING;
|
|
12733
13030
|
return {
|
|
12734
13031
|
...process.env,
|
|
12735
13032
|
ELECTRON_RUN_AS_NODE: "1",
|
|
@@ -12738,11 +13035,14 @@ ${bedrockFallbackHeader}` : bedrockFallbackHeader;
|
|
|
12738
13035
|
ENABLE_TOOL_SEARCH: "auto:0",
|
|
12739
13036
|
// Enable idle state as end-of-turn signal (required for SDK 0.2.114+)
|
|
12740
13037
|
CLAUDE_CODE_EMIT_SESSION_STATE_EVENTS: "1",
|
|
13038
|
+
...mcpNonblocking !== void 0 && {
|
|
13039
|
+
MCP_CONNECTION_NONBLOCKING: mcpNonblocking
|
|
13040
|
+
},
|
|
12741
13041
|
// Route to AWS Bedrock as a fallback when Anthropic returns 5xx
|
|
12742
13042
|
ANTHROPIC_CUSTOM_HEADERS: customHeaders
|
|
12743
13043
|
};
|
|
12744
13044
|
}
|
|
12745
|
-
function buildHooks(userHooks, onModeChange, settingsManager, logger, enrichmentDeps, enrichedReadCache, registeredAgents, cloudMode) {
|
|
13045
|
+
function buildHooks(userHooks, onModeChange, settingsManager, logger, enrichmentDeps, enrichedReadCache, registeredAgents, cloudMode, taskState, onTaskStateChange) {
|
|
12746
13046
|
const postToolUseHooks = [createPostToolUseHook({ onModeChange })];
|
|
12747
13047
|
if (enrichmentDeps && enrichedReadCache) {
|
|
12748
13048
|
postToolUseHooks.push(
|
|
@@ -12756,13 +13056,16 @@ function buildHooks(userHooks, onModeChange, settingsManager, logger, enrichment
|
|
|
12756
13056
|
if (cloudMode) {
|
|
12757
13057
|
preToolUseHooks.push(createSignedCommitGuardHook(logger));
|
|
12758
13058
|
}
|
|
13059
|
+
const taskHook = createTaskHook(taskState, onTaskStateChange);
|
|
12759
13060
|
return {
|
|
12760
13061
|
...userHooks,
|
|
12761
13062
|
PostToolUse: [
|
|
12762
13063
|
...userHooks?.PostToolUse || [],
|
|
12763
13064
|
{ hooks: postToolUseHooks }
|
|
12764
13065
|
],
|
|
12765
|
-
PreToolUse: [...userHooks?.PreToolUse || [], { hooks: preToolUseHooks }]
|
|
13066
|
+
PreToolUse: [...userHooks?.PreToolUse || [], { hooks: preToolUseHooks }],
|
|
13067
|
+
TaskCreated: [...userHooks?.TaskCreated || [], { hooks: [taskHook] }],
|
|
13068
|
+
TaskCompleted: [...userHooks?.TaskCompleted || [], { hooks: [taskHook] }]
|
|
12766
13069
|
};
|
|
12767
13070
|
}
|
|
12768
13071
|
var PH_EXPLORE_AGENT = {
|
|
@@ -12793,7 +13096,10 @@ Rules:
|
|
|
12793
13096
|
"WebFetch",
|
|
12794
13097
|
"WebSearch",
|
|
12795
13098
|
"NotebookRead",
|
|
12796
|
-
"
|
|
13099
|
+
"TaskCreate",
|
|
13100
|
+
"TaskUpdate",
|
|
13101
|
+
"TaskGet",
|
|
13102
|
+
"TaskList"
|
|
12797
13103
|
]
|
|
12798
13104
|
};
|
|
12799
13105
|
function buildAgents(userAgents) {
|
|
@@ -12921,7 +13227,9 @@ function buildSessionOptions(params) {
|
|
|
12921
13227
|
params.enrichmentDeps,
|
|
12922
13228
|
params.enrichedReadCache,
|
|
12923
13229
|
registeredAgentNames,
|
|
12924
|
-
params.cloudMode ?? false
|
|
13230
|
+
params.cloudMode ?? false,
|
|
13231
|
+
params.taskState,
|
|
13232
|
+
params.onTaskStateChange
|
|
12925
13233
|
),
|
|
12926
13234
|
outputFormat: params.outputFormat,
|
|
12927
13235
|
abortController: getAbortController(
|
|
@@ -17957,6 +18265,15 @@ function getManagedSettingsPath() {
|
|
|
17957
18265
|
return "/etc/claude-code/managed-settings.json";
|
|
17958
18266
|
}
|
|
17959
18267
|
}
|
|
18268
|
+
function mergeAvailableModels(existing, incoming, layer) {
|
|
18269
|
+
if (incoming === void 0) {
|
|
18270
|
+
return existing;
|
|
18271
|
+
}
|
|
18272
|
+
if (layer === "enterprise") {
|
|
18273
|
+
return Array.from(new Set(incoming));
|
|
18274
|
+
}
|
|
18275
|
+
return Array.from(/* @__PURE__ */ new Set([...existing ?? [], ...incoming]));
|
|
18276
|
+
}
|
|
17960
18277
|
var SettingsManager = class {
|
|
17961
18278
|
cwd;
|
|
17962
18279
|
repoRoot;
|
|
@@ -18012,10 +18329,10 @@ var SettingsManager = class {
|
|
|
18012
18329
|
}
|
|
18013
18330
|
mergeAllSettings() {
|
|
18014
18331
|
const allSettings = [
|
|
18015
|
-
this.userSettings,
|
|
18016
|
-
this.projectSettings,
|
|
18017
|
-
this.localSettings,
|
|
18018
|
-
this.enterpriseSettings
|
|
18332
|
+
{ layer: "user", settings: this.userSettings },
|
|
18333
|
+
{ layer: "project", settings: this.projectSettings },
|
|
18334
|
+
{ layer: "local", settings: this.localSettings },
|
|
18335
|
+
{ layer: "enterprise", settings: this.enterpriseSettings }
|
|
18019
18336
|
];
|
|
18020
18337
|
const permissions = {
|
|
18021
18338
|
allow: [],
|
|
@@ -18024,7 +18341,7 @@ var SettingsManager = class {
|
|
|
18024
18341
|
};
|
|
18025
18342
|
const merged = { permissions };
|
|
18026
18343
|
const posthogApprovedExecTools = /* @__PURE__ */ new Set();
|
|
18027
|
-
for (const settings of allSettings) {
|
|
18344
|
+
for (const { layer, settings } of allSettings) {
|
|
18028
18345
|
if (settings.permissions) {
|
|
18029
18346
|
if (settings.permissions.allow) {
|
|
18030
18347
|
permissions.allow?.push(...settings.permissions.allow);
|
|
@@ -18051,6 +18368,11 @@ var SettingsManager = class {
|
|
|
18051
18368
|
if (settings.model) {
|
|
18052
18369
|
merged.model = settings.model;
|
|
18053
18370
|
}
|
|
18371
|
+
merged.availableModels = mergeAvailableModels(
|
|
18372
|
+
merged.availableModels,
|
|
18373
|
+
settings.availableModels,
|
|
18374
|
+
layer
|
|
18375
|
+
);
|
|
18054
18376
|
if (settings.posthogApprovedExecTools) {
|
|
18055
18377
|
for (const tool2 of settings.posthogApprovedExecTools) {
|
|
18056
18378
|
posthogApprovedExecTools.add(tool2);
|
|
@@ -18259,6 +18581,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18259
18581
|
},
|
|
18260
18582
|
loadSession: true,
|
|
18261
18583
|
sessionCapabilities: {
|
|
18584
|
+
additionalDirectories: {},
|
|
18262
18585
|
list: {},
|
|
18263
18586
|
fork: {},
|
|
18264
18587
|
resume: {}
|
|
@@ -18284,10 +18607,18 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18284
18607
|
if (fs10.existsSync(path14.resolve(os6.homedir(), ".claude.json.backup")) && !fs10.existsSync(path14.resolve(os6.homedir(), ".claude.json"))) {
|
|
18285
18608
|
throw RequestError2.authRequired();
|
|
18286
18609
|
}
|
|
18287
|
-
const response = await this.createSession(
|
|
18288
|
-
|
|
18289
|
-
|
|
18290
|
-
|
|
18610
|
+
const response = await this.createSession(
|
|
18611
|
+
{
|
|
18612
|
+
cwd: params.cwd,
|
|
18613
|
+
mcpServers: params.mcpServers ?? [],
|
|
18614
|
+
additionalDirectories: params.additionalDirectories,
|
|
18615
|
+
_meta: params._meta
|
|
18616
|
+
},
|
|
18617
|
+
{
|
|
18618
|
+
// Revisit these meta values once we support resume
|
|
18619
|
+
resume: params._meta?.claudeCode?.options?.resume
|
|
18620
|
+
}
|
|
18621
|
+
);
|
|
18291
18622
|
return response;
|
|
18292
18623
|
}
|
|
18293
18624
|
async unstable_forkSession(params) {
|
|
@@ -18295,24 +18626,27 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18295
18626
|
{
|
|
18296
18627
|
cwd: params.cwd,
|
|
18297
18628
|
mcpServers: params.mcpServers ?? [],
|
|
18629
|
+
additionalDirectories: params.additionalDirectories,
|
|
18298
18630
|
_meta: params._meta
|
|
18299
18631
|
},
|
|
18300
18632
|
{ resume: params.sessionId, forkSession: true }
|
|
18301
18633
|
);
|
|
18302
18634
|
}
|
|
18303
|
-
async
|
|
18635
|
+
async resumeSession(params) {
|
|
18304
18636
|
const existing = this.getExistingSessionState(params.sessionId);
|
|
18305
18637
|
if (existing) return existing;
|
|
18306
18638
|
const response = await this.createSession(
|
|
18307
18639
|
{
|
|
18308
18640
|
cwd: params.cwd,
|
|
18309
18641
|
mcpServers: params.mcpServers ?? [],
|
|
18642
|
+
additionalDirectories: params.additionalDirectories,
|
|
18310
18643
|
_meta: params._meta
|
|
18311
18644
|
},
|
|
18312
18645
|
{
|
|
18313
18646
|
resume: params.sessionId
|
|
18314
18647
|
}
|
|
18315
18648
|
);
|
|
18649
|
+
await this.rehydrateTaskStateFromJsonl(params.sessionId);
|
|
18316
18650
|
return response;
|
|
18317
18651
|
}
|
|
18318
18652
|
async loadSession(params) {
|
|
@@ -18322,6 +18656,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18322
18656
|
{
|
|
18323
18657
|
cwd: params.cwd,
|
|
18324
18658
|
mcpServers: params.mcpServers ?? [],
|
|
18659
|
+
additionalDirectories: params.additionalDirectories,
|
|
18325
18660
|
_meta: params._meta
|
|
18326
18661
|
},
|
|
18327
18662
|
{ resume: params.sessionId, skipBackgroundFetches: true }
|
|
@@ -18400,6 +18735,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18400
18735
|
await this.broadcastUserMessage(params);
|
|
18401
18736
|
this.session.promptRunning = true;
|
|
18402
18737
|
let handedOff = false;
|
|
18738
|
+
let errored = false;
|
|
18403
18739
|
let lastAssistantTotalUsage = null;
|
|
18404
18740
|
let lastStreamUsage = {
|
|
18405
18741
|
input_tokens: 0,
|
|
@@ -18407,6 +18743,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18407
18743
|
cache_read_input_tokens: 0,
|
|
18408
18744
|
cache_creation_input_tokens: 0
|
|
18409
18745
|
};
|
|
18746
|
+
let compactionInProgress = false;
|
|
18410
18747
|
if (this.session.lastContextWindowSize == null) {
|
|
18411
18748
|
this.session.lastContextWindowSize = this.getContextWindowForModel(
|
|
18412
18749
|
this.session.modelId ?? ""
|
|
@@ -18464,6 +18801,40 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18464
18801
|
if (message.subtype === "local_command_output") {
|
|
18465
18802
|
promptReplayed = true;
|
|
18466
18803
|
}
|
|
18804
|
+
if (message.subtype === "status") {
|
|
18805
|
+
if (message.status === "compacting") {
|
|
18806
|
+
compactionInProgress = true;
|
|
18807
|
+
} else if (message.compact_result === "success" && compactionInProgress) {
|
|
18808
|
+
compactionInProgress = false;
|
|
18809
|
+
await this.client.sessionUpdate({
|
|
18810
|
+
sessionId: params.sessionId,
|
|
18811
|
+
update: {
|
|
18812
|
+
sessionUpdate: "agent_message_chunk",
|
|
18813
|
+
content: {
|
|
18814
|
+
type: "text",
|
|
18815
|
+
text: "\n\nCompacting completed."
|
|
18816
|
+
}
|
|
18817
|
+
}
|
|
18818
|
+
});
|
|
18819
|
+
break;
|
|
18820
|
+
} else if (message.compact_result === "failed" && compactionInProgress) {
|
|
18821
|
+
compactionInProgress = false;
|
|
18822
|
+
const reason = message.compact_error ? `: ${message.compact_error}` : ".";
|
|
18823
|
+
await this.client.sessionUpdate({
|
|
18824
|
+
sessionId: params.sessionId,
|
|
18825
|
+
update: {
|
|
18826
|
+
sessionUpdate: "agent_message_chunk",
|
|
18827
|
+
content: {
|
|
18828
|
+
type: "text",
|
|
18829
|
+
text: `
|
|
18830
|
+
|
|
18831
|
+
Compacting failed${reason}`
|
|
18832
|
+
}
|
|
18833
|
+
}
|
|
18834
|
+
});
|
|
18835
|
+
break;
|
|
18836
|
+
}
|
|
18837
|
+
}
|
|
18467
18838
|
if (message.subtype === "session_state_changed" && message.state === "idle") {
|
|
18468
18839
|
if (!promptReplayed) {
|
|
18469
18840
|
const cmdName = commandMatch?.[1].slice(1);
|
|
@@ -18503,7 +18874,9 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18503
18874
|
size: lastContextWindowSize
|
|
18504
18875
|
}
|
|
18505
18876
|
});
|
|
18506
|
-
return {
|
|
18877
|
+
return {
|
|
18878
|
+
stopReason: this.session.cancelled ? "cancelled" : "end_turn"
|
|
18879
|
+
};
|
|
18507
18880
|
}
|
|
18508
18881
|
await handleSystemMessage(message, context);
|
|
18509
18882
|
break;
|
|
@@ -18686,6 +19059,28 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18686
19059
|
}
|
|
18687
19060
|
throw new Error("Session did not end in result");
|
|
18688
19061
|
} catch (error) {
|
|
19062
|
+
errored = true;
|
|
19063
|
+
try {
|
|
19064
|
+
await this.session.query.interrupt();
|
|
19065
|
+
const MAX_DRAIN = 100;
|
|
19066
|
+
for (let i2 = 0; i2 < MAX_DRAIN; i2++) {
|
|
19067
|
+
const { value: m, done } = await this.session.query.next();
|
|
19068
|
+
if (done || !m) break;
|
|
19069
|
+
if (m.type === "system" && m.subtype === "session_state_changed" && m.state === "idle") {
|
|
19070
|
+
break;
|
|
19071
|
+
}
|
|
19072
|
+
if (i2 === MAX_DRAIN - 1) {
|
|
19073
|
+
this.logger.error(
|
|
19074
|
+
`Session ${params.sessionId}: drained ${MAX_DRAIN} messages after error without observing idle`
|
|
19075
|
+
);
|
|
19076
|
+
}
|
|
19077
|
+
}
|
|
19078
|
+
} catch (drainErr) {
|
|
19079
|
+
this.logger.error(
|
|
19080
|
+
`Session ${params.sessionId}: failed to drain query after prompt error`,
|
|
19081
|
+
{ error: drainErr }
|
|
19082
|
+
);
|
|
19083
|
+
}
|
|
18689
19084
|
if (error instanceof RequestError2 || !(error instanceof Error)) {
|
|
18690
19085
|
throw error;
|
|
18691
19086
|
}
|
|
@@ -18706,9 +19101,19 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18706
19101
|
this.toolUseStreamCache.clear();
|
|
18707
19102
|
if (!handedOff) {
|
|
18708
19103
|
this.session.promptRunning = false;
|
|
18709
|
-
|
|
18710
|
-
pending.
|
|
18711
|
-
|
|
19104
|
+
if (errored) {
|
|
19105
|
+
for (const pending of this.session.pendingMessages.values()) {
|
|
19106
|
+
pending.resolve(true);
|
|
19107
|
+
}
|
|
19108
|
+
this.session.pendingMessages.clear();
|
|
19109
|
+
} else if (this.session.pendingMessages.size > 0) {
|
|
19110
|
+
const next = [...this.session.pendingMessages.entries()].sort(
|
|
19111
|
+
(a, b) => a[1].order - b[1].order
|
|
19112
|
+
)[0];
|
|
19113
|
+
if (next) {
|
|
19114
|
+
next[1].resolve(false);
|
|
19115
|
+
this.session.pendingMessages.delete(next[0]);
|
|
19116
|
+
}
|
|
18712
19117
|
}
|
|
18713
19118
|
}
|
|
18714
19119
|
}
|
|
@@ -18759,7 +19164,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18759
19164
|
);
|
|
18760
19165
|
}
|
|
18761
19166
|
const mcpServers = parseMcpServers(
|
|
18762
|
-
params
|
|
19167
|
+
params,
|
|
19168
|
+
this.logger
|
|
18763
19169
|
);
|
|
18764
19170
|
await this.refreshSession(mcpServers);
|
|
18765
19171
|
return { refreshed: true };
|
|
@@ -18944,7 +19350,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18944
19350
|
const settingsManager = new SettingsManager(cwd);
|
|
18945
19351
|
await settingsManager.initialize();
|
|
18946
19352
|
const earlyModelId = settingsManager.getSettings().model || meta?.model || "";
|
|
18947
|
-
const mcpServers = supportsMcpInjection(earlyModelId) ? parseMcpServers(params) : {};
|
|
19353
|
+
const mcpServers = supportsMcpInjection(earlyModelId) ? parseMcpServers(params, this.logger) : {};
|
|
18948
19354
|
const localToolsServer = createLocalToolsMcpServer(
|
|
18949
19355
|
{ cwd, token: resolveGithubToken(), taskId },
|
|
18950
19356
|
meta
|
|
@@ -18968,6 +19374,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18968
19374
|
cwd
|
|
18969
19375
|
});
|
|
18970
19376
|
const permissionMode = meta?.permissionMode && CODE_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
|
|
19377
|
+
const taskState = /* @__PURE__ */ new Map();
|
|
18971
19378
|
const options = buildSessionOptions({
|
|
18972
19379
|
cwd,
|
|
18973
19380
|
mcpServers,
|
|
@@ -18981,7 +19388,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18981
19388
|
forkSession,
|
|
18982
19389
|
additionalDirectories: [
|
|
18983
19390
|
...meta?.claudeCode?.options?.additionalDirectories ?? [],
|
|
18984
|
-
|
|
19391
|
+
// Prefer the official ACP `additionalDirectories` field. Fall back
|
|
19392
|
+
// to the legacy `_meta.additionalRoots` extension for clients that
|
|
19393
|
+
// haven't been updated yet.
|
|
19394
|
+
...params.additionalDirectories ?? meta?.additionalRoots ?? []
|
|
18985
19395
|
],
|
|
18986
19396
|
disableBuiltInTools: meta?.disableBuiltInTools,
|
|
18987
19397
|
outputFormat,
|
|
@@ -18992,7 +19402,17 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18992
19402
|
effort,
|
|
18993
19403
|
enrichmentDeps: this.enrichment?.deps,
|
|
18994
19404
|
enrichedReadCache: this.enrichedReadCache,
|
|
18995
|
-
cloudMode: cloudRun
|
|
19405
|
+
cloudMode: cloudRun,
|
|
19406
|
+
taskState,
|
|
19407
|
+
onTaskStateChange: async () => {
|
|
19408
|
+
await this.client.sessionUpdate({
|
|
19409
|
+
sessionId,
|
|
19410
|
+
update: {
|
|
19411
|
+
sessionUpdate: "plan",
|
|
19412
|
+
entries: taskStateToPlanEntries(taskState)
|
|
19413
|
+
}
|
|
19414
|
+
});
|
|
19415
|
+
}
|
|
18996
19416
|
});
|
|
18997
19417
|
const abortController = options.abortController;
|
|
18998
19418
|
const q = query({ prompt: input, options });
|
|
@@ -19021,6 +19441,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19021
19441
|
systemPrompt: estimateSystemPrompt(systemPrompt),
|
|
19022
19442
|
rules: estimateRulesTokens(readClaudeMdQuietly(cwd, this.logger))
|
|
19023
19443
|
},
|
|
19444
|
+
taskState,
|
|
19024
19445
|
// Custom properties
|
|
19025
19446
|
cwd,
|
|
19026
19447
|
notificationHistory: [],
|
|
@@ -19060,7 +19481,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19060
19481
|
}
|
|
19061
19482
|
}
|
|
19062
19483
|
const initPromise2 = !isResume ? withTimeout(q.initializationResult(), SESSION_VALIDATION_TIMEOUT_MS) : void 0;
|
|
19063
|
-
const [
|
|
19484
|
+
const [rawModelOptions] = await Promise.all([
|
|
19064
19485
|
this.getModelConfigOptions(
|
|
19065
19486
|
settingsManager.getSettings().model || meta?.model || void 0
|
|
19066
19487
|
),
|
|
@@ -19072,6 +19493,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19072
19493
|
})
|
|
19073
19494
|
] : []
|
|
19074
19495
|
]);
|
|
19496
|
+
const settingsAvailableModels = settingsManager.getSettings().availableModels;
|
|
19497
|
+
const modelOptions = Array.isArray(settingsAvailableModels) ? applyAvailableModelsAllowlist(rawModelOptions, settingsAvailableModels) : rawModelOptions;
|
|
19075
19498
|
if (initPromise2) {
|
|
19076
19499
|
try {
|
|
19077
19500
|
const initResult = await initPromise2;
|
|
@@ -19095,9 +19518,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19095
19518
|
throw err2;
|
|
19096
19519
|
}
|
|
19097
19520
|
}
|
|
19098
|
-
const
|
|
19099
|
-
|
|
19100
|
-
|
|
19521
|
+
const resolvedModelId = resolveInitialModelId(modelOptions, [
|
|
19522
|
+
settingsManager.getSettings().model,
|
|
19523
|
+
meta?.model
|
|
19524
|
+
]);
|
|
19101
19525
|
session.modelId = resolvedModelId;
|
|
19102
19526
|
session.lastContextWindowSize = this.getContextWindowForModel(resolvedModelId);
|
|
19103
19527
|
const resolvedSdkModel = toSdkModelId(resolvedModelId);
|
|
@@ -19305,6 +19729,34 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19305
19729
|
[key]: tokens
|
|
19306
19730
|
};
|
|
19307
19731
|
}
|
|
19732
|
+
/**
|
|
19733
|
+
* Rebuild the in-memory taskState from JSONL and push a plan update so the
|
|
19734
|
+
* client's plan panel reflects pre-resume tasks. `loadSession` already covers
|
|
19735
|
+
* this via the full `replaySessionHistory` notification stream; resume
|
|
19736
|
+
* deliberately stays quiet (the client keeps its own message history) so we
|
|
19737
|
+
* walk the transcript here for state only.
|
|
19738
|
+
*/
|
|
19739
|
+
async rehydrateTaskStateFromJsonl(sessionId) {
|
|
19740
|
+
try {
|
|
19741
|
+
const messages = await getSessionMessages(sessionId, {
|
|
19742
|
+
dir: this.session.cwd
|
|
19743
|
+
});
|
|
19744
|
+
rehydrateTaskState(messages, this.session.taskState);
|
|
19745
|
+
if (this.session.taskState.size === 0) return;
|
|
19746
|
+
await this.client.sessionUpdate({
|
|
19747
|
+
sessionId,
|
|
19748
|
+
update: {
|
|
19749
|
+
sessionUpdate: "plan",
|
|
19750
|
+
entries: taskStateToPlanEntries(this.session.taskState)
|
|
19751
|
+
}
|
|
19752
|
+
});
|
|
19753
|
+
} catch (err2) {
|
|
19754
|
+
this.logger.warn("Failed to rehydrate task state", {
|
|
19755
|
+
sessionId,
|
|
19756
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
19757
|
+
});
|
|
19758
|
+
}
|
|
19759
|
+
}
|
|
19308
19760
|
async replaySessionHistory(sessionId) {
|
|
19309
19761
|
try {
|
|
19310
19762
|
const messages = await getSessionMessages(sessionId, {
|
|
@@ -20095,7 +20547,7 @@ var CodexAcpAgent = class extends BaseAcpAgent {
|
|
|
20095
20547
|
}
|
|
20096
20548
|
return response;
|
|
20097
20549
|
}
|
|
20098
|
-
async
|
|
20550
|
+
async resumeSession(params) {
|
|
20099
20551
|
const meta = params._meta;
|
|
20100
20552
|
const injectedParams = this.applyLocalTools(
|
|
20101
20553
|
this.applyStructuredOutput(
|