@posthog/agent 2.3.727 → 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 +544 -74
- 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 +544 -74
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +544 -74
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +4 -4
- package/src/adapters/claude/UPSTREAM.md +81 -3
- package/src/adapters/claude/claude-agent.slash-command.test.ts +22 -2
- package/src/adapters/claude/claude-agent.ts +232 -19
- 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 +15 -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/server/bin.cjs
CHANGED
|
@@ -4433,6 +4433,7 @@ var GATEWAY_TO_SDK_MODEL = {
|
|
|
4433
4433
|
"claude-opus-4-5": "opus",
|
|
4434
4434
|
"claude-opus-4-6": "opus",
|
|
4435
4435
|
"claude-opus-4-7": "opus",
|
|
4436
|
+
"claude-opus-4-8": "opus",
|
|
4436
4437
|
"claude-sonnet-4-5": "sonnet",
|
|
4437
4438
|
"claude-sonnet-4-6": "sonnet",
|
|
4438
4439
|
"claude-haiku-4-5": "haiku"
|
|
@@ -4443,6 +4444,7 @@ function toSdkModelId(modelId) {
|
|
|
4443
4444
|
var MODELS_WITH_1M_CONTEXT = /* @__PURE__ */ new Set([
|
|
4444
4445
|
"claude-opus-4-6",
|
|
4445
4446
|
"claude-opus-4-7",
|
|
4447
|
+
"claude-opus-4-8",
|
|
4446
4448
|
"claude-sonnet-4-6"
|
|
4447
4449
|
]);
|
|
4448
4450
|
function supports1MContext(modelId) {
|
|
@@ -4452,11 +4454,13 @@ var MODELS_WITH_EFFORT = /* @__PURE__ */ new Set([
|
|
|
4452
4454
|
"claude-opus-4-5",
|
|
4453
4455
|
"claude-opus-4-6",
|
|
4454
4456
|
"claude-opus-4-7",
|
|
4457
|
+
"claude-opus-4-8",
|
|
4455
4458
|
"claude-sonnet-4-6"
|
|
4456
4459
|
]);
|
|
4457
4460
|
var MODELS_WITH_XHIGH_EFFORT = /* @__PURE__ */ new Set([
|
|
4458
4461
|
"claude-opus-4-6",
|
|
4459
|
-
"claude-opus-4-7"
|
|
4462
|
+
"claude-opus-4-7",
|
|
4463
|
+
"claude-opus-4-8"
|
|
4460
4464
|
]);
|
|
4461
4465
|
function supportsEffort(modelId) {
|
|
4462
4466
|
return MODELS_WITH_EFFORT.has(modelId);
|
|
@@ -4496,6 +4500,19 @@ function tokenizeModelPreference(model) {
|
|
|
4496
4500
|
}).filter((token) => token && token !== "claude").filter((token) => /[a-z]/.test(token) || token.endsWith("m"));
|
|
4497
4501
|
return { tokens, contextHint };
|
|
4498
4502
|
}
|
|
4503
|
+
var MODEL_FAMILY_VERSION_PATTERN = /\b(\d+)[-.](\d+)\b/;
|
|
4504
|
+
function extractModelFamilyVersion(s) {
|
|
4505
|
+
if (!s) return null;
|
|
4506
|
+
const match = s.match(MODEL_FAMILY_VERSION_PATTERN);
|
|
4507
|
+
return match ? `${match[1]}.${match[2]}` : null;
|
|
4508
|
+
}
|
|
4509
|
+
function modelVersionsCompatible(preference, candidate) {
|
|
4510
|
+
const preferred = extractModelFamilyVersion(preference);
|
|
4511
|
+
if (!preferred) return true;
|
|
4512
|
+
const candidateVersion = extractModelFamilyVersion(candidate.value) ?? extractModelFamilyVersion(candidate.name) ?? extractModelFamilyVersion(candidate.description);
|
|
4513
|
+
if (!candidateVersion) return true;
|
|
4514
|
+
return preferred === candidateVersion;
|
|
4515
|
+
}
|
|
4499
4516
|
function scoreModelMatch(model, tokens, contextHint) {
|
|
4500
4517
|
const haystack = `${model.value} ${model.name ?? ""}`.toLowerCase();
|
|
4501
4518
|
let score = 0;
|
|
@@ -4515,6 +4532,7 @@ function resolveModelPreference(preference, options) {
|
|
|
4515
4532
|
);
|
|
4516
4533
|
if (directMatch) return directMatch.value;
|
|
4517
4534
|
const includesMatch = options.find((o) => {
|
|
4535
|
+
if (!modelVersionsCompatible(trimmed2, o)) return false;
|
|
4518
4536
|
const value = o.value.toLowerCase();
|
|
4519
4537
|
const display = (o.name ?? "").toLowerCase();
|
|
4520
4538
|
return value.includes(lower) || display.includes(lower) || lower.includes(value);
|
|
@@ -4525,6 +4543,7 @@ function resolveModelPreference(preference, options) {
|
|
|
4525
4543
|
let bestMatch = null;
|
|
4526
4544
|
let bestScore = 0;
|
|
4527
4545
|
for (const model of options) {
|
|
4546
|
+
if (!modelVersionsCompatible(trimmed2, model)) continue;
|
|
4528
4547
|
const score = scoreModelMatch(model, tokens, contextHint);
|
|
4529
4548
|
if (0 < score && (!bestMatch || bestScore < score)) {
|
|
4530
4549
|
bestMatch = model;
|
|
@@ -9471,7 +9490,7 @@ var import_zod4 = require("zod");
|
|
|
9471
9490
|
// package.json
|
|
9472
9491
|
var package_default = {
|
|
9473
9492
|
name: "@posthog/agent",
|
|
9474
|
-
version: "2.3.
|
|
9493
|
+
version: "2.3.736",
|
|
9475
9494
|
repository: "https://github.com/PostHog/code",
|
|
9476
9495
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
9477
9496
|
exports: {
|
|
@@ -9591,9 +9610,9 @@ var package_default = {
|
|
|
9591
9610
|
vitest: "^2.1.8"
|
|
9592
9611
|
},
|
|
9593
9612
|
dependencies: {
|
|
9594
|
-
"@agentclientprotocol/sdk": "0.
|
|
9595
|
-
"@anthropic-ai/claude-agent-sdk": "0.
|
|
9596
|
-
"@anthropic-ai/sdk": "0.
|
|
9613
|
+
"@agentclientprotocol/sdk": "0.22.1",
|
|
9614
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.154",
|
|
9615
|
+
"@anthropic-ai/sdk": "0.100.0",
|
|
9597
9616
|
"@hono/node-server": "^1.19.9",
|
|
9598
9617
|
"@opentelemetry/api-logs": "^0.208.0",
|
|
9599
9618
|
"@opentelemetry/exporter-logs-otlp-http": "^0.208.0",
|
|
@@ -15308,6 +15327,30 @@ var registerHookCallback = (toolUseID, {
|
|
|
15308
15327
|
onPostToolUseHook
|
|
15309
15328
|
};
|
|
15310
15329
|
};
|
|
15330
|
+
var createTaskHook = (taskState, onChange) => async (input) => {
|
|
15331
|
+
const taskId = "task_id" in input && typeof input.task_id === "string" ? input.task_id : void 0;
|
|
15332
|
+
if (!taskId) return { continue: true };
|
|
15333
|
+
let mutated = false;
|
|
15334
|
+
if (input.hook_event_name === "TaskCreated") {
|
|
15335
|
+
if (!input.task_subject) return { continue: true };
|
|
15336
|
+
if (taskState.has(taskId)) return { continue: true };
|
|
15337
|
+
taskState.set(taskId, {
|
|
15338
|
+
subject: input.task_subject,
|
|
15339
|
+
status: "pending",
|
|
15340
|
+
description: input.task_description
|
|
15341
|
+
});
|
|
15342
|
+
mutated = true;
|
|
15343
|
+
} else if (input.hook_event_name === "TaskCompleted") {
|
|
15344
|
+
const existing = taskState.get(taskId);
|
|
15345
|
+
if (!existing || existing.status === "completed") {
|
|
15346
|
+
return { continue: true };
|
|
15347
|
+
}
|
|
15348
|
+
taskState.set(taskId, { ...existing, status: "completed" });
|
|
15349
|
+
mutated = true;
|
|
15350
|
+
}
|
|
15351
|
+
if (mutated && onChange) await onChange();
|
|
15352
|
+
return { continue: true };
|
|
15353
|
+
};
|
|
15311
15354
|
var createPostToolUseHook = ({ onModeChange }) => async (input, toolUseID) => {
|
|
15312
15355
|
if (input.hook_event_name === "PostToolUse") {
|
|
15313
15356
|
const toolName = input.tool_name;
|
|
@@ -15322,10 +15365,8 @@ var createPostToolUseHook = ({ onModeChange }) => async (input, toolUseID) => {
|
|
|
15322
15365
|
input.tool_input,
|
|
15323
15366
|
input.tool_response
|
|
15324
15367
|
);
|
|
15325
|
-
delete toolUseCallbacks[toolUseID];
|
|
15326
|
-
} else {
|
|
15327
|
-
delete toolUseCallbacks[toolUseID];
|
|
15328
15368
|
}
|
|
15369
|
+
delete toolUseCallbacks[toolUseID];
|
|
15329
15370
|
}
|
|
15330
15371
|
}
|
|
15331
15372
|
return { continue: true };
|
|
@@ -15472,6 +15513,104 @@ var createPreToolUseHook = (settingsManager, logger) => async (input, _toolUseID
|
|
|
15472
15513
|
}
|
|
15473
15514
|
};
|
|
15474
15515
|
|
|
15516
|
+
// src/adapters/claude/conversion/task-state.ts
|
|
15517
|
+
function parseTaskCreateOutput(content) {
|
|
15518
|
+
const tryParse = (text2) => {
|
|
15519
|
+
try {
|
|
15520
|
+
const parsed = JSON.parse(text2);
|
|
15521
|
+
if (parsed && typeof parsed === "object" && parsed.task && typeof parsed.task.id === "string") {
|
|
15522
|
+
return parsed;
|
|
15523
|
+
}
|
|
15524
|
+
} catch {
|
|
15525
|
+
}
|
|
15526
|
+
return void 0;
|
|
15527
|
+
};
|
|
15528
|
+
if (typeof content === "string") {
|
|
15529
|
+
return tryParse(content);
|
|
15530
|
+
}
|
|
15531
|
+
if (Array.isArray(content)) {
|
|
15532
|
+
for (const block of content) {
|
|
15533
|
+
if (block && typeof block === "object" && "type" in block && block.type === "text") {
|
|
15534
|
+
const text2 = block.text;
|
|
15535
|
+
if (typeof text2 === "string") {
|
|
15536
|
+
const parsed = tryParse(text2);
|
|
15537
|
+
if (parsed) return parsed;
|
|
15538
|
+
}
|
|
15539
|
+
}
|
|
15540
|
+
}
|
|
15541
|
+
}
|
|
15542
|
+
return void 0;
|
|
15543
|
+
}
|
|
15544
|
+
function applyTaskCreate(state, input, output) {
|
|
15545
|
+
const taskId = output?.task?.id;
|
|
15546
|
+
if (!taskId || !input) return;
|
|
15547
|
+
state.set(taskId, {
|
|
15548
|
+
subject: input.subject,
|
|
15549
|
+
status: "pending",
|
|
15550
|
+
activeForm: input.activeForm,
|
|
15551
|
+
description: input.description
|
|
15552
|
+
});
|
|
15553
|
+
}
|
|
15554
|
+
function applyTaskUpdate(state, input) {
|
|
15555
|
+
if (!input?.taskId) return;
|
|
15556
|
+
if (input.status === "deleted") {
|
|
15557
|
+
state.delete(input.taskId);
|
|
15558
|
+
return;
|
|
15559
|
+
}
|
|
15560
|
+
const existing = state.get(input.taskId);
|
|
15561
|
+
const subject = input.subject ?? existing?.subject;
|
|
15562
|
+
if (!subject) return;
|
|
15563
|
+
state.set(input.taskId, {
|
|
15564
|
+
subject,
|
|
15565
|
+
status: input.status ?? existing?.status ?? "pending",
|
|
15566
|
+
activeForm: input.activeForm ?? existing?.activeForm,
|
|
15567
|
+
description: input.description ?? existing?.description
|
|
15568
|
+
});
|
|
15569
|
+
}
|
|
15570
|
+
function taskStateToPlanEntries(state) {
|
|
15571
|
+
return Array.from(state.values()).map((task) => ({
|
|
15572
|
+
content: task.subject,
|
|
15573
|
+
status: task.status,
|
|
15574
|
+
priority: "medium"
|
|
15575
|
+
}));
|
|
15576
|
+
}
|
|
15577
|
+
function isToolUseBlock(block) {
|
|
15578
|
+
return !!block && typeof block === "object" && block.type === "tool_use" && typeof block.id === "string" && typeof block.name === "string";
|
|
15579
|
+
}
|
|
15580
|
+
function isToolResultBlock(block) {
|
|
15581
|
+
return !!block && typeof block === "object" && block.type === "tool_result" && typeof block.tool_use_id === "string";
|
|
15582
|
+
}
|
|
15583
|
+
function rehydrateTaskState(messages, state) {
|
|
15584
|
+
const pendingInputs = /* @__PURE__ */ new Map();
|
|
15585
|
+
for (const msg of messages) {
|
|
15586
|
+
const content = msg.message?.content;
|
|
15587
|
+
if (!Array.isArray(content)) continue;
|
|
15588
|
+
if (msg.type === "assistant") {
|
|
15589
|
+
for (const block of content) {
|
|
15590
|
+
if (isToolUseBlock(block) && (block.name === "TaskCreate" || block.name === "TaskUpdate")) {
|
|
15591
|
+
pendingInputs.set(block.id, { name: block.name, input: block.input });
|
|
15592
|
+
}
|
|
15593
|
+
}
|
|
15594
|
+
} else if (msg.type === "user") {
|
|
15595
|
+
for (const block of content) {
|
|
15596
|
+
if (!isToolResultBlock(block) || block.is_error) continue;
|
|
15597
|
+
const cached = pendingInputs.get(block.tool_use_id);
|
|
15598
|
+
if (!cached) continue;
|
|
15599
|
+
if (cached.name === "TaskCreate") {
|
|
15600
|
+
applyTaskCreate(
|
|
15601
|
+
state,
|
|
15602
|
+
cached.input,
|
|
15603
|
+
parseTaskCreateOutput(block.content)
|
|
15604
|
+
);
|
|
15605
|
+
} else if (cached.name === "TaskUpdate") {
|
|
15606
|
+
applyTaskUpdate(state, cached.input);
|
|
15607
|
+
}
|
|
15608
|
+
pendingInputs.delete(block.tool_use_id);
|
|
15609
|
+
}
|
|
15610
|
+
}
|
|
15611
|
+
}
|
|
15612
|
+
}
|
|
15613
|
+
|
|
15475
15614
|
// src/adapters/claude/conversion/tool-use-to-acp.ts
|
|
15476
15615
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
15477
15616
|
var import_node_path3 = __toESM(require("path"), 1);
|
|
@@ -15823,9 +15962,31 @@ function toolInfoFromToolUse(toolUse, options) {
|
|
|
15823
15962
|
content: []
|
|
15824
15963
|
};
|
|
15825
15964
|
}
|
|
15826
|
-
case "
|
|
15965
|
+
case "TaskCreate": {
|
|
15966
|
+
const subject = typeof input?.subject === "string" ? input.subject : void 0;
|
|
15967
|
+
return {
|
|
15968
|
+
title: subject ? `Create task: ${subject}` : "Create task",
|
|
15969
|
+
kind: "think",
|
|
15970
|
+
content: []
|
|
15971
|
+
};
|
|
15972
|
+
}
|
|
15973
|
+
case "TaskUpdate": {
|
|
15974
|
+
const subject = typeof input?.subject === "string" ? input.subject : void 0;
|
|
15975
|
+
return {
|
|
15976
|
+
title: subject ? `Update task: ${subject}` : "Update task",
|
|
15977
|
+
kind: "think",
|
|
15978
|
+
content: []
|
|
15979
|
+
};
|
|
15980
|
+
}
|
|
15981
|
+
case "TaskList":
|
|
15982
|
+
return {
|
|
15983
|
+
title: "List tasks",
|
|
15984
|
+
kind: "think",
|
|
15985
|
+
content: []
|
|
15986
|
+
};
|
|
15987
|
+
case "TaskGet":
|
|
15827
15988
|
return {
|
|
15828
|
-
title:
|
|
15989
|
+
title: "Get task",
|
|
15829
15990
|
kind: "think",
|
|
15830
15991
|
content: []
|
|
15831
15992
|
};
|
|
@@ -16109,13 +16270,6 @@ ${content}
|
|
|
16109
16270
|
}
|
|
16110
16271
|
return {};
|
|
16111
16272
|
}
|
|
16112
|
-
function planEntries(input) {
|
|
16113
|
-
return input.todos.map((input2) => ({
|
|
16114
|
-
content: input2.content,
|
|
16115
|
-
status: input2.status,
|
|
16116
|
-
priority: "medium"
|
|
16117
|
-
}));
|
|
16118
|
-
}
|
|
16119
16273
|
function resolveFileContent(filePath, oldText, cachedFileContent) {
|
|
16120
16274
|
if (cachedFileContent && filePath in cachedFileContent) {
|
|
16121
16275
|
const cached = cachedFileContent[filePath];
|
|
@@ -16201,14 +16355,7 @@ function handleThinkingChunk(chunk, parentToolCallId) {
|
|
|
16201
16355
|
function handleToolUseChunk(chunk, ctx) {
|
|
16202
16356
|
const alreadyCached = chunk.id in ctx.toolUseCache;
|
|
16203
16357
|
ctx.toolUseCache[chunk.id] = chunk;
|
|
16204
|
-
if (chunk.name === "
|
|
16205
|
-
const input = chunk.input;
|
|
16206
|
-
if (Array.isArray(input.todos)) {
|
|
16207
|
-
return {
|
|
16208
|
-
sessionUpdate: "plan",
|
|
16209
|
-
entries: planEntries(chunk.input)
|
|
16210
|
-
};
|
|
16211
|
-
}
|
|
16358
|
+
if (chunk.name === "TaskCreate" || chunk.name === "TaskUpdate" || chunk.name === "TaskList" || chunk.name === "TaskGet") {
|
|
16212
16359
|
return null;
|
|
16213
16360
|
}
|
|
16214
16361
|
if (!alreadyCached && ctx.registerHooks !== false) {
|
|
@@ -16216,7 +16363,7 @@ function handleToolUseChunk(chunk, ctx) {
|
|
|
16216
16363
|
onPostToolUseHook: async (toolUseId, _toolInput, toolResponse) => {
|
|
16217
16364
|
const toolUse = ctx.toolUseCache[toolUseId];
|
|
16218
16365
|
if (toolUse) {
|
|
16219
|
-
const editUpdate = toolUse.name === "Edit" ? toolUpdateFromEditToolResponse(toolResponse) : null;
|
|
16366
|
+
const editUpdate = toolUse.name === "Edit" || toolUse.name === "Write" ? toolUpdateFromEditToolResponse(toolResponse) : null;
|
|
16220
16367
|
await ctx.client.sessionUpdate({
|
|
16221
16368
|
sessionId: ctx.sessionId,
|
|
16222
16369
|
update: {
|
|
@@ -16328,7 +16475,28 @@ function handleToolResultChunk(chunk, ctx) {
|
|
|
16328
16475
|
);
|
|
16329
16476
|
return [];
|
|
16330
16477
|
}
|
|
16331
|
-
if (toolUse.name === "
|
|
16478
|
+
if (toolUse.name === "TaskCreate" || toolUse.name === "TaskUpdate" || toolUse.name === "TaskList" || toolUse.name === "TaskGet") {
|
|
16479
|
+
if (chunk.is_error || !ctx.taskState) return [];
|
|
16480
|
+
if (toolUse.name === "TaskCreate") {
|
|
16481
|
+
applyTaskCreate(
|
|
16482
|
+
ctx.taskState,
|
|
16483
|
+
toolUse.input,
|
|
16484
|
+
parseTaskCreateOutput(chunk.content)
|
|
16485
|
+
);
|
|
16486
|
+
} else if (toolUse.name === "TaskUpdate") {
|
|
16487
|
+
applyTaskUpdate(
|
|
16488
|
+
ctx.taskState,
|
|
16489
|
+
toolUse.input
|
|
16490
|
+
);
|
|
16491
|
+
}
|
|
16492
|
+
if (toolUse.name === "TaskCreate" || toolUse.name === "TaskUpdate") {
|
|
16493
|
+
return [
|
|
16494
|
+
{
|
|
16495
|
+
sessionUpdate: "plan",
|
|
16496
|
+
entries: taskStateToPlanEntries(ctx.taskState)
|
|
16497
|
+
}
|
|
16498
|
+
];
|
|
16499
|
+
}
|
|
16332
16500
|
return [];
|
|
16333
16501
|
}
|
|
16334
16502
|
if (!chunk.is_error) {
|
|
@@ -16425,13 +16593,15 @@ function processContentChunk(chunk, role, ctx) {
|
|
|
16425
16593
|
case "container_upload":
|
|
16426
16594
|
case "compaction":
|
|
16427
16595
|
case "compaction_delta":
|
|
16596
|
+
case "advisor_tool_result":
|
|
16597
|
+
case "mid_conv_system":
|
|
16428
16598
|
return [];
|
|
16429
16599
|
default:
|
|
16430
16600
|
unreachable(chunk, ctx.logger);
|
|
16431
16601
|
return [];
|
|
16432
16602
|
}
|
|
16433
16603
|
}
|
|
16434
|
-
function toAcpNotifications(content, role, sessionId, toolUseCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, mcpToolUseResult, enrichedReadCache) {
|
|
16604
|
+
function toAcpNotifications(content, role, sessionId, toolUseCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, mcpToolUseResult, enrichedReadCache, taskState) {
|
|
16435
16605
|
if (typeof content === "string") {
|
|
16436
16606
|
const update = {
|
|
16437
16607
|
sessionUpdate: messageUpdateType(role),
|
|
@@ -16457,7 +16627,8 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, fileContentC
|
|
|
16457
16627
|
registerHooks,
|
|
16458
16628
|
supportsTerminalOutput,
|
|
16459
16629
|
cwd,
|
|
16460
|
-
mcpToolUseResult
|
|
16630
|
+
mcpToolUseResult,
|
|
16631
|
+
taskState
|
|
16461
16632
|
};
|
|
16462
16633
|
const output = [];
|
|
16463
16634
|
for (const chunk of content) {
|
|
@@ -16467,7 +16638,7 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, fileContentC
|
|
|
16467
16638
|
}
|
|
16468
16639
|
return output;
|
|
16469
16640
|
}
|
|
16470
|
-
function streamEventToAcpNotifications(message, sessionId, toolUseCache, toolUseStreamCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, enrichedReadCache) {
|
|
16641
|
+
function streamEventToAcpNotifications(message, sessionId, toolUseCache, toolUseStreamCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, enrichedReadCache, taskState) {
|
|
16471
16642
|
const event = message.event;
|
|
16472
16643
|
switch (event.type) {
|
|
16473
16644
|
case "content_block_start": {
|
|
@@ -16491,7 +16662,8 @@ function streamEventToAcpNotifications(message, sessionId, toolUseCache, toolUse
|
|
|
16491
16662
|
supportsTerminalOutput,
|
|
16492
16663
|
cwd,
|
|
16493
16664
|
void 0,
|
|
16494
|
-
enrichedReadCache
|
|
16665
|
+
enrichedReadCache,
|
|
16666
|
+
taskState
|
|
16495
16667
|
);
|
|
16496
16668
|
}
|
|
16497
16669
|
case "content_block_delta": {
|
|
@@ -16516,12 +16688,18 @@ function streamEventToAcpNotifications(message, sessionId, toolUseCache, toolUse
|
|
|
16516
16688
|
supportsTerminalOutput,
|
|
16517
16689
|
cwd,
|
|
16518
16690
|
void 0,
|
|
16519
|
-
enrichedReadCache
|
|
16691
|
+
enrichedReadCache,
|
|
16692
|
+
taskState
|
|
16520
16693
|
);
|
|
16521
16694
|
}
|
|
16522
16695
|
case "content_block_stop":
|
|
16523
16696
|
toolUseStreamCache.delete(event.index);
|
|
16524
16697
|
return [];
|
|
16698
|
+
// `ping` is a Messages-API keep-alive event that the SDK's
|
|
16699
|
+
// `BetaRawMessageStreamEvent` union doesn't include even though the
|
|
16700
|
+
// wire format emits it; the `as never` cast lets us no-op it here
|
|
16701
|
+
// instead of falling through to `unreachable`.
|
|
16702
|
+
case "ping":
|
|
16525
16703
|
case "message_start":
|
|
16526
16704
|
case "message_delta":
|
|
16527
16705
|
case "message_stop":
|
|
@@ -16592,6 +16770,38 @@ async function handleSystemMessage(message, context) {
|
|
|
16592
16770
|
});
|
|
16593
16771
|
break;
|
|
16594
16772
|
}
|
|
16773
|
+
case "memory_recall": {
|
|
16774
|
+
const isSynthesis = message.mode === "synthesize";
|
|
16775
|
+
if (!isSynthesis && message.memories.length === 0) break;
|
|
16776
|
+
const locations = isSynthesis ? [] : message.memories.map((m) => ({ path: m.path }));
|
|
16777
|
+
const content = isSynthesis ? message.memories.filter(
|
|
16778
|
+
(m) => typeof m.content === "string"
|
|
16779
|
+
).map((m) => ({
|
|
16780
|
+
type: "content",
|
|
16781
|
+
content: { type: "text", text: m.content }
|
|
16782
|
+
})) : [];
|
|
16783
|
+
const count = message.memories.length;
|
|
16784
|
+
const title = isSynthesis ? "Recalled synthesized memory" : `Recalled ${count} ${count === 1 ? "memory" : "memories"}`;
|
|
16785
|
+
await client.sessionUpdate({
|
|
16786
|
+
sessionId: message.session_id,
|
|
16787
|
+
update: {
|
|
16788
|
+
sessionUpdate: "tool_call",
|
|
16789
|
+
toolCallId: message.uuid,
|
|
16790
|
+
title,
|
|
16791
|
+
kind: "read",
|
|
16792
|
+
status: "completed",
|
|
16793
|
+
...locations.length > 0 && { locations },
|
|
16794
|
+
...content.length > 0 && { content },
|
|
16795
|
+
_meta: {
|
|
16796
|
+
claudeCode: {
|
|
16797
|
+
toolName: "memory_recall",
|
|
16798
|
+
toolResponse: { mode: message.mode }
|
|
16799
|
+
}
|
|
16800
|
+
}
|
|
16801
|
+
}
|
|
16802
|
+
});
|
|
16803
|
+
break;
|
|
16804
|
+
}
|
|
16595
16805
|
default:
|
|
16596
16806
|
break;
|
|
16597
16807
|
}
|
|
@@ -16701,7 +16911,8 @@ async function handleStreamEvent(message, context) {
|
|
|
16701
16911
|
context.registerHooks,
|
|
16702
16912
|
context.supportsTerminalOutput,
|
|
16703
16913
|
context.session.cwd,
|
|
16704
|
-
context.enrichedReadCache
|
|
16914
|
+
context.enrichedReadCache,
|
|
16915
|
+
context.session.taskState
|
|
16705
16916
|
)) {
|
|
16706
16917
|
await client.sessionUpdate(notification);
|
|
16707
16918
|
context.session.notificationHistory.push(notification);
|
|
@@ -16713,6 +16924,17 @@ function hasLocalCommandStdout(content) {
|
|
|
16713
16924
|
function hasLocalCommandStderr(content) {
|
|
16714
16925
|
return typeof content === "string" && content.includes("<local-command-stderr>");
|
|
16715
16926
|
}
|
|
16927
|
+
function isSdkLocalCommandMessage(content) {
|
|
16928
|
+
return typeof content === "string" && content.includes("<command-name>") && (content.includes("<local-command-stdout>") || content.includes("<local-command-stderr>"));
|
|
16929
|
+
}
|
|
16930
|
+
var LOCAL_COMMAND_TAG_PATTERN = /<(command-name|command-message|command-args|local-command-stdout|local-command-stderr)>[\s\S]*?<\/\1>/g;
|
|
16931
|
+
function stripMarkerTags(text2) {
|
|
16932
|
+
return text2.replace(LOCAL_COMMAND_TAG_PATTERN, "");
|
|
16933
|
+
}
|
|
16934
|
+
function stripLocalCommandMetadata(content) {
|
|
16935
|
+
const stripped = stripMarkerTags(content);
|
|
16936
|
+
return stripped.trim() === "" ? null : stripped;
|
|
16937
|
+
}
|
|
16716
16938
|
function isLoginRequiredMessage(message) {
|
|
16717
16939
|
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;
|
|
16718
16940
|
}
|
|
@@ -16721,7 +16943,7 @@ function isPlainTextUserMessage(message) {
|
|
|
16721
16943
|
return message.type === "user" && (typeof content === "string" || Array.isArray(content) && content.length === 1 && content[0].type === "text");
|
|
16722
16944
|
}
|
|
16723
16945
|
function shouldSkipUserAssistantMessage(message) {
|
|
16724
|
-
return
|
|
16946
|
+
return isSdkLocalCommandMessage(message.message.content) || isLoginRequiredMessage(message);
|
|
16725
16947
|
}
|
|
16726
16948
|
function logSpecialMessages(message, logger) {
|
|
16727
16949
|
const content = message.message.content;
|
|
@@ -16742,11 +16964,39 @@ function filterMessageContent(content) {
|
|
|
16742
16964
|
}
|
|
16743
16965
|
async function handleUserAssistantMessage(message, context) {
|
|
16744
16966
|
const { session, sessionId, client, toolUseCache, fileContentCache, logger } = context;
|
|
16967
|
+
if (message.message.role === "system") {
|
|
16968
|
+
return {};
|
|
16969
|
+
}
|
|
16745
16970
|
if (shouldSkipUserAssistantMessage(message)) {
|
|
16746
16971
|
logSpecialMessages(message, logger);
|
|
16747
16972
|
if (isLoginRequiredMessage(message)) {
|
|
16748
16973
|
return { shouldStop: true, error: import_sdk.RequestError.authRequired() };
|
|
16749
16974
|
}
|
|
16975
|
+
const rawContent = message.message.content;
|
|
16976
|
+
if (typeof rawContent === "string") {
|
|
16977
|
+
const stripped = stripLocalCommandMetadata(rawContent);
|
|
16978
|
+
if (stripped !== null) {
|
|
16979
|
+
for (const notification of toAcpNotifications(
|
|
16980
|
+
stripped,
|
|
16981
|
+
message.message.role,
|
|
16982
|
+
sessionId,
|
|
16983
|
+
toolUseCache,
|
|
16984
|
+
fileContentCache,
|
|
16985
|
+
client,
|
|
16986
|
+
logger,
|
|
16987
|
+
void 0,
|
|
16988
|
+
context.registerHooks,
|
|
16989
|
+
context.supportsTerminalOutput,
|
|
16990
|
+
session.cwd,
|
|
16991
|
+
void 0,
|
|
16992
|
+
context.enrichedReadCache,
|
|
16993
|
+
session.taskState
|
|
16994
|
+
)) {
|
|
16995
|
+
await client.sessionUpdate(notification);
|
|
16996
|
+
session.notificationHistory.push(notification);
|
|
16997
|
+
}
|
|
16998
|
+
}
|
|
16999
|
+
}
|
|
16750
17000
|
return {};
|
|
16751
17001
|
}
|
|
16752
17002
|
if (isPlainTextUserMessage(message)) {
|
|
@@ -16769,7 +17019,8 @@ async function handleUserAssistantMessage(message, context) {
|
|
|
16769
17019
|
context.supportsTerminalOutput,
|
|
16770
17020
|
session.cwd,
|
|
16771
17021
|
mcpToolUseResult,
|
|
16772
|
-
context.enrichedReadCache
|
|
17022
|
+
context.enrichedReadCache,
|
|
17023
|
+
session.taskState
|
|
16773
17024
|
)) {
|
|
16774
17025
|
await client.sessionUpdate(notification);
|
|
16775
17026
|
session.notificationHistory.push(notification);
|
|
@@ -16962,8 +17213,10 @@ var WEB_TOOLS = /* @__PURE__ */ new Set(["WebSearch", "WebFetch"]);
|
|
|
16962
17213
|
var AGENT_TOOLS = /* @__PURE__ */ new Set([
|
|
16963
17214
|
"Task",
|
|
16964
17215
|
"Agent",
|
|
16965
|
-
"
|
|
16966
|
-
"
|
|
17216
|
+
"TaskCreate",
|
|
17217
|
+
"TaskUpdate",
|
|
17218
|
+
"TaskGet",
|
|
17219
|
+
"TaskList"
|
|
16967
17220
|
]);
|
|
16968
17221
|
var BASE_ALLOWED_TOOLS = [
|
|
16969
17222
|
...READ_TOOLS,
|
|
@@ -17047,8 +17300,8 @@ function buildPermissionOptions(toolName, toolInput, repoRoot, suggestions) {
|
|
|
17047
17300
|
if (toolName === "Task") {
|
|
17048
17301
|
return permissionOptions("Yes, allow all sub-tasks");
|
|
17049
17302
|
}
|
|
17050
|
-
if (toolName === "
|
|
17051
|
-
return permissionOptions("Yes, allow all
|
|
17303
|
+
if (toolName === "TaskCreate" || toolName === "TaskUpdate" || toolName === "TaskGet" || toolName === "TaskList") {
|
|
17304
|
+
return permissionOptions("Yes, allow all task updates");
|
|
17052
17305
|
}
|
|
17053
17306
|
return permissionOptions("Yes, always allow");
|
|
17054
17307
|
}
|
|
@@ -17600,6 +17853,7 @@ async function canUseTool(context) {
|
|
|
17600
17853
|
|
|
17601
17854
|
// src/adapters/claude/session/commands.ts
|
|
17602
17855
|
var UNSUPPORTED_COMMANDS = [
|
|
17856
|
+
"clear",
|
|
17603
17857
|
"context",
|
|
17604
17858
|
"cost",
|
|
17605
17859
|
"keybindings-help",
|
|
@@ -17654,18 +17908,30 @@ function loadUserClaudeJsonMcpServers(cwd, logger, homeDir = os3.homedir()) {
|
|
|
17654
17908
|
const projectScoped = project?.mcpServers && typeof project.mcpServers === "object" ? project.mcpServers : {};
|
|
17655
17909
|
return { ...topLevel, ...projectScoped };
|
|
17656
17910
|
}
|
|
17657
|
-
function parseMcpServers(params) {
|
|
17911
|
+
function parseMcpServers(params, logger) {
|
|
17658
17912
|
const mcpServers = {};
|
|
17659
17913
|
if (!Array.isArray(params.mcpServers)) {
|
|
17660
17914
|
return mcpServers;
|
|
17661
17915
|
}
|
|
17662
17916
|
for (const server of params.mcpServers) {
|
|
17663
17917
|
if ("type" in server) {
|
|
17664
|
-
|
|
17665
|
-
|
|
17666
|
-
|
|
17667
|
-
|
|
17668
|
-
|
|
17918
|
+
if (server.type === "http" || server.type === "sse") {
|
|
17919
|
+
mcpServers[server.name] = {
|
|
17920
|
+
type: server.type,
|
|
17921
|
+
url: server.url,
|
|
17922
|
+
headers: server.headers ? Object.fromEntries(
|
|
17923
|
+
server.headers.map((e) => [
|
|
17924
|
+
e.name,
|
|
17925
|
+
e.value
|
|
17926
|
+
])
|
|
17927
|
+
) : void 0
|
|
17928
|
+
};
|
|
17929
|
+
} else {
|
|
17930
|
+
logger?.warn("parseMcpServers: dropping unsupported MCP server type", {
|
|
17931
|
+
name: server.name,
|
|
17932
|
+
type: server.type
|
|
17933
|
+
});
|
|
17934
|
+
}
|
|
17669
17935
|
} else {
|
|
17670
17936
|
mcpServers[server.name] = {
|
|
17671
17937
|
type: "stdio",
|
|
@@ -17678,6 +17944,36 @@ function parseMcpServers(params) {
|
|
|
17678
17944
|
return mcpServers;
|
|
17679
17945
|
}
|
|
17680
17946
|
|
|
17947
|
+
// src/adapters/claude/session/model-config.ts
|
|
17948
|
+
function applyAvailableModelsAllowlist(modelOptions, allowlist) {
|
|
17949
|
+
const filtered = [];
|
|
17950
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17951
|
+
for (const entry of allowlist) {
|
|
17952
|
+
const trimmed2 = entry.trim();
|
|
17953
|
+
if (!trimmed2 || seen.has(trimmed2)) continue;
|
|
17954
|
+
const match = modelOptions.options.find((o) => o.value === trimmed2);
|
|
17955
|
+
if (match) {
|
|
17956
|
+
filtered.push(match);
|
|
17957
|
+
seen.add(trimmed2);
|
|
17958
|
+
}
|
|
17959
|
+
}
|
|
17960
|
+
if (filtered.length === 0) return modelOptions;
|
|
17961
|
+
const currentModelId = filtered.some(
|
|
17962
|
+
(o) => o.value === modelOptions.currentModelId
|
|
17963
|
+
) ? modelOptions.currentModelId : filtered[0].value;
|
|
17964
|
+
return { currentModelId, options: filtered };
|
|
17965
|
+
}
|
|
17966
|
+
function resolveInitialModelId(modelOptions, preferredModelIds) {
|
|
17967
|
+
const allowedModelIds = new Set(modelOptions.options.map((opt) => opt.value));
|
|
17968
|
+
for (const candidate of preferredModelIds) {
|
|
17969
|
+
const trimmed2 = candidate?.trim();
|
|
17970
|
+
if (trimmed2 && allowedModelIds.has(trimmed2)) {
|
|
17971
|
+
return trimmed2;
|
|
17972
|
+
}
|
|
17973
|
+
}
|
|
17974
|
+
return modelOptions.currentModelId;
|
|
17975
|
+
}
|
|
17976
|
+
|
|
17681
17977
|
// src/adapters/claude/session/options.ts
|
|
17682
17978
|
var import_node_child_process3 = require("child_process");
|
|
17683
17979
|
var fs8 = __toESM(require("fs"), 1);
|
|
@@ -17745,6 +18041,7 @@ function buildEnvironment() {
|
|
|
17745
18041
|
const existingCustomHeaders = process.env.ANTHROPIC_CUSTOM_HEADERS;
|
|
17746
18042
|
const customHeaders = existingCustomHeaders ? `${existingCustomHeaders}
|
|
17747
18043
|
${bedrockFallbackHeader}` : bedrockFallbackHeader;
|
|
18044
|
+
const mcpNonblocking = process.env.MCP_CONNECTION_NONBLOCKING;
|
|
17748
18045
|
return {
|
|
17749
18046
|
...process.env,
|
|
17750
18047
|
ELECTRON_RUN_AS_NODE: "1",
|
|
@@ -17753,11 +18050,14 @@ ${bedrockFallbackHeader}` : bedrockFallbackHeader;
|
|
|
17753
18050
|
ENABLE_TOOL_SEARCH: "auto:0",
|
|
17754
18051
|
// Enable idle state as end-of-turn signal (required for SDK 0.2.114+)
|
|
17755
18052
|
CLAUDE_CODE_EMIT_SESSION_STATE_EVENTS: "1",
|
|
18053
|
+
...mcpNonblocking !== void 0 && {
|
|
18054
|
+
MCP_CONNECTION_NONBLOCKING: mcpNonblocking
|
|
18055
|
+
},
|
|
17756
18056
|
// Route to AWS Bedrock as a fallback when Anthropic returns 5xx
|
|
17757
18057
|
ANTHROPIC_CUSTOM_HEADERS: customHeaders
|
|
17758
18058
|
};
|
|
17759
18059
|
}
|
|
17760
|
-
function buildHooks(userHooks, onModeChange, settingsManager, logger, enrichmentDeps, enrichedReadCache, registeredAgents, cloudMode) {
|
|
18060
|
+
function buildHooks(userHooks, onModeChange, settingsManager, logger, enrichmentDeps, enrichedReadCache, registeredAgents, cloudMode, taskState, onTaskStateChange) {
|
|
17761
18061
|
const postToolUseHooks = [createPostToolUseHook({ onModeChange })];
|
|
17762
18062
|
if (enrichmentDeps && enrichedReadCache) {
|
|
17763
18063
|
postToolUseHooks.push(
|
|
@@ -17771,13 +18071,16 @@ function buildHooks(userHooks, onModeChange, settingsManager, logger, enrichment
|
|
|
17771
18071
|
if (cloudMode) {
|
|
17772
18072
|
preToolUseHooks.push(createSignedCommitGuardHook(logger));
|
|
17773
18073
|
}
|
|
18074
|
+
const taskHook = createTaskHook(taskState, onTaskStateChange);
|
|
17774
18075
|
return {
|
|
17775
18076
|
...userHooks,
|
|
17776
18077
|
PostToolUse: [
|
|
17777
18078
|
...userHooks?.PostToolUse || [],
|
|
17778
18079
|
{ hooks: postToolUseHooks }
|
|
17779
18080
|
],
|
|
17780
|
-
PreToolUse: [...userHooks?.PreToolUse || [], { hooks: preToolUseHooks }]
|
|
18081
|
+
PreToolUse: [...userHooks?.PreToolUse || [], { hooks: preToolUseHooks }],
|
|
18082
|
+
TaskCreated: [...userHooks?.TaskCreated || [], { hooks: [taskHook] }],
|
|
18083
|
+
TaskCompleted: [...userHooks?.TaskCompleted || [], { hooks: [taskHook] }]
|
|
17781
18084
|
};
|
|
17782
18085
|
}
|
|
17783
18086
|
var PH_EXPLORE_AGENT = {
|
|
@@ -17808,7 +18111,10 @@ Rules:
|
|
|
17808
18111
|
"WebFetch",
|
|
17809
18112
|
"WebSearch",
|
|
17810
18113
|
"NotebookRead",
|
|
17811
|
-
"
|
|
18114
|
+
"TaskCreate",
|
|
18115
|
+
"TaskUpdate",
|
|
18116
|
+
"TaskGet",
|
|
18117
|
+
"TaskList"
|
|
17812
18118
|
]
|
|
17813
18119
|
};
|
|
17814
18120
|
function buildAgents(userAgents) {
|
|
@@ -17936,7 +18242,9 @@ function buildSessionOptions(params) {
|
|
|
17936
18242
|
params.enrichmentDeps,
|
|
17937
18243
|
params.enrichedReadCache,
|
|
17938
18244
|
registeredAgentNames,
|
|
17939
|
-
params.cloudMode ?? false
|
|
18245
|
+
params.cloudMode ?? false,
|
|
18246
|
+
params.taskState,
|
|
18247
|
+
params.onTaskStateChange
|
|
17940
18248
|
),
|
|
17941
18249
|
outputFormat: params.outputFormat,
|
|
17942
18250
|
abortController: getAbortController(
|
|
@@ -18165,6 +18473,15 @@ function getManagedSettingsPath() {
|
|
|
18165
18473
|
return "/etc/claude-code/managed-settings.json";
|
|
18166
18474
|
}
|
|
18167
18475
|
}
|
|
18476
|
+
function mergeAvailableModels(existing, incoming, layer) {
|
|
18477
|
+
if (incoming === void 0) {
|
|
18478
|
+
return existing;
|
|
18479
|
+
}
|
|
18480
|
+
if (layer === "enterprise") {
|
|
18481
|
+
return Array.from(new Set(incoming));
|
|
18482
|
+
}
|
|
18483
|
+
return Array.from(/* @__PURE__ */ new Set([...existing ?? [], ...incoming]));
|
|
18484
|
+
}
|
|
18168
18485
|
var SettingsManager = class {
|
|
18169
18486
|
cwd;
|
|
18170
18487
|
repoRoot;
|
|
@@ -18220,10 +18537,10 @@ var SettingsManager = class {
|
|
|
18220
18537
|
}
|
|
18221
18538
|
mergeAllSettings() {
|
|
18222
18539
|
const allSettings = [
|
|
18223
|
-
this.userSettings,
|
|
18224
|
-
this.projectSettings,
|
|
18225
|
-
this.localSettings,
|
|
18226
|
-
this.enterpriseSettings
|
|
18540
|
+
{ layer: "user", settings: this.userSettings },
|
|
18541
|
+
{ layer: "project", settings: this.projectSettings },
|
|
18542
|
+
{ layer: "local", settings: this.localSettings },
|
|
18543
|
+
{ layer: "enterprise", settings: this.enterpriseSettings }
|
|
18227
18544
|
];
|
|
18228
18545
|
const permissions = {
|
|
18229
18546
|
allow: [],
|
|
@@ -18232,7 +18549,7 @@ var SettingsManager = class {
|
|
|
18232
18549
|
};
|
|
18233
18550
|
const merged = { permissions };
|
|
18234
18551
|
const posthogApprovedExecTools = /* @__PURE__ */ new Set();
|
|
18235
|
-
for (const settings of allSettings) {
|
|
18552
|
+
for (const { layer, settings } of allSettings) {
|
|
18236
18553
|
if (settings.permissions) {
|
|
18237
18554
|
if (settings.permissions.allow) {
|
|
18238
18555
|
permissions.allow?.push(...settings.permissions.allow);
|
|
@@ -18259,6 +18576,11 @@ var SettingsManager = class {
|
|
|
18259
18576
|
if (settings.model) {
|
|
18260
18577
|
merged.model = settings.model;
|
|
18261
18578
|
}
|
|
18579
|
+
merged.availableModels = mergeAvailableModels(
|
|
18580
|
+
merged.availableModels,
|
|
18581
|
+
settings.availableModels,
|
|
18582
|
+
layer
|
|
18583
|
+
);
|
|
18262
18584
|
if (settings.posthogApprovedExecTools) {
|
|
18263
18585
|
for (const tool2 of settings.posthogApprovedExecTools) {
|
|
18264
18586
|
posthogApprovedExecTools.add(tool2);
|
|
@@ -18401,6 +18723,14 @@ function readClaudeMdQuietly(cwd, logger) {
|
|
|
18401
18723
|
return void 0;
|
|
18402
18724
|
}
|
|
18403
18725
|
}
|
|
18726
|
+
function collectKnownSlashCommands(commands) {
|
|
18727
|
+
const names = /* @__PURE__ */ new Set();
|
|
18728
|
+
if (!commands) return names;
|
|
18729
|
+
for (const cmd of commands) {
|
|
18730
|
+
if (cmd.name) names.add(cmd.name);
|
|
18731
|
+
}
|
|
18732
|
+
return names;
|
|
18733
|
+
}
|
|
18404
18734
|
function sanitizeTitle(text2) {
|
|
18405
18735
|
const sanitized = text2.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
|
|
18406
18736
|
if (sanitized.length <= MAX_TITLE_LENGTH) {
|
|
@@ -18459,6 +18789,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18459
18789
|
},
|
|
18460
18790
|
loadSession: true,
|
|
18461
18791
|
sessionCapabilities: {
|
|
18792
|
+
additionalDirectories: {},
|
|
18462
18793
|
list: {},
|
|
18463
18794
|
fork: {},
|
|
18464
18795
|
resume: {}
|
|
@@ -18484,10 +18815,18 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18484
18815
|
if (fs10.existsSync(path12.resolve(os6.homedir(), ".claude.json.backup")) && !fs10.existsSync(path12.resolve(os6.homedir(), ".claude.json"))) {
|
|
18485
18816
|
throw import_sdk2.RequestError.authRequired();
|
|
18486
18817
|
}
|
|
18487
|
-
const response = await this.createSession(
|
|
18488
|
-
|
|
18489
|
-
|
|
18490
|
-
|
|
18818
|
+
const response = await this.createSession(
|
|
18819
|
+
{
|
|
18820
|
+
cwd: params.cwd,
|
|
18821
|
+
mcpServers: params.mcpServers ?? [],
|
|
18822
|
+
additionalDirectories: params.additionalDirectories,
|
|
18823
|
+
_meta: params._meta
|
|
18824
|
+
},
|
|
18825
|
+
{
|
|
18826
|
+
// Revisit these meta values once we support resume
|
|
18827
|
+
resume: params._meta?.claudeCode?.options?.resume
|
|
18828
|
+
}
|
|
18829
|
+
);
|
|
18491
18830
|
return response;
|
|
18492
18831
|
}
|
|
18493
18832
|
async unstable_forkSession(params) {
|
|
@@ -18495,24 +18834,27 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18495
18834
|
{
|
|
18496
18835
|
cwd: params.cwd,
|
|
18497
18836
|
mcpServers: params.mcpServers ?? [],
|
|
18837
|
+
additionalDirectories: params.additionalDirectories,
|
|
18498
18838
|
_meta: params._meta
|
|
18499
18839
|
},
|
|
18500
18840
|
{ resume: params.sessionId, forkSession: true }
|
|
18501
18841
|
);
|
|
18502
18842
|
}
|
|
18503
|
-
async
|
|
18843
|
+
async resumeSession(params) {
|
|
18504
18844
|
const existing = this.getExistingSessionState(params.sessionId);
|
|
18505
18845
|
if (existing) return existing;
|
|
18506
18846
|
const response = await this.createSession(
|
|
18507
18847
|
{
|
|
18508
18848
|
cwd: params.cwd,
|
|
18509
18849
|
mcpServers: params.mcpServers ?? [],
|
|
18850
|
+
additionalDirectories: params.additionalDirectories,
|
|
18510
18851
|
_meta: params._meta
|
|
18511
18852
|
},
|
|
18512
18853
|
{
|
|
18513
18854
|
resume: params.sessionId
|
|
18514
18855
|
}
|
|
18515
18856
|
);
|
|
18857
|
+
await this.rehydrateTaskStateFromJsonl(params.sessionId);
|
|
18516
18858
|
return response;
|
|
18517
18859
|
}
|
|
18518
18860
|
async loadSession(params) {
|
|
@@ -18522,6 +18864,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18522
18864
|
{
|
|
18523
18865
|
cwd: params.cwd,
|
|
18524
18866
|
mcpServers: params.mcpServers ?? [],
|
|
18867
|
+
additionalDirectories: params.additionalDirectories,
|
|
18525
18868
|
_meta: params._meta
|
|
18526
18869
|
},
|
|
18527
18870
|
{ resume: params.sessionId, skipBackgroundFetches: true }
|
|
@@ -18600,6 +18943,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18600
18943
|
await this.broadcastUserMessage(params);
|
|
18601
18944
|
this.session.promptRunning = true;
|
|
18602
18945
|
let handedOff = false;
|
|
18946
|
+
let errored = false;
|
|
18603
18947
|
let lastAssistantTotalUsage = null;
|
|
18604
18948
|
let lastStreamUsage = {
|
|
18605
18949
|
input_tokens: 0,
|
|
@@ -18607,6 +18951,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18607
18951
|
cache_read_input_tokens: 0,
|
|
18608
18952
|
cache_creation_input_tokens: 0
|
|
18609
18953
|
};
|
|
18954
|
+
let compactionInProgress = false;
|
|
18610
18955
|
if (this.session.lastContextWindowSize == null) {
|
|
18611
18956
|
this.session.lastContextWindowSize = this.getContextWindowForModel(
|
|
18612
18957
|
this.session.modelId ?? ""
|
|
@@ -18664,9 +19009,45 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18664
19009
|
if (message.subtype === "local_command_output") {
|
|
18665
19010
|
promptReplayed = true;
|
|
18666
19011
|
}
|
|
19012
|
+
if (message.subtype === "status") {
|
|
19013
|
+
if (message.status === "compacting") {
|
|
19014
|
+
compactionInProgress = true;
|
|
19015
|
+
} else if (message.compact_result === "success" && compactionInProgress) {
|
|
19016
|
+
compactionInProgress = false;
|
|
19017
|
+
await this.client.sessionUpdate({
|
|
19018
|
+
sessionId: params.sessionId,
|
|
19019
|
+
update: {
|
|
19020
|
+
sessionUpdate: "agent_message_chunk",
|
|
19021
|
+
content: {
|
|
19022
|
+
type: "text",
|
|
19023
|
+
text: "\n\nCompacting completed."
|
|
19024
|
+
}
|
|
19025
|
+
}
|
|
19026
|
+
});
|
|
19027
|
+
break;
|
|
19028
|
+
} else if (message.compact_result === "failed" && compactionInProgress) {
|
|
19029
|
+
compactionInProgress = false;
|
|
19030
|
+
const reason = message.compact_error ? `: ${message.compact_error}` : ".";
|
|
19031
|
+
await this.client.sessionUpdate({
|
|
19032
|
+
sessionId: params.sessionId,
|
|
19033
|
+
update: {
|
|
19034
|
+
sessionUpdate: "agent_message_chunk",
|
|
19035
|
+
content: {
|
|
19036
|
+
type: "text",
|
|
19037
|
+
text: `
|
|
19038
|
+
|
|
19039
|
+
Compacting failed${reason}`
|
|
19040
|
+
}
|
|
19041
|
+
}
|
|
19042
|
+
});
|
|
19043
|
+
break;
|
|
19044
|
+
}
|
|
19045
|
+
}
|
|
18667
19046
|
if (message.subtype === "session_state_changed" && message.state === "idle") {
|
|
18668
19047
|
if (!promptReplayed) {
|
|
18669
|
-
|
|
19048
|
+
const cmdName = commandMatch?.[1].slice(1);
|
|
19049
|
+
const known = cmdName !== void 0 && this.session.knownSlashCommands?.has(cmdName) === true;
|
|
19050
|
+
if (commandMatch && !known) {
|
|
18670
19051
|
const cmd = commandMatch[1];
|
|
18671
19052
|
this.logger.warn(
|
|
18672
19053
|
"Slash command produced no output; treating as unsupported",
|
|
@@ -18685,7 +19066,9 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18685
19066
|
return { stopReason: "end_turn" };
|
|
18686
19067
|
}
|
|
18687
19068
|
this.logger.debug("Skipping idle state before prompt replay", {
|
|
18688
|
-
sessionId: params.sessionId
|
|
19069
|
+
sessionId: params.sessionId,
|
|
19070
|
+
command: commandMatch?.[1],
|
|
19071
|
+
known
|
|
18689
19072
|
});
|
|
18690
19073
|
break;
|
|
18691
19074
|
}
|
|
@@ -18699,7 +19082,9 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18699
19082
|
size: lastContextWindowSize
|
|
18700
19083
|
}
|
|
18701
19084
|
});
|
|
18702
|
-
return {
|
|
19085
|
+
return {
|
|
19086
|
+
stopReason: this.session.cancelled ? "cancelled" : "end_turn"
|
|
19087
|
+
};
|
|
18703
19088
|
}
|
|
18704
19089
|
await handleSystemMessage(message, context);
|
|
18705
19090
|
break;
|
|
@@ -18882,6 +19267,28 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18882
19267
|
}
|
|
18883
19268
|
throw new Error("Session did not end in result");
|
|
18884
19269
|
} catch (error) {
|
|
19270
|
+
errored = true;
|
|
19271
|
+
try {
|
|
19272
|
+
await this.session.query.interrupt();
|
|
19273
|
+
const MAX_DRAIN = 100;
|
|
19274
|
+
for (let i2 = 0; i2 < MAX_DRAIN; i2++) {
|
|
19275
|
+
const { value: m, done } = await this.session.query.next();
|
|
19276
|
+
if (done || !m) break;
|
|
19277
|
+
if (m.type === "system" && m.subtype === "session_state_changed" && m.state === "idle") {
|
|
19278
|
+
break;
|
|
19279
|
+
}
|
|
19280
|
+
if (i2 === MAX_DRAIN - 1) {
|
|
19281
|
+
this.logger.error(
|
|
19282
|
+
`Session ${params.sessionId}: drained ${MAX_DRAIN} messages after error without observing idle`
|
|
19283
|
+
);
|
|
19284
|
+
}
|
|
19285
|
+
}
|
|
19286
|
+
} catch (drainErr) {
|
|
19287
|
+
this.logger.error(
|
|
19288
|
+
`Session ${params.sessionId}: failed to drain query after prompt error`,
|
|
19289
|
+
{ error: drainErr }
|
|
19290
|
+
);
|
|
19291
|
+
}
|
|
18885
19292
|
if (error instanceof import_sdk2.RequestError || !(error instanceof Error)) {
|
|
18886
19293
|
throw error;
|
|
18887
19294
|
}
|
|
@@ -18902,9 +19309,19 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18902
19309
|
this.toolUseStreamCache.clear();
|
|
18903
19310
|
if (!handedOff) {
|
|
18904
19311
|
this.session.promptRunning = false;
|
|
18905
|
-
|
|
18906
|
-
pending.
|
|
18907
|
-
|
|
19312
|
+
if (errored) {
|
|
19313
|
+
for (const pending of this.session.pendingMessages.values()) {
|
|
19314
|
+
pending.resolve(true);
|
|
19315
|
+
}
|
|
19316
|
+
this.session.pendingMessages.clear();
|
|
19317
|
+
} else if (this.session.pendingMessages.size > 0) {
|
|
19318
|
+
const next = [...this.session.pendingMessages.entries()].sort(
|
|
19319
|
+
(a, b) => a[1].order - b[1].order
|
|
19320
|
+
)[0];
|
|
19321
|
+
if (next) {
|
|
19322
|
+
next[1].resolve(false);
|
|
19323
|
+
this.session.pendingMessages.delete(next[0]);
|
|
19324
|
+
}
|
|
18908
19325
|
}
|
|
18909
19326
|
}
|
|
18910
19327
|
}
|
|
@@ -18955,7 +19372,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
18955
19372
|
);
|
|
18956
19373
|
}
|
|
18957
19374
|
const mcpServers = parseMcpServers(
|
|
18958
|
-
params
|
|
19375
|
+
params,
|
|
19376
|
+
this.logger
|
|
18959
19377
|
);
|
|
18960
19378
|
await this.refreshSession(mcpServers);
|
|
18961
19379
|
return { refreshed: true };
|
|
@@ -19140,7 +19558,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19140
19558
|
const settingsManager = new SettingsManager(cwd);
|
|
19141
19559
|
await settingsManager.initialize();
|
|
19142
19560
|
const earlyModelId = settingsManager.getSettings().model || meta?.model || "";
|
|
19143
|
-
const mcpServers = supportsMcpInjection(earlyModelId) ? parseMcpServers(params) : {};
|
|
19561
|
+
const mcpServers = supportsMcpInjection(earlyModelId) ? parseMcpServers(params, this.logger) : {};
|
|
19144
19562
|
const localToolsServer = createLocalToolsMcpServer(
|
|
19145
19563
|
{ cwd, token: resolveGithubToken(), taskId },
|
|
19146
19564
|
meta
|
|
@@ -19164,6 +19582,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19164
19582
|
cwd
|
|
19165
19583
|
});
|
|
19166
19584
|
const permissionMode = meta?.permissionMode && CODE_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
|
|
19585
|
+
const taskState = /* @__PURE__ */ new Map();
|
|
19167
19586
|
const options = buildSessionOptions({
|
|
19168
19587
|
cwd,
|
|
19169
19588
|
mcpServers,
|
|
@@ -19177,7 +19596,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19177
19596
|
forkSession,
|
|
19178
19597
|
additionalDirectories: [
|
|
19179
19598
|
...meta?.claudeCode?.options?.additionalDirectories ?? [],
|
|
19180
|
-
|
|
19599
|
+
// Prefer the official ACP `additionalDirectories` field. Fall back
|
|
19600
|
+
// to the legacy `_meta.additionalRoots` extension for clients that
|
|
19601
|
+
// haven't been updated yet.
|
|
19602
|
+
...params.additionalDirectories ?? meta?.additionalRoots ?? []
|
|
19181
19603
|
],
|
|
19182
19604
|
disableBuiltInTools: meta?.disableBuiltInTools,
|
|
19183
19605
|
outputFormat,
|
|
@@ -19188,7 +19610,17 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19188
19610
|
effort,
|
|
19189
19611
|
enrichmentDeps: this.enrichment?.deps,
|
|
19190
19612
|
enrichedReadCache: this.enrichedReadCache,
|
|
19191
|
-
cloudMode: cloudRun
|
|
19613
|
+
cloudMode: cloudRun,
|
|
19614
|
+
taskState,
|
|
19615
|
+
onTaskStateChange: async () => {
|
|
19616
|
+
await this.client.sessionUpdate({
|
|
19617
|
+
sessionId,
|
|
19618
|
+
update: {
|
|
19619
|
+
sessionUpdate: "plan",
|
|
19620
|
+
entries: taskStateToPlanEntries(taskState)
|
|
19621
|
+
}
|
|
19622
|
+
});
|
|
19623
|
+
}
|
|
19192
19624
|
});
|
|
19193
19625
|
const abortController = options.abortController;
|
|
19194
19626
|
const q = (0, import_claude_agent_sdk2.query)({ prompt: input, options });
|
|
@@ -19217,6 +19649,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19217
19649
|
systemPrompt: estimateSystemPrompt(systemPrompt),
|
|
19218
19650
|
rules: estimateRulesTokens(readClaudeMdQuietly(cwd, this.logger))
|
|
19219
19651
|
},
|
|
19652
|
+
taskState,
|
|
19220
19653
|
// Custom properties
|
|
19221
19654
|
cwd,
|
|
19222
19655
|
notificationHistory: [],
|
|
@@ -19235,6 +19668,9 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19235
19668
|
`Session ${forkSession ? "fork" : "resumption"} timed out for sessionId=${sessionId}`
|
|
19236
19669
|
);
|
|
19237
19670
|
}
|
|
19671
|
+
session.knownSlashCommands = collectKnownSlashCommands(
|
|
19672
|
+
result.value.commands
|
|
19673
|
+
);
|
|
19238
19674
|
} catch (err2) {
|
|
19239
19675
|
settingsManager.dispose();
|
|
19240
19676
|
if (err2 instanceof Error && err2.message === "Query closed before response received") {
|
|
@@ -19253,7 +19689,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19253
19689
|
}
|
|
19254
19690
|
}
|
|
19255
19691
|
const initPromise2 = !isResume ? withTimeout(q.initializationResult(), SESSION_VALIDATION_TIMEOUT_MS) : void 0;
|
|
19256
|
-
const [
|
|
19692
|
+
const [rawModelOptions] = await Promise.all([
|
|
19257
19693
|
this.getModelConfigOptions(
|
|
19258
19694
|
settingsManager.getSettings().model || meta?.model || void 0
|
|
19259
19695
|
),
|
|
@@ -19265,6 +19701,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19265
19701
|
})
|
|
19266
19702
|
] : []
|
|
19267
19703
|
]);
|
|
19704
|
+
const settingsAvailableModels = settingsManager.getSettings().availableModels;
|
|
19705
|
+
const modelOptions = Array.isArray(settingsAvailableModels) ? applyAvailableModelsAllowlist(rawModelOptions, settingsAvailableModels) : rawModelOptions;
|
|
19268
19706
|
if (initPromise2) {
|
|
19269
19707
|
try {
|
|
19270
19708
|
const initResult = await initPromise2;
|
|
@@ -19274,6 +19712,9 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19274
19712
|
`Session initialization timed out for sessionId=${sessionId}`
|
|
19275
19713
|
);
|
|
19276
19714
|
}
|
|
19715
|
+
session.knownSlashCommands = collectKnownSlashCommands(
|
|
19716
|
+
initResult.value.commands
|
|
19717
|
+
);
|
|
19277
19718
|
} catch (err2) {
|
|
19278
19719
|
settingsManager.dispose();
|
|
19279
19720
|
this.logger.error("Session initialization failed", {
|
|
@@ -19285,9 +19726,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19285
19726
|
throw err2;
|
|
19286
19727
|
}
|
|
19287
19728
|
}
|
|
19288
|
-
const
|
|
19289
|
-
|
|
19290
|
-
|
|
19729
|
+
const resolvedModelId = resolveInitialModelId(modelOptions, [
|
|
19730
|
+
settingsManager.getSettings().model,
|
|
19731
|
+
meta?.model
|
|
19732
|
+
]);
|
|
19291
19733
|
session.modelId = resolvedModelId;
|
|
19292
19734
|
session.lastContextWindowSize = this.getContextWindowForModel(resolvedModelId);
|
|
19293
19735
|
const resolvedSdkModel = toSdkModelId(resolvedModelId);
|
|
@@ -19495,6 +19937,34 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
19495
19937
|
[key]: tokens
|
|
19496
19938
|
};
|
|
19497
19939
|
}
|
|
19940
|
+
/**
|
|
19941
|
+
* Rebuild the in-memory taskState from JSONL and push a plan update so the
|
|
19942
|
+
* client's plan panel reflects pre-resume tasks. `loadSession` already covers
|
|
19943
|
+
* this via the full `replaySessionHistory` notification stream; resume
|
|
19944
|
+
* deliberately stays quiet (the client keeps its own message history) so we
|
|
19945
|
+
* walk the transcript here for state only.
|
|
19946
|
+
*/
|
|
19947
|
+
async rehydrateTaskStateFromJsonl(sessionId) {
|
|
19948
|
+
try {
|
|
19949
|
+
const messages = await (0, import_claude_agent_sdk2.getSessionMessages)(sessionId, {
|
|
19950
|
+
dir: this.session.cwd
|
|
19951
|
+
});
|
|
19952
|
+
rehydrateTaskState(messages, this.session.taskState);
|
|
19953
|
+
if (this.session.taskState.size === 0) return;
|
|
19954
|
+
await this.client.sessionUpdate({
|
|
19955
|
+
sessionId,
|
|
19956
|
+
update: {
|
|
19957
|
+
sessionUpdate: "plan",
|
|
19958
|
+
entries: taskStateToPlanEntries(this.session.taskState)
|
|
19959
|
+
}
|
|
19960
|
+
});
|
|
19961
|
+
} catch (err2) {
|
|
19962
|
+
this.logger.warn("Failed to rehydrate task state", {
|
|
19963
|
+
sessionId,
|
|
19964
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
19965
|
+
});
|
|
19966
|
+
}
|
|
19967
|
+
}
|
|
19498
19968
|
async replaySessionHistory(sessionId) {
|
|
19499
19969
|
try {
|
|
19500
19970
|
const messages = await (0, import_claude_agent_sdk2.getSessionMessages)(sessionId, {
|
|
@@ -20248,7 +20718,7 @@ var CodexAcpAgent = class extends BaseAcpAgent {
|
|
|
20248
20718
|
}
|
|
20249
20719
|
return response;
|
|
20250
20720
|
}
|
|
20251
|
-
async
|
|
20721
|
+
async resumeSession(params) {
|
|
20252
20722
|
const meta = params._meta;
|
|
20253
20723
|
const injectedParams = this.applyLocalTools(
|
|
20254
20724
|
this.applyStructuredOutput(
|