@posthog/agent 2.3.67 → 2.3.73
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/permissions/permission-options.js +12 -2
- package/dist/adapters/claude/permissions/permission-options.js.map +1 -1
- package/dist/adapters/claude/session/jsonl-hydration.js.map +1 -1
- package/dist/agent.js +239 -70
- package/dist/agent.js.map +1 -1
- package/dist/claude-cli/cli.js +4002 -2916
- 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/tree-sitter-bash/arm64-darwin/tree-sitter-bash.node +0 -0
- package/dist/claude-cli/vendor/tree-sitter-bash/arm64-linux/tree-sitter-bash.node +0 -0
- package/dist/claude-cli/vendor/tree-sitter-bash/arm64-win32/tree-sitter-bash.node +0 -0
- package/dist/claude-cli/vendor/tree-sitter-bash/x64-darwin/tree-sitter-bash.node +0 -0
- package/dist/claude-cli/vendor/tree-sitter-bash/x64-linux/tree-sitter-bash.node +0 -0
- package/dist/claude-cli/vendor/tree-sitter-bash/x64-win32/tree-sitter-bash.node +0 -0
- package/dist/posthog-api.js +3 -3
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.js +239 -70
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +239 -70
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +3 -3
- package/src/adapters/base-acp-agent.ts +11 -2
- package/src/adapters/claude/UPSTREAM.md +3 -4
- package/src/adapters/claude/claude-agent.ts +217 -35
- package/src/adapters/claude/conversion/sdk-to-acp.ts +2 -25
- package/src/adapters/claude/permissions/permission-handlers.ts +5 -7
- package/src/adapters/claude/permissions/permission-options.ts +17 -2
- package/src/adapters/claude/session/models.ts +94 -4
- package/src/adapters/claude/types.ts +3 -0
package/dist/server/bin.cjs
CHANGED
|
@@ -904,7 +904,7 @@ var import_hono = require("hono");
|
|
|
904
904
|
// package.json
|
|
905
905
|
var package_default = {
|
|
906
906
|
name: "@posthog/agent",
|
|
907
|
-
version: "2.3.
|
|
907
|
+
version: "2.3.73",
|
|
908
908
|
repository: "https://github.com/PostHog/code",
|
|
909
909
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
910
910
|
exports: {
|
|
@@ -991,8 +991,8 @@ var package_default = {
|
|
|
991
991
|
vitest: "^2.1.8"
|
|
992
992
|
},
|
|
993
993
|
dependencies: {
|
|
994
|
-
"@agentclientprotocol/sdk": "0.
|
|
995
|
-
"@anthropic-ai/claude-agent-sdk": "0.2.
|
|
994
|
+
"@agentclientprotocol/sdk": "0.16.1",
|
|
995
|
+
"@anthropic-ai/claude-agent-sdk": "0.2.76",
|
|
996
996
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
997
997
|
"@hono/node-server": "^1.19.9",
|
|
998
998
|
"@opentelemetry/api-logs": "^0.208.0",
|
|
@@ -1372,12 +1372,14 @@ function formatGatewayModelName(model) {
|
|
|
1372
1372
|
}
|
|
1373
1373
|
|
|
1374
1374
|
// src/adapters/base-acp-agent.ts
|
|
1375
|
+
var DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
1375
1376
|
var BaseAcpAgent = class {
|
|
1376
1377
|
session;
|
|
1377
1378
|
sessionId;
|
|
1378
1379
|
client;
|
|
1379
1380
|
logger;
|
|
1380
1381
|
fileContentCache = {};
|
|
1382
|
+
gatewayModels = [];
|
|
1381
1383
|
constructor(client) {
|
|
1382
1384
|
this.client = client;
|
|
1383
1385
|
this.logger = new Logger({ debug: true, prefix: "[BaseAcpAgent]" });
|
|
@@ -1430,8 +1432,8 @@ var BaseAcpAgent = class {
|
|
|
1430
1432
|
throw new Error("Method not implemented.");
|
|
1431
1433
|
}
|
|
1432
1434
|
async getModelConfigOptions(currentModelOverride) {
|
|
1433
|
-
|
|
1434
|
-
const options = gatewayModels.filter((model) => isAnthropicModel(model)).map((model) => ({
|
|
1435
|
+
this.gatewayModels = await fetchGatewayModels();
|
|
1436
|
+
const options = this.gatewayModels.filter((model) => isAnthropicModel(model)).map((model) => ({
|
|
1435
1437
|
value: model.id,
|
|
1436
1438
|
name: formatGatewayModelName(model),
|
|
1437
1439
|
description: `Context: ${model.context_window.toLocaleString()} tokens`
|
|
@@ -1452,6 +1454,10 @@ var BaseAcpAgent = class {
|
|
|
1452
1454
|
}
|
|
1453
1455
|
return { currentModelId, options };
|
|
1454
1456
|
}
|
|
1457
|
+
getContextWindowForModel(modelId) {
|
|
1458
|
+
const match = this.gatewayModels.find((m) => m.id === modelId);
|
|
1459
|
+
return match?.context_window ?? DEFAULT_CONTEXT_WINDOW;
|
|
1460
|
+
}
|
|
1455
1461
|
};
|
|
1456
1462
|
|
|
1457
1463
|
// src/adapters/claude/conversion/acp-to-sdk.ts
|
|
@@ -2627,7 +2633,7 @@ function streamEventToAcpNotifications(message, sessionId, toolUseCache, fileCon
|
|
|
2627
2633
|
}
|
|
2628
2634
|
}
|
|
2629
2635
|
async function handleSystemMessage(message, context) {
|
|
2630
|
-
const { sessionId, client, logger } = context;
|
|
2636
|
+
const { session, sessionId, client, logger } = context;
|
|
2631
2637
|
switch (message.subtype) {
|
|
2632
2638
|
case "init":
|
|
2633
2639
|
break;
|
|
@@ -2635,7 +2641,8 @@ async function handleSystemMessage(message, context) {
|
|
|
2635
2641
|
await client.extNotification("_posthog/compact_boundary", {
|
|
2636
2642
|
sessionId,
|
|
2637
2643
|
trigger: message.compact_metadata.trigger,
|
|
2638
|
-
preTokens: message.compact_metadata.pre_tokens
|
|
2644
|
+
preTokens: message.compact_metadata.pre_tokens,
|
|
2645
|
+
contextSize: session.contextSize
|
|
2639
2646
|
});
|
|
2640
2647
|
break;
|
|
2641
2648
|
case "hook_response":
|
|
@@ -2807,21 +2814,6 @@ function filterMessageContent(content) {
|
|
|
2807
2814
|
async function handleUserAssistantMessage(message, context) {
|
|
2808
2815
|
const { session, sessionId, client, toolUseCache, fileContentCache, logger } = context;
|
|
2809
2816
|
if (shouldSkipUserAssistantMessage(message)) {
|
|
2810
|
-
const content2 = message.message.content;
|
|
2811
|
-
if (typeof content2 === "string" && hasLocalCommandStdout(content2) && content2.includes("Context Usage")) {
|
|
2812
|
-
const stripped = content2.replace("<local-command-stdout>", "").replace("</local-command-stdout>", "");
|
|
2813
|
-
for (const notification of toAcpNotifications(
|
|
2814
|
-
stripped,
|
|
2815
|
-
"assistant",
|
|
2816
|
-
sessionId,
|
|
2817
|
-
toolUseCache,
|
|
2818
|
-
fileContentCache,
|
|
2819
|
-
client,
|
|
2820
|
-
logger
|
|
2821
|
-
)) {
|
|
2822
|
-
await client.sessionUpdate(notification);
|
|
2823
|
-
}
|
|
2824
|
-
}
|
|
2825
2817
|
logSpecialMessages(message, logger);
|
|
2826
2818
|
if (isLoginRequiredMessage(message)) {
|
|
2827
2819
|
return { shouldStop: true, error: import_sdk.RequestError.authRequired() };
|
|
@@ -3081,8 +3073,17 @@ function buildPermissionOptions(toolName, toolInput, cwd, suggestions) {
|
|
|
3081
3073
|
}
|
|
3082
3074
|
return permissionOptions("Yes, always allow");
|
|
3083
3075
|
}
|
|
3076
|
+
var ALLOW_BYPASS2 = !IS_ROOT || !!process.env.IS_SANDBOX;
|
|
3084
3077
|
function buildExitPlanModePermissionOptions() {
|
|
3085
|
-
|
|
3078
|
+
const options = [];
|
|
3079
|
+
if (ALLOW_BYPASS2) {
|
|
3080
|
+
options.push({
|
|
3081
|
+
kind: "allow_always",
|
|
3082
|
+
name: "Yes, bypass all permissions",
|
|
3083
|
+
optionId: "bypassPermissions"
|
|
3084
|
+
});
|
|
3085
|
+
}
|
|
3086
|
+
options.push(
|
|
3086
3087
|
{
|
|
3087
3088
|
kind: "allow_always",
|
|
3088
3089
|
name: "Yes, and auto-accept edits",
|
|
@@ -3099,7 +3100,8 @@ function buildExitPlanModePermissionOptions() {
|
|
|
3099
3100
|
optionId: "reject_with_feedback",
|
|
3100
3101
|
_meta: { customInput: true }
|
|
3101
3102
|
}
|
|
3102
|
-
|
|
3103
|
+
);
|
|
3104
|
+
return options;
|
|
3103
3105
|
}
|
|
3104
3106
|
|
|
3105
3107
|
// src/adapters/claude/permissions/permission-handlers.ts
|
|
@@ -3173,7 +3175,7 @@ async function requestPlanApproval(context, updatedInput) {
|
|
|
3173
3175
|
}
|
|
3174
3176
|
async function applyPlanApproval(response, context, updatedInput) {
|
|
3175
3177
|
const { session } = context;
|
|
3176
|
-
if (response.outcome?.outcome === "selected" && (response.outcome.optionId === "default" || response.outcome.optionId === "acceptEdits")) {
|
|
3178
|
+
if (response.outcome?.outcome === "selected" && (response.outcome.optionId === "default" || response.outcome.optionId === "acceptEdits" || response.outcome.optionId === "bypassPermissions")) {
|
|
3177
3179
|
session.permissionMode = response.outcome.optionId;
|
|
3178
3180
|
await session.query.setPermissionMode(response.outcome.optionId);
|
|
3179
3181
|
await context.client.sessionUpdate({
|
|
@@ -3246,8 +3248,7 @@ async function handleAskUserQuestionTool(context) {
|
|
|
3246
3248
|
context.logger.warn("[AskUserQuestion] No questions found in input");
|
|
3247
3249
|
return {
|
|
3248
3250
|
behavior: "deny",
|
|
3249
|
-
message: "No questions provided"
|
|
3250
|
-
interrupt: true
|
|
3251
|
+
message: "No questions provided"
|
|
3251
3252
|
};
|
|
3252
3253
|
}
|
|
3253
3254
|
const { client, sessionId, toolUseID, toolInput } = context;
|
|
@@ -3278,16 +3279,14 @@ async function handleAskUserQuestionTool(context) {
|
|
|
3278
3279
|
const customMessage = response._meta?.message;
|
|
3279
3280
|
return {
|
|
3280
3281
|
behavior: "deny",
|
|
3281
|
-
message: typeof customMessage === "string" ? customMessage : "User cancelled the questions"
|
|
3282
|
-
interrupt: true
|
|
3282
|
+
message: typeof customMessage === "string" ? customMessage : "User cancelled the questions"
|
|
3283
3283
|
};
|
|
3284
3284
|
}
|
|
3285
3285
|
const answers = response._meta?.answers;
|
|
3286
3286
|
if (!answers || Object.keys(answers).length === 0) {
|
|
3287
3287
|
return {
|
|
3288
3288
|
behavior: "deny",
|
|
3289
|
-
message: "User did not provide answers"
|
|
3290
|
-
interrupt: true
|
|
3289
|
+
message: "User did not provide answers"
|
|
3291
3290
|
};
|
|
3292
3291
|
}
|
|
3293
3292
|
return {
|
|
@@ -3354,8 +3353,7 @@ async function handleDefaultPermissionFlow(context) {
|
|
|
3354
3353
|
await emitToolDenial(context, message);
|
|
3355
3354
|
return {
|
|
3356
3355
|
behavior: "deny",
|
|
3357
|
-
message
|
|
3358
|
-
interrupt: true
|
|
3356
|
+
message
|
|
3359
3357
|
};
|
|
3360
3358
|
}
|
|
3361
3359
|
}
|
|
@@ -3469,16 +3467,6 @@ var GATEWAY_TO_SDK_MODEL = {
|
|
|
3469
3467
|
function toSdkModelId(modelId) {
|
|
3470
3468
|
return GATEWAY_TO_SDK_MODEL[modelId] ?? modelId;
|
|
3471
3469
|
}
|
|
3472
|
-
var MODELS_WITH_1M_CONTEXT = /* @__PURE__ */ new Set([
|
|
3473
|
-
"claude-opus-4-6",
|
|
3474
|
-
"claude-sonnet-4-6"
|
|
3475
|
-
]);
|
|
3476
|
-
function supports1MContext(modelId) {
|
|
3477
|
-
return MODELS_WITH_1M_CONTEXT.has(modelId);
|
|
3478
|
-
}
|
|
3479
|
-
function getDefaultContextWindow(modelId) {
|
|
3480
|
-
return supports1MContext(modelId) ? 1e6 : 2e5;
|
|
3481
|
-
}
|
|
3482
3470
|
var MODELS_WITH_EFFORT = /* @__PURE__ */ new Set([
|
|
3483
3471
|
"claude-opus-4-5",
|
|
3484
3472
|
"claude-opus-4-6",
|
|
@@ -3503,6 +3491,56 @@ function getEffortOptions(modelId) {
|
|
|
3503
3491
|
}
|
|
3504
3492
|
return options;
|
|
3505
3493
|
}
|
|
3494
|
+
var MODEL_CONTEXT_HINT_PATTERN = /\[(\d+m)\]$/i;
|
|
3495
|
+
function tokenizeModelPreference(model) {
|
|
3496
|
+
const lower = model.trim().toLowerCase();
|
|
3497
|
+
const contextHint = lower.match(MODEL_CONTEXT_HINT_PATTERN)?.[1]?.toLowerCase();
|
|
3498
|
+
const normalized = lower.replace(MODEL_CONTEXT_HINT_PATTERN, " $1 ");
|
|
3499
|
+
const rawTokens = normalized.split(/[^a-z0-9]+/).filter(Boolean);
|
|
3500
|
+
const tokens = rawTokens.map((token) => {
|
|
3501
|
+
if (token === "opusplan") return "opus";
|
|
3502
|
+
if (token === "best" || token === "default") return "";
|
|
3503
|
+
return token;
|
|
3504
|
+
}).filter((token) => token && token !== "claude").filter((token) => /[a-z]/.test(token) || token.endsWith("m"));
|
|
3505
|
+
return { tokens, contextHint };
|
|
3506
|
+
}
|
|
3507
|
+
function scoreModelMatch(model, tokens, contextHint) {
|
|
3508
|
+
const haystack = `${model.value} ${model.name ?? ""}`.toLowerCase();
|
|
3509
|
+
let score = 0;
|
|
3510
|
+
for (const token of tokens) {
|
|
3511
|
+
if (haystack.includes(token)) {
|
|
3512
|
+
score += token === contextHint ? 3 : 1;
|
|
3513
|
+
}
|
|
3514
|
+
}
|
|
3515
|
+
return score;
|
|
3516
|
+
}
|
|
3517
|
+
function resolveModelPreference(preference, options) {
|
|
3518
|
+
const trimmed2 = preference.trim();
|
|
3519
|
+
if (!trimmed2) return null;
|
|
3520
|
+
const lower = trimmed2.toLowerCase();
|
|
3521
|
+
const directMatch = options.find(
|
|
3522
|
+
(o) => o.value === trimmed2 || o.value.toLowerCase() === lower || o.name && o.name.toLowerCase() === lower
|
|
3523
|
+
);
|
|
3524
|
+
if (directMatch) return directMatch.value;
|
|
3525
|
+
const includesMatch = options.find((o) => {
|
|
3526
|
+
const value = o.value.toLowerCase();
|
|
3527
|
+
const display = (o.name ?? "").toLowerCase();
|
|
3528
|
+
return value.includes(lower) || display.includes(lower) || lower.includes(value);
|
|
3529
|
+
});
|
|
3530
|
+
if (includesMatch) return includesMatch.value;
|
|
3531
|
+
const { tokens, contextHint } = tokenizeModelPreference(trimmed2);
|
|
3532
|
+
if (tokens.length === 0) return null;
|
|
3533
|
+
let bestMatch = null;
|
|
3534
|
+
let bestScore = 0;
|
|
3535
|
+
for (const model of options) {
|
|
3536
|
+
const score = scoreModelMatch(model, tokens, contextHint);
|
|
3537
|
+
if (0 < score && (!bestMatch || bestScore < score)) {
|
|
3538
|
+
bestMatch = model;
|
|
3539
|
+
bestScore = score;
|
|
3540
|
+
}
|
|
3541
|
+
}
|
|
3542
|
+
return bestMatch?.value ?? null;
|
|
3543
|
+
}
|
|
3506
3544
|
|
|
3507
3545
|
// src/adapters/claude/session/options.ts
|
|
3508
3546
|
var import_node_child_process = require("child_process");
|
|
@@ -3983,6 +4021,7 @@ var SettingsManager = class {
|
|
|
3983
4021
|
// src/adapters/claude/claude-agent.ts
|
|
3984
4022
|
var SESSION_VALIDATION_TIMEOUT_MS = 1e4;
|
|
3985
4023
|
var MAX_TITLE_LENGTH = 256;
|
|
4024
|
+
var LOCAL_ONLY_COMMANDS = /* @__PURE__ */ new Set(["/context", "/heapdump", "/extra-usage"]);
|
|
3986
4025
|
function sanitizeTitle(text2) {
|
|
3987
4026
|
const sanitized = text2.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
|
|
3988
4027
|
if (sanitized.length <= MAX_TITLE_LENGTH) {
|
|
@@ -4019,7 +4058,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4019
4058
|
sessionCapabilities: {
|
|
4020
4059
|
list: {},
|
|
4021
4060
|
fork: {},
|
|
4022
|
-
resume: {}
|
|
4061
|
+
resume: {},
|
|
4062
|
+
close: {}
|
|
4023
4063
|
},
|
|
4024
4064
|
_meta: {
|
|
4025
4065
|
posthog: {
|
|
@@ -4059,6 +4099,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4059
4099
|
);
|
|
4060
4100
|
}
|
|
4061
4101
|
async unstable_resumeSession(params) {
|
|
4102
|
+
const existing = this.getExistingSessionState(params.sessionId);
|
|
4103
|
+
if (existing) return existing;
|
|
4062
4104
|
const response = await this.createSession(
|
|
4063
4105
|
{
|
|
4064
4106
|
cwd: params.cwd,
|
|
@@ -4072,6 +4114,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4072
4114
|
return response;
|
|
4073
4115
|
}
|
|
4074
4116
|
async loadSession(params) {
|
|
4117
|
+
const existing = this.getExistingSessionState(params.sessionId);
|
|
4118
|
+
if (existing) return existing;
|
|
4075
4119
|
const response = await this.createSession(
|
|
4076
4120
|
{
|
|
4077
4121
|
cwd: params.cwd,
|
|
@@ -4088,7 +4132,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4088
4132
|
configOptions: response.configOptions
|
|
4089
4133
|
};
|
|
4090
4134
|
}
|
|
4091
|
-
async
|
|
4135
|
+
async listSessions(params) {
|
|
4092
4136
|
const sdkSessions = await (0, import_claude_agent_sdk.listSessions)({ dir: params.cwd ?? void 0 });
|
|
4093
4137
|
const sessions = [];
|
|
4094
4138
|
for (const session of sdkSessions) {
|
|
@@ -4104,6 +4148,9 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4104
4148
|
sessions
|
|
4105
4149
|
};
|
|
4106
4150
|
}
|
|
4151
|
+
async unstable_listSessions(params) {
|
|
4152
|
+
return this.listSessions(params);
|
|
4153
|
+
}
|
|
4107
4154
|
async prompt(params) {
|
|
4108
4155
|
this.session.cancelled = false;
|
|
4109
4156
|
this.session.interruptReason = void 0;
|
|
@@ -4114,17 +4161,37 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4114
4161
|
cachedWriteTokens: 0
|
|
4115
4162
|
};
|
|
4116
4163
|
const userMessage = promptToClaude(params);
|
|
4164
|
+
const promptUuid = (0, import_node_crypto.randomUUID)();
|
|
4165
|
+
userMessage.uuid = promptUuid;
|
|
4166
|
+
let promptReplayed = false;
|
|
4167
|
+
let isLocalOnlyCommand = false;
|
|
4168
|
+
const msgContent = userMessage.message.content;
|
|
4169
|
+
let firstTextPart = "";
|
|
4170
|
+
if (typeof msgContent === "string") {
|
|
4171
|
+
firstTextPart = msgContent;
|
|
4172
|
+
} else if (Array.isArray(msgContent)) {
|
|
4173
|
+
for (const block of msgContent) {
|
|
4174
|
+
if ("type" in block && block.type === "text" && "text" in block) {
|
|
4175
|
+
firstTextPart = block.text;
|
|
4176
|
+
break;
|
|
4177
|
+
}
|
|
4178
|
+
}
|
|
4179
|
+
}
|
|
4180
|
+
const commandMatch = firstTextPart.match(/^(\/\S+)/);
|
|
4181
|
+
if (commandMatch && LOCAL_ONLY_COMMANDS.has(commandMatch[1])) {
|
|
4182
|
+
isLocalOnlyCommand = true;
|
|
4183
|
+
promptReplayed = true;
|
|
4184
|
+
}
|
|
4117
4185
|
if (this.session.promptRunning) {
|
|
4118
|
-
const uuid = (0, import_node_crypto.randomUUID)();
|
|
4119
|
-
userMessage.uuid = uuid;
|
|
4120
4186
|
this.session.input.push(userMessage);
|
|
4121
4187
|
const order = this.session.nextPendingOrder++;
|
|
4122
4188
|
const cancelled = await new Promise((resolve4) => {
|
|
4123
|
-
this.session.pendingMessages.set(
|
|
4189
|
+
this.session.pendingMessages.set(promptUuid, { resolve: resolve4, order });
|
|
4124
4190
|
});
|
|
4125
4191
|
if (cancelled) {
|
|
4126
4192
|
return { stopReason: "cancelled" };
|
|
4127
4193
|
}
|
|
4194
|
+
promptReplayed = true;
|
|
4128
4195
|
} else {
|
|
4129
4196
|
this.session.input.push(userMessage);
|
|
4130
4197
|
}
|
|
@@ -4132,6 +4199,16 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4132
4199
|
this.session.promptRunning = true;
|
|
4133
4200
|
let handedOff = false;
|
|
4134
4201
|
let lastAssistantTotalUsage = null;
|
|
4202
|
+
if (this.session.lastContextWindowSize == null) {
|
|
4203
|
+
this.session.lastContextWindowSize = this.getContextWindowForModel(
|
|
4204
|
+
this.session.modelId ?? ""
|
|
4205
|
+
);
|
|
4206
|
+
this.logger.debug("Initial context window size from gateway", {
|
|
4207
|
+
modelId: this.session.modelId,
|
|
4208
|
+
contextWindowSize: this.session.lastContextWindowSize
|
|
4209
|
+
});
|
|
4210
|
+
}
|
|
4211
|
+
let lastContextWindowSize = this.session.lastContextWindowSize;
|
|
4135
4212
|
const supportsTerminalOutput = this.clientCapabilities?._meta?.terminal_output === true;
|
|
4136
4213
|
const context = {
|
|
4137
4214
|
session: this.session,
|
|
@@ -4158,10 +4235,21 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4158
4235
|
case "system":
|
|
4159
4236
|
if (message.subtype === "compact_boundary") {
|
|
4160
4237
|
lastAssistantTotalUsage = 0;
|
|
4238
|
+
promptReplayed = true;
|
|
4239
|
+
}
|
|
4240
|
+
if (message.subtype === "local_command_output") {
|
|
4241
|
+
promptReplayed = true;
|
|
4161
4242
|
}
|
|
4162
4243
|
await handleSystemMessage(message, context);
|
|
4163
4244
|
break;
|
|
4164
4245
|
case "result": {
|
|
4246
|
+
if (!promptReplayed) {
|
|
4247
|
+
this.logger.debug(
|
|
4248
|
+
"Skipping background task result before prompt replay",
|
|
4249
|
+
{ sessionId: params.sessionId }
|
|
4250
|
+
);
|
|
4251
|
+
break;
|
|
4252
|
+
}
|
|
4165
4253
|
if (this.session.cancelled) {
|
|
4166
4254
|
return { stopReason: "cancelled" };
|
|
4167
4255
|
}
|
|
@@ -4172,8 +4260,19 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4172
4260
|
const contextWindows = Object.values(message.modelUsage).map(
|
|
4173
4261
|
(m) => m.contextWindow
|
|
4174
4262
|
);
|
|
4175
|
-
|
|
4176
|
-
|
|
4263
|
+
if (contextWindows.length > 0) {
|
|
4264
|
+
const sdkContextWindow = Math.min(...contextWindows);
|
|
4265
|
+
if (sdkContextWindow > lastContextWindowSize) {
|
|
4266
|
+
lastContextWindowSize = sdkContextWindow;
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4269
|
+
this.session.lastContextWindowSize = lastContextWindowSize;
|
|
4270
|
+
this.logger.debug("Context window size from result", {
|
|
4271
|
+
sdkReported: contextWindows,
|
|
4272
|
+
resolved: lastContextWindowSize,
|
|
4273
|
+
modelId: this.session.modelId
|
|
4274
|
+
});
|
|
4275
|
+
this.session.contextSize = lastContextWindowSize;
|
|
4177
4276
|
if (lastAssistantTotalUsage !== null) {
|
|
4178
4277
|
this.session.contextUsed = lastAssistantTotalUsage;
|
|
4179
4278
|
}
|
|
@@ -4183,7 +4282,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4183
4282
|
update: {
|
|
4184
4283
|
sessionUpdate: "usage_update",
|
|
4185
4284
|
used: lastAssistantTotalUsage,
|
|
4186
|
-
size:
|
|
4285
|
+
size: lastContextWindowSize,
|
|
4187
4286
|
cost: {
|
|
4188
4287
|
amount: message.total_cost_usd,
|
|
4189
4288
|
currency: "USD"
|
|
@@ -4210,6 +4309,15 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4210
4309
|
};
|
|
4211
4310
|
const result = handleResultMessage(message);
|
|
4212
4311
|
if (result.error) throw result.error;
|
|
4312
|
+
if (isLocalOnlyCommand && message.subtype === "success" && message.result) {
|
|
4313
|
+
await this.client.sessionUpdate({
|
|
4314
|
+
sessionId: params.sessionId,
|
|
4315
|
+
update: {
|
|
4316
|
+
sessionUpdate: "agent_message_chunk",
|
|
4317
|
+
content: { type: "text", text: message.result }
|
|
4318
|
+
}
|
|
4319
|
+
});
|
|
4320
|
+
}
|
|
4213
4321
|
return { stopReason: result.stopReason ?? "end_turn", usage };
|
|
4214
4322
|
}
|
|
4215
4323
|
case "stream_event":
|
|
@@ -4221,6 +4329,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4221
4329
|
break;
|
|
4222
4330
|
}
|
|
4223
4331
|
if (message.type === "user" && "uuid" in message && message.uuid) {
|
|
4332
|
+
if (message.uuid === promptUuid) {
|
|
4333
|
+
promptReplayed = true;
|
|
4334
|
+
break;
|
|
4335
|
+
}
|
|
4224
4336
|
const pending = this.session.pendingMessages.get(
|
|
4225
4337
|
message.uuid
|
|
4226
4338
|
);
|
|
@@ -4236,7 +4348,16 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4236
4348
|
}
|
|
4237
4349
|
if ("usage" in message.message && message.parent_tool_use_id === null) {
|
|
4238
4350
|
const usage = message.message.usage;
|
|
4239
|
-
lastAssistantTotalUsage = usage.input_tokens + usage.
|
|
4351
|
+
lastAssistantTotalUsage = usage.input_tokens + usage.cache_read_input_tokens + usage.cache_creation_input_tokens;
|
|
4352
|
+
await this.client.sessionUpdate({
|
|
4353
|
+
sessionId: params.sessionId,
|
|
4354
|
+
update: {
|
|
4355
|
+
sessionUpdate: "usage_update",
|
|
4356
|
+
used: lastAssistantTotalUsage,
|
|
4357
|
+
size: lastContextWindowSize,
|
|
4358
|
+
cost: null
|
|
4359
|
+
}
|
|
4360
|
+
});
|
|
4240
4361
|
}
|
|
4241
4362
|
const result = await handleUserAssistantMessage(message, context);
|
|
4242
4363
|
if (result.error) throw result.error;
|
|
@@ -4266,6 +4387,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4266
4387
|
this.logger.error(`Process died: ${msg}`, {
|
|
4267
4388
|
sessionId: this.sessionId
|
|
4268
4389
|
});
|
|
4390
|
+
this.session.settingsManager.dispose();
|
|
4269
4391
|
this.session.input.end();
|
|
4270
4392
|
throw import_sdk2.RequestError.internalError(
|
|
4271
4393
|
void 0,
|
|
@@ -4293,9 +4415,11 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4293
4415
|
await this.session.query.interrupt();
|
|
4294
4416
|
}
|
|
4295
4417
|
async unstable_setSessionModel(params) {
|
|
4296
|
-
|
|
4297
|
-
await this.session.query.setModel(sdkModelId);
|
|
4418
|
+
await this.session.query.setModel(toSdkModelId(params.modelId));
|
|
4298
4419
|
this.session.modelId = params.modelId;
|
|
4420
|
+
this.session.lastContextWindowSize = this.getContextWindowForModel(
|
|
4421
|
+
params.modelId
|
|
4422
|
+
);
|
|
4299
4423
|
this.rebuildEffortConfigOption(params.modelId);
|
|
4300
4424
|
await this.updateConfigOption("model", params.modelId);
|
|
4301
4425
|
return {};
|
|
@@ -4312,42 +4436,55 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4312
4436
|
if (!option) {
|
|
4313
4437
|
throw new Error(`Unknown config option: ${params.configId}`);
|
|
4314
4438
|
}
|
|
4439
|
+
if (typeof params.value !== "string") {
|
|
4440
|
+
throw new Error(
|
|
4441
|
+
`Invalid value type for config option ${params.configId}`
|
|
4442
|
+
);
|
|
4443
|
+
}
|
|
4315
4444
|
const allValues = "options" in option && Array.isArray(option.options) ? option.options.flatMap(
|
|
4316
4445
|
(o) => "options" in o && Array.isArray(o.options) ? o.options : [o]
|
|
4317
4446
|
) : [];
|
|
4318
|
-
|
|
4447
|
+
let validValue = allValues.find((o) => o.value === params.value);
|
|
4448
|
+
if (!validValue && params.configId === "model") {
|
|
4449
|
+
const resolved = resolveModelPreference(params.value, allValues);
|
|
4450
|
+
if (resolved) {
|
|
4451
|
+
validValue = allValues.find((o) => o.value === resolved);
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4319
4454
|
if (!validValue) {
|
|
4320
4455
|
throw new Error(
|
|
4321
4456
|
`Invalid value for config option ${params.configId}: ${params.value}`
|
|
4322
4457
|
);
|
|
4323
4458
|
}
|
|
4459
|
+
const resolvedValue = validValue.value;
|
|
4324
4460
|
if (params.configId === "mode") {
|
|
4325
|
-
await this.applySessionMode(
|
|
4461
|
+
await this.applySessionMode(resolvedValue);
|
|
4326
4462
|
await this.client.sessionUpdate({
|
|
4327
4463
|
sessionId: this.sessionId,
|
|
4328
4464
|
update: {
|
|
4329
4465
|
sessionUpdate: "current_mode_update",
|
|
4330
|
-
currentModeId:
|
|
4466
|
+
currentModeId: resolvedValue
|
|
4331
4467
|
}
|
|
4332
4468
|
});
|
|
4333
4469
|
} else if (params.configId === "model") {
|
|
4334
|
-
const sdkModelId = toSdkModelId(
|
|
4470
|
+
const sdkModelId = toSdkModelId(resolvedValue);
|
|
4335
4471
|
await this.session.query.setModel(sdkModelId);
|
|
4336
|
-
this.session.modelId =
|
|
4337
|
-
this.
|
|
4472
|
+
this.session.modelId = resolvedValue;
|
|
4473
|
+
this.session.lastContextWindowSize = this.getContextWindowForModel(resolvedValue);
|
|
4474
|
+
this.rebuildEffortConfigOption(resolvedValue);
|
|
4338
4475
|
} else if (params.configId === "effort") {
|
|
4339
|
-
const newEffort =
|
|
4476
|
+
const newEffort = resolvedValue;
|
|
4340
4477
|
this.session.effort = newEffort;
|
|
4341
4478
|
this.session.queryOptions.effort = newEffort;
|
|
4342
4479
|
}
|
|
4343
4480
|
this.session.configOptions = this.session.configOptions.map(
|
|
4344
|
-
(o) => o.id === params.configId ? { ...o, currentValue:
|
|
4481
|
+
(o) => o.id === params.configId && typeof o.currentValue === "string" ? { ...o, currentValue: resolvedValue } : o
|
|
4345
4482
|
);
|
|
4346
4483
|
return { configOptions: this.session.configOptions };
|
|
4347
4484
|
}
|
|
4348
4485
|
async updateConfigOption(configId, value) {
|
|
4349
4486
|
this.session.configOptions = this.session.configOptions.map(
|
|
4350
|
-
(o) => o.id === configId ? { ...o, currentValue: value } : o
|
|
4487
|
+
(o) => o.id === configId && typeof o.currentValue === "string" ? { ...o, currentValue: value } : o
|
|
4351
4488
|
);
|
|
4352
4489
|
await this.client.sessionUpdate({
|
|
4353
4490
|
sessionId: this.sessionId,
|
|
@@ -4414,7 +4551,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4414
4551
|
sessionId,
|
|
4415
4552
|
isResume,
|
|
4416
4553
|
forkSession,
|
|
4417
|
-
additionalDirectories:
|
|
4554
|
+
additionalDirectories: [
|
|
4555
|
+
...meta?.claudeCode?.options?.additionalDirectories ?? [],
|
|
4556
|
+
...meta?.additionalRoots ?? []
|
|
4557
|
+
],
|
|
4418
4558
|
disableBuiltInTools: meta?.disableBuiltInTools,
|
|
4419
4559
|
settingsManager,
|
|
4420
4560
|
onModeChange: this.createOnModeChange(),
|
|
@@ -4491,11 +4631,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4491
4631
|
const modelOptions = await this.getModelConfigOptions();
|
|
4492
4632
|
const resolvedModelId = settingsModel || modelOptions.currentModelId;
|
|
4493
4633
|
session.modelId = resolvedModelId;
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
}
|
|
4634
|
+
session.lastContextWindowSize = this.getContextWindowForModel(resolvedModelId);
|
|
4635
|
+
const resolvedSdkModel = toSdkModelId(resolvedModelId);
|
|
4636
|
+
if (!isResume && resolvedSdkModel !== DEFAULT_MODEL) {
|
|
4637
|
+
await this.session.query.setModel(resolvedSdkModel);
|
|
4499
4638
|
}
|
|
4500
4639
|
const availableModes2 = getAvailableModes();
|
|
4501
4640
|
const modes = {
|
|
@@ -4558,6 +4697,35 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4558
4697
|
await this.updateConfigOption("mode", newMode);
|
|
4559
4698
|
};
|
|
4560
4699
|
}
|
|
4700
|
+
getExistingSessionState(sessionId) {
|
|
4701
|
+
if (this.sessionId !== sessionId || !this.session) return null;
|
|
4702
|
+
const availableModes2 = getAvailableModes();
|
|
4703
|
+
const modes = {
|
|
4704
|
+
currentModeId: this.session.permissionMode,
|
|
4705
|
+
availableModes: availableModes2.map((mode) => ({
|
|
4706
|
+
id: mode.id,
|
|
4707
|
+
name: mode.name,
|
|
4708
|
+
description: mode.description ?? void 0
|
|
4709
|
+
}))
|
|
4710
|
+
};
|
|
4711
|
+
const modelOptions = this.session.configOptions.find(
|
|
4712
|
+
(o) => o.id === "model"
|
|
4713
|
+
);
|
|
4714
|
+
const models = {
|
|
4715
|
+
currentModelId: this.session.modelId ?? DEFAULT_MODEL,
|
|
4716
|
+
availableModels: modelOptions && "options" in modelOptions ? modelOptions.options.map((opt) => ({
|
|
4717
|
+
modelId: opt.value,
|
|
4718
|
+
name: opt.name,
|
|
4719
|
+
description: opt.description
|
|
4720
|
+
})) : []
|
|
4721
|
+
};
|
|
4722
|
+
return {
|
|
4723
|
+
sessionId,
|
|
4724
|
+
modes,
|
|
4725
|
+
models,
|
|
4726
|
+
configOptions: this.session.configOptions
|
|
4727
|
+
};
|
|
4728
|
+
}
|
|
4561
4729
|
buildConfigOptions(currentModeId, modelOptions, currentEffort = "high") {
|
|
4562
4730
|
const modeOptions = getAvailableModes().map((mode) => ({
|
|
4563
4731
|
value: mode.id,
|
|
@@ -4613,7 +4781,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
4613
4781
|
}
|
|
4614
4782
|
return;
|
|
4615
4783
|
}
|
|
4616
|
-
const
|
|
4784
|
+
const rawCurrentValue = existingEffort?.currentValue;
|
|
4785
|
+
const currentValue = typeof rawCurrentValue === "string" ? rawCurrentValue : "high";
|
|
4617
4786
|
const isValidValue = effortOptions.some((o) => o.value === currentValue);
|
|
4618
4787
|
const resolvedValue = isValidValue ? currentValue : "high";
|
|
4619
4788
|
if (resolvedValue !== currentValue && this.session.effort) {
|