@ganglion/xacpx 0.18.0 → 0.18.1
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/bridge/bridge-main.js +616 -60
- package/dist/cli.js +1973 -1949
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -33177,2120 +33177,2141 @@ var init_prompt_media = __esm(() => {
|
|
|
33177
33177
|
};
|
|
33178
33178
|
});
|
|
33179
33179
|
|
|
33180
|
-
// src/transport/
|
|
33181
|
-
|
|
33182
|
-
|
|
33183
|
-
|
|
33184
|
-
|
|
33185
|
-
|
|
33186
|
-
|
|
33187
|
-
edit: "✏️",
|
|
33188
|
-
think: "\uD83E\uDDE0",
|
|
33189
|
-
other: "\uD83D\uDD27"
|
|
33190
|
-
};
|
|
33191
|
-
DEFAULT_TOOL_EMOJI = TOOL_KIND_EMOJI.other;
|
|
33192
|
-
});
|
|
33193
|
-
|
|
33194
|
-
// src/transport/streaming-prompt.ts
|
|
33195
|
-
function createStreamingPromptState(formatToolCalls = false, options) {
|
|
33196
|
-
let toolEventMode;
|
|
33197
|
-
let onToolEvent;
|
|
33198
|
-
let onThought;
|
|
33199
|
-
let onPlan;
|
|
33200
|
-
let onUsage;
|
|
33201
|
-
let onCommands;
|
|
33202
|
-
let rawStream = false;
|
|
33203
|
-
let driver;
|
|
33204
|
-
if (options === undefined) {
|
|
33205
|
-
toolEventMode = "text";
|
|
33206
|
-
onToolEvent = undefined;
|
|
33207
|
-
} else if (typeof options === "function") {
|
|
33208
|
-
onToolEvent = options;
|
|
33209
|
-
toolEventMode = "structured";
|
|
33210
|
-
} else {
|
|
33211
|
-
onToolEvent = options.onToolEvent;
|
|
33212
|
-
onThought = options.onThought;
|
|
33213
|
-
onPlan = options.onPlan;
|
|
33214
|
-
onUsage = options.onUsage;
|
|
33215
|
-
onCommands = options.onCommands;
|
|
33216
|
-
rawStream = options.rawStream ?? false;
|
|
33217
|
-
driver = options.driver?.trim().toLowerCase() || undefined;
|
|
33218
|
-
toolEventMode = resolveToolEventMode({
|
|
33219
|
-
toolEventMode: options.mode,
|
|
33220
|
-
onToolEvent
|
|
33221
|
-
});
|
|
33222
|
-
}
|
|
33223
|
-
return {
|
|
33224
|
-
buffer: "",
|
|
33225
|
-
segments: [],
|
|
33226
|
-
hasAgentMessage: false,
|
|
33227
|
-
pendingLine: "",
|
|
33228
|
-
formatToolCalls,
|
|
33229
|
-
emittedToolCallIds: new Set,
|
|
33230
|
-
toolCalls: new Map,
|
|
33231
|
-
toolEventMode,
|
|
33232
|
-
driver,
|
|
33233
|
-
rawStream,
|
|
33234
|
-
onToolEvent,
|
|
33235
|
-
onThought,
|
|
33236
|
-
onPlan,
|
|
33237
|
-
onUsage,
|
|
33238
|
-
onCommands,
|
|
33239
|
-
finalize() {
|
|
33240
|
-
if (this.pendingLine.trim().length > 0) {
|
|
33241
|
-
parseStreamingChunks(this, this.pendingLine);
|
|
33242
|
-
}
|
|
33243
|
-
const remaining = this.rawStream ? this.buffer : this.buffer.trim();
|
|
33244
|
-
this.buffer = "";
|
|
33245
|
-
this.pendingLine = "";
|
|
33246
|
-
return remaining;
|
|
33247
|
-
}
|
|
33248
|
-
};
|
|
33180
|
+
// src/transport/claude-background-followup.ts
|
|
33181
|
+
import { access as access4, open as open5, readFile as readFile14, readdir as readdir3, stat as stat3 } from "node:fs/promises";
|
|
33182
|
+
import { constants as fsConstants } from "node:fs";
|
|
33183
|
+
import { homedir as homedir10 } from "node:os";
|
|
33184
|
+
import { basename as basename3, dirname as dirname12, join as join20 } from "node:path";
|
|
33185
|
+
function isClaudeAsyncAgentLaunch(event) {
|
|
33186
|
+
return isAsyncAgentLaunchOutput(event.rawOutput);
|
|
33249
33187
|
}
|
|
33250
|
-
function
|
|
33251
|
-
|
|
33252
|
-
|
|
33253
|
-
|
|
33254
|
-
|
|
33255
|
-
|
|
33256
|
-
state.pendingLine = state.pendingLine.slice(boundary + 1);
|
|
33257
|
-
parseStreamingChunks(state, line);
|
|
33188
|
+
function isAsyncAgentLaunchOutput(rawOutput) {
|
|
33189
|
+
const candidate = typeof rawOutput === "string" ? tryParseJsonObject(rawOutput) ?? rawOutput : rawOutput;
|
|
33190
|
+
if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) {
|
|
33191
|
+
const status = candidate.status;
|
|
33192
|
+
if (status !== undefined)
|
|
33193
|
+
return status === "async_launched";
|
|
33258
33194
|
}
|
|
33195
|
+
return ASYNC_AGENT_LAUNCH.test(textOfUnknown(rawOutput));
|
|
33259
33196
|
}
|
|
33260
|
-
function
|
|
33261
|
-
|
|
33262
|
-
if (trimmed.length === 0)
|
|
33197
|
+
function tryParseJsonObject(text) {
|
|
33198
|
+
if (!text.trimStart().startsWith("{"))
|
|
33263
33199
|
return;
|
|
33264
|
-
let event;
|
|
33265
33200
|
try {
|
|
33266
|
-
|
|
33201
|
+
const parsed = JSON.parse(text);
|
|
33202
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : undefined;
|
|
33267
33203
|
} catch {
|
|
33268
33204
|
return;
|
|
33269
33205
|
}
|
|
33270
|
-
|
|
33271
|
-
|
|
33272
|
-
const
|
|
33273
|
-
if (
|
|
33274
|
-
return;
|
|
33275
|
-
|
|
33276
|
-
|
|
33277
|
-
|
|
33278
|
-
|
|
33279
|
-
|
|
33280
|
-
|
|
33281
|
-
|
|
33282
|
-
|
|
33283
|
-
|
|
33284
|
-
|
|
33285
|
-
|
|
33286
|
-
if (
|
|
33287
|
-
|
|
33288
|
-
|
|
33289
|
-
|
|
33290
|
-
|
|
33291
|
-
state.emittedToolCallIds.add(toolCallId);
|
|
33292
|
-
}
|
|
33293
|
-
state.segments.push(formatted);
|
|
33294
|
-
}
|
|
33206
|
+
}
|
|
33207
|
+
function claudeAsyncAgentId(event) {
|
|
33208
|
+
const fromObject = findStringField(event.rawOutput, new Set(["agentId", "agent_id"]));
|
|
33209
|
+
if (fromObject)
|
|
33210
|
+
return fromObject;
|
|
33211
|
+
return /\bagent(?:Id|_id)["']?\s*[:=]\s*["']?([A-Za-z0-9_-]+)/i.exec(textOfUnknown(event.rawOutput))?.[1];
|
|
33212
|
+
}
|
|
33213
|
+
async function findClaudeTranscriptPath(input) {
|
|
33214
|
+
const configDirName = input.driver === "qoder" ? ".qoder" : ".claude";
|
|
33215
|
+
const projectsDir = join20(input.homeDir ?? homedir10(), configDirName, "projects");
|
|
33216
|
+
const direct = join20(projectsDir, encodeClaudeProjectDirectory(input.cwd), `${input.sessionId}.jsonl`);
|
|
33217
|
+
if (await exists(direct))
|
|
33218
|
+
return direct;
|
|
33219
|
+
try {
|
|
33220
|
+
const entries = await readdir3(projectsDir, { withFileTypes: true });
|
|
33221
|
+
for (const entry of entries) {
|
|
33222
|
+
if (!entry.isDirectory())
|
|
33223
|
+
continue;
|
|
33224
|
+
const candidate = join20(projectsDir, entry.name, `${input.sessionId}.jsonl`);
|
|
33225
|
+
if (await exists(candidate))
|
|
33226
|
+
return candidate;
|
|
33295
33227
|
}
|
|
33228
|
+
} catch {
|
|
33296
33229
|
return;
|
|
33297
33230
|
}
|
|
33298
|
-
|
|
33299
|
-
|
|
33300
|
-
|
|
33301
|
-
|
|
33302
|
-
|
|
33303
|
-
|
|
33304
|
-
if (update.sessionUpdate === "usage_update") {
|
|
33305
|
-
const used = typeof update.used === "number" && Number.isFinite(update.used) ? update.used : undefined;
|
|
33306
|
-
const size = typeof update.size === "number" && Number.isFinite(update.size) ? update.size : undefined;
|
|
33307
|
-
if (used !== undefined && size !== undefined && size > 0) {
|
|
33308
|
-
const cost = normalizeUsageCost(update.cost);
|
|
33309
|
-
const breakdown = normalizeUsageBreakdown(update._meta?.usage);
|
|
33310
|
-
state.onUsage?.({ used, size, ...cost ? { cost } : {}, ...breakdown ? { breakdown } : {} });
|
|
33311
|
-
}
|
|
33312
|
-
return;
|
|
33231
|
+
return;
|
|
33232
|
+
}
|
|
33233
|
+
async function followClaudeBackgroundTurn(options) {
|
|
33234
|
+
const transcriptPath = options.transcriptPath ?? await findClaudeTranscriptPath(options);
|
|
33235
|
+
if (!transcriptPath) {
|
|
33236
|
+
return { status: "unavailable", completedToolCallIds: [], failedToolCallIds: [] };
|
|
33313
33237
|
}
|
|
33314
|
-
|
|
33315
|
-
|
|
33316
|
-
|
|
33317
|
-
|
|
33318
|
-
return;
|
|
33238
|
+
let initial;
|
|
33239
|
+
try {
|
|
33240
|
+
initial = await readFile14(transcriptPath);
|
|
33241
|
+
} catch {
|
|
33242
|
+
return { status: "unavailable", transcriptPath, completedToolCallIds: [], failedToolCallIds: [] };
|
|
33319
33243
|
}
|
|
33320
|
-
const
|
|
33321
|
-
|
|
33322
|
-
|
|
33323
|
-
|
|
33324
|
-
|
|
33325
|
-
|
|
33326
|
-
|
|
33244
|
+
const initialCompleteEnd = initial.lastIndexOf(10);
|
|
33245
|
+
const initialComplete = initial.subarray(0, initialCompleteEnd >= 0 ? initialCompleteEnd : 0).toString("utf8");
|
|
33246
|
+
const mainCursor = {
|
|
33247
|
+
offset: initial.length,
|
|
33248
|
+
partial: initialCompleteEnd >= 0 ? initial.subarray(initialCompleteEnd + 1).toString("utf8") : initial.toString("utf8")
|
|
33249
|
+
};
|
|
33250
|
+
const initialRecords = initialComplete.split(`
|
|
33251
|
+
`).map(parseRecord);
|
|
33252
|
+
const launched = new Set([...options.launchedToolCallIds].filter(Boolean));
|
|
33253
|
+
const completed = new Set;
|
|
33254
|
+
const failed = new Set;
|
|
33255
|
+
const toolEvents = new Map;
|
|
33256
|
+
for (const event of options.initialToolEvents ?? [])
|
|
33257
|
+
toolEvents.set(event.toolCallId, event);
|
|
33258
|
+
const parentToolCallIdByAgentId = new Map;
|
|
33259
|
+
for (const [toolCallId, agentId] of options.subagentIdsByToolCallId ?? []) {
|
|
33260
|
+
if (toolCallId && agentId)
|
|
33261
|
+
parentToolCallIdByAgentId.set(agentId, toolCallId);
|
|
33327
33262
|
}
|
|
33328
|
-
const
|
|
33329
|
-
|
|
33330
|
-
|
|
33331
|
-
|
|
33332
|
-
|
|
33333
|
-
|
|
33334
|
-
|
|
33335
|
-
|
|
33336
|
-
|
|
33337
|
-
|
|
33338
|
-
|
|
33339
|
-
|
|
33340
|
-
|
|
33341
|
-
|
|
33342
|
-
const
|
|
33343
|
-
|
|
33344
|
-
|
|
33345
|
-
|
|
33263
|
+
const boundary = findPromptBoundary(initialRecords, launched);
|
|
33264
|
+
let launchSeen = boundary >= 0 || initialRecords.some((record3) => hasTrackedLaunch(record3, launched));
|
|
33265
|
+
let boundarySeen = boundary >= 0;
|
|
33266
|
+
let sequence = 0;
|
|
33267
|
+
let lastNotificationSequence = -1;
|
|
33268
|
+
let done = false;
|
|
33269
|
+
const emitTool = async (event) => {
|
|
33270
|
+
toolEvents.set(event.toolCallId, event);
|
|
33271
|
+
await options.onToolEvent?.(event);
|
|
33272
|
+
};
|
|
33273
|
+
const processRecord = async (record3) => {
|
|
33274
|
+
if (!record3)
|
|
33275
|
+
return;
|
|
33276
|
+
sequence += 1;
|
|
33277
|
+
const blocks = contentBlocks(record3.message?.content);
|
|
33278
|
+
if (record3.type === "user") {
|
|
33279
|
+
const userText = blocks.map(blockText).filter(Boolean).join(`
|
|
33280
|
+
`);
|
|
33281
|
+
for (const notification of taskNotifications(userText)) {
|
|
33282
|
+
if (launched.has(notification.toolCallId)) {
|
|
33283
|
+
completed.add(notification.toolCallId);
|
|
33284
|
+
if (notification.failed)
|
|
33285
|
+
failed.add(notification.toolCallId);
|
|
33286
|
+
lastNotificationSequence = sequence;
|
|
33287
|
+
const previous = toolEvents.get(notification.toolCallId);
|
|
33288
|
+
if (previous) {
|
|
33289
|
+
await emitTool({
|
|
33290
|
+
...previous,
|
|
33291
|
+
status: notification.failed ? "error" : "success",
|
|
33292
|
+
...notification.failed ? { rawOutput: { message: "background Agent failed" } } : {}
|
|
33293
|
+
});
|
|
33294
|
+
}
|
|
33295
|
+
}
|
|
33296
|
+
}
|
|
33297
|
+
for (const block of blocks) {
|
|
33298
|
+
if (readString(block, "type") !== "tool_result")
|
|
33299
|
+
continue;
|
|
33300
|
+
const toolCallId = readString(block, "tool_use_id");
|
|
33301
|
+
if (!toolCallId)
|
|
33302
|
+
continue;
|
|
33303
|
+
const output = blockText(block);
|
|
33304
|
+
if (ASYNC_AGENT_LAUNCH.test(output))
|
|
33305
|
+
launched.add(toolCallId);
|
|
33306
|
+
const previous = toolEvents.get(toolCallId);
|
|
33307
|
+
await emitTool({
|
|
33308
|
+
toolCallId,
|
|
33309
|
+
toolName: previous?.toolName ?? "Tool",
|
|
33310
|
+
kind: previous?.kind ?? "other",
|
|
33311
|
+
...previous?.parentToolCallId ? { parentToolCallId: previous.parentToolCallId } : {},
|
|
33312
|
+
...previous?.isSubagent ? { isSubagent: true } : {},
|
|
33313
|
+
...previous?.summary ? { summary: previous.summary } : {},
|
|
33314
|
+
...previous?.rawInput !== undefined ? { rawInput: previous.rawInput } : {},
|
|
33315
|
+
...output ? { rawOutput: output } : {},
|
|
33316
|
+
status: readBoolean(block, "is_error") ? "error" : "success"
|
|
33317
|
+
});
|
|
33318
|
+
}
|
|
33319
|
+
return;
|
|
33346
33320
|
}
|
|
33347
|
-
|
|
33348
|
-
|
|
33349
|
-
|
|
33350
|
-
|
|
33351
|
-
|
|
33352
|
-
|
|
33353
|
-
|
|
33354
|
-
|
|
33355
|
-
|
|
33356
|
-
|
|
33357
|
-
|
|
33358
|
-
|
|
33359
|
-
|
|
33360
|
-
|
|
33361
|
-
|
|
33362
|
-
|
|
33363
|
-
|
|
33364
|
-
|
|
33365
|
-
|
|
33366
|
-
|
|
33367
|
-
|
|
33368
|
-
|
|
33369
|
-
|
|
33370
|
-
|
|
33371
|
-
|
|
33372
|
-
|
|
33373
|
-
|
|
33374
|
-
if (typeof v === "object")
|
|
33375
|
-
return Object.keys(v).length === 0;
|
|
33376
|
-
return false;
|
|
33377
|
-
}
|
|
33378
|
-
function mergeToolCallUpdate(state, toolCallId, update) {
|
|
33379
|
-
const prev = state.toolCalls.get(toolCallId) ?? { toolCallId };
|
|
33380
|
-
const merged = { ...prev };
|
|
33381
|
-
for (const key of ["kind", "title", "rawInput", "content", "rawOutput", "locations", "status"]) {
|
|
33382
|
-
const next = update[key];
|
|
33383
|
-
if (!isEmptyToolField(next))
|
|
33384
|
-
merged[key] = next;
|
|
33385
|
-
}
|
|
33386
|
-
const nextMeta = update._meta;
|
|
33387
|
-
if (nextMeta) {
|
|
33388
|
-
const previousMeta = merged._meta;
|
|
33389
|
-
merged._meta = {
|
|
33390
|
-
...previousMeta,
|
|
33391
|
-
...nextMeta,
|
|
33392
|
-
...previousMeta?.qoder || nextMeta.qoder ? { qoder: { ...previousMeta?.qoder, ...nextMeta.qoder } } : {},
|
|
33393
|
-
...previousMeta?.codex || nextMeta.codex ? {
|
|
33394
|
-
codex: {
|
|
33395
|
-
...previousMeta?.codex,
|
|
33396
|
-
...nextMeta.codex,
|
|
33397
|
-
...previousMeta?.codex?.subagent || nextMeta.codex?.subagent ? { subagent: { ...previousMeta?.codex?.subagent, ...nextMeta.codex?.subagent } } : {}
|
|
33398
|
-
}
|
|
33399
|
-
} : {},
|
|
33400
|
-
...previousMeta?.claudeCode || nextMeta.claudeCode ? { claudeCode: { ...previousMeta?.claudeCode, ...nextMeta.claudeCode } } : {}
|
|
33401
|
-
};
|
|
33402
|
-
}
|
|
33403
|
-
merged.toolCallId = toolCallId;
|
|
33404
|
-
state.toolCalls.set(toolCallId, merged);
|
|
33405
|
-
return merged;
|
|
33406
|
-
}
|
|
33407
|
-
function buildToolUseEvent(update, driver) {
|
|
33408
|
-
if (!update)
|
|
33409
|
-
return null;
|
|
33410
|
-
const toolCallId = update.toolCallId;
|
|
33411
|
-
if (!toolCallId)
|
|
33412
|
-
return null;
|
|
33413
|
-
const kindRaw = update.kind ?? "";
|
|
33414
|
-
const kind = (() => {
|
|
33415
|
-
switch (kindRaw) {
|
|
33416
|
-
case "read":
|
|
33417
|
-
case "search":
|
|
33418
|
-
case "execute":
|
|
33419
|
-
case "edit":
|
|
33420
|
-
case "think":
|
|
33421
|
-
return kindRaw;
|
|
33422
|
-
default:
|
|
33423
|
-
return "other";
|
|
33424
|
-
}
|
|
33425
|
-
})();
|
|
33426
|
-
const title = (update.title ?? "").trim();
|
|
33427
|
-
const toolName = title || "Tool";
|
|
33428
|
-
const summaryRaw = summarizeToolInput(update.rawInput, title) || summarizeToolInput(update.rawOutput, title);
|
|
33429
|
-
const summary = summaryRaw && summaryRaw !== title ? summaryRaw : undefined;
|
|
33430
|
-
const statusRaw = readString(update, "status");
|
|
33431
|
-
const isClaudeDriver = driver === undefined || driver === "claude";
|
|
33432
|
-
const claudeMeta = isClaudeDriver ? update._meta?.claudeCode : undefined;
|
|
33433
|
-
const claudeToolResponse = claudeMeta?.toolResponse;
|
|
33434
|
-
const hasClaudeToolResponse = !isEmptyToolField(claudeToolResponse);
|
|
33435
|
-
const isAsyncAgentLaunch = update._meta?.claudeCode?.toolName === "Agent" && isRecord4(claudeToolResponse) && claudeToolResponse.status === "async_launched";
|
|
33436
|
-
const status = isAsyncAgentLaunch ? "running" : statusRaw === "completed" || statusRaw === "success" ? "success" : statusRaw === "failed" || statusRaw === "error" ? "error" : hasClaudeToolResponse ? "success" : "running";
|
|
33437
|
-
const rawInput = update.rawInput;
|
|
33438
|
-
const content = update.content;
|
|
33439
|
-
const rawOutput = update.rawOutput ?? claudeToolResponse;
|
|
33440
|
-
const locations = update.locations;
|
|
33441
|
-
const parentToolCallId = claudeMeta?.parentToolUseId?.trim();
|
|
33442
|
-
const isSubagent = claudeMeta?.toolName === "Agent" || driver === "qoder" && update._meta?.qoder?.toolName === "Agent" || driver === "kimi" && isKimiSubagentInput(rawInput) || driver === "codex" && isCodexSubagentMeta(update._meta?.codex?.subagent);
|
|
33443
|
-
return {
|
|
33444
|
-
toolCallId,
|
|
33445
|
-
...parentToolCallId ? { parentToolCallId } : {},
|
|
33446
|
-
...isSubagent ? { isSubagent: true } : {},
|
|
33447
|
-
toolName,
|
|
33448
|
-
kind,
|
|
33449
|
-
...summary ? { summary } : {},
|
|
33450
|
-
...rawInput !== undefined ? { rawInput } : {},
|
|
33451
|
-
...content !== undefined ? { content } : {},
|
|
33452
|
-
...rawOutput !== undefined ? { rawOutput } : {},
|
|
33453
|
-
...locations !== undefined ? { locations } : {},
|
|
33454
|
-
status
|
|
33455
|
-
};
|
|
33456
|
-
}
|
|
33457
|
-
function isKimiSubagentInput(rawInput) {
|
|
33458
|
-
return isRecord4(rawInput) && readFirstString(rawInput, ["prompt"]) !== undefined && readFirstString(rawInput, ["subagent_type", "subagentType"]) !== undefined;
|
|
33459
|
-
}
|
|
33460
|
-
function isCodexSubagentMeta(meta2) {
|
|
33461
|
-
return typeof meta2?.threadId === "string" && meta2.threadId.trim().length > 0 && typeof meta2.activity === "string" && meta2.activity.trim().length > 0;
|
|
33462
|
-
}
|
|
33463
|
-
function summarizeToolInput(rawInput, title = "") {
|
|
33464
|
-
if (rawInput == null)
|
|
33465
|
-
return;
|
|
33466
|
-
if (typeof rawInput === "string" || typeof rawInput === "number" || typeof rawInput === "boolean") {
|
|
33467
|
-
return String(rawInput);
|
|
33468
|
-
}
|
|
33469
|
-
if (!isRecord4(rawInput))
|
|
33470
|
-
return;
|
|
33471
|
-
const taskSummary = summarizeTaskInput(rawInput, title);
|
|
33472
|
-
if (taskSummary)
|
|
33473
|
-
return taskSummary;
|
|
33474
|
-
const command = readFirstString(rawInput, ["command", "cmd", "program"]);
|
|
33475
|
-
const args = readFirstStringArray(rawInput, ["args", "arguments"]);
|
|
33476
|
-
if (command) {
|
|
33477
|
-
return [command, ...args ?? []].join(" ");
|
|
33478
|
-
}
|
|
33479
|
-
const parsedCmd = rawInput.parsed_cmd;
|
|
33480
|
-
if (Array.isArray(parsedCmd) && parsedCmd.length > 0) {
|
|
33481
|
-
const parts = [];
|
|
33482
|
-
for (const entry of parsedCmd) {
|
|
33483
|
-
if (isRecord4(entry) && typeof entry.cmd === "string" && entry.cmd.length > 0) {
|
|
33484
|
-
parts.push(entry.cmd);
|
|
33321
|
+
if (record3.type !== "assistant" || record3.isSidechain === true)
|
|
33322
|
+
return;
|
|
33323
|
+
for (const block of blocks) {
|
|
33324
|
+
const type = readString(block, "type");
|
|
33325
|
+
if (type === "text") {
|
|
33326
|
+
const text = readString(block, "text");
|
|
33327
|
+
if (text)
|
|
33328
|
+
await options.onText?.(text);
|
|
33329
|
+
} else if (type === "thinking") {
|
|
33330
|
+
const thought = readString(block, "thinking");
|
|
33331
|
+
if (thought)
|
|
33332
|
+
await options.onThought?.(thought);
|
|
33333
|
+
} else if (type === "tool_use") {
|
|
33334
|
+
const toolCallId = readString(block, "id");
|
|
33335
|
+
if (!toolCallId)
|
|
33336
|
+
continue;
|
|
33337
|
+
const name = readString(block, "name") ?? "Tool";
|
|
33338
|
+
const rawInput = block.input;
|
|
33339
|
+
const event = {
|
|
33340
|
+
toolCallId,
|
|
33341
|
+
toolName: name,
|
|
33342
|
+
kind: classifyToolKind(name),
|
|
33343
|
+
...toolSummary(rawInput) ? { summary: toolSummary(rawInput) } : {},
|
|
33344
|
+
...rawInput !== undefined ? { rawInput } : {},
|
|
33345
|
+
status: "running"
|
|
33346
|
+
};
|
|
33347
|
+
await emitTool(event);
|
|
33485
33348
|
}
|
|
33486
33349
|
}
|
|
33487
|
-
if (
|
|
33488
|
-
|
|
33489
|
-
}
|
|
33490
|
-
}
|
|
33491
|
-
return readFirstString(rawInput, [
|
|
33492
|
-
"path",
|
|
33493
|
-
"file",
|
|
33494
|
-
"filePath",
|
|
33495
|
-
"filepath",
|
|
33496
|
-
"file_path",
|
|
33497
|
-
"target",
|
|
33498
|
-
"uri",
|
|
33499
|
-
"url",
|
|
33500
|
-
"query",
|
|
33501
|
-
"pattern",
|
|
33502
|
-
"text",
|
|
33503
|
-
"search",
|
|
33504
|
-
"name",
|
|
33505
|
-
"description"
|
|
33506
|
-
]);
|
|
33507
|
-
}
|
|
33508
|
-
function summarizeTaskInput(rawInput, title) {
|
|
33509
|
-
const subagentType = readFirstString(rawInput, ["subagent_type", "subagentType", "agent", "agentType"]);
|
|
33510
|
-
const description = readFirstString(rawInput, ["description", "task", "summary"]);
|
|
33511
|
-
if (subagentType && description) {
|
|
33512
|
-
return description === title ? subagentType : `${subagentType}: ${description}`;
|
|
33513
|
-
}
|
|
33514
|
-
if (subagentType)
|
|
33515
|
-
return subagentType;
|
|
33516
|
-
return;
|
|
33517
|
-
}
|
|
33518
|
-
function readFirstString(record3, keys) {
|
|
33519
|
-
for (const key of keys) {
|
|
33520
|
-
const value = record3[key];
|
|
33521
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
33522
|
-
return value.trim();
|
|
33523
|
-
}
|
|
33524
|
-
}
|
|
33525
|
-
return;
|
|
33526
|
-
}
|
|
33527
|
-
function readFirstStringArray(record3, keys) {
|
|
33528
|
-
for (const key of keys) {
|
|
33529
|
-
const value = record3[key];
|
|
33530
|
-
if (!Array.isArray(value))
|
|
33531
|
-
continue;
|
|
33532
|
-
const entries = value.map((entry) => typeof entry === "string" && entry.trim().length > 0 ? entry.trim() : undefined).filter((entry) => entry !== undefined);
|
|
33533
|
-
if (entries.length > 0) {
|
|
33534
|
-
return entries;
|
|
33350
|
+
if (record3.message?.stop_reason === "end_turn" && launched.size > 0 && [...launched].every((id) => completed.has(id)) && lastNotificationSequence >= 0 && sequence > lastNotificationSequence) {
|
|
33351
|
+
done = true;
|
|
33535
33352
|
}
|
|
33536
|
-
}
|
|
33537
|
-
|
|
33538
|
-
|
|
33539
|
-
|
|
33540
|
-
|
|
33541
|
-
|
|
33542
|
-
|
|
33543
|
-
|
|
33544
|
-
|
|
33545
|
-
if (n !== undefined)
|
|
33546
|
-
return n;
|
|
33547
|
-
}
|
|
33548
|
-
return;
|
|
33549
|
-
}
|
|
33550
|
-
function normalizeUsageBreakdown(value) {
|
|
33551
|
-
if (!isRecord4(value))
|
|
33552
|
-
return;
|
|
33553
|
-
const out = {};
|
|
33554
|
-
for (const [key, aliases] of USAGE_BREAKDOWN_FIELDS) {
|
|
33555
|
-
const n = firstFiniteNumber(value, aliases);
|
|
33556
|
-
if (n !== undefined)
|
|
33557
|
-
out[key] = n;
|
|
33558
|
-
}
|
|
33559
|
-
return Object.keys(out).length > 0 ? out : undefined;
|
|
33560
|
-
}
|
|
33561
|
-
function normalizeUsageCost(value) {
|
|
33562
|
-
if (!isRecord4(value))
|
|
33563
|
-
return;
|
|
33564
|
-
const amount = asFiniteNumber(value.amount);
|
|
33565
|
-
const currency = readString(value, "currency");
|
|
33566
|
-
if (amount === undefined && !currency)
|
|
33567
|
-
return;
|
|
33568
|
-
return { ...amount !== undefined ? { amount } : {}, ...currency ? { currency } : {} };
|
|
33569
|
-
}
|
|
33570
|
-
function normalizeAgentCommands(value) {
|
|
33571
|
-
if (!Array.isArray(value))
|
|
33572
|
-
return [];
|
|
33573
|
-
const out = [];
|
|
33574
|
-
for (const entry of value) {
|
|
33575
|
-
if (!isRecord4(entry))
|
|
33576
|
-
continue;
|
|
33577
|
-
const name = readString(entry, "name");
|
|
33578
|
-
if (!name)
|
|
33579
|
-
continue;
|
|
33580
|
-
const description = readString(entry, "description");
|
|
33581
|
-
out.push({ name, ...description ? { description } : {}, hasInput: entry.input != null });
|
|
33582
|
-
}
|
|
33583
|
-
return out;
|
|
33584
|
-
}
|
|
33585
|
-
function isRecord4(value) {
|
|
33586
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33587
|
-
}
|
|
33588
|
-
function readString(rawInput, key) {
|
|
33589
|
-
if (!isRecord4(rawInput))
|
|
33590
|
-
return;
|
|
33591
|
-
const value = rawInput[key];
|
|
33592
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
33593
|
-
}
|
|
33594
|
-
function truncateToolDisplay(text) {
|
|
33595
|
-
return text.length > 60 ? `${text.slice(0, 57)}...` : text;
|
|
33596
|
-
}
|
|
33597
|
-
function isGenericToolTitle(kind, title) {
|
|
33598
|
-
const normalizedTitle = title.trim().toLowerCase();
|
|
33599
|
-
if (kind === "execute" && ["bash", "shell", "sh", "powershell", "cmd"].includes(normalizedTitle)) {
|
|
33600
|
-
return true;
|
|
33601
|
-
}
|
|
33602
|
-
if (kind === "search" && ["grep", "rg", "search"].includes(normalizedTitle)) {
|
|
33603
|
-
return true;
|
|
33604
|
-
}
|
|
33605
|
-
if (kind === "read" && ["read", "cat"].includes(normalizedTitle)) {
|
|
33606
|
-
return true;
|
|
33607
|
-
}
|
|
33608
|
-
return false;
|
|
33609
|
-
}
|
|
33610
|
-
var USAGE_BREAKDOWN_FIELDS;
|
|
33611
|
-
var init_streaming_prompt = __esm(() => {
|
|
33612
|
-
init_tool_kind_emoji();
|
|
33613
|
-
USAGE_BREAKDOWN_FIELDS = [
|
|
33614
|
-
["inputTokens", ["inputTokens", "input_tokens"]],
|
|
33615
|
-
["outputTokens", ["outputTokens", "output_tokens"]],
|
|
33616
|
-
["cachedReadTokens", ["cachedReadTokens", "cacheReadInputTokens", "cache_read_input_tokens"]],
|
|
33617
|
-
["cachedWriteTokens", ["cachedWriteTokens", "cacheCreationInputTokens", "cache_creation_input_tokens"]],
|
|
33618
|
-
["thoughtTokens", ["thoughtTokens", "thought_tokens"]],
|
|
33619
|
-
["totalTokens", ["totalTokens", "total_tokens"]]
|
|
33620
|
-
];
|
|
33621
|
-
});
|
|
33622
|
-
|
|
33623
|
-
// src/transport/acpx-cli/node-pty-helper.ts
|
|
33624
|
-
import { chmod as chmodFs } from "node:fs/promises";
|
|
33625
|
-
import { dirname as dirname12, join as join20 } from "node:path";
|
|
33626
|
-
function resolveNodePtyHelperPath(packageJsonPath, platform, arch) {
|
|
33627
|
-
if (platform === "win32") {
|
|
33628
|
-
return null;
|
|
33629
|
-
}
|
|
33630
|
-
return join20(dirname12(packageJsonPath), "prebuilds", `${platform}-${arch}`, "spawn-helper");
|
|
33631
|
-
}
|
|
33632
|
-
async function ensureNodePtyHelperExecutable(helperPath, chmod5 = chmodFs) {
|
|
33633
|
-
if (!helperPath) {
|
|
33634
|
-
return;
|
|
33635
|
-
}
|
|
33636
|
-
try {
|
|
33637
|
-
await chmod5(helperPath, 493);
|
|
33638
|
-
} catch (error2) {
|
|
33639
|
-
if (error2.code === "ENOENT") {
|
|
33353
|
+
};
|
|
33354
|
+
const processAfterBoundary = async (record3) => {
|
|
33355
|
+
if (!record3)
|
|
33356
|
+
return;
|
|
33357
|
+
if (!boundarySeen) {
|
|
33358
|
+
if (hasTrackedLaunch(record3, launched))
|
|
33359
|
+
launchSeen = true;
|
|
33360
|
+
if (launchSeen && isMainEndTurn(record3))
|
|
33361
|
+
boundarySeen = true;
|
|
33640
33362
|
return;
|
|
33641
33363
|
}
|
|
33642
|
-
|
|
33643
|
-
}
|
|
33644
|
-
}
|
|
33645
|
-
var init_node_pty_helper = () => {};
|
|
33646
|
-
|
|
33647
|
-
// src/transport/codex-subagent-filter.ts
|
|
33648
|
-
import { closeSync, openSync, readdirSync, readSync, statSync as statSync2 } from "node:fs";
|
|
33649
|
-
import { homedir as homedir10 } from "node:os";
|
|
33650
|
-
import { join as join21 } from "node:path";
|
|
33651
|
-
function resolveCodexHome(env = process.env) {
|
|
33652
|
-
const fromEnv = env.CODEX_HOME?.trim();
|
|
33653
|
-
return fromEnv ? fromEnv : join21(homedir10(), ".codex");
|
|
33654
|
-
}
|
|
33655
|
-
function isPlainObject3(value) {
|
|
33656
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
33657
|
-
}
|
|
33658
|
-
function isSubagentSource(source) {
|
|
33659
|
-
if (!isPlainObject3(source) || !Object.hasOwn(source, "subagent"))
|
|
33660
|
-
return false;
|
|
33661
|
-
const subagent = source.subagent;
|
|
33662
|
-
if (!isPlainObject3(subagent))
|
|
33663
|
-
return false;
|
|
33664
|
-
return Object.values(subagent).some((variant) => isPlainObject3(variant) && typeof variant.parent_thread_id === "string");
|
|
33665
|
-
}
|
|
33666
|
-
function sessionMetaLineIsSubagent(line) {
|
|
33667
|
-
if (!line)
|
|
33668
|
-
return false;
|
|
33669
|
-
let parsed;
|
|
33670
|
-
try {
|
|
33671
|
-
parsed = JSON.parse(line);
|
|
33672
|
-
} catch {
|
|
33673
|
-
return false;
|
|
33674
|
-
}
|
|
33675
|
-
const payload = parsed?.payload;
|
|
33676
|
-
return isSubagentSource(payload?.source);
|
|
33677
|
-
}
|
|
33678
|
-
function createSubagentPredicate(reader) {
|
|
33679
|
-
let index = null;
|
|
33680
|
-
const cache = new Map;
|
|
33681
|
-
return (sessionId) => {
|
|
33682
|
-
const cached2 = cache.get(sessionId);
|
|
33683
|
-
if (cached2 !== undefined)
|
|
33684
|
-
return cached2;
|
|
33685
|
-
let result = false;
|
|
33686
|
-
try {
|
|
33687
|
-
if (!index) {
|
|
33688
|
-
index = new Map;
|
|
33689
|
-
for (const path15 of reader.listRolloutPaths()) {
|
|
33690
|
-
const id = path15.match(ROLLOUT_RE)?.[1];
|
|
33691
|
-
if (id)
|
|
33692
|
-
index.set(id.toLowerCase(), path15);
|
|
33693
|
-
}
|
|
33694
|
-
}
|
|
33695
|
-
const path14 = index.get(sessionId.toLowerCase());
|
|
33696
|
-
if (path14)
|
|
33697
|
-
result = sessionMetaLineIsSubagent(reader.readFirstLine(path14));
|
|
33698
|
-
} catch {
|
|
33699
|
-
result = false;
|
|
33700
|
-
}
|
|
33701
|
-
cache.set(sessionId, result);
|
|
33702
|
-
return result;
|
|
33364
|
+
await processRecord(record3);
|
|
33703
33365
|
};
|
|
33704
|
-
|
|
33705
|
-
|
|
33706
|
-
|
|
33707
|
-
|
|
33708
|
-
|
|
33709
|
-
|
|
33710
|
-
|
|
33711
|
-
|
|
33712
|
-
|
|
33366
|
+
const processSubagentRecord = async (record3, parentToolCallId) => {
|
|
33367
|
+
if (!record3)
|
|
33368
|
+
return;
|
|
33369
|
+
const blocks = contentBlocks(record3.message?.content);
|
|
33370
|
+
if (record3.type === "assistant") {
|
|
33371
|
+
for (const block of blocks) {
|
|
33372
|
+
if (readString(block, "type") !== "tool_use")
|
|
33373
|
+
continue;
|
|
33374
|
+
const toolCallId = readString(block, "id");
|
|
33375
|
+
if (!toolCallId)
|
|
33376
|
+
continue;
|
|
33377
|
+
const name = readString(block, "name") ?? "Tool";
|
|
33378
|
+
const rawInput = block.input;
|
|
33379
|
+
const previous = toolEvents.get(toolCallId);
|
|
33380
|
+
await emitTool({
|
|
33381
|
+
...previous,
|
|
33382
|
+
toolCallId,
|
|
33383
|
+
parentToolCallId: previous?.parentToolCallId ?? parentToolCallId,
|
|
33384
|
+
...previous?.isSubagent || isAgentToolName(name) ? { isSubagent: true } : {},
|
|
33385
|
+
toolName: previous?.toolName ?? name,
|
|
33386
|
+
kind: previous?.kind ?? classifyToolKind(name),
|
|
33387
|
+
...previous?.summary ? { summary: previous.summary } : toolSummary(rawInput) ? { summary: toolSummary(rawInput) } : {},
|
|
33388
|
+
...previous?.rawInput !== undefined ? { rawInput: previous.rawInput } : rawInput !== undefined ? { rawInput } : {},
|
|
33389
|
+
status: previous?.status === "success" || previous?.status === "error" ? previous.status : "running"
|
|
33390
|
+
});
|
|
33713
33391
|
}
|
|
33714
|
-
|
|
33715
|
-
|
|
33716
|
-
|
|
33717
|
-
|
|
33718
|
-
|
|
33719
|
-
|
|
33720
|
-
|
|
33721
|
-
const
|
|
33722
|
-
|
|
33723
|
-
|
|
33724
|
-
|
|
33725
|
-
|
|
33726
|
-
|
|
33727
|
-
|
|
33728
|
-
|
|
33729
|
-
|
|
33730
|
-
|
|
33731
|
-
|
|
33732
|
-
|
|
33733
|
-
|
|
33734
|
-
|
|
33735
|
-
}
|
|
33736
|
-
|
|
33737
|
-
|
|
33738
|
-
|
|
33739
|
-
|
|
33740
|
-
|
|
33741
|
-
|
|
33742
|
-
try {
|
|
33743
|
-
statSync2(path14);
|
|
33744
|
-
fd = openSync(path14, "r");
|
|
33745
|
-
const buf = Buffer.alloc(READ_CHUNK);
|
|
33746
|
-
let acc = "";
|
|
33747
|
-
let total = 0;
|
|
33748
|
-
for (;; ) {
|
|
33749
|
-
const bytes = readSync(fd, buf, 0, READ_CHUNK, total);
|
|
33750
|
-
if (bytes <= 0)
|
|
33751
|
-
break;
|
|
33752
|
-
acc += buf.toString("utf8", 0, bytes);
|
|
33753
|
-
total += bytes;
|
|
33754
|
-
const nl = acc.indexOf(`
|
|
33755
|
-
`);
|
|
33756
|
-
if (nl !== -1)
|
|
33757
|
-
return acc.slice(0, nl);
|
|
33758
|
-
if (total >= FIRST_LINE_READ_CAP)
|
|
33759
|
-
return;
|
|
33760
|
-
}
|
|
33761
|
-
return acc.length ? acc : undefined;
|
|
33762
|
-
} catch {
|
|
33763
|
-
return;
|
|
33764
|
-
} finally {
|
|
33765
|
-
if (fd !== undefined) {
|
|
33766
|
-
try {
|
|
33767
|
-
closeSync(fd);
|
|
33768
|
-
} catch {}
|
|
33769
|
-
}
|
|
33392
|
+
return;
|
|
33393
|
+
}
|
|
33394
|
+
if (record3.type !== "user")
|
|
33395
|
+
return;
|
|
33396
|
+
for (const block of blocks) {
|
|
33397
|
+
if (readString(block, "type") !== "tool_result")
|
|
33398
|
+
continue;
|
|
33399
|
+
const toolCallId = readString(block, "tool_use_id");
|
|
33400
|
+
if (!toolCallId)
|
|
33401
|
+
continue;
|
|
33402
|
+
const previous = toolEvents.get(toolCallId);
|
|
33403
|
+
const output = blockText(block);
|
|
33404
|
+
const event = {
|
|
33405
|
+
...previous,
|
|
33406
|
+
toolCallId,
|
|
33407
|
+
parentToolCallId: previous?.parentToolCallId ?? parentToolCallId,
|
|
33408
|
+
...previous?.isSubagent ? { isSubagent: true } : {},
|
|
33409
|
+
toolName: previous?.toolName ?? "Tool",
|
|
33410
|
+
kind: previous?.kind ?? "other",
|
|
33411
|
+
...previous?.summary ? { summary: previous.summary } : {},
|
|
33412
|
+
...previous?.rawInput !== undefined ? { rawInput: previous.rawInput } : {},
|
|
33413
|
+
...previous?.rawOutput !== undefined ? { rawOutput: previous.rawOutput } : output ? { rawOutput: output } : {},
|
|
33414
|
+
status: readBoolean(block, "is_error") || previous?.status === "error" ? "error" : "success"
|
|
33415
|
+
};
|
|
33416
|
+
if (event.isSubagent && isClaudeAsyncAgentLaunch(event)) {
|
|
33417
|
+
const agentId = claudeAsyncAgentId(event);
|
|
33418
|
+
if (agentId)
|
|
33419
|
+
parentToolCallIdByAgentId.set(agentId, event.toolCallId);
|
|
33770
33420
|
}
|
|
33421
|
+
await emitTool(event);
|
|
33771
33422
|
}
|
|
33772
33423
|
};
|
|
33773
|
-
|
|
33774
|
-
|
|
33775
|
-
|
|
33776
|
-
|
|
33777
|
-
|
|
33778
|
-
|
|
33779
|
-
|
|
33780
|
-
|
|
33781
|
-
|
|
33782
|
-
|
|
33783
|
-
|
|
33784
|
-
|
|
33785
|
-
|
|
33786
|
-
|
|
33787
|
-
|
|
33788
|
-
|
|
33789
|
-
|
|
33790
|
-
|
|
33791
|
-
|
|
33792
|
-
|
|
33793
|
-
|
|
33794
|
-
|
|
33795
|
-
|
|
33796
|
-
|
|
33797
|
-
|
|
33424
|
+
const subagentCursors = new Map;
|
|
33425
|
+
const processSubagentTranscripts = async () => {
|
|
33426
|
+
const transcripts = await findSubagentTranscripts(transcriptPath);
|
|
33427
|
+
let advanced = false;
|
|
33428
|
+
let discoveredNestedAgent = true;
|
|
33429
|
+
while (discoveredNestedAgent) {
|
|
33430
|
+
const mappedAgentCount = parentToolCallIdByAgentId.size;
|
|
33431
|
+
for (const subagent of transcripts) {
|
|
33432
|
+
const parentToolCallId = parentToolCallIdByAgentId.get(subagent.agentId);
|
|
33433
|
+
if (!parentToolCallId)
|
|
33434
|
+
continue;
|
|
33435
|
+
const cursor = subagentCursors.get(subagent.path) ?? { offset: 0, partial: "" };
|
|
33436
|
+
const previousOffset = cursor.offset;
|
|
33437
|
+
const lines = await readJsonlDelta(subagent.path, cursor);
|
|
33438
|
+
if (cursor.offset !== previousOffset)
|
|
33439
|
+
advanced = true;
|
|
33440
|
+
subagentCursors.set(subagent.path, cursor);
|
|
33441
|
+
for (const line of lines)
|
|
33442
|
+
await processSubagentRecord(parseRecord(line), parentToolCallId);
|
|
33443
|
+
}
|
|
33444
|
+
discoveredNestedAgent = parentToolCallIdByAgentId.size > mappedAgentCount;
|
|
33445
|
+
}
|
|
33446
|
+
return advanced;
|
|
33447
|
+
};
|
|
33448
|
+
await processSubagentTranscripts();
|
|
33449
|
+
if (boundary >= 0) {
|
|
33450
|
+
for (const record3 of initialRecords.slice(boundary + 1)) {
|
|
33451
|
+
await processRecord(record3);
|
|
33452
|
+
if (done)
|
|
33453
|
+
break;
|
|
33798
33454
|
}
|
|
33799
|
-
throw new Error(options.formatError(result));
|
|
33800
|
-
}
|
|
33801
|
-
const parsed = parseAgentSessionListOutput(result.stdout, filterLocally ? options.filterCwd : undefined);
|
|
33802
|
-
if (parsed && options.isSubagentSession) {
|
|
33803
|
-
return filterSubagentSessions(parsed, options.isSubagentSession);
|
|
33804
33455
|
}
|
|
33805
|
-
|
|
33806
|
-
|
|
33807
|
-
|
|
33808
|
-
|
|
33809
|
-
|
|
33810
|
-
|
|
33811
|
-
|
|
33812
|
-
|
|
33456
|
+
const startedAt = Date.now();
|
|
33457
|
+
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
33458
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
33459
|
+
while (!done) {
|
|
33460
|
+
throwIfAborted(options.signal);
|
|
33461
|
+
if (Date.now() - startedAt >= timeoutMs) {
|
|
33462
|
+
return {
|
|
33463
|
+
status: "timeout",
|
|
33464
|
+
transcriptPath,
|
|
33465
|
+
completedToolCallIds: [...completed],
|
|
33466
|
+
failedToolCallIds: [...failed]
|
|
33467
|
+
};
|
|
33468
|
+
}
|
|
33469
|
+
await waitForPoll(pollIntervalMs, options.signal);
|
|
33470
|
+
await processSubagentTranscripts();
|
|
33471
|
+
const lines = await readJsonlDelta(transcriptPath, mainCursor);
|
|
33472
|
+
for (const line of lines) {
|
|
33473
|
+
await processAfterBoundary(parseRecord(line));
|
|
33474
|
+
if (done)
|
|
33475
|
+
break;
|
|
33476
|
+
}
|
|
33813
33477
|
}
|
|
33814
|
-
if (
|
|
33815
|
-
|
|
33478
|
+
if (parentToolCallIdByAgentId.size > 0) {
|
|
33479
|
+
let stablePolls = 0;
|
|
33480
|
+
for (let poll = 0;poll < FINAL_SUBAGENT_DRAIN_MAX_POLLS && stablePolls < FINAL_SUBAGENT_DRAIN_STABLE_POLLS; poll += 1) {
|
|
33481
|
+
await waitForPoll(pollIntervalMs, options.signal);
|
|
33482
|
+
stablePolls = await processSubagentTranscripts() ? 0 : stablePolls + 1;
|
|
33483
|
+
}
|
|
33816
33484
|
}
|
|
33817
|
-
return filterCwd ? filterAgentSessionListByCwd(parsed, filterCwd) : parsed;
|
|
33818
|
-
}
|
|
33819
|
-
function isAgentSessionListResult(value) {
|
|
33820
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
33821
|
-
return false;
|
|
33822
|
-
const record3 = value;
|
|
33823
|
-
if (record3.source !== "agent" || !Array.isArray(record3.sessions))
|
|
33824
|
-
return false;
|
|
33825
|
-
return record3.sessions.every((session3) => {
|
|
33826
|
-
if (!session3 || typeof session3 !== "object" || Array.isArray(session3))
|
|
33827
|
-
return false;
|
|
33828
|
-
const item = session3;
|
|
33829
|
-
return typeof item.sessionId === "string";
|
|
33830
|
-
});
|
|
33831
|
-
}
|
|
33832
|
-
function filterAgentSessionListByCwd(result, cwd) {
|
|
33833
33485
|
return {
|
|
33834
|
-
|
|
33835
|
-
|
|
33486
|
+
status: "completed",
|
|
33487
|
+
transcriptPath,
|
|
33488
|
+
completedToolCallIds: [...completed],
|
|
33489
|
+
failedToolCallIds: [...failed]
|
|
33836
33490
|
};
|
|
33837
33491
|
}
|
|
33838
|
-
|
|
33839
|
-
|
|
33840
|
-
init_codex_subagent_filter();
|
|
33841
|
-
});
|
|
33842
|
-
|
|
33843
|
-
// src/transport/acpx-session-files.ts
|
|
33844
|
-
import { readdir as readdir3, unlink as unlink2 } from "node:fs/promises";
|
|
33845
|
-
import { homedir as homedir11 } from "node:os";
|
|
33846
|
-
import { join as join22 } from "node:path";
|
|
33847
|
-
async function deleteAcpxSessionFiles(options) {
|
|
33848
|
-
const dir = options.sessionsDir ?? join22(homedir11(), ".acpx", "sessions");
|
|
33849
|
-
const safeId = encodeURIComponent(options.acpxRecordId);
|
|
33850
|
-
await unlink2(join22(dir, `${safeId}.json`)).catch(() => {
|
|
33851
|
-
return;
|
|
33852
|
-
});
|
|
33853
|
-
let entries;
|
|
33492
|
+
async function readJsonlDelta(path14, cursor) {
|
|
33493
|
+
let size;
|
|
33854
33494
|
try {
|
|
33855
|
-
|
|
33495
|
+
size = (await stat3(path14)).size;
|
|
33856
33496
|
} catch {
|
|
33857
|
-
return;
|
|
33858
|
-
}
|
|
33859
|
-
const streamFiles = entries.filter((name) => name.startsWith(`${safeId}.stream.`));
|
|
33860
|
-
for (const name of streamFiles) {
|
|
33861
|
-
await unlink2(join22(dir, name)).catch(() => {
|
|
33862
|
-
return;
|
|
33863
|
-
});
|
|
33864
|
-
}
|
|
33865
|
-
}
|
|
33866
|
-
var init_acpx_session_files = () => {};
|
|
33867
|
-
|
|
33868
|
-
// src/transport/session-effort.ts
|
|
33869
|
-
function requireAdvertisedSessionEffort(raw, value) {
|
|
33870
|
-
const advertised = parseSessionEffortRecord(raw);
|
|
33871
|
-
if (!advertised) {
|
|
33872
|
-
throw new Error("the active agent does not advertise a reasoning-effort option");
|
|
33497
|
+
return [];
|
|
33873
33498
|
}
|
|
33874
|
-
if (
|
|
33875
|
-
|
|
33499
|
+
if (size < cursor.offset) {
|
|
33500
|
+
cursor.offset = 0;
|
|
33501
|
+
cursor.partial = "";
|
|
33876
33502
|
}
|
|
33877
|
-
|
|
33878
|
-
|
|
33879
|
-
|
|
33880
|
-
let record3;
|
|
33503
|
+
if (size <= cursor.offset)
|
|
33504
|
+
return [];
|
|
33505
|
+
let chunk;
|
|
33881
33506
|
try {
|
|
33882
|
-
|
|
33507
|
+
const handle = await open5(path14, "r");
|
|
33508
|
+
try {
|
|
33509
|
+
chunk = Buffer.alloc(size - cursor.offset);
|
|
33510
|
+
const result = await handle.read(chunk, 0, chunk.length, cursor.offset);
|
|
33511
|
+
chunk = chunk.subarray(0, result.bytesRead);
|
|
33512
|
+
} finally {
|
|
33513
|
+
await handle.close();
|
|
33514
|
+
}
|
|
33883
33515
|
} catch {
|
|
33884
|
-
return;
|
|
33885
|
-
}
|
|
33886
|
-
if (!isRecord5(record3) || !isRecord5(record3.acpx) || !Array.isArray(record3.acpx.config_options)) {
|
|
33887
|
-
return;
|
|
33516
|
+
return [];
|
|
33888
33517
|
}
|
|
33889
|
-
|
|
33890
|
-
|
|
33891
|
-
|
|
33892
|
-
|
|
33518
|
+
cursor.offset += chunk.length;
|
|
33519
|
+
cursor.partial += chunk.toString("utf8");
|
|
33520
|
+
const lines = cursor.partial.split(`
|
|
33521
|
+
`);
|
|
33522
|
+
cursor.partial = lines.pop() ?? "";
|
|
33523
|
+
return lines;
|
|
33524
|
+
}
|
|
33525
|
+
function findPromptBoundary(records, launched) {
|
|
33526
|
+
let launchIndex = -1;
|
|
33527
|
+
for (let index = 0;index < records.length; index += 1) {
|
|
33528
|
+
const record3 = records[index];
|
|
33529
|
+
if (record3?.type !== "assistant" || record3.isSidechain === true)
|
|
33893
33530
|
continue;
|
|
33894
|
-
const
|
|
33895
|
-
|
|
33896
|
-
|
|
33897
|
-
|
|
33898
|
-
|
|
33899
|
-
};
|
|
33531
|
+
for (const block of contentBlocks(record3.message?.content)) {
|
|
33532
|
+
if (readString(block, "type") === "tool_use" && launched.has(readString(block, "id") ?? "")) {
|
|
33533
|
+
launchIndex = index;
|
|
33534
|
+
}
|
|
33535
|
+
}
|
|
33900
33536
|
}
|
|
33901
|
-
|
|
33902
|
-
|
|
33903
|
-
|
|
33904
|
-
|
|
33905
|
-
|
|
33906
|
-
|
|
33907
|
-
|
|
33908
|
-
return Array.isArray(option.options) ? option.options.flatMap(effortOptionValues) : [];
|
|
33909
|
-
}
|
|
33910
|
-
function isRecord5(value) {
|
|
33911
|
-
return typeof value === "object" && value !== null;
|
|
33912
|
-
}
|
|
33913
|
-
var EFFORT_CONFIG_IDS;
|
|
33914
|
-
var init_session_effort = __esm(() => {
|
|
33915
|
-
EFFORT_CONFIG_IDS = new Set([
|
|
33916
|
-
"reasoning_effort",
|
|
33917
|
-
"effort",
|
|
33918
|
-
"thought_level",
|
|
33919
|
-
"thinking"
|
|
33920
|
-
]);
|
|
33921
|
-
});
|
|
33922
|
-
|
|
33923
|
-
// src/transport/permission-mode-flag.ts
|
|
33924
|
-
function permissionModeToFlag(permissionMode) {
|
|
33925
|
-
switch (permissionMode) {
|
|
33926
|
-
case "approve-reads":
|
|
33927
|
-
return "--approve-reads";
|
|
33928
|
-
case "deny-all":
|
|
33929
|
-
return "--deny-all";
|
|
33930
|
-
case "approve-all":
|
|
33931
|
-
return "--approve-all";
|
|
33537
|
+
if (launchIndex < 0)
|
|
33538
|
+
return -1;
|
|
33539
|
+
for (let index = launchIndex + 1;index < records.length; index += 1) {
|
|
33540
|
+
const record3 = records[index];
|
|
33541
|
+
if (record3?.type === "assistant" && record3.isSidechain !== true && record3.message?.stop_reason === "end_turn") {
|
|
33542
|
+
return index;
|
|
33543
|
+
}
|
|
33932
33544
|
}
|
|
33545
|
+
return -1;
|
|
33546
|
+
}
|
|
33547
|
+
function hasTrackedLaunch(record3, launched) {
|
|
33548
|
+
if (record3?.type !== "assistant" || record3.isSidechain === true)
|
|
33549
|
+
return false;
|
|
33550
|
+
return contentBlocks(record3.message?.content).some((block) => readString(block, "type") === "tool_use" && launched.has(readString(block, "id") ?? ""));
|
|
33933
33551
|
}
|
|
33934
|
-
|
|
33935
|
-
|
|
33936
|
-
|
|
33937
|
-
|
|
33938
|
-
if (
|
|
33939
|
-
|
|
33552
|
+
function isMainEndTurn(record3) {
|
|
33553
|
+
return record3.type === "assistant" && record3.isSidechain !== true && record3.message?.stop_reason === "end_turn";
|
|
33554
|
+
}
|
|
33555
|
+
function parseRecord(line) {
|
|
33556
|
+
if (!line.trim())
|
|
33557
|
+
return;
|
|
33558
|
+
try {
|
|
33559
|
+
return JSON.parse(line);
|
|
33560
|
+
} catch {
|
|
33561
|
+
return;
|
|
33940
33562
|
}
|
|
33941
|
-
return args;
|
|
33942
33563
|
}
|
|
33943
|
-
function
|
|
33944
|
-
if (typeof
|
|
33945
|
-
return [];
|
|
33946
|
-
return
|
|
33564
|
+
function contentBlocks(content) {
|
|
33565
|
+
if (typeof content === "string")
|
|
33566
|
+
return [{ type: "text", text: content }];
|
|
33567
|
+
return Array.isArray(content) ? content.filter((block) => !!block && typeof block === "object") : [];
|
|
33947
33568
|
}
|
|
33948
|
-
function
|
|
33949
|
-
|
|
33950
|
-
|
|
33569
|
+
function blockText(block) {
|
|
33570
|
+
if (typeof block.text === "string")
|
|
33571
|
+
return block.text;
|
|
33572
|
+
if (typeof block.content === "string")
|
|
33573
|
+
return block.content;
|
|
33574
|
+
if (Array.isArray(block.content))
|
|
33575
|
+
return block.content.map((item) => textOfUnknown(item)).filter(Boolean).join(`
|
|
33576
|
+
`);
|
|
33577
|
+
return textOfUnknown(block.content);
|
|
33951
33578
|
}
|
|
33952
|
-
function
|
|
33953
|
-
if (
|
|
33954
|
-
return
|
|
33955
|
-
|
|
33579
|
+
function textOfUnknown(value) {
|
|
33580
|
+
if (typeof value === "string")
|
|
33581
|
+
return value;
|
|
33582
|
+
if (Array.isArray(value))
|
|
33583
|
+
return value.map(textOfUnknown).filter(Boolean).join(`
|
|
33584
|
+
`);
|
|
33585
|
+
if (!value || typeof value !== "object")
|
|
33586
|
+
return "";
|
|
33587
|
+
const object4 = value;
|
|
33588
|
+
if (typeof object4.text === "string")
|
|
33589
|
+
return object4.text;
|
|
33590
|
+
if (object4.content !== undefined)
|
|
33591
|
+
return textOfUnknown(object4.content);
|
|
33592
|
+
try {
|
|
33593
|
+
return JSON.stringify(value);
|
|
33594
|
+
} catch {
|
|
33595
|
+
return "";
|
|
33596
|
+
}
|
|
33956
33597
|
}
|
|
33957
|
-
function
|
|
33958
|
-
|
|
33959
|
-
|
|
33960
|
-
|
|
33961
|
-
|
|
33962
|
-
|
|
33963
|
-
|
|
33964
|
-
|
|
33965
|
-
|
|
33966
|
-
|
|
33967
|
-
|
|
33968
|
-
|
|
33598
|
+
function findStringField(value, keys) {
|
|
33599
|
+
if (!value || typeof value !== "object")
|
|
33600
|
+
return;
|
|
33601
|
+
if (Array.isArray(value)) {
|
|
33602
|
+
for (const item of value) {
|
|
33603
|
+
const found = findStringField(item, keys);
|
|
33604
|
+
if (found)
|
|
33605
|
+
return found;
|
|
33606
|
+
}
|
|
33607
|
+
return;
|
|
33608
|
+
}
|
|
33609
|
+
const object4 = value;
|
|
33610
|
+
for (const key of keys) {
|
|
33611
|
+
const candidate = object4[key];
|
|
33612
|
+
if (typeof candidate === "string" && candidate.trim())
|
|
33613
|
+
return candidate.trim();
|
|
33614
|
+
}
|
|
33615
|
+
for (const candidate of Object.values(object4)) {
|
|
33616
|
+
const found = findStringField(candidate, keys);
|
|
33617
|
+
if (found)
|
|
33618
|
+
return found;
|
|
33619
|
+
}
|
|
33620
|
+
return;
|
|
33969
33621
|
}
|
|
33970
|
-
function
|
|
33971
|
-
const
|
|
33972
|
-
|
|
33973
|
-
|
|
33974
|
-
|
|
33975
|
-
|
|
33976
|
-
|
|
33977
|
-
|
|
33978
|
-
|
|
33979
|
-
|
|
33980
|
-
|
|
33981
|
-
|
|
33622
|
+
function taskNotifications(text) {
|
|
33623
|
+
const notifications = [];
|
|
33624
|
+
const blocks = [...text.matchAll(/<task-notification>([\s\S]*?)<\/task-notification>/gi)].map((match) => match[1] ?? "");
|
|
33625
|
+
for (const block of blocks.length > 0 ? blocks : [text]) {
|
|
33626
|
+
const toolCallId = /<tool-use-id>([^<]+)<\/tool-use-id>/i.exec(block)?.[1]?.trim();
|
|
33627
|
+
if (!toolCallId)
|
|
33628
|
+
continue;
|
|
33629
|
+
const status = /<status>([^<]+)<\/status>/i.exec(block)?.[1]?.trim().toLowerCase();
|
|
33630
|
+
notifications.push({
|
|
33631
|
+
toolCallId,
|
|
33632
|
+
failed: status === "failed" || status === "error" || status === "cancelled" || status === "canceled"
|
|
33633
|
+
});
|
|
33634
|
+
}
|
|
33635
|
+
return notifications;
|
|
33982
33636
|
}
|
|
33983
|
-
function
|
|
33984
|
-
const
|
|
33985
|
-
|
|
33637
|
+
function classifyToolKind(name) {
|
|
33638
|
+
const normalized = name.toLowerCase();
|
|
33639
|
+
if (/(read|view|open)/.test(normalized))
|
|
33640
|
+
return "read";
|
|
33641
|
+
if (/(grep|search|find|glob)/.test(normalized))
|
|
33642
|
+
return "search";
|
|
33643
|
+
if (/(edit|write|patch|replace|create)/.test(normalized))
|
|
33644
|
+
return "edit";
|
|
33645
|
+
if (/(bash|shell|exec|run|terminal|command)/.test(normalized))
|
|
33646
|
+
return "execute";
|
|
33647
|
+
if (/(think|reason|plan|agent|task)/.test(normalized))
|
|
33648
|
+
return "think";
|
|
33649
|
+
return "other";
|
|
33986
33650
|
}
|
|
33987
|
-
function
|
|
33988
|
-
const
|
|
33989
|
-
|
|
33990
|
-
return combined.includes("no named session") || combined.includes("no cwd session") || combined.includes("session not found") || combined.includes("unknown session") || combined.includes("no acpx session found");
|
|
33651
|
+
function isAgentToolName(name) {
|
|
33652
|
+
const normalized = name.trim().toLowerCase();
|
|
33653
|
+
return normalized === "agent" || normalized === "task";
|
|
33991
33654
|
}
|
|
33992
|
-
function
|
|
33993
|
-
|
|
33994
|
-
|
|
33995
|
-
|
|
33996
|
-
|
|
33997
|
-
|
|
33998
|
-
|
|
33999
|
-
|
|
34000
|
-
return
|
|
33655
|
+
async function findSubagentTranscripts(transcriptPath) {
|
|
33656
|
+
const sessionDir = join20(dirname12(transcriptPath), basename3(transcriptPath, ".jsonl"), "subagents");
|
|
33657
|
+
const found = [];
|
|
33658
|
+
const visit = async (directory) => {
|
|
33659
|
+
let entries;
|
|
33660
|
+
try {
|
|
33661
|
+
entries = await readdir3(directory, { withFileTypes: true });
|
|
33662
|
+
} catch {
|
|
33663
|
+
return;
|
|
34001
33664
|
}
|
|
34002
|
-
|
|
34003
|
-
|
|
34004
|
-
|
|
34005
|
-
|
|
33665
|
+
for (const entry of entries) {
|
|
33666
|
+
const path14 = join20(directory, entry.name);
|
|
33667
|
+
if (entry.isDirectory()) {
|
|
33668
|
+
await visit(path14);
|
|
33669
|
+
} else if (entry.isFile() && entry.name.startsWith("agent-") && entry.name.endsWith(".jsonl")) {
|
|
33670
|
+
found.push({ agentId: entry.name.slice("agent-".length, -".jsonl".length), path: path14 });
|
|
33671
|
+
}
|
|
34006
33672
|
}
|
|
33673
|
+
};
|
|
33674
|
+
await visit(sessionDir);
|
|
33675
|
+
return found;
|
|
33676
|
+
}
|
|
33677
|
+
function toolSummary(input) {
|
|
33678
|
+
if (!input || typeof input !== "object")
|
|
33679
|
+
return;
|
|
33680
|
+
const object4 = input;
|
|
33681
|
+
for (const key of ["description", "summary", "path", "file_path", "query", "pattern", "command"]) {
|
|
33682
|
+
if (typeof object4[key] === "string" && object4[key].trim())
|
|
33683
|
+
return object4[key].trim();
|
|
34007
33684
|
}
|
|
34008
33685
|
return;
|
|
34009
33686
|
}
|
|
34010
|
-
|
|
34011
|
-
|
|
34012
|
-
|
|
34013
|
-
|
|
34014
|
-
|
|
34015
|
-
import { spawn as spawn11 } from "node:child_process";
|
|
34016
|
-
import { spawn as spawnPty } from "node-pty";
|
|
34017
|
-
function managementTimeoutError(args, options, output = {}) {
|
|
34018
|
-
return new CommandTimeoutError(options.timeoutMs, renderCommandForError(args), {
|
|
34019
|
-
stage: options.stage,
|
|
34020
|
-
...output
|
|
34021
|
-
});
|
|
33687
|
+
function readString(object4, key) {
|
|
33688
|
+
if (!object4 || typeof object4 !== "object")
|
|
33689
|
+
return;
|
|
33690
|
+
const value = object4[key];
|
|
33691
|
+
return typeof value === "string" ? value : undefined;
|
|
34022
33692
|
}
|
|
34023
|
-
|
|
34024
|
-
return
|
|
34025
|
-
const spawnSpec = resolveSpawnCommand(command, args);
|
|
34026
|
-
const child = spawn11(spawnSpec.command, spawnSpec.args, {
|
|
34027
|
-
env: options?.env,
|
|
34028
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
34029
|
-
});
|
|
34030
|
-
let stdout2 = "";
|
|
34031
|
-
let stderr = "";
|
|
34032
|
-
const onAbort = () => {
|
|
34033
|
-
terminateProcessTree(child.pid ?? 0, { detachedProcessGroup: false });
|
|
34034
|
-
};
|
|
34035
|
-
options?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
34036
|
-
const timeoutId = options?.timeoutMs ? setTimeout(() => {
|
|
34037
|
-
onAbort();
|
|
34038
|
-
reject(managementTimeoutError(args, options, { stdout: stdout2, stderr }));
|
|
34039
|
-
}, options.timeoutMs) : undefined;
|
|
34040
|
-
child.stdout.on("data", (chunk) => {
|
|
34041
|
-
stdout2 += String(chunk);
|
|
34042
|
-
});
|
|
34043
|
-
child.stderr.on("data", (chunk) => {
|
|
34044
|
-
stderr += String(chunk);
|
|
34045
|
-
});
|
|
34046
|
-
child.on("error", (error2) => {
|
|
34047
|
-
options?.signal?.removeEventListener("abort", onAbort);
|
|
34048
|
-
if (timeoutId)
|
|
34049
|
-
clearTimeout(timeoutId);
|
|
34050
|
-
reject(error2);
|
|
34051
|
-
});
|
|
34052
|
-
child.on("close", (code) => {
|
|
34053
|
-
options?.signal?.removeEventListener("abort", onAbort);
|
|
34054
|
-
if (timeoutId)
|
|
34055
|
-
clearTimeout(timeoutId);
|
|
34056
|
-
resolve4({ code: code ?? 1, stdout: stdout2, stderr });
|
|
34057
|
-
});
|
|
34058
|
-
});
|
|
33693
|
+
function readBoolean(object4, key) {
|
|
33694
|
+
return !!object4 && typeof object4 === "object" && object4[key] === true;
|
|
34059
33695
|
}
|
|
34060
|
-
|
|
34061
|
-
|
|
34062
|
-
|
|
34063
|
-
|
|
34064
|
-
|
|
34065
|
-
|
|
34066
|
-
|
|
34067
|
-
|
|
34068
|
-
|
|
34069
|
-
|
|
34070
|
-
|
|
34071
|
-
|
|
34072
|
-
|
|
33696
|
+
function encodeClaudeProjectDirectory(cwd) {
|
|
33697
|
+
return cwd.replace(/[:\\/]/g, "-");
|
|
33698
|
+
}
|
|
33699
|
+
async function exists(path14) {
|
|
33700
|
+
try {
|
|
33701
|
+
await access4(path14, fsConstants.R_OK);
|
|
33702
|
+
return true;
|
|
33703
|
+
} catch {
|
|
33704
|
+
return false;
|
|
33705
|
+
}
|
|
33706
|
+
}
|
|
33707
|
+
function throwIfAborted(signal) {
|
|
33708
|
+
if (signal?.aborted)
|
|
33709
|
+
throw new DOMException("background follow-up aborted", "AbortError");
|
|
33710
|
+
}
|
|
33711
|
+
async function waitForPoll(ms, signal) {
|
|
33712
|
+
if (!signal) {
|
|
33713
|
+
await new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
33714
|
+
return;
|
|
33715
|
+
}
|
|
33716
|
+
throwIfAborted(signal);
|
|
33717
|
+
await new Promise((resolve4, reject) => {
|
|
33718
|
+
const timer = setTimeout(() => {
|
|
33719
|
+
signal.removeEventListener("abort", onAbort);
|
|
33720
|
+
resolve4();
|
|
33721
|
+
}, ms);
|
|
34073
33722
|
const onAbort = () => {
|
|
34074
|
-
|
|
33723
|
+
clearTimeout(timer);
|
|
33724
|
+
reject(new DOMException("background follow-up aborted", "AbortError"));
|
|
34075
33725
|
};
|
|
34076
|
-
|
|
34077
|
-
const timeoutId = options?.timeoutMs ? setTimeout(() => {
|
|
34078
|
-
onAbort();
|
|
34079
|
-
reject(managementTimeoutError(args, options, { stdout: output }));
|
|
34080
|
-
}, options.timeoutMs) : undefined;
|
|
34081
|
-
child.onData((chunk) => {
|
|
34082
|
-
output += chunk;
|
|
34083
|
-
});
|
|
34084
|
-
child.onExit(({ exitCode }) => {
|
|
34085
|
-
options?.signal?.removeEventListener("abort", onAbort);
|
|
34086
|
-
if (timeoutId)
|
|
34087
|
-
clearTimeout(timeoutId);
|
|
34088
|
-
resolve4({ code: exitCode, stdout: output, stderr: "" });
|
|
34089
|
-
});
|
|
33726
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
34090
33727
|
});
|
|
34091
33728
|
}
|
|
33729
|
+
var DEFAULT_POLL_INTERVAL_MS = 250, DEFAULT_TIMEOUT_MS, FINAL_SUBAGENT_DRAIN_MAX_POLLS = 4, FINAL_SUBAGENT_DRAIN_STABLE_POLLS = 2, ASYNC_AGENT_LAUNCH;
|
|
33730
|
+
var init_claude_background_followup = __esm(() => {
|
|
33731
|
+
DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
|
|
33732
|
+
ASYNC_AGENT_LAUNCH = /Async agent launched successfully|["']?status["']?\s*:\s*["']async_launched["']/i;
|
|
33733
|
+
});
|
|
34092
33734
|
|
|
34093
|
-
|
|
34094
|
-
|
|
34095
|
-
|
|
34096
|
-
|
|
34097
|
-
|
|
34098
|
-
|
|
34099
|
-
|
|
34100
|
-
|
|
34101
|
-
|
|
34102
|
-
|
|
34103
|
-
|
|
34104
|
-
|
|
34105
|
-
|
|
34106
|
-
|
|
34107
|
-
|
|
34108
|
-
|
|
34109
|
-
|
|
34110
|
-
|
|
34111
|
-
|
|
34112
|
-
|
|
34113
|
-
|
|
34114
|
-
|
|
34115
|
-
|
|
34116
|
-
|
|
34117
|
-
|
|
34118
|
-
|
|
33735
|
+
// src/transport/tool-kind-emoji.ts
|
|
33736
|
+
var TOOL_KIND_EMOJI, DEFAULT_TOOL_EMOJI;
|
|
33737
|
+
var init_tool_kind_emoji = __esm(() => {
|
|
33738
|
+
TOOL_KIND_EMOJI = {
|
|
33739
|
+
read: "\uD83D\uDCD6",
|
|
33740
|
+
search: "\uD83D\uDD0D",
|
|
33741
|
+
execute: "\uD83D\uDCBB",
|
|
33742
|
+
edit: "✏️",
|
|
33743
|
+
think: "\uD83E\uDDE0",
|
|
33744
|
+
other: "\uD83D\uDD27"
|
|
33745
|
+
};
|
|
33746
|
+
DEFAULT_TOOL_EMOJI = TOOL_KIND_EMOJI.other;
|
|
33747
|
+
});
|
|
33748
|
+
|
|
33749
|
+
// src/transport/streaming-prompt.ts
|
|
33750
|
+
function createStreamingPromptState(formatToolCalls = false, options) {
|
|
33751
|
+
let toolEventMode;
|
|
33752
|
+
let onToolEvent;
|
|
33753
|
+
let onThought;
|
|
33754
|
+
let onPlan;
|
|
33755
|
+
let onUsage;
|
|
33756
|
+
let onCommands;
|
|
33757
|
+
let rawStream = false;
|
|
33758
|
+
let driver;
|
|
33759
|
+
if (options === undefined) {
|
|
33760
|
+
toolEventMode = "text";
|
|
33761
|
+
onToolEvent = undefined;
|
|
33762
|
+
} else if (typeof options === "function") {
|
|
33763
|
+
onToolEvent = options;
|
|
33764
|
+
toolEventMode = "structured";
|
|
33765
|
+
} else {
|
|
33766
|
+
onToolEvent = options.onToolEvent;
|
|
33767
|
+
onThought = options.onThought;
|
|
33768
|
+
onPlan = options.onPlan;
|
|
33769
|
+
onUsage = options.onUsage;
|
|
33770
|
+
onCommands = options.onCommands;
|
|
33771
|
+
rawStream = options.rawStream ?? false;
|
|
33772
|
+
driver = options.driver?.trim().toLowerCase() || undefined;
|
|
33773
|
+
toolEventMode = resolveToolEventMode({
|
|
33774
|
+
toolEventMode: options.mode,
|
|
33775
|
+
onToolEvent
|
|
34119
33776
|
});
|
|
34120
|
-
this.streamingHooks = streamingHooks;
|
|
34121
|
-
this.resolveSpawnEnvironment = options.resolveSpawnEnvironment ?? resolveClaudeSpawnEnvironment;
|
|
34122
33777
|
}
|
|
34123
|
-
|
|
34124
|
-
|
|
34125
|
-
|
|
34126
|
-
|
|
34127
|
-
|
|
34128
|
-
|
|
34129
|
-
|
|
34130
|
-
|
|
34131
|
-
|
|
33778
|
+
return {
|
|
33779
|
+
buffer: "",
|
|
33780
|
+
segments: [],
|
|
33781
|
+
hasAgentMessage: false,
|
|
33782
|
+
pendingLine: "",
|
|
33783
|
+
formatToolCalls,
|
|
33784
|
+
emittedToolCallIds: new Set,
|
|
33785
|
+
toolCalls: new Map,
|
|
33786
|
+
toolEventMode,
|
|
33787
|
+
driver,
|
|
33788
|
+
rawStream,
|
|
33789
|
+
onToolEvent,
|
|
33790
|
+
onThought,
|
|
33791
|
+
onPlan,
|
|
33792
|
+
onUsage,
|
|
33793
|
+
onCommands,
|
|
33794
|
+
finalize() {
|
|
33795
|
+
if (this.pendingLine.trim().length > 0) {
|
|
33796
|
+
parseStreamingChunks(this, this.pendingLine);
|
|
34132
33797
|
}
|
|
34133
|
-
|
|
33798
|
+
const remaining = this.rawStream ? this.buffer : this.buffer.trim();
|
|
33799
|
+
this.buffer = "";
|
|
33800
|
+
this.pendingLine = "";
|
|
33801
|
+
return remaining;
|
|
34134
33802
|
}
|
|
33803
|
+
};
|
|
33804
|
+
}
|
|
33805
|
+
function parseStreamingDataChunk(state, chunk) {
|
|
33806
|
+
state.pendingLine += chunk;
|
|
33807
|
+
let boundary;
|
|
33808
|
+
while ((boundary = state.pendingLine.indexOf(`
|
|
33809
|
+
`)) !== -1) {
|
|
33810
|
+
const line = state.pendingLine.slice(0, boundary);
|
|
33811
|
+
state.pendingLine = state.pendingLine.slice(boundary + 1);
|
|
33812
|
+
parseStreamingChunks(state, line);
|
|
34135
33813
|
}
|
|
34136
|
-
|
|
34137
|
-
|
|
34138
|
-
|
|
34139
|
-
|
|
34140
|
-
|
|
34141
|
-
|
|
34142
|
-
|
|
34143
|
-
|
|
34144
|
-
|
|
34145
|
-
|
|
34146
|
-
env: this.spawnEnvironment(session3)
|
|
34147
|
-
});
|
|
34148
|
-
}
|
|
34149
|
-
async listAgentSessions(query) {
|
|
34150
|
-
return await runAgentSessionList({
|
|
34151
|
-
filterCwd: query.filterCwd,
|
|
34152
|
-
runList: async (includeFilterCwd) => {
|
|
34153
|
-
const args = this.buildAgentQueryArgs(query, "json", [
|
|
34154
|
-
"sessions",
|
|
34155
|
-
"list",
|
|
34156
|
-
...includeFilterCwd && query.filterCwd ? ["--filter-cwd", query.filterCwd] : [],
|
|
34157
|
-
...query.cursor ? ["--cursor", query.cursor] : []
|
|
34158
|
-
]);
|
|
34159
|
-
return await this.runCommandWithTimeout(this.runCommand, args, {
|
|
34160
|
-
timeoutMs: this.sessionInitTimeoutMs,
|
|
34161
|
-
env: this.spawnEnvironment(query)
|
|
34162
|
-
});
|
|
34163
|
-
},
|
|
34164
|
-
formatError: (result) => normalizeCommandError(result) ?? `command failed with exit code ${result.code}`,
|
|
34165
|
-
isSubagentSession: (query.driver ?? query.agent) === CODEX_AGENT_NAME ? codexSubagentPredicate() : undefined
|
|
34166
|
-
});
|
|
34167
|
-
}
|
|
34168
|
-
async tailSessionHistory(session3, lines) {
|
|
34169
|
-
const candidates = [
|
|
34170
|
-
["sessions", "history", session3.transportSession, "--limit", String(lines)],
|
|
34171
|
-
["sessions", "history", "quiet", "-s", session3.transportSession, String(lines)],
|
|
34172
|
-
["sessions", "history", "quiet", session3.transportSession, String(lines)],
|
|
34173
|
-
["sessions", "history", "-s", session3.transportSession, "--tail", String(lines)],
|
|
34174
|
-
["sessions", "history", session3.transportSession, "--tail", String(lines)],
|
|
34175
|
-
["sessions", "history", "--name", session3.transportSession, "--tail", String(lines)]
|
|
34176
|
-
];
|
|
34177
|
-
const deadline = Date.now() + this.managementCommandTimeoutMs;
|
|
34178
|
-
let lastResult;
|
|
34179
|
-
for (const tail2 of candidates) {
|
|
34180
|
-
const args = this.buildArgs(session3, tail2);
|
|
34181
|
-
const result = await this.runCommandWithTimeout(this.runCommand, args, {
|
|
34182
|
-
timeoutMs: Math.max(deadline - Date.now(), 1),
|
|
34183
|
-
stage: "session-history",
|
|
34184
|
-
env: this.spawnEnvironment(session3)
|
|
34185
|
-
});
|
|
34186
|
-
if (result.code === 0) {
|
|
34187
|
-
return { text: result.stdout.trimEnd() };
|
|
34188
|
-
}
|
|
34189
|
-
lastResult = result;
|
|
34190
|
-
}
|
|
34191
|
-
const detail = lastResult ? normalizeCommandError(lastResult) ?? `command failed with exit code ${lastResult.code}` : "command failed";
|
|
34192
|
-
throw new Error(detail);
|
|
33814
|
+
}
|
|
33815
|
+
function parseStreamingChunks(state, line) {
|
|
33816
|
+
const trimmed = line.trim();
|
|
33817
|
+
if (trimmed.length === 0)
|
|
33818
|
+
return;
|
|
33819
|
+
let event;
|
|
33820
|
+
try {
|
|
33821
|
+
event = JSON.parse(trimmed);
|
|
33822
|
+
} catch {
|
|
33823
|
+
return;
|
|
34193
33824
|
}
|
|
34194
|
-
|
|
34195
|
-
|
|
34196
|
-
|
|
33825
|
+
if (event.method !== "session/update")
|
|
33826
|
+
return;
|
|
33827
|
+
const update = event.params?.update;
|
|
33828
|
+
if (!update)
|
|
33829
|
+
return;
|
|
33830
|
+
if (update.sessionUpdate === "tool_call" || update.sessionUpdate === "tool_call_update") {
|
|
33831
|
+
const wantsStructured = state.toolEventMode === "structured" || state.toolEventMode === "both";
|
|
33832
|
+
const wantsText = (state.toolEventMode === "text" || state.toolEventMode === "both") && state.formatToolCalls;
|
|
33833
|
+
if (wantsStructured && state.onToolEvent) {
|
|
33834
|
+
const merged = update.toolCallId ? mergeToolCallUpdate(state, update.toolCallId, update) : update;
|
|
33835
|
+
const toolEvent = buildToolUseEvent(merged, state.driver);
|
|
33836
|
+
if (toolEvent)
|
|
33837
|
+
state.onToolEvent(toolEvent);
|
|
34197
33838
|
}
|
|
34198
|
-
|
|
34199
|
-
|
|
34200
|
-
|
|
34201
|
-
|
|
34202
|
-
|
|
34203
|
-
|
|
34204
|
-
|
|
34205
|
-
|
|
34206
|
-
let toolEventMode = resolveToolEventMode(options);
|
|
34207
|
-
if ((toolEventMode === "structured" || toolEventMode === "both") && !options?.onToolEvent) {
|
|
34208
|
-
toolEventMode = "text";
|
|
34209
|
-
}
|
|
34210
|
-
const { result: result2, overflowCount } = await this.runStreamingPrompt(this.command, args, reply, formatToolCalls, toolEventMode, replyContext, options?.onSegment, options?.onToolEvent, options?.onThought, options?.onPlan, options?.onUsage, options?.onCommands, rawStream, this.spawnEnvironment(session3), session3.driver ?? session3.agent);
|
|
34211
|
-
const baseText = getPromptText(result2);
|
|
34212
|
-
if (!reply) {
|
|
34213
|
-
return { text: baseText };
|
|
33839
|
+
if (wantsText) {
|
|
33840
|
+
const formatted = formatToolCallEvent(update, update.sessionUpdate);
|
|
33841
|
+
if (formatted) {
|
|
33842
|
+
const toolCallId = update.toolCallId;
|
|
33843
|
+
if (toolCallId) {
|
|
33844
|
+
if (state.emittedToolCallIds.has(toolCallId))
|
|
33845
|
+
return;
|
|
33846
|
+
state.emittedToolCallIds.add(toolCallId);
|
|
34214
33847
|
}
|
|
34215
|
-
|
|
34216
|
-
return { text: summary ? `${summary}
|
|
34217
|
-
|
|
34218
|
-
${baseText}` : "" };
|
|
33848
|
+
state.segments.push(formatted);
|
|
34219
33849
|
}
|
|
34220
|
-
const spawnOptions = this.withSpawnEnvironment(session3);
|
|
34221
|
-
const result = spawnOptions ? await this.runCommand(this.command, args, spawnOptions) : await this.runCommand(this.command, args);
|
|
34222
|
-
return { text: getPromptText(result) };
|
|
34223
|
-
} finally {
|
|
34224
|
-
try {
|
|
34225
|
-
await structuredPrompt?.cleanup();
|
|
34226
|
-
} catch {}
|
|
34227
33850
|
}
|
|
33851
|
+
return;
|
|
34228
33852
|
}
|
|
34229
|
-
|
|
34230
|
-
|
|
34231
|
-
|
|
34232
|
-
|
|
34233
|
-
|
|
34234
|
-
modeId
|
|
34235
|
-
]), this.withSpawnEnvironment(session3, {
|
|
34236
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34237
|
-
stage: "set-mode"
|
|
34238
|
-
}));
|
|
34239
|
-
}
|
|
34240
|
-
async setModel(session3, modelId) {
|
|
34241
|
-
await this.run(this.buildArgs({ ...session3, model: modelId }, [
|
|
34242
|
-
"set",
|
|
34243
|
-
"-s",
|
|
34244
|
-
session3.transportSession,
|
|
34245
|
-
"model",
|
|
34246
|
-
modelId
|
|
34247
|
-
]), this.withSpawnEnvironment({ ...session3, model: modelId }, {
|
|
34248
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34249
|
-
stage: "set-model"
|
|
34250
|
-
}));
|
|
33853
|
+
if (update.sessionUpdate === "plan") {
|
|
33854
|
+
const entries = Array.isArray(update.entries) ? update.entries.filter((x) => !!x && typeof x === "object" && typeof x.content === "string" && typeof x.status === "string") : [];
|
|
33855
|
+
if (entries.length > 0)
|
|
33856
|
+
state.onPlan?.(entries);
|
|
33857
|
+
return;
|
|
34251
33858
|
}
|
|
34252
|
-
|
|
34253
|
-
const
|
|
34254
|
-
const
|
|
34255
|
-
|
|
34256
|
-
|
|
34257
|
-
|
|
34258
|
-
|
|
34259
|
-
env: this.spawnEnvironment(session3)
|
|
34260
|
-
});
|
|
34261
|
-
if (result.code !== 0) {
|
|
34262
|
-
const detail = normalizeCommandError(result) ?? `command failed with exit code ${result.code}`;
|
|
34263
|
-
throw new Error(detail);
|
|
34264
|
-
}
|
|
34265
|
-
try {
|
|
34266
|
-
const json = JSON.parse(result.stdout);
|
|
34267
|
-
return {
|
|
34268
|
-
current: typeof json.model === "string" ? json.model : undefined,
|
|
34269
|
-
available: Array.isArray(json.availableModels) ? json.availableModels.filter((m) => typeof m === "string") : []
|
|
34270
|
-
};
|
|
34271
|
-
} catch {
|
|
34272
|
-
return { available: [] };
|
|
33859
|
+
if (update.sessionUpdate === "usage_update") {
|
|
33860
|
+
const used = typeof update.used === "number" && Number.isFinite(update.used) ? update.used : undefined;
|
|
33861
|
+
const size = typeof update.size === "number" && Number.isFinite(update.size) ? update.size : undefined;
|
|
33862
|
+
if (used !== undefined && size !== undefined && size > 0) {
|
|
33863
|
+
const cost = normalizeUsageCost(update.cost);
|
|
33864
|
+
const breakdown = normalizeUsageBreakdown(update._meta?.usage);
|
|
33865
|
+
state.onUsage?.({ used, size, ...cost ? { cost } : {}, ...breakdown ? { breakdown } : {} });
|
|
34273
33866
|
}
|
|
33867
|
+
return;
|
|
34274
33868
|
}
|
|
34275
|
-
|
|
34276
|
-
|
|
34277
|
-
|
|
34278
|
-
|
|
34279
|
-
|
|
34280
|
-
], "json"), this.withSpawnEnvironment(session3, {
|
|
34281
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34282
|
-
stage: "get-session-effort"
|
|
34283
|
-
}));
|
|
34284
|
-
const effort = parseSessionEffortRecord(output);
|
|
34285
|
-
return effort ? { current: effort.current, available: effort.available } : { available: [] };
|
|
34286
|
-
}
|
|
34287
|
-
async setSessionEffort(session3, effort) {
|
|
34288
|
-
const record3 = await this.readSessionEffortRecord(session3);
|
|
34289
|
-
await this.applyAdvertisedSessionEffort(session3, effort, record3);
|
|
33869
|
+
if (update.sessionUpdate === "available_commands_update") {
|
|
33870
|
+
if (Array.isArray(update.availableCommands)) {
|
|
33871
|
+
state.onCommands?.(normalizeAgentCommands(update.availableCommands));
|
|
33872
|
+
}
|
|
33873
|
+
return;
|
|
34290
33874
|
}
|
|
34291
|
-
|
|
34292
|
-
|
|
34293
|
-
const
|
|
34294
|
-
if (
|
|
34295
|
-
|
|
33875
|
+
const isThoughtChunk = update.sessionUpdate === "agent_thought_chunk" && update.content?.type === "text" && typeof update.content.text === "string";
|
|
33876
|
+
if (isThoughtChunk) {
|
|
33877
|
+
const chunk2 = update.content.text;
|
|
33878
|
+
if (chunk2.length > 0) {
|
|
33879
|
+
state.onThought?.(chunk2);
|
|
34296
33880
|
}
|
|
34297
|
-
|
|
33881
|
+
return;
|
|
34298
33882
|
}
|
|
34299
|
-
|
|
34300
|
-
|
|
34301
|
-
|
|
34302
|
-
|
|
34303
|
-
|
|
34304
|
-
|
|
34305
|
-
|
|
34306
|
-
|
|
34307
|
-
|
|
33883
|
+
const isMessageChunk = update.sessionUpdate === "agent_message_chunk" && update.content?.type === "text" && typeof update.content.text === "string";
|
|
33884
|
+
if (!isMessageChunk)
|
|
33885
|
+
return;
|
|
33886
|
+
state.hasAgentMessage = true;
|
|
33887
|
+
const chunk = update.content.text ?? "";
|
|
33888
|
+
if (chunk.length === 0)
|
|
33889
|
+
return;
|
|
33890
|
+
state.buffer += chunk;
|
|
33891
|
+
if (state.rawStream)
|
|
33892
|
+
return;
|
|
33893
|
+
let boundary;
|
|
33894
|
+
while ((boundary = state.buffer.indexOf(`
|
|
33895
|
+
|
|
33896
|
+
`)) !== -1) {
|
|
33897
|
+
const segment = state.buffer.slice(0, boundary).trim();
|
|
33898
|
+
state.buffer = state.buffer.slice(boundary + 2);
|
|
33899
|
+
if (segment.length > 0) {
|
|
33900
|
+
state.segments.push(segment);
|
|
33901
|
+
}
|
|
34308
33902
|
}
|
|
34309
|
-
|
|
34310
|
-
|
|
34311
|
-
|
|
34312
|
-
|
|
34313
|
-
|
|
34314
|
-
|
|
34315
|
-
|
|
34316
|
-
|
|
34317
|
-
|
|
34318
|
-
|
|
34319
|
-
|
|
34320
|
-
|
|
33903
|
+
}
|
|
33904
|
+
function formatToolCallEvent(update, sessionUpdate) {
|
|
33905
|
+
if (!update)
|
|
33906
|
+
return null;
|
|
33907
|
+
const kind = update.kind ?? "";
|
|
33908
|
+
const title = update.title ?? "";
|
|
33909
|
+
if (title.length === 0)
|
|
33910
|
+
return null;
|
|
33911
|
+
const emoji2 = TOOL_KIND_EMOJI[kind] ?? DEFAULT_TOOL_EMOJI;
|
|
33912
|
+
const inputSummary = summarizeToolInput(update.rawInput, title) || summarizeToolInput(update.rawOutput, title);
|
|
33913
|
+
const status = readString2(update, "status");
|
|
33914
|
+
if (!inputSummary && status === "pending")
|
|
33915
|
+
return null;
|
|
33916
|
+
if (!inputSummary && isGenericToolTitle(kind, title))
|
|
33917
|
+
return null;
|
|
33918
|
+
const summaryText = inputSummary && inputSummary !== title ? `: ${truncateToolDisplay(inputSummary)}` : "";
|
|
33919
|
+
const statusText = status ? ` (${status})` : "";
|
|
33920
|
+
return `${emoji2} ${title}${statusText}${summaryText}`;
|
|
33921
|
+
}
|
|
33922
|
+
function isEmptyToolField(v) {
|
|
33923
|
+
if (v === undefined || v === null)
|
|
33924
|
+
return true;
|
|
33925
|
+
if (typeof v === "string")
|
|
33926
|
+
return v.trim().length === 0;
|
|
33927
|
+
if (Array.isArray(v))
|
|
33928
|
+
return v.length === 0;
|
|
33929
|
+
if (typeof v === "object")
|
|
33930
|
+
return Object.keys(v).length === 0;
|
|
33931
|
+
return false;
|
|
33932
|
+
}
|
|
33933
|
+
function mergeToolCallUpdate(state, toolCallId, update) {
|
|
33934
|
+
const prev = state.toolCalls.get(toolCallId) ?? { toolCallId };
|
|
33935
|
+
const merged = { ...prev };
|
|
33936
|
+
for (const key of ["kind", "title", "rawInput", "content", "rawOutput", "locations", "status"]) {
|
|
33937
|
+
const next = update[key];
|
|
33938
|
+
if (!isEmptyToolField(next))
|
|
33939
|
+
merged[key] = next;
|
|
34321
33940
|
}
|
|
34322
|
-
|
|
34323
|
-
|
|
34324
|
-
|
|
34325
|
-
|
|
34326
|
-
|
|
34327
|
-
|
|
34328
|
-
|
|
34329
|
-
|
|
34330
|
-
|
|
34331
|
-
|
|
34332
|
-
|
|
34333
|
-
|
|
33941
|
+
const nextMeta = update._meta;
|
|
33942
|
+
if (nextMeta) {
|
|
33943
|
+
const previousMeta = merged._meta;
|
|
33944
|
+
merged._meta = {
|
|
33945
|
+
...previousMeta,
|
|
33946
|
+
...nextMeta,
|
|
33947
|
+
...previousMeta?.qoder || nextMeta.qoder ? { qoder: { ...previousMeta?.qoder, ...nextMeta.qoder } } : {},
|
|
33948
|
+
...previousMeta?.codex || nextMeta.codex ? {
|
|
33949
|
+
codex: {
|
|
33950
|
+
...previousMeta?.codex,
|
|
33951
|
+
...nextMeta.codex,
|
|
33952
|
+
...previousMeta?.codex?.subagent || nextMeta.codex?.subagent ? { subagent: { ...previousMeta?.codex?.subagent, ...nextMeta.codex?.subagent } } : {}
|
|
33953
|
+
}
|
|
33954
|
+
} : {},
|
|
33955
|
+
...previousMeta?.claudeCode || nextMeta.claudeCode ? { claudeCode: { ...previousMeta?.claudeCode, ...nextMeta.claudeCode } } : {}
|
|
34334
33956
|
};
|
|
34335
33957
|
}
|
|
34336
|
-
|
|
34337
|
-
|
|
34338
|
-
|
|
34339
|
-
|
|
34340
|
-
|
|
34341
|
-
|
|
34342
|
-
|
|
34343
|
-
|
|
34344
|
-
|
|
34345
|
-
|
|
34346
|
-
|
|
34347
|
-
|
|
34348
|
-
|
|
34349
|
-
|
|
34350
|
-
|
|
33958
|
+
merged.toolCallId = toolCallId;
|
|
33959
|
+
state.toolCalls.set(toolCallId, merged);
|
|
33960
|
+
return merged;
|
|
33961
|
+
}
|
|
33962
|
+
function buildToolUseEvent(update, driver) {
|
|
33963
|
+
if (!update)
|
|
33964
|
+
return null;
|
|
33965
|
+
const toolCallId = update.toolCallId;
|
|
33966
|
+
if (!toolCallId)
|
|
33967
|
+
return null;
|
|
33968
|
+
const kindRaw = update.kind ?? "";
|
|
33969
|
+
const kind = (() => {
|
|
33970
|
+
switch (kindRaw) {
|
|
33971
|
+
case "read":
|
|
33972
|
+
case "search":
|
|
33973
|
+
case "execute":
|
|
33974
|
+
case "edit":
|
|
33975
|
+
case "think":
|
|
33976
|
+
return kindRaw;
|
|
33977
|
+
default:
|
|
33978
|
+
return "other";
|
|
33979
|
+
}
|
|
33980
|
+
})();
|
|
33981
|
+
const title = (update.title ?? "").trim();
|
|
33982
|
+
const toolName = title || "Tool";
|
|
33983
|
+
const summaryRaw = summarizeToolInput(update.rawInput, title) || summarizeToolInput(update.rawOutput, title);
|
|
33984
|
+
const summary = summaryRaw && summaryRaw !== title ? summaryRaw : undefined;
|
|
33985
|
+
const statusRaw = readString2(update, "status");
|
|
33986
|
+
const isClaudeDriver = driver === undefined || driver === "claude";
|
|
33987
|
+
const claudeMeta = isClaudeDriver ? update._meta?.claudeCode : undefined;
|
|
33988
|
+
const claudeToolResponse = claudeMeta?.toolResponse;
|
|
33989
|
+
const hasClaudeToolResponse = !isEmptyToolField(claudeToolResponse);
|
|
33990
|
+
const isAsyncAgentLaunch = update._meta?.claudeCode?.toolName === "Agent" && isRecord4(claudeToolResponse) && claudeToolResponse.status === "async_launched" || driver === "qoder" && update._meta?.qoder?.toolName === "Agent" && isAsyncAgentLaunchOutput(update.rawOutput);
|
|
33991
|
+
const status = isAsyncAgentLaunch ? "running" : statusRaw === "completed" || statusRaw === "success" ? "success" : statusRaw === "failed" || statusRaw === "error" ? "error" : hasClaudeToolResponse ? "success" : "running";
|
|
33992
|
+
const rawInput = update.rawInput;
|
|
33993
|
+
const content = update.content;
|
|
33994
|
+
const rawOutput = update.rawOutput ?? claudeToolResponse;
|
|
33995
|
+
const locations = update.locations;
|
|
33996
|
+
const parentToolCallId = claudeMeta?.parentToolUseId?.trim();
|
|
33997
|
+
const isSubagent = claudeMeta?.toolName === "Agent" || driver === "qoder" && update._meta?.qoder?.toolName === "Agent" || driver === "kimi" && isKimiSubagentInput(rawInput) || driver === "codex" && isCodexSubagentMeta(update._meta?.codex?.subagent);
|
|
33998
|
+
return {
|
|
33999
|
+
toolCallId,
|
|
34000
|
+
...parentToolCallId ? { parentToolCallId } : {},
|
|
34001
|
+
...isSubagent ? { isSubagent: true } : {},
|
|
34002
|
+
toolName,
|
|
34003
|
+
kind,
|
|
34004
|
+
...summary ? { summary } : {},
|
|
34005
|
+
...rawInput !== undefined ? { rawInput } : {},
|
|
34006
|
+
...content !== undefined ? { content } : {},
|
|
34007
|
+
...rawOutput !== undefined ? { rawOutput } : {},
|
|
34008
|
+
...locations !== undefined ? { locations } : {},
|
|
34009
|
+
status
|
|
34010
|
+
};
|
|
34011
|
+
}
|
|
34012
|
+
function isKimiSubagentInput(rawInput) {
|
|
34013
|
+
return isRecord4(rawInput) && readFirstString(rawInput, ["prompt"]) !== undefined && readFirstString(rawInput, ["subagent_type", "subagentType"]) !== undefined;
|
|
34014
|
+
}
|
|
34015
|
+
function isCodexSubagentMeta(meta2) {
|
|
34016
|
+
return typeof meta2?.threadId === "string" && meta2.threadId.trim().length > 0 && typeof meta2.activity === "string" && meta2.activity.trim().length > 0;
|
|
34017
|
+
}
|
|
34018
|
+
function summarizeToolInput(rawInput, title = "") {
|
|
34019
|
+
if (rawInput == null)
|
|
34020
|
+
return;
|
|
34021
|
+
if (typeof rawInput === "string" || typeof rawInput === "number" || typeof rawInput === "boolean") {
|
|
34022
|
+
return String(rawInput);
|
|
34351
34023
|
}
|
|
34352
|
-
|
|
34353
|
-
|
|
34354
|
-
|
|
34355
|
-
|
|
34024
|
+
if (!isRecord4(rawInput))
|
|
34025
|
+
return;
|
|
34026
|
+
const taskSummary = summarizeTaskInput(rawInput, title);
|
|
34027
|
+
if (taskSummary)
|
|
34028
|
+
return taskSummary;
|
|
34029
|
+
const command = readFirstString(rawInput, ["command", "cmd", "program"]);
|
|
34030
|
+
const args = readFirstStringArray(rawInput, ["args", "arguments"]);
|
|
34031
|
+
if (command) {
|
|
34032
|
+
return [command, ...args ?? []].join(" ");
|
|
34356
34033
|
}
|
|
34357
|
-
|
|
34358
|
-
|
|
34359
|
-
const
|
|
34360
|
-
|
|
34361
|
-
"
|
|
34362
|
-
|
|
34363
|
-
|
|
34364
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34365
|
-
stage: "remove-session"
|
|
34366
|
-
}));
|
|
34367
|
-
if (result.code === 0) {
|
|
34368
|
-
return;
|
|
34034
|
+
const parsedCmd = rawInput.parsed_cmd;
|
|
34035
|
+
if (Array.isArray(parsedCmd) && parsedCmd.length > 0) {
|
|
34036
|
+
const parts = [];
|
|
34037
|
+
for (const entry of parsedCmd) {
|
|
34038
|
+
if (isRecord4(entry) && typeof entry.cmd === "string" && entry.cmd.length > 0) {
|
|
34039
|
+
parts.push(entry.cmd);
|
|
34040
|
+
}
|
|
34369
34041
|
}
|
|
34370
|
-
if (
|
|
34371
|
-
return;
|
|
34042
|
+
if (parts.length > 0) {
|
|
34043
|
+
return parts.join(" ");
|
|
34372
34044
|
}
|
|
34373
|
-
const detail = normalizeCommandError(result) ?? `command failed with exit code ${result.code}`;
|
|
34374
|
-
throw new Error(detail);
|
|
34375
34045
|
}
|
|
34376
|
-
|
|
34377
|
-
|
|
34378
|
-
|
|
34379
|
-
|
|
34380
|
-
|
|
34381
|
-
|
|
34046
|
+
return readFirstString(rawInput, [
|
|
34047
|
+
"path",
|
|
34048
|
+
"file",
|
|
34049
|
+
"filePath",
|
|
34050
|
+
"filepath",
|
|
34051
|
+
"file_path",
|
|
34052
|
+
"target",
|
|
34053
|
+
"uri",
|
|
34054
|
+
"url",
|
|
34055
|
+
"query",
|
|
34056
|
+
"pattern",
|
|
34057
|
+
"text",
|
|
34058
|
+
"search",
|
|
34059
|
+
"name",
|
|
34060
|
+
"description"
|
|
34061
|
+
]);
|
|
34062
|
+
}
|
|
34063
|
+
function summarizeTaskInput(rawInput, title) {
|
|
34064
|
+
const subagentType = readFirstString(rawInput, ["subagent_type", "subagentType", "agent", "agentType"]);
|
|
34065
|
+
const description = readFirstString(rawInput, ["description", "task", "summary"]);
|
|
34066
|
+
if (subagentType && description) {
|
|
34067
|
+
return description === title ? subagentType : `${subagentType}: ${description}`;
|
|
34068
|
+
}
|
|
34069
|
+
if (subagentType)
|
|
34070
|
+
return subagentType;
|
|
34071
|
+
return;
|
|
34072
|
+
}
|
|
34073
|
+
function readFirstString(record3, keys) {
|
|
34074
|
+
for (const key of keys) {
|
|
34075
|
+
const value = record3[key];
|
|
34076
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
34077
|
+
return value.trim();
|
|
34382
34078
|
}
|
|
34383
|
-
await this.removeSession(session3);
|
|
34384
|
-
await deleteAcpxSessionFiles({ acpxRecordId });
|
|
34385
34079
|
}
|
|
34386
|
-
|
|
34387
|
-
|
|
34388
|
-
|
|
34389
|
-
|
|
34390
|
-
|
|
34391
|
-
|
|
34080
|
+
return;
|
|
34081
|
+
}
|
|
34082
|
+
function readFirstStringArray(record3, keys) {
|
|
34083
|
+
for (const key of keys) {
|
|
34084
|
+
const value = record3[key];
|
|
34085
|
+
if (!Array.isArray(value))
|
|
34086
|
+
continue;
|
|
34087
|
+
const entries = value.map((entry) => typeof entry === "string" && entry.trim().length > 0 ? entry.trim() : undefined).filter((entry) => entry !== undefined);
|
|
34088
|
+
if (entries.length > 0) {
|
|
34089
|
+
return entries;
|
|
34392
34090
|
}
|
|
34393
|
-
await terminateAcpxQueueOwner(acpxRecordId);
|
|
34394
34091
|
}
|
|
34395
|
-
|
|
34396
|
-
|
|
34397
|
-
|
|
34092
|
+
return;
|
|
34093
|
+
}
|
|
34094
|
+
function asFiniteNumber(value) {
|
|
34095
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
34096
|
+
}
|
|
34097
|
+
function firstFiniteNumber(record3, keys) {
|
|
34098
|
+
for (const key of keys) {
|
|
34099
|
+
const n = asFiniteNumber(record3[key]);
|
|
34100
|
+
if (n !== undefined)
|
|
34101
|
+
return n;
|
|
34398
34102
|
}
|
|
34399
|
-
|
|
34400
|
-
|
|
34103
|
+
return;
|
|
34104
|
+
}
|
|
34105
|
+
function normalizeUsageBreakdown(value) {
|
|
34106
|
+
if (!isRecord4(value))
|
|
34107
|
+
return;
|
|
34108
|
+
const out = {};
|
|
34109
|
+
for (const [key, aliases] of USAGE_BREAKDOWN_FIELDS) {
|
|
34110
|
+
const n = firstFiniteNumber(value, aliases);
|
|
34111
|
+
if (n !== undefined)
|
|
34112
|
+
out[key] = n;
|
|
34401
34113
|
}
|
|
34402
|
-
|
|
34403
|
-
|
|
34404
|
-
|
|
34405
|
-
|
|
34406
|
-
|
|
34407
|
-
|
|
34408
|
-
|
|
34409
|
-
|
|
34410
|
-
|
|
34411
|
-
|
|
34412
|
-
|
|
34413
|
-
|
|
34414
|
-
|
|
34415
|
-
|
|
34416
|
-
|
|
34417
|
-
|
|
34114
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
34115
|
+
}
|
|
34116
|
+
function normalizeUsageCost(value) {
|
|
34117
|
+
if (!isRecord4(value))
|
|
34118
|
+
return;
|
|
34119
|
+
const amount = asFiniteNumber(value.amount);
|
|
34120
|
+
const currency = readString2(value, "currency");
|
|
34121
|
+
if (amount === undefined && !currency)
|
|
34122
|
+
return;
|
|
34123
|
+
return { ...amount !== undefined ? { amount } : {}, ...currency ? { currency } : {} };
|
|
34124
|
+
}
|
|
34125
|
+
function normalizeAgentCommands(value) {
|
|
34126
|
+
if (!Array.isArray(value))
|
|
34127
|
+
return [];
|
|
34128
|
+
const out = [];
|
|
34129
|
+
for (const entry of value) {
|
|
34130
|
+
if (!isRecord4(entry))
|
|
34131
|
+
continue;
|
|
34132
|
+
const name = readString2(entry, "name");
|
|
34133
|
+
if (!name)
|
|
34134
|
+
continue;
|
|
34135
|
+
const description = readString2(entry, "description");
|
|
34136
|
+
out.push({ name, ...description ? { description } : {}, hasInput: entry.input != null });
|
|
34418
34137
|
}
|
|
34419
|
-
|
|
34420
|
-
|
|
34421
|
-
|
|
34422
|
-
|
|
34423
|
-
|
|
34424
|
-
|
|
34425
|
-
|
|
34426
|
-
|
|
34427
|
-
|
|
34428
|
-
|
|
34138
|
+
return out;
|
|
34139
|
+
}
|
|
34140
|
+
function isRecord4(value) {
|
|
34141
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34142
|
+
}
|
|
34143
|
+
function readString2(rawInput, key) {
|
|
34144
|
+
if (!isRecord4(rawInput))
|
|
34145
|
+
return;
|
|
34146
|
+
const value = rawInput[key];
|
|
34147
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
34148
|
+
}
|
|
34149
|
+
function truncateToolDisplay(text) {
|
|
34150
|
+
return text.length > 60 ? `${text.slice(0, 57)}...` : text;
|
|
34151
|
+
}
|
|
34152
|
+
function isGenericToolTitle(kind, title) {
|
|
34153
|
+
const normalizedTitle = title.trim().toLowerCase();
|
|
34154
|
+
if (kind === "execute" && ["bash", "shell", "sh", "powershell", "cmd"].includes(normalizedTitle)) {
|
|
34155
|
+
return true;
|
|
34429
34156
|
}
|
|
34430
|
-
|
|
34431
|
-
|
|
34432
|
-
return;
|
|
34433
|
-
}
|
|
34434
|
-
const record3 = await this.readSessionRecord(session3);
|
|
34435
|
-
const env = this.spawnEnvironment(session3);
|
|
34436
|
-
await this.queueOwnerLauncher.launch({
|
|
34437
|
-
acpxRecordId: record3.acpxRecordId,
|
|
34438
|
-
coordinatorSession: session3.mcpCoordinatorSession,
|
|
34439
|
-
...session3.mcpSourceHandle ? { sourceHandle: session3.mcpSourceHandle } : {},
|
|
34440
|
-
permissionMode: this.permissionMode,
|
|
34441
|
-
nonInteractivePermissions: this.nonInteractivePermissions,
|
|
34442
|
-
...session3.model?.trim() ? { sessionOptions: { model: session3.model.trim() } } : {},
|
|
34443
|
-
...env ? { env } : {}
|
|
34444
|
-
});
|
|
34157
|
+
if (kind === "search" && ["grep", "rg", "search"].includes(normalizedTitle)) {
|
|
34158
|
+
return true;
|
|
34445
34159
|
}
|
|
34446
|
-
|
|
34447
|
-
|
|
34448
|
-
"sessions",
|
|
34449
|
-
"show",
|
|
34450
|
-
session3.transportSession
|
|
34451
|
-
], "json"), this.withSpawnEnvironment(session3, {
|
|
34452
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34453
|
-
stage: "read-session-record"
|
|
34454
|
-
}));
|
|
34455
|
-
if (result.code !== 0) {
|
|
34456
|
-
const detail = normalizeCommandError(result) ?? `command failed with exit code ${result.code}`;
|
|
34457
|
-
throw new Error(detail);
|
|
34458
|
-
}
|
|
34459
|
-
const record3 = parseAcpxSessionRecordId(result.stdout);
|
|
34460
|
-
if (record3)
|
|
34461
|
-
return record3;
|
|
34462
|
-
throw new Error("failed to resolve acpx session record id");
|
|
34160
|
+
if (kind === "read" && ["read", "cat"].includes(normalizedTitle)) {
|
|
34161
|
+
return true;
|
|
34463
34162
|
}
|
|
34464
|
-
|
|
34465
|
-
|
|
34466
|
-
|
|
34163
|
+
return false;
|
|
34164
|
+
}
|
|
34165
|
+
var USAGE_BREAKDOWN_FIELDS;
|
|
34166
|
+
var init_streaming_prompt = __esm(() => {
|
|
34167
|
+
init_claude_background_followup();
|
|
34168
|
+
init_tool_kind_emoji();
|
|
34169
|
+
USAGE_BREAKDOWN_FIELDS = [
|
|
34170
|
+
["inputTokens", ["inputTokens", "input_tokens"]],
|
|
34171
|
+
["outputTokens", ["outputTokens", "output_tokens"]],
|
|
34172
|
+
["cachedReadTokens", ["cachedReadTokens", "cacheReadInputTokens", "cache_read_input_tokens"]],
|
|
34173
|
+
["cachedWriteTokens", ["cachedWriteTokens", "cacheCreationInputTokens", "cache_creation_input_tokens"]],
|
|
34174
|
+
["thoughtTokens", ["thoughtTokens", "thought_tokens"]],
|
|
34175
|
+
["totalTokens", ["totalTokens", "total_tokens"]]
|
|
34176
|
+
];
|
|
34177
|
+
});
|
|
34178
|
+
|
|
34179
|
+
// src/transport/acpx-cli/node-pty-helper.ts
|
|
34180
|
+
import { chmod as chmodFs } from "node:fs/promises";
|
|
34181
|
+
import { dirname as dirname13, join as join21 } from "node:path";
|
|
34182
|
+
function resolveNodePtyHelperPath(packageJsonPath, platform, arch) {
|
|
34183
|
+
if (platform === "win32") {
|
|
34184
|
+
return null;
|
|
34467
34185
|
}
|
|
34468
|
-
|
|
34469
|
-
|
|
34470
|
-
|
|
34471
|
-
|
|
34472
|
-
|
|
34473
|
-
}
|
|
34474
|
-
return result.stdout;
|
|
34186
|
+
return join21(dirname13(packageJsonPath), "prebuilds", `${platform}-${arch}`, "spawn-helper");
|
|
34187
|
+
}
|
|
34188
|
+
async function ensureNodePtyHelperExecutable(helperPath, chmod5 = chmodFs) {
|
|
34189
|
+
if (!helperPath) {
|
|
34190
|
+
return;
|
|
34475
34191
|
}
|
|
34476
|
-
|
|
34477
|
-
|
|
34478
|
-
|
|
34479
|
-
|
|
34480
|
-
|
|
34192
|
+
try {
|
|
34193
|
+
await chmod5(helperPath, 493);
|
|
34194
|
+
} catch (error2) {
|
|
34195
|
+
if (error2.code === "ENOENT") {
|
|
34196
|
+
return;
|
|
34481
34197
|
}
|
|
34482
|
-
|
|
34198
|
+
throw error2;
|
|
34483
34199
|
}
|
|
34484
|
-
|
|
34485
|
-
|
|
34486
|
-
|
|
34487
|
-
|
|
34488
|
-
|
|
34489
|
-
|
|
34490
|
-
|
|
34491
|
-
|
|
34492
|
-
|
|
34493
|
-
|
|
34494
|
-
|
|
34495
|
-
|
|
34496
|
-
|
|
34497
|
-
|
|
34498
|
-
|
|
34499
|
-
|
|
34500
|
-
|
|
34501
|
-
|
|
34502
|
-
|
|
34200
|
+
}
|
|
34201
|
+
var init_node_pty_helper = () => {};
|
|
34202
|
+
|
|
34203
|
+
// src/transport/codex-subagent-filter.ts
|
|
34204
|
+
import { closeSync, openSync, readdirSync, readSync, statSync as statSync2 } from "node:fs";
|
|
34205
|
+
import { homedir as homedir11 } from "node:os";
|
|
34206
|
+
import { join as join22 } from "node:path";
|
|
34207
|
+
function resolveCodexHome(env = process.env) {
|
|
34208
|
+
const fromEnv = env.CODEX_HOME?.trim();
|
|
34209
|
+
return fromEnv ? fromEnv : join22(homedir11(), ".codex");
|
|
34210
|
+
}
|
|
34211
|
+
function isPlainObject3(value) {
|
|
34212
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
34213
|
+
}
|
|
34214
|
+
function isSubagentSource(source) {
|
|
34215
|
+
if (!isPlainObject3(source) || !Object.hasOwn(source, "subagent"))
|
|
34216
|
+
return false;
|
|
34217
|
+
const subagent = source.subagent;
|
|
34218
|
+
if (!isPlainObject3(subagent))
|
|
34219
|
+
return false;
|
|
34220
|
+
return Object.values(subagent).some((variant) => isPlainObject3(variant) && typeof variant.parent_thread_id === "string");
|
|
34221
|
+
}
|
|
34222
|
+
function sessionMetaLineIsSubagent(line) {
|
|
34223
|
+
if (!line)
|
|
34224
|
+
return false;
|
|
34225
|
+
let parsed;
|
|
34226
|
+
try {
|
|
34227
|
+
parsed = JSON.parse(line);
|
|
34228
|
+
} catch {
|
|
34229
|
+
return false;
|
|
34503
34230
|
}
|
|
34504
|
-
|
|
34505
|
-
|
|
34506
|
-
|
|
34507
|
-
|
|
34508
|
-
|
|
34509
|
-
|
|
34510
|
-
|
|
34511
|
-
const
|
|
34512
|
-
|
|
34513
|
-
|
|
34514
|
-
|
|
34515
|
-
|
|
34516
|
-
|
|
34517
|
-
|
|
34518
|
-
|
|
34519
|
-
|
|
34520
|
-
|
|
34521
|
-
|
|
34522
|
-
let segmentError;
|
|
34523
|
-
let toolEventChain = Promise.resolve();
|
|
34524
|
-
let toolEventError;
|
|
34525
|
-
let thoughtChain = Promise.resolve();
|
|
34526
|
-
let thoughtError;
|
|
34527
|
-
let planChain = Promise.resolve();
|
|
34528
|
-
let planError;
|
|
34529
|
-
let usageChain = Promise.resolve();
|
|
34530
|
-
let usageError;
|
|
34531
|
-
let commandsChain = Promise.resolve();
|
|
34532
|
-
let commandsError;
|
|
34533
|
-
const userOnToolEvent = onToolEvent;
|
|
34534
|
-
const userOnThought = onThought;
|
|
34535
|
-
const userOnPlan = onPlan;
|
|
34536
|
-
const userOnUsage = onUsage;
|
|
34537
|
-
const userOnCommands = onCommands;
|
|
34538
|
-
const state = createStreamingPromptState(formatToolCalls, {
|
|
34539
|
-
mode: toolEventMode,
|
|
34540
|
-
driver,
|
|
34541
|
-
rawStream,
|
|
34542
|
-
...userOnToolEvent ? {
|
|
34543
|
-
onToolEvent: (event) => {
|
|
34544
|
-
toolEventChain = toolEventChain.then(() => userOnToolEvent(event)).catch((error2) => {
|
|
34545
|
-
toolEventError ??= error2;
|
|
34546
|
-
});
|
|
34547
|
-
}
|
|
34548
|
-
} : {},
|
|
34549
|
-
...userOnThought ? {
|
|
34550
|
-
onThought: (chunk) => {
|
|
34551
|
-
thoughtChain = thoughtChain.then(() => userOnThought(chunk)).catch((error2) => {
|
|
34552
|
-
thoughtError ??= error2;
|
|
34553
|
-
});
|
|
34554
|
-
}
|
|
34555
|
-
} : {},
|
|
34556
|
-
...userOnPlan ? {
|
|
34557
|
-
onPlan: (entries) => {
|
|
34558
|
-
planChain = planChain.then(() => userOnPlan(entries)).catch((error2) => {
|
|
34559
|
-
planError ??= error2;
|
|
34560
|
-
});
|
|
34561
|
-
}
|
|
34562
|
-
} : {},
|
|
34563
|
-
...userOnUsage ? {
|
|
34564
|
-
onUsage: (usage) => {
|
|
34565
|
-
usageChain = usageChain.then(() => userOnUsage(usage)).catch((error2) => {
|
|
34566
|
-
usageError ??= error2;
|
|
34567
|
-
});
|
|
34568
|
-
}
|
|
34569
|
-
} : {},
|
|
34570
|
-
...userOnCommands ? {
|
|
34571
|
-
onCommands: (commands) => {
|
|
34572
|
-
commandsChain = commandsChain.then(() => userOnCommands(commands)).catch((error2) => {
|
|
34573
|
-
commandsError ??= error2;
|
|
34574
|
-
});
|
|
34575
|
-
}
|
|
34576
|
-
} : {}
|
|
34577
|
-
});
|
|
34578
|
-
const sink2 = reply ? rawStream ? createVerbatimReplySink(reply) : createQuotaGatedReplySink({
|
|
34579
|
-
reply,
|
|
34580
|
-
...replyContext ? { replyContext } : {}
|
|
34581
|
-
}) : null;
|
|
34582
|
-
const feedSegment = (segment) => {
|
|
34583
|
-
if (onSegment) {
|
|
34584
|
-
segmentChain = segmentChain.then(() => onSegment(segment)).catch((error2) => {
|
|
34585
|
-
segmentError ??= error2;
|
|
34586
|
-
});
|
|
34587
|
-
}
|
|
34588
|
-
sink2?.feedSegment(segment);
|
|
34589
|
-
lastReplyAt = now();
|
|
34590
|
-
};
|
|
34591
|
-
const flushBuffer = () => {
|
|
34592
|
-
const remaining = rawStream ? state.buffer : state.buffer.trim();
|
|
34593
|
-
if (remaining.length > 0) {
|
|
34594
|
-
state.buffer = "";
|
|
34595
|
-
feedSegment(remaining);
|
|
34596
|
-
}
|
|
34597
|
-
};
|
|
34598
|
-
const timer = setIntervalFn(() => {
|
|
34599
|
-
if (state.buffer.trim().length > 0 && now() - lastReplyAt >= maxSegmentWaitMs) {
|
|
34600
|
-
flushBuffer();
|
|
34231
|
+
const payload = parsed?.payload;
|
|
34232
|
+
return isSubagentSource(payload?.source);
|
|
34233
|
+
}
|
|
34234
|
+
function createSubagentPredicate(reader) {
|
|
34235
|
+
let index = null;
|
|
34236
|
+
const cache = new Map;
|
|
34237
|
+
return (sessionId) => {
|
|
34238
|
+
const cached2 = cache.get(sessionId);
|
|
34239
|
+
if (cached2 !== undefined)
|
|
34240
|
+
return cached2;
|
|
34241
|
+
let result = false;
|
|
34242
|
+
try {
|
|
34243
|
+
if (!index) {
|
|
34244
|
+
index = new Map;
|
|
34245
|
+
for (const path15 of reader.listRolloutPaths()) {
|
|
34246
|
+
const id = path15.match(ROLLOUT_RE)?.[1];
|
|
34247
|
+
if (id)
|
|
34248
|
+
index.set(id.toLowerCase(), path15);
|
|
34601
34249
|
}
|
|
34602
|
-
}
|
|
34603
|
-
|
|
34604
|
-
|
|
34605
|
-
|
|
34606
|
-
|
|
34607
|
-
|
|
34608
|
-
|
|
34250
|
+
}
|
|
34251
|
+
const path14 = index.get(sessionId.toLowerCase());
|
|
34252
|
+
if (path14)
|
|
34253
|
+
result = sessionMetaLineIsSubagent(reader.readFirstLine(path14));
|
|
34254
|
+
} catch {
|
|
34255
|
+
result = false;
|
|
34256
|
+
}
|
|
34257
|
+
cache.set(sessionId, result);
|
|
34258
|
+
return result;
|
|
34259
|
+
};
|
|
34260
|
+
}
|
|
34261
|
+
function filterSubagentSessions(result, isSubagent) {
|
|
34262
|
+
return {
|
|
34263
|
+
...result,
|
|
34264
|
+
sessions: result.sessions.filter((session3) => {
|
|
34265
|
+
try {
|
|
34266
|
+
return !isSubagent(session3.sessionId);
|
|
34267
|
+
} catch {
|
|
34268
|
+
return true;
|
|
34269
|
+
}
|
|
34270
|
+
})
|
|
34271
|
+
};
|
|
34272
|
+
}
|
|
34273
|
+
function nodeRolloutReader(home) {
|
|
34274
|
+
const root = join22(home, "sessions");
|
|
34275
|
+
return {
|
|
34276
|
+
listRolloutPaths() {
|
|
34277
|
+
const out = [];
|
|
34278
|
+
const walk = (dir) => {
|
|
34279
|
+
let entries;
|
|
34280
|
+
try {
|
|
34281
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
34282
|
+
} catch {
|
|
34283
|
+
return;
|
|
34609
34284
|
}
|
|
34610
|
-
|
|
34611
|
-
|
|
34612
|
-
|
|
34613
|
-
|
|
34614
|
-
|
|
34615
|
-
|
|
34616
|
-
reject(err);
|
|
34617
|
-
});
|
|
34618
|
-
child.on("close", (code) => {
|
|
34619
|
-
clearIntervalFn(timer);
|
|
34620
|
-
const remaining = state.finalize();
|
|
34621
|
-
if (remaining.length > 0) {
|
|
34622
|
-
feedSegment(remaining);
|
|
34285
|
+
for (const entry of entries) {
|
|
34286
|
+
const full = join22(dir, entry.name);
|
|
34287
|
+
if (entry.isDirectory())
|
|
34288
|
+
walk(full);
|
|
34289
|
+
else if (entry.isFile() && entry.name.startsWith("rollout-") && entry.name.endsWith(".jsonl"))
|
|
34290
|
+
out.push(full);
|
|
34623
34291
|
}
|
|
34624
|
-
|
|
34625
|
-
|
|
34626
|
-
|
|
34627
|
-
|
|
34628
|
-
|
|
34629
|
-
|
|
34630
|
-
|
|
34631
|
-
|
|
34632
|
-
|
|
34633
|
-
|
|
34634
|
-
|
|
34635
|
-
|
|
34636
|
-
|
|
34637
|
-
|
|
34638
|
-
|
|
34639
|
-
|
|
34640
|
-
|
|
34641
|
-
|
|
34642
|
-
|
|
34643
|
-
|
|
34644
|
-
|
|
34645
|
-
return;
|
|
34646
|
-
|
|
34647
|
-
if (thoughtError) {
|
|
34648
|
-
reject(thoughtError);
|
|
34649
|
-
return;
|
|
34650
|
-
}
|
|
34651
|
-
if (planError) {
|
|
34652
|
-
reject(planError);
|
|
34653
|
-
return;
|
|
34654
|
-
}
|
|
34655
|
-
if (usageError) {
|
|
34656
|
-
reject(usageError);
|
|
34657
|
-
return;
|
|
34658
|
-
}
|
|
34659
|
-
if (commandsError) {
|
|
34660
|
-
reject(commandsError);
|
|
34292
|
+
};
|
|
34293
|
+
walk(root);
|
|
34294
|
+
return out;
|
|
34295
|
+
},
|
|
34296
|
+
readFirstLine(path14) {
|
|
34297
|
+
let fd;
|
|
34298
|
+
try {
|
|
34299
|
+
statSync2(path14);
|
|
34300
|
+
fd = openSync(path14, "r");
|
|
34301
|
+
const buf = Buffer.alloc(READ_CHUNK);
|
|
34302
|
+
let acc = "";
|
|
34303
|
+
let total = 0;
|
|
34304
|
+
for (;; ) {
|
|
34305
|
+
const bytes = readSync(fd, buf, 0, READ_CHUNK, total);
|
|
34306
|
+
if (bytes <= 0)
|
|
34307
|
+
break;
|
|
34308
|
+
acc += buf.toString("utf8", 0, bytes);
|
|
34309
|
+
total += bytes;
|
|
34310
|
+
const nl = acc.indexOf(`
|
|
34311
|
+
`);
|
|
34312
|
+
if (nl !== -1)
|
|
34313
|
+
return acc.slice(0, nl);
|
|
34314
|
+
if (total >= FIRST_LINE_READ_CAP)
|
|
34661
34315
|
return;
|
|
34662
|
-
|
|
34663
|
-
|
|
34664
|
-
|
|
34665
|
-
|
|
34666
|
-
|
|
34667
|
-
|
|
34668
|
-
|
|
34669
|
-
|
|
34670
|
-
|
|
34316
|
+
}
|
|
34317
|
+
return acc.length ? acc : undefined;
|
|
34318
|
+
} catch {
|
|
34319
|
+
return;
|
|
34320
|
+
} finally {
|
|
34321
|
+
if (fd !== undefined) {
|
|
34322
|
+
try {
|
|
34323
|
+
closeSync(fd);
|
|
34324
|
+
} catch {}
|
|
34325
|
+
}
|
|
34326
|
+
}
|
|
34327
|
+
}
|
|
34328
|
+
};
|
|
34329
|
+
}
|
|
34330
|
+
function codexSubagentPredicate(env) {
|
|
34331
|
+
return createSubagentPredicate(nodeRolloutReader(resolveCodexHome(env)));
|
|
34332
|
+
}
|
|
34333
|
+
var CODEX_AGENT_NAME = "codex", FIRST_LINE_READ_CAP, READ_CHUNK, ROLLOUT_RE;
|
|
34334
|
+
var init_codex_subagent_filter = __esm(() => {
|
|
34335
|
+
FIRST_LINE_READ_CAP = 1024 * 1024;
|
|
34336
|
+
READ_CHUNK = 64 * 1024;
|
|
34337
|
+
ROLLOUT_RE = /rollout-.*-([0-9a-fA-F-]{36})\.jsonl$/;
|
|
34338
|
+
});
|
|
34339
|
+
|
|
34340
|
+
// src/transport/agent-session-list.ts
|
|
34341
|
+
function isUnknownFilterCwdOption(output) {
|
|
34342
|
+
return /(?:unknown|unrecognized) option/i.test(output) && output.includes("--filter-cwd");
|
|
34343
|
+
}
|
|
34344
|
+
async function runAgentSessionList(options) {
|
|
34345
|
+
let result = await options.runList(true);
|
|
34346
|
+
let filterLocally = false;
|
|
34347
|
+
if (result.code !== 0 && options.filterCwd && isUnknownFilterCwdOption(result.stdout + result.stderr)) {
|
|
34348
|
+
result = await options.runList(false);
|
|
34349
|
+
filterLocally = true;
|
|
34350
|
+
}
|
|
34351
|
+
if (result.code !== 0) {
|
|
34352
|
+
if ((result.stdout + result.stderr).includes("sessionCapabilities.list")) {
|
|
34353
|
+
return;
|
|
34354
|
+
}
|
|
34355
|
+
throw new Error(options.formatError(result));
|
|
34356
|
+
}
|
|
34357
|
+
const parsed = parseAgentSessionListOutput(result.stdout, filterLocally ? options.filterCwd : undefined);
|
|
34358
|
+
if (parsed && options.isSubagentSession) {
|
|
34359
|
+
return filterSubagentSessions(parsed, options.isSubagentSession);
|
|
34360
|
+
}
|
|
34361
|
+
return parsed;
|
|
34362
|
+
}
|
|
34363
|
+
function parseAgentSessionListOutput(stdout2, filterCwd) {
|
|
34364
|
+
let parsed;
|
|
34365
|
+
try {
|
|
34366
|
+
parsed = JSON.parse(stdout2);
|
|
34367
|
+
} catch {
|
|
34368
|
+
throw new Error("failed to parse acpx sessions list output");
|
|
34369
|
+
}
|
|
34370
|
+
if (!isAgentSessionListResult(parsed)) {
|
|
34371
|
+
return;
|
|
34372
|
+
}
|
|
34373
|
+
return filterCwd ? filterAgentSessionListByCwd(parsed, filterCwd) : parsed;
|
|
34374
|
+
}
|
|
34375
|
+
function isAgentSessionListResult(value) {
|
|
34376
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
34377
|
+
return false;
|
|
34378
|
+
const record3 = value;
|
|
34379
|
+
if (record3.source !== "agent" || !Array.isArray(record3.sessions))
|
|
34380
|
+
return false;
|
|
34381
|
+
return record3.sessions.every((session3) => {
|
|
34382
|
+
if (!session3 || typeof session3 !== "object" || Array.isArray(session3))
|
|
34383
|
+
return false;
|
|
34384
|
+
const item = session3;
|
|
34385
|
+
return typeof item.sessionId === "string";
|
|
34386
|
+
});
|
|
34387
|
+
}
|
|
34388
|
+
function filterAgentSessionListByCwd(result, cwd) {
|
|
34389
|
+
return {
|
|
34390
|
+
...result,
|
|
34391
|
+
sessions: result.sessions.filter((session3) => session3.cwd && isSamePath(session3.cwd, cwd))
|
|
34392
|
+
};
|
|
34393
|
+
}
|
|
34394
|
+
var init_agent_session_list = __esm(() => {
|
|
34395
|
+
init_path();
|
|
34396
|
+
init_codex_subagent_filter();
|
|
34397
|
+
});
|
|
34398
|
+
|
|
34399
|
+
// src/transport/acpx-session-files.ts
|
|
34400
|
+
import { readdir as readdir4, unlink as unlink2 } from "node:fs/promises";
|
|
34401
|
+
import { homedir as homedir12 } from "node:os";
|
|
34402
|
+
import { join as join23 } from "node:path";
|
|
34403
|
+
async function deleteAcpxSessionFiles(options) {
|
|
34404
|
+
const dir = options.sessionsDir ?? join23(homedir12(), ".acpx", "sessions");
|
|
34405
|
+
const safeId = encodeURIComponent(options.acpxRecordId);
|
|
34406
|
+
await unlink2(join23(dir, `${safeId}.json`)).catch(() => {
|
|
34407
|
+
return;
|
|
34408
|
+
});
|
|
34409
|
+
let entries;
|
|
34410
|
+
try {
|
|
34411
|
+
entries = await readdir4(dir);
|
|
34412
|
+
} catch {
|
|
34413
|
+
return;
|
|
34414
|
+
}
|
|
34415
|
+
const streamFiles = entries.filter((name) => name.startsWith(`${safeId}.stream.`));
|
|
34416
|
+
for (const name of streamFiles) {
|
|
34417
|
+
await unlink2(join23(dir, name)).catch(() => {
|
|
34418
|
+
return;
|
|
34671
34419
|
});
|
|
34672
34420
|
}
|
|
34673
|
-
|
|
34674
|
-
|
|
34675
|
-
|
|
34676
|
-
|
|
34677
|
-
|
|
34678
|
-
|
|
34421
|
+
}
|
|
34422
|
+
var init_acpx_session_files = () => {};
|
|
34423
|
+
|
|
34424
|
+
// src/transport/session-effort.ts
|
|
34425
|
+
function requireAdvertisedSessionEffort(raw, value) {
|
|
34426
|
+
const advertised = parseSessionEffortRecord(raw);
|
|
34427
|
+
if (!advertised) {
|
|
34428
|
+
throw new Error("the active agent does not advertise a reasoning-effort option");
|
|
34679
34429
|
}
|
|
34680
|
-
|
|
34681
|
-
|
|
34430
|
+
if (!advertised.available.includes(value)) {
|
|
34431
|
+
throw new Error(`reasoning effort "${value}" is not advertised by the active agent`);
|
|
34682
34432
|
}
|
|
34683
|
-
|
|
34684
|
-
|
|
34685
|
-
|
|
34433
|
+
return advertised;
|
|
34434
|
+
}
|
|
34435
|
+
function parseSessionEffortRecord(raw) {
|
|
34436
|
+
let record3;
|
|
34437
|
+
try {
|
|
34438
|
+
record3 = JSON.parse(raw);
|
|
34439
|
+
} catch {
|
|
34440
|
+
return;
|
|
34686
34441
|
}
|
|
34687
|
-
|
|
34442
|
+
if (!isRecord5(record3) || !isRecord5(record3.acpx) || !Array.isArray(record3.acpx.config_options)) {
|
|
34443
|
+
return;
|
|
34444
|
+
}
|
|
34445
|
+
for (const candidate of record3.acpx.config_options) {
|
|
34446
|
+
if (!isRecord5(candidate) || typeof candidate.id !== "string")
|
|
34447
|
+
continue;
|
|
34448
|
+
if (candidate.category !== "thought_level" && !EFFORT_CONFIG_IDS.has(candidate.id))
|
|
34449
|
+
continue;
|
|
34450
|
+
const available = Array.isArray(candidate.options) ? candidate.options.flatMap(effortOptionValues) : [];
|
|
34688
34451
|
return {
|
|
34689
|
-
|
|
34690
|
-
|
|
34691
|
-
|
|
34692
|
-
model: session3.model,
|
|
34693
|
-
permission: this.permissionInput()
|
|
34452
|
+
configId: candidate.id,
|
|
34453
|
+
current: typeof candidate.currentValue === "string" ? candidate.currentValue : undefined,
|
|
34454
|
+
available
|
|
34694
34455
|
};
|
|
34695
34456
|
}
|
|
34696
|
-
|
|
34697
|
-
|
|
34698
|
-
|
|
34699
|
-
|
|
34700
|
-
return
|
|
34701
|
-
|
|
34702
|
-
|
|
34703
|
-
|
|
34704
|
-
|
|
34457
|
+
return;
|
|
34458
|
+
}
|
|
34459
|
+
function effortOptionValues(option) {
|
|
34460
|
+
if (!isRecord5(option))
|
|
34461
|
+
return [];
|
|
34462
|
+
if (typeof option.value === "string")
|
|
34463
|
+
return [option.value];
|
|
34464
|
+
return Array.isArray(option.options) ? option.options.flatMap(effortOptionValues) : [];
|
|
34465
|
+
}
|
|
34466
|
+
function isRecord5(value) {
|
|
34467
|
+
return typeof value === "object" && value !== null;
|
|
34468
|
+
}
|
|
34469
|
+
var EFFORT_CONFIG_IDS;
|
|
34470
|
+
var init_session_effort = __esm(() => {
|
|
34471
|
+
EFFORT_CONFIG_IDS = new Set([
|
|
34472
|
+
"reasoning_effort",
|
|
34473
|
+
"effort",
|
|
34474
|
+
"thought_level",
|
|
34475
|
+
"thinking"
|
|
34476
|
+
]);
|
|
34477
|
+
});
|
|
34478
|
+
|
|
34479
|
+
// src/transport/permission-mode-flag.ts
|
|
34480
|
+
function permissionModeToFlag(permissionMode) {
|
|
34481
|
+
switch (permissionMode) {
|
|
34482
|
+
case "approve-reads":
|
|
34483
|
+
return "--approve-reads";
|
|
34484
|
+
case "deny-all":
|
|
34485
|
+
return "--deny-all";
|
|
34486
|
+
case "approve-all":
|
|
34487
|
+
return "--approve-all";
|
|
34705
34488
|
}
|
|
34706
|
-
|
|
34707
|
-
|
|
34489
|
+
}
|
|
34490
|
+
|
|
34491
|
+
// src/transport/acpx-command-builder.ts
|
|
34492
|
+
function buildPermissionArgs(input) {
|
|
34493
|
+
const args = [permissionModeToFlag(input.permissionMode), "--non-interactive-permissions", input.nonInteractivePermissions];
|
|
34494
|
+
if (typeof input.permissionPolicy === "string" && input.permissionPolicy.trim().length > 0) {
|
|
34495
|
+
args.push("--permission-policy", input.permissionPolicy);
|
|
34708
34496
|
}
|
|
34497
|
+
return args;
|
|
34709
34498
|
}
|
|
34710
|
-
function
|
|
34711
|
-
|
|
34712
|
-
|
|
34713
|
-
|
|
34714
|
-
|
|
34715
|
-
|
|
34716
|
-
|
|
34717
|
-
|
|
34718
|
-
|
|
34719
|
-
|
|
34499
|
+
function buildQueueOwnerTtlArgs(queueOwnerTtlSeconds) {
|
|
34500
|
+
if (typeof queueOwnerTtlSeconds !== "number" || !Number.isFinite(queueOwnerTtlSeconds))
|
|
34501
|
+
return [];
|
|
34502
|
+
return ["--ttl", String(queueOwnerTtlSeconds)];
|
|
34503
|
+
}
|
|
34504
|
+
function buildModelArgs(model) {
|
|
34505
|
+
const trimmed = model?.trim();
|
|
34506
|
+
return trimmed ? ["--model", trimmed] : [];
|
|
34507
|
+
}
|
|
34508
|
+
function appendAgentAndTail(prefix, input, tail2) {
|
|
34509
|
+
if (input.agentCommand)
|
|
34510
|
+
return [...prefix, "--agent", input.agentCommand, ...tail2];
|
|
34511
|
+
return [...prefix, input.agent, ...tail2];
|
|
34512
|
+
}
|
|
34513
|
+
function buildSessionArgs(input, tail2, options = {}) {
|
|
34514
|
+
const prefix = [
|
|
34515
|
+
"--format",
|
|
34516
|
+
options.format ?? "quiet",
|
|
34517
|
+
"--cwd",
|
|
34518
|
+
input.cwd,
|
|
34519
|
+
...buildPermissionArgs(input.permission),
|
|
34520
|
+
...buildModelArgs(input.model)
|
|
34521
|
+
];
|
|
34522
|
+
if (options.verbose)
|
|
34523
|
+
prefix.push("--verbose");
|
|
34524
|
+
return appendAgentAndTail(prefix, input, tail2);
|
|
34525
|
+
}
|
|
34526
|
+
function buildPromptArgs(input, tail2) {
|
|
34527
|
+
const prefix = [
|
|
34528
|
+
"--format",
|
|
34529
|
+
"json",
|
|
34530
|
+
"--json-strict",
|
|
34531
|
+
"--cwd",
|
|
34532
|
+
input.cwd,
|
|
34533
|
+
...buildPermissionArgs(input.permission),
|
|
34534
|
+
...buildModelArgs(input.model),
|
|
34535
|
+
...buildQueueOwnerTtlArgs(input.queueOwnerTtlSeconds)
|
|
34536
|
+
];
|
|
34537
|
+
return appendAgentAndTail(prefix, input, tail2);
|
|
34538
|
+
}
|
|
34539
|
+
function buildAgentQueryArgs(input, format, tail2) {
|
|
34540
|
+
const prefix = ["--format", format, "--cwd", input.cwd, ...buildPermissionArgs(input.permission)];
|
|
34541
|
+
return appendAgentAndTail(prefix, input, tail2);
|
|
34542
|
+
}
|
|
34543
|
+
function isMissingAcpxSessionError(stderr, stdout2) {
|
|
34544
|
+
const combined = `${stderr}
|
|
34545
|
+
${stdout2}`.toLowerCase();
|
|
34546
|
+
return combined.includes("no named session") || combined.includes("no cwd session") || combined.includes("session not found") || combined.includes("unknown session") || combined.includes("no acpx session found");
|
|
34547
|
+
}
|
|
34548
|
+
function parseAcpxSessionRecordId(stdout2) {
|
|
34549
|
+
try {
|
|
34550
|
+
const parsed = JSON.parse(stdout2);
|
|
34551
|
+
const acpxRecordId = typeof parsed.acpxRecordId === "string" ? parsed.acpxRecordId : typeof parsed.id === "string" ? parsed.id : undefined;
|
|
34552
|
+
const providerSessionId = typeof parsed.agentSessionId === "string" && parsed.agentSessionId.length > 0 ? parsed.agentSessionId : undefined;
|
|
34553
|
+
const acpSessionId = typeof parsed.acpSessionId === "string" && parsed.acpSessionId.length > 0 ? parsed.acpSessionId : undefined;
|
|
34554
|
+
const agentSessionId = providerSessionId ?? acpSessionId;
|
|
34555
|
+
if (acpxRecordId && /^[\w.:-]+$/.test(acpxRecordId) && acpxRecordId.length >= 8) {
|
|
34556
|
+
return { acpxRecordId, agentSessionId };
|
|
34720
34557
|
}
|
|
34721
|
-
|
|
34722
|
-
|
|
34723
|
-
|
|
34558
|
+
} catch {
|
|
34559
|
+
const firstLine = stdout2.trim().split(/\r?\n/, 1)[0];
|
|
34560
|
+
if (firstLine && /^[\w.:-]+$/.test(firstLine) && firstLine.length >= 8) {
|
|
34561
|
+
return { acpxRecordId: firstLine };
|
|
34724
34562
|
}
|
|
34725
|
-
rendered.push(/\s/.test(arg) || arg.includes(":") ? `"${arg}"` : arg);
|
|
34726
|
-
}
|
|
34727
|
-
return rendered.join(" ");
|
|
34728
|
-
}
|
|
34729
|
-
function resolveChildEnvironment(baseEnv, explicitEnv, locale) {
|
|
34730
|
-
const source = explicitEnv ?? baseEnv;
|
|
34731
|
-
const env = {};
|
|
34732
|
-
for (const [key, value] of Object.entries(source)) {
|
|
34733
|
-
if (typeof value === "string")
|
|
34734
|
-
env[key] = value;
|
|
34735
34563
|
}
|
|
34736
|
-
|
|
34737
|
-
return env;
|
|
34564
|
+
return;
|
|
34738
34565
|
}
|
|
34739
|
-
var
|
|
34740
|
-
var
|
|
34741
|
-
init_spawn_command();
|
|
34742
|
-
init_claude_settings_policy();
|
|
34743
|
-
init_i18n();
|
|
34744
|
-
init_prompt_output();
|
|
34745
|
-
init_prompt_media();
|
|
34746
|
-
init_streaming_prompt();
|
|
34747
|
-
init_quota_gated_reply_sink();
|
|
34748
|
-
init_node_pty_helper();
|
|
34749
|
-
init_terminate_process_tree();
|
|
34750
|
-
init_acpx_queue_owner_launcher();
|
|
34751
|
-
init_daemon_files();
|
|
34752
|
-
init_agent_session_list();
|
|
34753
|
-
init_codex_subagent_filter();
|
|
34754
|
-
init_acpx_session_files();
|
|
34755
|
-
init_session_effort();
|
|
34756
|
-
init_command_timeouts();
|
|
34757
|
-
init_acpx_command_builder();
|
|
34758
|
-
require4 = createRequire5(import.meta.url);
|
|
34759
|
-
});
|
|
34566
|
+
var DEFAULT_PERMISSION_MODE2 = "approve-all", DEFAULT_NON_INTERACTIVE = "deny";
|
|
34567
|
+
var init_acpx_command_builder = () => {};
|
|
34760
34568
|
|
|
34761
|
-
// src/transport/
|
|
34762
|
-
import {
|
|
34763
|
-
import {
|
|
34764
|
-
import {
|
|
34765
|
-
|
|
34766
|
-
|
|
34767
|
-
|
|
34569
|
+
// src/transport/acpx-cli/acpx-cli-transport.ts
|
|
34570
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
34571
|
+
import { spawn as spawn11 } from "node:child_process";
|
|
34572
|
+
import { spawn as spawnPty } from "node-pty";
|
|
34573
|
+
function managementTimeoutError(args, options, output = {}) {
|
|
34574
|
+
return new CommandTimeoutError(options.timeoutMs, renderCommandForError(args), {
|
|
34575
|
+
stage: options.stage,
|
|
34576
|
+
...output
|
|
34577
|
+
});
|
|
34768
34578
|
}
|
|
34769
|
-
function
|
|
34770
|
-
|
|
34771
|
-
|
|
34772
|
-
|
|
34773
|
-
|
|
34579
|
+
async function defaultRunner(command, args, options) {
|
|
34580
|
+
return await new Promise((resolve4, reject) => {
|
|
34581
|
+
const spawnSpec = resolveSpawnCommand(command, args);
|
|
34582
|
+
const child = spawn11(spawnSpec.command, spawnSpec.args, {
|
|
34583
|
+
env: options?.env,
|
|
34584
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
34585
|
+
});
|
|
34586
|
+
let stdout2 = "";
|
|
34587
|
+
let stderr = "";
|
|
34588
|
+
const onAbort = () => {
|
|
34589
|
+
terminateProcessTree(child.pid ?? 0, { detachedProcessGroup: false });
|
|
34590
|
+
};
|
|
34591
|
+
options?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
34592
|
+
const timeoutId = options?.timeoutMs ? setTimeout(() => {
|
|
34593
|
+
onAbort();
|
|
34594
|
+
reject(managementTimeoutError(args, options, { stdout: stdout2, stderr }));
|
|
34595
|
+
}, options.timeoutMs) : undefined;
|
|
34596
|
+
child.stdout.on("data", (chunk) => {
|
|
34597
|
+
stdout2 += String(chunk);
|
|
34598
|
+
});
|
|
34599
|
+
child.stderr.on("data", (chunk) => {
|
|
34600
|
+
stderr += String(chunk);
|
|
34601
|
+
});
|
|
34602
|
+
child.on("error", (error2) => {
|
|
34603
|
+
options?.signal?.removeEventListener("abort", onAbort);
|
|
34604
|
+
if (timeoutId)
|
|
34605
|
+
clearTimeout(timeoutId);
|
|
34606
|
+
reject(error2);
|
|
34607
|
+
});
|
|
34608
|
+
child.on("close", (code) => {
|
|
34609
|
+
options?.signal?.removeEventListener("abort", onAbort);
|
|
34610
|
+
if (timeoutId)
|
|
34611
|
+
clearTimeout(timeoutId);
|
|
34612
|
+
resolve4({ code: code ?? 1, stdout: stdout2, stderr });
|
|
34613
|
+
});
|
|
34614
|
+
});
|
|
34774
34615
|
}
|
|
34775
|
-
async function
|
|
34776
|
-
const
|
|
34777
|
-
|
|
34778
|
-
|
|
34779
|
-
|
|
34780
|
-
|
|
34781
|
-
|
|
34782
|
-
|
|
34783
|
-
|
|
34784
|
-
|
|
34785
|
-
|
|
34786
|
-
|
|
34787
|
-
|
|
34616
|
+
async function defaultPtyRunner(command, args, options) {
|
|
34617
|
+
const helperPath = resolveNodePtyHelperPath(require4.resolve("node-pty/package.json"), process.platform, process.arch);
|
|
34618
|
+
await ensureNodePtyHelperExecutable(helperPath);
|
|
34619
|
+
return await new Promise((resolve4, reject) => {
|
|
34620
|
+
const spawnSpec = resolveSpawnCommand(command, args);
|
|
34621
|
+
const child = spawnPty(spawnSpec.command, spawnSpec.args, {
|
|
34622
|
+
name: "xterm-color",
|
|
34623
|
+
cols: 80,
|
|
34624
|
+
rows: 24,
|
|
34625
|
+
cwd: process.cwd(),
|
|
34626
|
+
env: resolveChildEnvironment(process.env, options?.env, getLocale())
|
|
34627
|
+
});
|
|
34628
|
+
let output = "";
|
|
34629
|
+
const onAbort = () => {
|
|
34630
|
+
child.kill();
|
|
34631
|
+
};
|
|
34632
|
+
options?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
34633
|
+
const timeoutId = options?.timeoutMs ? setTimeout(() => {
|
|
34634
|
+
onAbort();
|
|
34635
|
+
reject(managementTimeoutError(args, options, { stdout: output }));
|
|
34636
|
+
}, options.timeoutMs) : undefined;
|
|
34637
|
+
child.onData((chunk) => {
|
|
34638
|
+
output += chunk;
|
|
34639
|
+
});
|
|
34640
|
+
child.onExit(({ exitCode }) => {
|
|
34641
|
+
options?.signal?.removeEventListener("abort", onAbort);
|
|
34642
|
+
if (timeoutId)
|
|
34643
|
+
clearTimeout(timeoutId);
|
|
34644
|
+
resolve4({ code: exitCode, stdout: output, stderr: "" });
|
|
34645
|
+
});
|
|
34646
|
+
});
|
|
34647
|
+
}
|
|
34648
|
+
|
|
34649
|
+
class AcpxCliTransport {
|
|
34650
|
+
command;
|
|
34651
|
+
sessionInitTimeoutMs;
|
|
34652
|
+
managementCommandTimeoutMs;
|
|
34653
|
+
permissionMode;
|
|
34654
|
+
nonInteractivePermissions;
|
|
34655
|
+
permissionPolicy;
|
|
34656
|
+
queueOwnerTtlSeconds;
|
|
34657
|
+
runCommand;
|
|
34658
|
+
runPtyCommand;
|
|
34659
|
+
queueOwnerLauncher;
|
|
34660
|
+
streamingHooks;
|
|
34661
|
+
resolveSpawnEnvironment;
|
|
34662
|
+
constructor(options, runCommand = defaultRunner, runPtyCommand = defaultPtyRunner, queueOwnerLauncher, streamingHooks = {}) {
|
|
34663
|
+
this.command = options.command ?? "acpx";
|
|
34664
|
+
this.sessionInitTimeoutMs = options.sessionInitTimeoutMs ?? 120000;
|
|
34665
|
+
this.managementCommandTimeoutMs = options.managementCommandTimeoutMs ?? DEFAULT_MANAGEMENT_COMMAND_TIMEOUT_MS;
|
|
34666
|
+
this.permissionMode = options.permissionMode ?? DEFAULT_PERMISSION_MODE2;
|
|
34667
|
+
this.nonInteractivePermissions = options.nonInteractivePermissions ?? DEFAULT_NON_INTERACTIVE;
|
|
34668
|
+
this.permissionPolicy = options.permissionPolicy;
|
|
34669
|
+
this.queueOwnerTtlSeconds = options.queueOwnerTtlSeconds;
|
|
34670
|
+
this.runCommand = runCommand;
|
|
34671
|
+
this.runPtyCommand = runPtyCommand;
|
|
34672
|
+
this.queueOwnerLauncher = queueOwnerLauncher ?? new AcpxQueueOwnerLauncher({
|
|
34673
|
+
acpxCommand: this.command,
|
|
34674
|
+
...typeof this.queueOwnerTtlSeconds === "number" && Number.isFinite(this.queueOwnerTtlSeconds) ? { ttlMs: this.queueOwnerTtlSeconds * 1000 } : {}
|
|
34675
|
+
});
|
|
34676
|
+
this.streamingHooks = streamingHooks;
|
|
34677
|
+
this.resolveSpawnEnvironment = options.resolveSpawnEnvironment ?? resolveClaudeSpawnEnvironment;
|
|
34678
|
+
}
|
|
34679
|
+
async ensureSession(session3, _onProgress) {
|
|
34680
|
+
this.invalidateRecordIdCache(session3);
|
|
34681
|
+
try {
|
|
34682
|
+
await this.runEnsureSession(session3);
|
|
34683
|
+
} catch (error2) {
|
|
34684
|
+
const requestedModel = session3.model?.trim();
|
|
34685
|
+
if (requestedModel && isModelNotAdvertisedError(error2 instanceof Error ? error2.message : null)) {
|
|
34686
|
+
await this.runEnsureSession({ ...session3, model: undefined });
|
|
34687
|
+
return;
|
|
34688
|
+
}
|
|
34689
|
+
throw error2;
|
|
34788
34690
|
}
|
|
34789
|
-
} catch {
|
|
34790
|
-
return;
|
|
34791
34691
|
}
|
|
34792
|
-
|
|
34793
|
-
|
|
34794
|
-
|
|
34795
|
-
|
|
34796
|
-
|
|
34797
|
-
|
|
34692
|
+
async runEnsureSession(session3) {
|
|
34693
|
+
const args = this.buildArgs(session3, [
|
|
34694
|
+
"sessions",
|
|
34695
|
+
"new",
|
|
34696
|
+
"--name",
|
|
34697
|
+
session3.transportSession
|
|
34698
|
+
]);
|
|
34699
|
+
const runEnsure = session3.agentCommand ? this.run : this.runWithPty;
|
|
34700
|
+
await runEnsure.call(this, args, {
|
|
34701
|
+
timeoutMs: this.sessionInitTimeoutMs,
|
|
34702
|
+
env: this.spawnEnvironment(session3)
|
|
34703
|
+
});
|
|
34798
34704
|
}
|
|
34799
|
-
|
|
34800
|
-
|
|
34801
|
-
|
|
34802
|
-
|
|
34803
|
-
|
|
34705
|
+
async listAgentSessions(query) {
|
|
34706
|
+
return await runAgentSessionList({
|
|
34707
|
+
filterCwd: query.filterCwd,
|
|
34708
|
+
runList: async (includeFilterCwd) => {
|
|
34709
|
+
const args = this.buildAgentQueryArgs(query, "json", [
|
|
34710
|
+
"sessions",
|
|
34711
|
+
"list",
|
|
34712
|
+
...includeFilterCwd && query.filterCwd ? ["--filter-cwd", query.filterCwd] : [],
|
|
34713
|
+
...query.cursor ? ["--cursor", query.cursor] : []
|
|
34714
|
+
]);
|
|
34715
|
+
return await this.runCommandWithTimeout(this.runCommand, args, {
|
|
34716
|
+
timeoutMs: this.sessionInitTimeoutMs,
|
|
34717
|
+
env: this.spawnEnvironment(query)
|
|
34718
|
+
});
|
|
34719
|
+
},
|
|
34720
|
+
formatError: (result) => normalizeCommandError(result) ?? `command failed with exit code ${result.code}`,
|
|
34721
|
+
isSubagentSession: (query.driver ?? query.agent) === CODEX_AGENT_NAME ? codexSubagentPredicate() : undefined
|
|
34722
|
+
});
|
|
34804
34723
|
}
|
|
34805
|
-
|
|
34806
|
-
|
|
34807
|
-
|
|
34808
|
-
|
|
34809
|
-
|
|
34810
|
-
|
|
34811
|
-
|
|
34812
|
-
|
|
34813
|
-
|
|
34814
|
-
|
|
34815
|
-
|
|
34816
|
-
|
|
34817
|
-
|
|
34818
|
-
|
|
34819
|
-
|
|
34820
|
-
|
|
34821
|
-
|
|
34822
|
-
|
|
34724
|
+
async tailSessionHistory(session3, lines) {
|
|
34725
|
+
const candidates = [
|
|
34726
|
+
["sessions", "history", session3.transportSession, "--limit", String(lines)],
|
|
34727
|
+
["sessions", "history", "quiet", "-s", session3.transportSession, String(lines)],
|
|
34728
|
+
["sessions", "history", "quiet", session3.transportSession, String(lines)],
|
|
34729
|
+
["sessions", "history", "-s", session3.transportSession, "--tail", String(lines)],
|
|
34730
|
+
["sessions", "history", session3.transportSession, "--tail", String(lines)],
|
|
34731
|
+
["sessions", "history", "--name", session3.transportSession, "--tail", String(lines)]
|
|
34732
|
+
];
|
|
34733
|
+
const deadline = Date.now() + this.managementCommandTimeoutMs;
|
|
34734
|
+
let lastResult;
|
|
34735
|
+
for (const tail2 of candidates) {
|
|
34736
|
+
const args = this.buildArgs(session3, tail2);
|
|
34737
|
+
const result = await this.runCommandWithTimeout(this.runCommand, args, {
|
|
34738
|
+
timeoutMs: Math.max(deadline - Date.now(), 1),
|
|
34739
|
+
stage: "session-history",
|
|
34740
|
+
env: this.spawnEnvironment(session3)
|
|
34741
|
+
});
|
|
34742
|
+
if (result.code === 0) {
|
|
34743
|
+
return { text: result.stdout.trimEnd() };
|
|
34744
|
+
}
|
|
34745
|
+
lastResult = result;
|
|
34746
|
+
}
|
|
34747
|
+
const detail = lastResult ? normalizeCommandError(lastResult) ?? `command failed with exit code ${lastResult.code}` : "command failed";
|
|
34748
|
+
throw new Error(detail);
|
|
34823
34749
|
}
|
|
34824
|
-
|
|
34825
|
-
|
|
34826
|
-
|
|
34827
|
-
|
|
34828
|
-
|
|
34829
|
-
|
|
34830
|
-
|
|
34831
|
-
|
|
34832
|
-
|
|
34833
|
-
|
|
34834
|
-
|
|
34835
|
-
|
|
34836
|
-
|
|
34837
|
-
|
|
34838
|
-
|
|
34839
|
-
if (record3.type === "user") {
|
|
34840
|
-
const userText = blocks.map(blockText).filter(Boolean).join(`
|
|
34841
|
-
`);
|
|
34842
|
-
for (const notification of taskNotifications(userText)) {
|
|
34843
|
-
if (launched.has(notification.toolCallId)) {
|
|
34844
|
-
completed.add(notification.toolCallId);
|
|
34845
|
-
if (notification.failed)
|
|
34846
|
-
failed.add(notification.toolCallId);
|
|
34847
|
-
lastNotificationSequence = sequence;
|
|
34848
|
-
const previous = toolEvents.get(notification.toolCallId);
|
|
34849
|
-
if (previous) {
|
|
34850
|
-
await emitTool({
|
|
34851
|
-
...previous,
|
|
34852
|
-
status: notification.failed ? "error" : "success",
|
|
34853
|
-
...notification.failed ? { rawOutput: { message: "Claude background Agent failed" } } : {}
|
|
34854
|
-
});
|
|
34855
|
-
}
|
|
34750
|
+
async prompt(session3, text, reply, replyContext, options) {
|
|
34751
|
+
if (session3.effort?.trim()) {
|
|
34752
|
+
await this.reapplySessionEffort(session3, session3.effort.trim());
|
|
34753
|
+
}
|
|
34754
|
+
await this.launchMcpQueueOwnerIfNeeded(session3);
|
|
34755
|
+
const structuredPrompt = await createStructuredPromptFile(text, options?.media);
|
|
34756
|
+
const args = this.buildPromptArgs(session3, text, structuredPrompt?.filePath);
|
|
34757
|
+
try {
|
|
34758
|
+
if (reply || options?.onSegment || options?.onToolEvent || options?.onThought || options?.onPlan || options?.onUsage || options?.onCommands) {
|
|
34759
|
+
const effectiveReplyMode = session3.effectiveReplyMode ?? session3.replyMode;
|
|
34760
|
+
const formatToolCalls = (effectiveReplyMode ?? "verbose") === "verbose";
|
|
34761
|
+
const rawStream = effectiveReplyMode === "stream";
|
|
34762
|
+
let toolEventMode = resolveToolEventMode(options);
|
|
34763
|
+
if ((toolEventMode === "structured" || toolEventMode === "both") && !options?.onToolEvent) {
|
|
34764
|
+
toolEventMode = "text";
|
|
34856
34765
|
}
|
|
34766
|
+
const { result: result2, overflowCount } = await this.runStreamingPrompt(this.command, args, reply, formatToolCalls, toolEventMode, replyContext, options?.onSegment, options?.onToolEvent, options?.onThought, options?.onPlan, options?.onUsage, options?.onCommands, rawStream, this.spawnEnvironment(session3), session3.driver ?? session3.agent);
|
|
34767
|
+
const baseText = getPromptText(result2);
|
|
34768
|
+
if (!reply) {
|
|
34769
|
+
return { text: baseText };
|
|
34770
|
+
}
|
|
34771
|
+
const summary = buildOverflowSummary(overflowCount);
|
|
34772
|
+
return { text: summary ? `${summary}
|
|
34773
|
+
|
|
34774
|
+
${baseText}` : "" };
|
|
34857
34775
|
}
|
|
34858
|
-
|
|
34859
|
-
|
|
34860
|
-
|
|
34861
|
-
|
|
34862
|
-
|
|
34863
|
-
|
|
34864
|
-
|
|
34865
|
-
if (ASYNC_AGENT_LAUNCH.test(output))
|
|
34866
|
-
launched.add(toolCallId);
|
|
34867
|
-
const previous = toolEvents.get(toolCallId);
|
|
34868
|
-
await emitTool({
|
|
34869
|
-
toolCallId,
|
|
34870
|
-
toolName: previous?.toolName ?? "Tool",
|
|
34871
|
-
kind: previous?.kind ?? "other",
|
|
34872
|
-
...previous?.parentToolCallId ? { parentToolCallId: previous.parentToolCallId } : {},
|
|
34873
|
-
...previous?.isSubagent ? { isSubagent: true } : {},
|
|
34874
|
-
...previous?.summary ? { summary: previous.summary } : {},
|
|
34875
|
-
...previous?.rawInput !== undefined ? { rawInput: previous.rawInput } : {},
|
|
34876
|
-
...output ? { rawOutput: output } : {},
|
|
34877
|
-
status: readBoolean(block, "is_error") ? "error" : "success"
|
|
34878
|
-
});
|
|
34879
|
-
}
|
|
34880
|
-
return;
|
|
34776
|
+
const spawnOptions = this.withSpawnEnvironment(session3);
|
|
34777
|
+
const result = spawnOptions ? await this.runCommand(this.command, args, spawnOptions) : await this.runCommand(this.command, args);
|
|
34778
|
+
return { text: getPromptText(result) };
|
|
34779
|
+
} finally {
|
|
34780
|
+
try {
|
|
34781
|
+
await structuredPrompt?.cleanup();
|
|
34782
|
+
} catch {}
|
|
34881
34783
|
}
|
|
34882
|
-
|
|
34883
|
-
|
|
34884
|
-
|
|
34885
|
-
|
|
34886
|
-
|
|
34887
|
-
|
|
34888
|
-
|
|
34889
|
-
|
|
34890
|
-
|
|
34891
|
-
|
|
34892
|
-
|
|
34893
|
-
|
|
34894
|
-
|
|
34895
|
-
|
|
34896
|
-
|
|
34897
|
-
|
|
34898
|
-
|
|
34899
|
-
|
|
34900
|
-
|
|
34901
|
-
|
|
34902
|
-
|
|
34903
|
-
|
|
34904
|
-
|
|
34905
|
-
|
|
34906
|
-
|
|
34907
|
-
|
|
34908
|
-
|
|
34909
|
-
|
|
34784
|
+
}
|
|
34785
|
+
async setMode(session3, modeId) {
|
|
34786
|
+
await this.run(this.buildArgs(session3, [
|
|
34787
|
+
"set-mode",
|
|
34788
|
+
"-s",
|
|
34789
|
+
session3.transportSession,
|
|
34790
|
+
modeId
|
|
34791
|
+
]), this.withSpawnEnvironment(session3, {
|
|
34792
|
+
timeoutMs: this.managementCommandTimeoutMs,
|
|
34793
|
+
stage: "set-mode"
|
|
34794
|
+
}));
|
|
34795
|
+
}
|
|
34796
|
+
async setModel(session3, modelId) {
|
|
34797
|
+
await this.run(this.buildArgs({ ...session3, model: modelId }, [
|
|
34798
|
+
"set",
|
|
34799
|
+
"-s",
|
|
34800
|
+
session3.transportSession,
|
|
34801
|
+
"model",
|
|
34802
|
+
modelId
|
|
34803
|
+
]), this.withSpawnEnvironment({ ...session3, model: modelId }, {
|
|
34804
|
+
timeoutMs: this.managementCommandTimeoutMs,
|
|
34805
|
+
stage: "set-model"
|
|
34806
|
+
}));
|
|
34807
|
+
}
|
|
34808
|
+
async getSessionModel(session3) {
|
|
34809
|
+
const prefix = ["--format", "json", "--cwd", session3.cwd, ...this.buildPermissionArgs()];
|
|
34810
|
+
const tail2 = ["status", "-s", session3.transportSession];
|
|
34811
|
+
const args = session3.agentCommand ? [...prefix, "--agent", session3.agentCommand, ...tail2] : [...prefix, session3.agent, ...tail2];
|
|
34812
|
+
const result = await this.runCommandWithTimeout(this.runCommand, args, {
|
|
34813
|
+
timeoutMs: this.managementCommandTimeoutMs,
|
|
34814
|
+
stage: "get-session-model",
|
|
34815
|
+
env: this.spawnEnvironment(session3)
|
|
34816
|
+
});
|
|
34817
|
+
if (result.code !== 0) {
|
|
34818
|
+
const detail = normalizeCommandError(result) ?? `command failed with exit code ${result.code}`;
|
|
34819
|
+
throw new Error(detail);
|
|
34910
34820
|
}
|
|
34911
|
-
|
|
34912
|
-
|
|
34821
|
+
try {
|
|
34822
|
+
const json = JSON.parse(result.stdout);
|
|
34823
|
+
return {
|
|
34824
|
+
current: typeof json.model === "string" ? json.model : undefined,
|
|
34825
|
+
available: Array.isArray(json.availableModels) ? json.availableModels.filter((m) => typeof m === "string") : []
|
|
34826
|
+
};
|
|
34827
|
+
} catch {
|
|
34828
|
+
return { available: [] };
|
|
34913
34829
|
}
|
|
34914
|
-
}
|
|
34915
|
-
|
|
34916
|
-
|
|
34830
|
+
}
|
|
34831
|
+
async getSessionEffort(session3) {
|
|
34832
|
+
const output = await this.run(this.buildArgs(session3, [
|
|
34833
|
+
"sessions",
|
|
34834
|
+
"show",
|
|
34835
|
+
session3.transportSession
|
|
34836
|
+
], "json"), this.withSpawnEnvironment(session3, {
|
|
34837
|
+
timeoutMs: this.managementCommandTimeoutMs,
|
|
34838
|
+
stage: "get-session-effort"
|
|
34839
|
+
}));
|
|
34840
|
+
const effort = parseSessionEffortRecord(output);
|
|
34841
|
+
return effort ? { current: effort.current, available: effort.available } : { available: [] };
|
|
34842
|
+
}
|
|
34843
|
+
async setSessionEffort(session3, effort) {
|
|
34844
|
+
const record3 = await this.readSessionEffortRecord(session3);
|
|
34845
|
+
await this.applyAdvertisedSessionEffort(session3, effort, record3);
|
|
34846
|
+
}
|
|
34847
|
+
async reapplySessionEffort(session3, effort) {
|
|
34848
|
+
const record3 = await this.readSessionEffortRecord(session3);
|
|
34849
|
+
const observed = parseSessionEffortRecord(record3);
|
|
34850
|
+
if (!observed?.available.includes(effort)) {
|
|
34917
34851
|
return;
|
|
34918
|
-
|
|
34919
|
-
|
|
34920
|
-
|
|
34921
|
-
|
|
34922
|
-
|
|
34852
|
+
}
|
|
34853
|
+
await this.applyAdvertisedSessionEffort(session3, effort, record3);
|
|
34854
|
+
}
|
|
34855
|
+
async readSessionEffortRecord(session3) {
|
|
34856
|
+
return await this.run(this.buildArgs(session3, [
|
|
34857
|
+
"sessions",
|
|
34858
|
+
"show",
|
|
34859
|
+
session3.transportSession
|
|
34860
|
+
], "json"), this.withSpawnEnvironment(session3, {
|
|
34861
|
+
timeoutMs: this.managementCommandTimeoutMs,
|
|
34862
|
+
stage: "get-session-effort"
|
|
34863
|
+
}));
|
|
34864
|
+
}
|
|
34865
|
+
async applyAdvertisedSessionEffort(session3, effort, record3) {
|
|
34866
|
+
const advertised = requireAdvertisedSessionEffort(record3, effort);
|
|
34867
|
+
await this.run(this.buildArgs(session3, [
|
|
34868
|
+
"set",
|
|
34869
|
+
"-s",
|
|
34870
|
+
session3.transportSession,
|
|
34871
|
+
advertised.configId,
|
|
34872
|
+
effort
|
|
34873
|
+
]), this.withSpawnEnvironment(session3, {
|
|
34874
|
+
timeoutMs: this.managementCommandTimeoutMs,
|
|
34875
|
+
stage: "set-session-effort"
|
|
34876
|
+
}));
|
|
34877
|
+
}
|
|
34878
|
+
async cancel(session3) {
|
|
34879
|
+
const output = await this.run(this.buildArgs(session3, [
|
|
34880
|
+
"cancel",
|
|
34881
|
+
"-s",
|
|
34882
|
+
session3.transportSession
|
|
34883
|
+
]), this.withSpawnEnvironment(session3, {
|
|
34884
|
+
timeoutMs: this.managementCommandTimeoutMs,
|
|
34885
|
+
stage: "cancel"
|
|
34886
|
+
}));
|
|
34887
|
+
return {
|
|
34888
|
+
cancelled: true,
|
|
34889
|
+
message: output.trim()
|
|
34890
|
+
};
|
|
34891
|
+
}
|
|
34892
|
+
async resumeAgentSession(session3, agentSessionId) {
|
|
34893
|
+
this.invalidateRecordIdCache(session3);
|
|
34894
|
+
const args = this.buildArgs(session3, [
|
|
34895
|
+
"sessions",
|
|
34896
|
+
"new",
|
|
34897
|
+
"--name",
|
|
34898
|
+
session3.transportSession,
|
|
34899
|
+
"--resume-session",
|
|
34900
|
+
agentSessionId
|
|
34901
|
+
]);
|
|
34902
|
+
const runResume = session3.agentCommand ? this.run : this.runWithPty;
|
|
34903
|
+
await runResume.call(this, args, {
|
|
34904
|
+
timeoutMs: this.sessionInitTimeoutMs,
|
|
34905
|
+
env: this.spawnEnvironment(session3)
|
|
34906
|
+
});
|
|
34907
|
+
}
|
|
34908
|
+
async updatePermissionPolicy(policy) {
|
|
34909
|
+
this.permissionMode = policy.permissionMode;
|
|
34910
|
+
this.nonInteractivePermissions = policy.nonInteractivePermissions;
|
|
34911
|
+
this.permissionPolicy = policy.permissionPolicy;
|
|
34912
|
+
}
|
|
34913
|
+
async removeSession(session3) {
|
|
34914
|
+
this.invalidateRecordIdCache(session3);
|
|
34915
|
+
const result = await this.runCommandWithTimeout(this.runCommand, this.buildArgs(session3, [
|
|
34916
|
+
"sessions",
|
|
34917
|
+
"close",
|
|
34918
|
+
session3.transportSession
|
|
34919
|
+
]), this.withSpawnEnvironment(session3, {
|
|
34920
|
+
timeoutMs: this.managementCommandTimeoutMs,
|
|
34921
|
+
stage: "remove-session"
|
|
34922
|
+
}));
|
|
34923
|
+
if (result.code === 0) {
|
|
34923
34924
|
return;
|
|
34924
34925
|
}
|
|
34925
|
-
|
|
34926
|
-
};
|
|
34927
|
-
const processSubagentRecord = async (record3, parentToolCallId) => {
|
|
34928
|
-
if (!record3)
|
|
34926
|
+
if (isMissingAcpxSessionError(result.stderr, result.stdout)) {
|
|
34929
34927
|
return;
|
|
34930
|
-
|
|
34931
|
-
|
|
34932
|
-
|
|
34933
|
-
|
|
34934
|
-
|
|
34935
|
-
|
|
34936
|
-
|
|
34937
|
-
|
|
34938
|
-
|
|
34939
|
-
const rawInput = block.input;
|
|
34940
|
-
const previous = toolEvents.get(toolCallId);
|
|
34941
|
-
await emitTool({
|
|
34942
|
-
...previous,
|
|
34943
|
-
toolCallId,
|
|
34944
|
-
parentToolCallId: previous?.parentToolCallId ?? parentToolCallId,
|
|
34945
|
-
...previous?.isSubagent || isAgentToolName(name) ? { isSubagent: true } : {},
|
|
34946
|
-
toolName: previous?.toolName ?? name,
|
|
34947
|
-
kind: previous?.kind ?? classifyToolKind(name),
|
|
34948
|
-
...previous?.summary ? { summary: previous.summary } : toolSummary(rawInput) ? { summary: toolSummary(rawInput) } : {},
|
|
34949
|
-
...previous?.rawInput !== undefined ? { rawInput: previous.rawInput } : rawInput !== undefined ? { rawInput } : {},
|
|
34950
|
-
status: previous?.status === "success" || previous?.status === "error" ? previous.status : "running"
|
|
34951
|
-
});
|
|
34952
|
-
}
|
|
34928
|
+
}
|
|
34929
|
+
const detail = normalizeCommandError(result) ?? `command failed with exit code ${result.code}`;
|
|
34930
|
+
throw new Error(detail);
|
|
34931
|
+
}
|
|
34932
|
+
async deleteSession(session3) {
|
|
34933
|
+
let acpxRecordId;
|
|
34934
|
+
try {
|
|
34935
|
+
({ acpxRecordId } = await this.readSessionRecord(session3));
|
|
34936
|
+
} catch {
|
|
34953
34937
|
return;
|
|
34954
34938
|
}
|
|
34955
|
-
|
|
34939
|
+
await this.removeSession(session3);
|
|
34940
|
+
await deleteAcpxSessionFiles({ acpxRecordId });
|
|
34941
|
+
}
|
|
34942
|
+
async freeWarmProcess(session3) {
|
|
34943
|
+
let acpxRecordId;
|
|
34944
|
+
try {
|
|
34945
|
+
({ acpxRecordId } = await this.readSessionRecord(session3));
|
|
34946
|
+
} catch {
|
|
34956
34947
|
return;
|
|
34957
|
-
for (const block of blocks) {
|
|
34958
|
-
if (readString2(block, "type") !== "tool_result")
|
|
34959
|
-
continue;
|
|
34960
|
-
const toolCallId = readString2(block, "tool_use_id");
|
|
34961
|
-
if (!toolCallId)
|
|
34962
|
-
continue;
|
|
34963
|
-
const previous = toolEvents.get(toolCallId);
|
|
34964
|
-
const output = blockText(block);
|
|
34965
|
-
const event = {
|
|
34966
|
-
...previous,
|
|
34967
|
-
toolCallId,
|
|
34968
|
-
parentToolCallId: previous?.parentToolCallId ?? parentToolCallId,
|
|
34969
|
-
...previous?.isSubagent ? { isSubagent: true } : {},
|
|
34970
|
-
toolName: previous?.toolName ?? "Tool",
|
|
34971
|
-
kind: previous?.kind ?? "other",
|
|
34972
|
-
...previous?.summary ? { summary: previous.summary } : {},
|
|
34973
|
-
...previous?.rawInput !== undefined ? { rawInput: previous.rawInput } : {},
|
|
34974
|
-
...previous?.rawOutput !== undefined ? { rawOutput: previous.rawOutput } : output ? { rawOutput: output } : {},
|
|
34975
|
-
status: readBoolean(block, "is_error") || previous?.status === "error" ? "error" : "success"
|
|
34976
|
-
};
|
|
34977
|
-
if (event.isSubagent && isClaudeAsyncAgentLaunch(event)) {
|
|
34978
|
-
const agentId = claudeAsyncAgentId(event);
|
|
34979
|
-
if (agentId)
|
|
34980
|
-
parentToolCallIdByAgentId.set(agentId, event.toolCallId);
|
|
34981
|
-
}
|
|
34982
|
-
await emitTool(event);
|
|
34983
34948
|
}
|
|
34984
|
-
|
|
34985
|
-
|
|
34986
|
-
|
|
34987
|
-
|
|
34988
|
-
|
|
34989
|
-
|
|
34990
|
-
|
|
34991
|
-
|
|
34992
|
-
|
|
34993
|
-
|
|
34994
|
-
|
|
34995
|
-
|
|
34996
|
-
|
|
34997
|
-
|
|
34998
|
-
|
|
34999
|
-
|
|
35000
|
-
|
|
35001
|
-
subagentCursors.set(subagent.path, cursor);
|
|
35002
|
-
for (const line of lines)
|
|
35003
|
-
await processSubagentRecord(parseRecord(line), parentToolCallId);
|
|
34949
|
+
await terminateAcpxQueueOwner(acpxRecordId);
|
|
34950
|
+
}
|
|
34951
|
+
recordIdCache = new Map;
|
|
34952
|
+
recordIdCacheKey(session3) {
|
|
34953
|
+
return JSON.stringify([session3.agent, session3.agentCommand ?? null, session3.cwd, session3.transportSession]);
|
|
34954
|
+
}
|
|
34955
|
+
invalidateRecordIdCache(session3) {
|
|
34956
|
+
this.recordIdCache.delete(this.recordIdCacheKey(session3));
|
|
34957
|
+
}
|
|
34958
|
+
async isSessionWarm(session3) {
|
|
34959
|
+
const cacheKey = this.recordIdCacheKey(session3);
|
|
34960
|
+
let acpxRecordId = this.recordIdCache.get(cacheKey);
|
|
34961
|
+
if (!acpxRecordId) {
|
|
34962
|
+
try {
|
|
34963
|
+
({ acpxRecordId } = await this.readSessionRecord(session3));
|
|
34964
|
+
} catch {
|
|
34965
|
+
return false;
|
|
35004
34966
|
}
|
|
35005
|
-
|
|
34967
|
+
this.recordIdCache.set(cacheKey, acpxRecordId);
|
|
35006
34968
|
}
|
|
35007
|
-
|
|
35008
|
-
|
|
35009
|
-
|
|
35010
|
-
if (boundary >= 0) {
|
|
35011
|
-
for (const record3 of initialRecords.slice(boundary + 1)) {
|
|
35012
|
-
await processRecord(record3);
|
|
35013
|
-
if (done)
|
|
35014
|
-
break;
|
|
34969
|
+
const pid = await readQueueOwnerPid(acpxRecordId);
|
|
34970
|
+
if (pid === undefined) {
|
|
34971
|
+
return false;
|
|
35015
34972
|
}
|
|
34973
|
+
return isProcessAlive(pid);
|
|
35016
34974
|
}
|
|
35017
|
-
|
|
35018
|
-
|
|
35019
|
-
|
|
35020
|
-
|
|
35021
|
-
|
|
35022
|
-
|
|
35023
|
-
|
|
35024
|
-
|
|
35025
|
-
|
|
35026
|
-
|
|
35027
|
-
|
|
35028
|
-
|
|
35029
|
-
|
|
35030
|
-
|
|
35031
|
-
await processSubagentTranscripts();
|
|
35032
|
-
const lines = await readJsonlDelta(transcriptPath, mainCursor);
|
|
35033
|
-
for (const line of lines) {
|
|
35034
|
-
await processAfterBoundary(parseRecord(line));
|
|
35035
|
-
if (done)
|
|
35036
|
-
break;
|
|
34975
|
+
async hasSession(session3) {
|
|
34976
|
+
const result = await this.runCommandWithTimeout(this.runCommand, this.buildArgs(session3, [
|
|
34977
|
+
"sessions",
|
|
34978
|
+
"show",
|
|
34979
|
+
session3.transportSession
|
|
34980
|
+
]), this.withSpawnEnvironment(session3, {
|
|
34981
|
+
timeoutMs: this.managementCommandTimeoutMs,
|
|
34982
|
+
stage: "has-session"
|
|
34983
|
+
}));
|
|
34984
|
+
return result.code === 0;
|
|
34985
|
+
}
|
|
34986
|
+
async launchMcpQueueOwnerIfNeeded(session3) {
|
|
34987
|
+
if (!session3.mcpCoordinatorSession) {
|
|
34988
|
+
return;
|
|
35037
34989
|
}
|
|
34990
|
+
const record3 = await this.readSessionRecord(session3);
|
|
34991
|
+
const env = this.spawnEnvironment(session3);
|
|
34992
|
+
await this.queueOwnerLauncher.launch({
|
|
34993
|
+
acpxRecordId: record3.acpxRecordId,
|
|
34994
|
+
coordinatorSession: session3.mcpCoordinatorSession,
|
|
34995
|
+
...session3.mcpSourceHandle ? { sourceHandle: session3.mcpSourceHandle } : {},
|
|
34996
|
+
permissionMode: this.permissionMode,
|
|
34997
|
+
nonInteractivePermissions: this.nonInteractivePermissions,
|
|
34998
|
+
...session3.model?.trim() ? { sessionOptions: { model: session3.model.trim() } } : {},
|
|
34999
|
+
...env ? { env } : {}
|
|
35000
|
+
});
|
|
35038
35001
|
}
|
|
35039
|
-
|
|
35040
|
-
|
|
35041
|
-
|
|
35042
|
-
|
|
35043
|
-
|
|
35002
|
+
async readSessionRecord(session3) {
|
|
35003
|
+
const result = await this.runCommandWithTimeout(this.runCommand, this.buildArgs(session3, [
|
|
35004
|
+
"sessions",
|
|
35005
|
+
"show",
|
|
35006
|
+
session3.transportSession
|
|
35007
|
+
], "json"), this.withSpawnEnvironment(session3, {
|
|
35008
|
+
timeoutMs: this.managementCommandTimeoutMs,
|
|
35009
|
+
stage: "read-session-record"
|
|
35010
|
+
}));
|
|
35011
|
+
if (result.code !== 0) {
|
|
35012
|
+
const detail = normalizeCommandError(result) ?? `command failed with exit code ${result.code}`;
|
|
35013
|
+
throw new Error(detail);
|
|
35044
35014
|
}
|
|
35015
|
+
const record3 = parseAcpxSessionRecordId(result.stdout);
|
|
35016
|
+
if (record3)
|
|
35017
|
+
return record3;
|
|
35018
|
+
throw new Error("failed to resolve acpx session record id");
|
|
35045
35019
|
}
|
|
35046
|
-
|
|
35047
|
-
|
|
35048
|
-
|
|
35049
|
-
completedToolCallIds: [...completed],
|
|
35050
|
-
failedToolCallIds: [...failed]
|
|
35051
|
-
};
|
|
35052
|
-
}
|
|
35053
|
-
async function readJsonlDelta(path14, cursor) {
|
|
35054
|
-
let size;
|
|
35055
|
-
try {
|
|
35056
|
-
size = (await stat3(path14)).size;
|
|
35057
|
-
} catch {
|
|
35058
|
-
return [];
|
|
35020
|
+
async getAgentSessionId(session3) {
|
|
35021
|
+
const record3 = await this.readSessionRecord(session3);
|
|
35022
|
+
return record3.agentSessionId;
|
|
35059
35023
|
}
|
|
35060
|
-
|
|
35061
|
-
|
|
35062
|
-
|
|
35024
|
+
async run(args, options) {
|
|
35025
|
+
const result = await this.runCommandWithTimeout(this.runCommand, args, options);
|
|
35026
|
+
if (result.code !== 0) {
|
|
35027
|
+
const detail = normalizeCommandError(result) ?? `command failed with exit code ${result.code}`;
|
|
35028
|
+
throw new Error(detail);
|
|
35029
|
+
}
|
|
35030
|
+
return result.stdout;
|
|
35063
35031
|
}
|
|
35064
|
-
|
|
35065
|
-
|
|
35066
|
-
|
|
35067
|
-
|
|
35068
|
-
|
|
35069
|
-
try {
|
|
35070
|
-
chunk = Buffer.alloc(size - cursor.offset);
|
|
35071
|
-
const result = await handle.read(chunk, 0, chunk.length, cursor.offset);
|
|
35072
|
-
chunk = chunk.subarray(0, result.bytesRead);
|
|
35073
|
-
} finally {
|
|
35074
|
-
await handle.close();
|
|
35032
|
+
async runWithPty(args, options) {
|
|
35033
|
+
const result = await this.runCommandWithTimeout(this.runPtyCommand, args, options);
|
|
35034
|
+
if (result.code !== 0) {
|
|
35035
|
+
const detail = normalizeCommandError(result) ?? `command failed with exit code ${result.code}`;
|
|
35036
|
+
throw new Error(detail);
|
|
35075
35037
|
}
|
|
35076
|
-
|
|
35077
|
-
return [];
|
|
35038
|
+
return result.stdout;
|
|
35078
35039
|
}
|
|
35079
|
-
|
|
35080
|
-
|
|
35081
|
-
|
|
35082
|
-
|
|
35083
|
-
cursor.partial = lines.pop() ?? "";
|
|
35084
|
-
return lines;
|
|
35085
|
-
}
|
|
35086
|
-
function findPromptBoundary(records, launched) {
|
|
35087
|
-
let launchIndex = -1;
|
|
35088
|
-
for (let index = 0;index < records.length; index += 1) {
|
|
35089
|
-
const record3 = records[index];
|
|
35090
|
-
if (record3?.type !== "assistant" || record3.isSidechain === true)
|
|
35091
|
-
continue;
|
|
35092
|
-
for (const block of contentBlocks(record3.message?.content)) {
|
|
35093
|
-
if (readString2(block, "type") === "tool_use" && launched.has(readString2(block, "id") ?? "")) {
|
|
35094
|
-
launchIndex = index;
|
|
35095
|
-
}
|
|
35040
|
+
async runCommandWithTimeout(runner, args, options) {
|
|
35041
|
+
const spawnSpec = resolveSpawnCommand(this.command, args);
|
|
35042
|
+
if (!options?.timeoutMs) {
|
|
35043
|
+
return await runner(spawnSpec.command, spawnSpec.args, options);
|
|
35096
35044
|
}
|
|
35045
|
+
const abortController = new AbortController;
|
|
35046
|
+
let timeoutId;
|
|
35047
|
+
return await Promise.race([
|
|
35048
|
+
runner(spawnSpec.command, spawnSpec.args, { ...options, signal: abortController.signal }).finally(() => {
|
|
35049
|
+
if (timeoutId)
|
|
35050
|
+
clearTimeout(timeoutId);
|
|
35051
|
+
}),
|
|
35052
|
+
new Promise((_, reject) => {
|
|
35053
|
+
timeoutId = setTimeout(() => {
|
|
35054
|
+
reject(managementTimeoutError(args, options));
|
|
35055
|
+
abortController.abort();
|
|
35056
|
+
}, options.timeoutMs);
|
|
35057
|
+
})
|
|
35058
|
+
]);
|
|
35059
|
+
}
|
|
35060
|
+
async runStreamingPrompt(command, args, reply, formatToolCalls = false, toolEventMode = "text", replyContext, onSegment, onToolEvent, onThought, onPlan, onUsage, onCommands, rawStream = false, env, driver) {
|
|
35061
|
+
const hooks = this.streamingHooks;
|
|
35062
|
+
const doSpawn = hooks.spawnPrompt ?? ((cmd, spawnArgs) => spawn11(cmd, spawnArgs, {
|
|
35063
|
+
env,
|
|
35064
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
35065
|
+
}));
|
|
35066
|
+
const setIntervalFn = hooks.setIntervalFn ?? ((fn, delay) => setInterval(fn, delay));
|
|
35067
|
+
const clearIntervalFn = hooks.clearIntervalFn ?? ((timer) => clearInterval(timer));
|
|
35068
|
+
const maxSegmentWaitMs = hooks.maxSegmentWaitMs ?? (rawStream ? 200 : 30000);
|
|
35069
|
+
const flushCheckIntervalMs = hooks.flushCheckIntervalMs ?? (rawStream ? 80 : 5000);
|
|
35070
|
+
const now = hooks.now ?? (() => Date.now());
|
|
35071
|
+
return await new Promise((resolve4, reject) => {
|
|
35072
|
+
const spawnSpec = resolveSpawnCommand(command, args);
|
|
35073
|
+
const child = doSpawn(spawnSpec.command, spawnSpec.args);
|
|
35074
|
+
let stdout2 = "";
|
|
35075
|
+
let stderr = "";
|
|
35076
|
+
let lastReplyAt = now();
|
|
35077
|
+
let segmentChain = Promise.resolve();
|
|
35078
|
+
let segmentError;
|
|
35079
|
+
let toolEventChain = Promise.resolve();
|
|
35080
|
+
let toolEventError;
|
|
35081
|
+
let thoughtChain = Promise.resolve();
|
|
35082
|
+
let thoughtError;
|
|
35083
|
+
let planChain = Promise.resolve();
|
|
35084
|
+
let planError;
|
|
35085
|
+
let usageChain = Promise.resolve();
|
|
35086
|
+
let usageError;
|
|
35087
|
+
let commandsChain = Promise.resolve();
|
|
35088
|
+
let commandsError;
|
|
35089
|
+
const userOnToolEvent = onToolEvent;
|
|
35090
|
+
const userOnThought = onThought;
|
|
35091
|
+
const userOnPlan = onPlan;
|
|
35092
|
+
const userOnUsage = onUsage;
|
|
35093
|
+
const userOnCommands = onCommands;
|
|
35094
|
+
const state = createStreamingPromptState(formatToolCalls, {
|
|
35095
|
+
mode: toolEventMode,
|
|
35096
|
+
driver,
|
|
35097
|
+
rawStream,
|
|
35098
|
+
...userOnToolEvent ? {
|
|
35099
|
+
onToolEvent: (event) => {
|
|
35100
|
+
toolEventChain = toolEventChain.then(() => userOnToolEvent(event)).catch((error2) => {
|
|
35101
|
+
toolEventError ??= error2;
|
|
35102
|
+
});
|
|
35103
|
+
}
|
|
35104
|
+
} : {},
|
|
35105
|
+
...userOnThought ? {
|
|
35106
|
+
onThought: (chunk) => {
|
|
35107
|
+
thoughtChain = thoughtChain.then(() => userOnThought(chunk)).catch((error2) => {
|
|
35108
|
+
thoughtError ??= error2;
|
|
35109
|
+
});
|
|
35110
|
+
}
|
|
35111
|
+
} : {},
|
|
35112
|
+
...userOnPlan ? {
|
|
35113
|
+
onPlan: (entries) => {
|
|
35114
|
+
planChain = planChain.then(() => userOnPlan(entries)).catch((error2) => {
|
|
35115
|
+
planError ??= error2;
|
|
35116
|
+
});
|
|
35117
|
+
}
|
|
35118
|
+
} : {},
|
|
35119
|
+
...userOnUsage ? {
|
|
35120
|
+
onUsage: (usage) => {
|
|
35121
|
+
usageChain = usageChain.then(() => userOnUsage(usage)).catch((error2) => {
|
|
35122
|
+
usageError ??= error2;
|
|
35123
|
+
});
|
|
35124
|
+
}
|
|
35125
|
+
} : {},
|
|
35126
|
+
...userOnCommands ? {
|
|
35127
|
+
onCommands: (commands) => {
|
|
35128
|
+
commandsChain = commandsChain.then(() => userOnCommands(commands)).catch((error2) => {
|
|
35129
|
+
commandsError ??= error2;
|
|
35130
|
+
});
|
|
35131
|
+
}
|
|
35132
|
+
} : {}
|
|
35133
|
+
});
|
|
35134
|
+
const sink2 = reply ? rawStream ? createVerbatimReplySink(reply) : createQuotaGatedReplySink({
|
|
35135
|
+
reply,
|
|
35136
|
+
...replyContext ? { replyContext } : {}
|
|
35137
|
+
}) : null;
|
|
35138
|
+
const feedSegment = (segment) => {
|
|
35139
|
+
if (onSegment) {
|
|
35140
|
+
segmentChain = segmentChain.then(() => onSegment(segment)).catch((error2) => {
|
|
35141
|
+
segmentError ??= error2;
|
|
35142
|
+
});
|
|
35143
|
+
}
|
|
35144
|
+
sink2?.feedSegment(segment);
|
|
35145
|
+
lastReplyAt = now();
|
|
35146
|
+
};
|
|
35147
|
+
const flushBuffer = () => {
|
|
35148
|
+
const remaining = rawStream ? state.buffer : state.buffer.trim();
|
|
35149
|
+
if (remaining.length > 0) {
|
|
35150
|
+
state.buffer = "";
|
|
35151
|
+
feedSegment(remaining);
|
|
35152
|
+
}
|
|
35153
|
+
};
|
|
35154
|
+
const timer = setIntervalFn(() => {
|
|
35155
|
+
if (state.buffer.trim().length > 0 && now() - lastReplyAt >= maxSegmentWaitMs) {
|
|
35156
|
+
flushBuffer();
|
|
35157
|
+
}
|
|
35158
|
+
}, flushCheckIntervalMs);
|
|
35159
|
+
child.stdout.setEncoding("utf8");
|
|
35160
|
+
child.stdout.on("data", (chunk) => {
|
|
35161
|
+
stdout2 += String(chunk);
|
|
35162
|
+
parseStreamingDataChunk(state, String(chunk));
|
|
35163
|
+
for (const segment of state.segments.splice(0)) {
|
|
35164
|
+
feedSegment(segment);
|
|
35165
|
+
}
|
|
35166
|
+
});
|
|
35167
|
+
child.stderr.on("data", (chunk) => {
|
|
35168
|
+
stderr += String(chunk);
|
|
35169
|
+
});
|
|
35170
|
+
child.on("error", (err) => {
|
|
35171
|
+
clearIntervalFn(timer);
|
|
35172
|
+
reject(err);
|
|
35173
|
+
});
|
|
35174
|
+
child.on("close", (code) => {
|
|
35175
|
+
clearIntervalFn(timer);
|
|
35176
|
+
const remaining = state.finalize();
|
|
35177
|
+
if (remaining.length > 0) {
|
|
35178
|
+
feedSegment(remaining);
|
|
35179
|
+
}
|
|
35180
|
+
const { overflowCount } = sink2?.finalize() ?? { overflowCount: 0 };
|
|
35181
|
+
Promise.all([
|
|
35182
|
+
sink2?.drain({ timeoutMs: 30000 }) ?? Promise.resolve(),
|
|
35183
|
+
segmentChain,
|
|
35184
|
+
toolEventChain,
|
|
35185
|
+
thoughtChain,
|
|
35186
|
+
planChain,
|
|
35187
|
+
usageChain,
|
|
35188
|
+
commandsChain
|
|
35189
|
+
]).then(() => {
|
|
35190
|
+
const deferred = sink2?.getPendingError();
|
|
35191
|
+
if (deferred) {
|
|
35192
|
+
reject(deferred);
|
|
35193
|
+
return;
|
|
35194
|
+
}
|
|
35195
|
+
if (segmentError) {
|
|
35196
|
+
reject(segmentError);
|
|
35197
|
+
return;
|
|
35198
|
+
}
|
|
35199
|
+
if (toolEventError) {
|
|
35200
|
+
reject(toolEventError);
|
|
35201
|
+
return;
|
|
35202
|
+
}
|
|
35203
|
+
if (thoughtError) {
|
|
35204
|
+
reject(thoughtError);
|
|
35205
|
+
return;
|
|
35206
|
+
}
|
|
35207
|
+
if (planError) {
|
|
35208
|
+
reject(planError);
|
|
35209
|
+
return;
|
|
35210
|
+
}
|
|
35211
|
+
if (usageError) {
|
|
35212
|
+
reject(usageError);
|
|
35213
|
+
return;
|
|
35214
|
+
}
|
|
35215
|
+
if (commandsError) {
|
|
35216
|
+
reject(commandsError);
|
|
35217
|
+
return;
|
|
35218
|
+
}
|
|
35219
|
+
resolve4({
|
|
35220
|
+
result: { code: code ?? 1, stdout: stdout2, stderr },
|
|
35221
|
+
overflowCount
|
|
35222
|
+
});
|
|
35223
|
+
}).catch((error2) => {
|
|
35224
|
+
reject(error2);
|
|
35225
|
+
});
|
|
35226
|
+
});
|
|
35227
|
+
});
|
|
35097
35228
|
}
|
|
35098
|
-
|
|
35099
|
-
return
|
|
35100
|
-
|
|
35101
|
-
|
|
35102
|
-
|
|
35103
|
-
|
|
35104
|
-
}
|
|
35229
|
+
permissionInput() {
|
|
35230
|
+
return {
|
|
35231
|
+
permissionMode: this.permissionMode,
|
|
35232
|
+
nonInteractivePermissions: this.nonInteractivePermissions,
|
|
35233
|
+
permissionPolicy: this.permissionPolicy
|
|
35234
|
+
};
|
|
35105
35235
|
}
|
|
35106
|
-
|
|
35107
|
-
|
|
35108
|
-
function hasTrackedLaunch(record3, launched) {
|
|
35109
|
-
if (record3?.type !== "assistant" || record3.isSidechain === true)
|
|
35110
|
-
return false;
|
|
35111
|
-
return contentBlocks(record3.message?.content).some((block) => readString2(block, "type") === "tool_use" && launched.has(readString2(block, "id") ?? ""));
|
|
35112
|
-
}
|
|
35113
|
-
function isMainEndTurn(record3) {
|
|
35114
|
-
return record3.type === "assistant" && record3.isSidechain !== true && record3.message?.stop_reason === "end_turn";
|
|
35115
|
-
}
|
|
35116
|
-
function parseRecord(line) {
|
|
35117
|
-
if (!line.trim())
|
|
35118
|
-
return;
|
|
35119
|
-
try {
|
|
35120
|
-
return JSON.parse(line);
|
|
35121
|
-
} catch {
|
|
35122
|
-
return;
|
|
35236
|
+
spawnEnvironment(input) {
|
|
35237
|
+
return this.resolveSpawnEnvironment(input);
|
|
35123
35238
|
}
|
|
35124
|
-
|
|
35125
|
-
|
|
35126
|
-
|
|
35127
|
-
return [{ type: "text", text: content }];
|
|
35128
|
-
return Array.isArray(content) ? content.filter((block) => !!block && typeof block === "object") : [];
|
|
35129
|
-
}
|
|
35130
|
-
function blockText(block) {
|
|
35131
|
-
if (typeof block.text === "string")
|
|
35132
|
-
return block.text;
|
|
35133
|
-
if (typeof block.content === "string")
|
|
35134
|
-
return block.content;
|
|
35135
|
-
if (Array.isArray(block.content))
|
|
35136
|
-
return block.content.map((item) => textOfUnknown(item)).filter(Boolean).join(`
|
|
35137
|
-
`);
|
|
35138
|
-
return textOfUnknown(block.content);
|
|
35139
|
-
}
|
|
35140
|
-
function textOfUnknown(value) {
|
|
35141
|
-
if (typeof value === "string")
|
|
35142
|
-
return value;
|
|
35143
|
-
if (Array.isArray(value))
|
|
35144
|
-
return value.map(textOfUnknown).filter(Boolean).join(`
|
|
35145
|
-
`);
|
|
35146
|
-
if (!value || typeof value !== "object")
|
|
35147
|
-
return "";
|
|
35148
|
-
const object4 = value;
|
|
35149
|
-
if (typeof object4.text === "string")
|
|
35150
|
-
return object4.text;
|
|
35151
|
-
if (object4.content !== undefined)
|
|
35152
|
-
return textOfUnknown(object4.content);
|
|
35153
|
-
try {
|
|
35154
|
-
return JSON.stringify(value);
|
|
35155
|
-
} catch {
|
|
35156
|
-
return "";
|
|
35239
|
+
withSpawnEnvironment(input, options) {
|
|
35240
|
+
const env = this.spawnEnvironment(input);
|
|
35241
|
+
return env ? { ...options ?? {}, env } : options;
|
|
35157
35242
|
}
|
|
35158
|
-
|
|
35159
|
-
|
|
35160
|
-
|
|
35161
|
-
|
|
35162
|
-
|
|
35163
|
-
|
|
35164
|
-
|
|
35165
|
-
|
|
35166
|
-
return found;
|
|
35167
|
-
}
|
|
35168
|
-
return;
|
|
35243
|
+
sessionInput(session3) {
|
|
35244
|
+
return {
|
|
35245
|
+
agent: session3.agent,
|
|
35246
|
+
agentCommand: session3.agentCommand,
|
|
35247
|
+
cwd: session3.cwd,
|
|
35248
|
+
model: session3.model,
|
|
35249
|
+
permission: this.permissionInput()
|
|
35250
|
+
};
|
|
35169
35251
|
}
|
|
35170
|
-
|
|
35171
|
-
|
|
35172
|
-
const candidate = object4[key];
|
|
35173
|
-
if (typeof candidate === "string" && candidate.trim())
|
|
35174
|
-
return candidate.trim();
|
|
35252
|
+
buildArgs(session3, tail2, format = "quiet") {
|
|
35253
|
+
return buildSessionArgs(this.sessionInput(session3), tail2, { format });
|
|
35175
35254
|
}
|
|
35176
|
-
|
|
35177
|
-
|
|
35178
|
-
if (found)
|
|
35179
|
-
return found;
|
|
35255
|
+
buildAgentQueryArgs(query, format, tail2) {
|
|
35256
|
+
return buildAgentQueryArgs({ agent: query.agent, agentCommand: query.agentCommand, cwd: query.cwd, permission: this.permissionInput() }, format, tail2);
|
|
35180
35257
|
}
|
|
35181
|
-
|
|
35182
|
-
|
|
35183
|
-
|
|
35184
|
-
|
|
35185
|
-
|
|
35186
|
-
|
|
35187
|
-
const toolCallId = /<tool-use-id>([^<]+)<\/tool-use-id>/i.exec(block)?.[1]?.trim();
|
|
35188
|
-
if (!toolCallId)
|
|
35189
|
-
continue;
|
|
35190
|
-
const status = /<status>([^<]+)<\/status>/i.exec(block)?.[1]?.trim().toLowerCase();
|
|
35191
|
-
notifications.push({
|
|
35192
|
-
toolCallId,
|
|
35193
|
-
failed: status === "failed" || status === "error" || status === "cancelled" || status === "canceled"
|
|
35194
|
-
});
|
|
35258
|
+
buildPromptArgs(session3, text, promptFile) {
|
|
35259
|
+
const tail2 = promptFile ? ["prompt", "-s", session3.transportSession, "--file", promptFile] : ["prompt", "-s", session3.transportSession, text];
|
|
35260
|
+
return buildPromptArgs({ ...this.sessionInput(session3), queueOwnerTtlSeconds: this.queueOwnerTtlSeconds }, tail2);
|
|
35261
|
+
}
|
|
35262
|
+
buildPermissionArgs() {
|
|
35263
|
+
return buildPermissionArgs(this.permissionInput());
|
|
35195
35264
|
}
|
|
35196
|
-
return notifications;
|
|
35197
|
-
}
|
|
35198
|
-
function classifyToolKind(name) {
|
|
35199
|
-
const normalized = name.toLowerCase();
|
|
35200
|
-
if (/(read|view|open)/.test(normalized))
|
|
35201
|
-
return "read";
|
|
35202
|
-
if (/(grep|search|find|glob)/.test(normalized))
|
|
35203
|
-
return "search";
|
|
35204
|
-
if (/(edit|write|patch|replace|create)/.test(normalized))
|
|
35205
|
-
return "edit";
|
|
35206
|
-
if (/(bash|shell|exec|run|terminal|command)/.test(normalized))
|
|
35207
|
-
return "execute";
|
|
35208
|
-
if (/(think|reason|plan|agent|task)/.test(normalized))
|
|
35209
|
-
return "think";
|
|
35210
|
-
return "other";
|
|
35211
|
-
}
|
|
35212
|
-
function isAgentToolName(name) {
|
|
35213
|
-
const normalized = name.trim().toLowerCase();
|
|
35214
|
-
return normalized === "agent" || normalized === "task";
|
|
35215
35265
|
}
|
|
35216
|
-
|
|
35217
|
-
const
|
|
35218
|
-
|
|
35219
|
-
|
|
35220
|
-
|
|
35221
|
-
|
|
35222
|
-
entries = await readdir4(directory, { withFileTypes: true });
|
|
35223
|
-
} catch {
|
|
35224
|
-
return;
|
|
35266
|
+
function renderCommandForError(args) {
|
|
35267
|
+
const rendered = [];
|
|
35268
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
35269
|
+
const arg = args[index];
|
|
35270
|
+
if (arg === undefined) {
|
|
35271
|
+
continue;
|
|
35225
35272
|
}
|
|
35226
|
-
|
|
35227
|
-
|
|
35228
|
-
|
|
35229
|
-
await visit(path14);
|
|
35230
|
-
} else if (entry.isFile() && entry.name.startsWith("agent-") && entry.name.endsWith(".jsonl")) {
|
|
35231
|
-
found.push({ agentId: entry.name.slice("agent-".length, -".jsonl".length), path: path14 });
|
|
35232
|
-
}
|
|
35273
|
+
if (arg === "--format") {
|
|
35274
|
+
index += 1;
|
|
35275
|
+
continue;
|
|
35233
35276
|
}
|
|
35234
|
-
|
|
35235
|
-
|
|
35236
|
-
|
|
35237
|
-
}
|
|
35238
|
-
|
|
35239
|
-
if (!input || typeof input !== "object")
|
|
35240
|
-
return;
|
|
35241
|
-
const object4 = input;
|
|
35242
|
-
for (const key of ["description", "summary", "path", "file_path", "query", "pattern", "command"]) {
|
|
35243
|
-
if (typeof object4[key] === "string" && object4[key].trim())
|
|
35244
|
-
return object4[key].trim();
|
|
35245
|
-
}
|
|
35246
|
-
return;
|
|
35247
|
-
}
|
|
35248
|
-
function readString2(object4, key) {
|
|
35249
|
-
if (!object4 || typeof object4 !== "object")
|
|
35250
|
-
return;
|
|
35251
|
-
const value = object4[key];
|
|
35252
|
-
return typeof value === "string" ? value : undefined;
|
|
35253
|
-
}
|
|
35254
|
-
function readBoolean(object4, key) {
|
|
35255
|
-
return !!object4 && typeof object4 === "object" && object4[key] === true;
|
|
35256
|
-
}
|
|
35257
|
-
function encodeClaudeProjectDirectory(cwd) {
|
|
35258
|
-
return cwd.replace(/[:\\/]/g, "-");
|
|
35259
|
-
}
|
|
35260
|
-
async function exists(path14) {
|
|
35261
|
-
try {
|
|
35262
|
-
await access4(path14, fsConstants.R_OK);
|
|
35263
|
-
return true;
|
|
35264
|
-
} catch {
|
|
35265
|
-
return false;
|
|
35277
|
+
if (arg === "--cwd") {
|
|
35278
|
+
index += 1;
|
|
35279
|
+
continue;
|
|
35280
|
+
}
|
|
35281
|
+
rendered.push(/\s/.test(arg) || arg.includes(":") ? `"${arg}"` : arg);
|
|
35266
35282
|
}
|
|
35283
|
+
return rendered.join(" ");
|
|
35267
35284
|
}
|
|
35268
|
-
function
|
|
35269
|
-
|
|
35270
|
-
|
|
35271
|
-
|
|
35272
|
-
|
|
35273
|
-
|
|
35274
|
-
await new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
35275
|
-
return;
|
|
35285
|
+
function resolveChildEnvironment(baseEnv, explicitEnv, locale) {
|
|
35286
|
+
const source = explicitEnv ?? baseEnv;
|
|
35287
|
+
const env = {};
|
|
35288
|
+
for (const [key, value] of Object.entries(source)) {
|
|
35289
|
+
if (typeof value === "string")
|
|
35290
|
+
env[key] = value;
|
|
35276
35291
|
}
|
|
35277
|
-
|
|
35278
|
-
|
|
35279
|
-
const timer = setTimeout(() => {
|
|
35280
|
-
signal.removeEventListener("abort", onAbort);
|
|
35281
|
-
resolve4();
|
|
35282
|
-
}, ms);
|
|
35283
|
-
const onAbort = () => {
|
|
35284
|
-
clearTimeout(timer);
|
|
35285
|
-
reject(new DOMException("Claude background follow-up aborted", "AbortError"));
|
|
35286
|
-
};
|
|
35287
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
35288
|
-
});
|
|
35292
|
+
env.XACPX_LANG = locale;
|
|
35293
|
+
return env;
|
|
35289
35294
|
}
|
|
35290
|
-
var
|
|
35291
|
-
var
|
|
35292
|
-
|
|
35293
|
-
|
|
35295
|
+
var require4;
|
|
35296
|
+
var init_acpx_cli_transport = __esm(() => {
|
|
35297
|
+
init_spawn_command();
|
|
35298
|
+
init_claude_settings_policy();
|
|
35299
|
+
init_i18n();
|
|
35300
|
+
init_prompt_output();
|
|
35301
|
+
init_prompt_media();
|
|
35302
|
+
init_streaming_prompt();
|
|
35303
|
+
init_quota_gated_reply_sink();
|
|
35304
|
+
init_node_pty_helper();
|
|
35305
|
+
init_terminate_process_tree();
|
|
35306
|
+
init_acpx_queue_owner_launcher();
|
|
35307
|
+
init_daemon_files();
|
|
35308
|
+
init_agent_session_list();
|
|
35309
|
+
init_codex_subagent_filter();
|
|
35310
|
+
init_acpx_session_files();
|
|
35311
|
+
init_session_effort();
|
|
35312
|
+
init_command_timeouts();
|
|
35313
|
+
init_acpx_command_builder();
|
|
35314
|
+
require4 = createRequire5(import.meta.url);
|
|
35294
35315
|
});
|
|
35295
35316
|
|
|
35296
35317
|
// src/transport/claude-background-followup-transport.ts
|
|
@@ -35308,7 +35329,7 @@ function createClaudeBackgroundFollowupTransport(delegate, options) {
|
|
|
35308
35329
|
pendingToolEvents.set(event.toolCallId, event);
|
|
35309
35330
|
else
|
|
35310
35331
|
pendingToolEvents.delete(event.toolCallId);
|
|
35311
|
-
if (isClaudeAsyncAgentLaunch(event)) {
|
|
35332
|
+
if (event.isSubagent && isClaudeAsyncAgentLaunch(event)) {
|
|
35312
35333
|
asyncToolCallIds.add(event.toolCallId);
|
|
35313
35334
|
const agentId = claudeAsyncAgentId(event);
|
|
35314
35335
|
if (agentId)
|
|
@@ -35320,31 +35341,33 @@ function createClaudeBackgroundFollowupTransport(delegate, options) {
|
|
|
35320
35341
|
...promptOptions,
|
|
35321
35342
|
...forwardToolEvent ? { onToolEvent: forwardToolEvent } : {}
|
|
35322
35343
|
});
|
|
35323
|
-
const
|
|
35324
|
-
|
|
35344
|
+
const driver = (options.resolveDriver?.(session3.agent) ?? session3.agent).trim().toLowerCase();
|
|
35345
|
+
const supportsFollowup = driver === "claude" || driver === "qoder";
|
|
35346
|
+
if (!supportsFollowup || asyncToolCallIds.size === 0 || !reply || !forwardToolEvent)
|
|
35325
35347
|
return result;
|
|
35326
35348
|
let agentSessionId = session3.agentSessionId;
|
|
35327
35349
|
if (!agentSessionId) {
|
|
35328
35350
|
try {
|
|
35329
35351
|
agentSessionId = await delegate.getAgentSessionId?.(session3);
|
|
35330
35352
|
} catch (error2) {
|
|
35331
|
-
await options.logger.error("transport.claude_background_followup.session_id_failed", "failed to resolve
|
|
35353
|
+
await options.logger.error("transport.claude_background_followup.session_id_failed", "failed to resolve agent session id for background follow-up", { alias: session3.alias, error: error2 instanceof Error ? error2.message : String(error2) });
|
|
35332
35354
|
}
|
|
35333
35355
|
}
|
|
35334
35356
|
if (!agentSessionId) {
|
|
35335
35357
|
for (const event of [...pendingToolEvents.values()]) {
|
|
35336
35358
|
await forwardToolEvent({
|
|
35337
35359
|
...event,
|
|
35338
|
-
rawOutput: { message: "
|
|
35360
|
+
rawOutput: { message: "background continuation could not be tracked: session id unavailable" },
|
|
35339
35361
|
status: "error"
|
|
35340
35362
|
});
|
|
35341
35363
|
}
|
|
35342
35364
|
return result;
|
|
35343
35365
|
}
|
|
35344
|
-
await options.logger.info("transport.claude_background_followup.started", "following
|
|
35366
|
+
await options.logger.info("transport.claude_background_followup.started", "following background-agent continuation", { alias: session3.alias, agentSessionId, driver, taskCount: asyncToolCallIds.size });
|
|
35345
35367
|
const followup = await followBackgroundTurn({
|
|
35346
35368
|
cwd: session3.cwd,
|
|
35347
35369
|
sessionId: agentSessionId,
|
|
35370
|
+
driver,
|
|
35348
35371
|
launchedToolCallIds: asyncToolCallIds,
|
|
35349
35372
|
initialToolEvents: latestToolEvents.values(),
|
|
35350
35373
|
subagentIdsByToolCallId,
|
|
@@ -35373,12 +35396,13 @@ function createClaudeBackgroundFollowupTransport(delegate, options) {
|
|
|
35373
35396
|
await forwardToolEvent({
|
|
35374
35397
|
...event,
|
|
35375
35398
|
status: followup.status === "completed" && !failed ? "success" : "error",
|
|
35376
|
-
...followup.status === "completed" && !failed ? {} : { rawOutput: { message: failed ? "
|
|
35399
|
+
...followup.status === "completed" && !failed ? {} : { rawOutput: { message: failed ? "background Agent failed" : `background continuation ${followup.status}` } }
|
|
35377
35400
|
});
|
|
35378
35401
|
}
|
|
35379
|
-
await options.logger.info(`transport.claude_background_followup.${followup.status}`, `
|
|
35402
|
+
await options.logger.info(`transport.claude_background_followup.${followup.status}`, `background-agent follow-up ${followup.status}`, {
|
|
35380
35403
|
alias: session3.alias,
|
|
35381
35404
|
agentSessionId,
|
|
35405
|
+
driver,
|
|
35382
35406
|
completedTaskCount: followup.completedToolCallIds.length,
|
|
35383
35407
|
failedTaskCount: followup.failedToolCallIds.length
|
|
35384
35408
|
});
|