@ganglion/xacpx 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridge/bridge-main.js +617 -61
- package/dist/cli.js +2029 -1959
- package/dist/control/control-service.d.ts +2 -0
- package/dist/control/workspace-git.d.ts +3 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -33177,2125 +33177,2146 @@ 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/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 isAsyncAgentLaunch(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 asyncAgentId(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 findNativeTranscriptPath(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 followBackgroundTurn(options) {
|
|
33234
|
+
const transcriptPath = options.transcriptPath ?? await findNativeTranscriptPath(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
|
-
|
|
33375
|
-
|
|
33376
|
-
|
|
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";
|
|
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);
|
|
33348
|
+
}
|
|
33349
|
+
}
|
|
33350
|
+
if (record3.message?.stop_reason === "end_turn" && launched.size > 0 && [...launched].every((id) => completed.has(id)) && lastNotificationSequence >= 0 && sequence > lastNotificationSequence) {
|
|
33351
|
+
done = true;
|
|
33424
33352
|
}
|
|
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
33353
|
};
|
|
33456
|
-
|
|
33457
|
-
|
|
33458
|
-
|
|
33459
|
-
|
|
33460
|
-
|
|
33461
|
-
|
|
33462
|
-
|
|
33463
|
-
|
|
33464
|
-
|
|
33465
|
-
|
|
33466
|
-
|
|
33467
|
-
|
|
33468
|
-
|
|
33469
|
-
|
|
33470
|
-
|
|
33471
|
-
|
|
33472
|
-
|
|
33473
|
-
|
|
33474
|
-
|
|
33475
|
-
|
|
33476
|
-
|
|
33477
|
-
|
|
33478
|
-
|
|
33479
|
-
|
|
33480
|
-
|
|
33481
|
-
|
|
33482
|
-
|
|
33483
|
-
|
|
33484
|
-
|
|
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;
|
|
33362
|
+
return;
|
|
33363
|
+
}
|
|
33364
|
+
await processRecord(record3);
|
|
33365
|
+
};
|
|
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
|
+
});
|
|
33485
33391
|
}
|
|
33392
|
+
return;
|
|
33486
33393
|
}
|
|
33487
|
-
if (
|
|
33488
|
-
return
|
|
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 && isAsyncAgentLaunch(event)) {
|
|
33417
|
+
const agentId = asyncAgentId(event);
|
|
33418
|
+
if (agentId)
|
|
33419
|
+
parentToolCallIdByAgentId.set(agentId, event.toolCallId);
|
|
33420
|
+
}
|
|
33421
|
+
await emitTool(event);
|
|
33422
|
+
}
|
|
33423
|
+
};
|
|
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;
|
|
33489
33454
|
}
|
|
33490
33455
|
}
|
|
33491
|
-
|
|
33492
|
-
|
|
33493
|
-
|
|
33494
|
-
|
|
33495
|
-
|
|
33496
|
-
|
|
33497
|
-
|
|
33498
|
-
|
|
33499
|
-
|
|
33500
|
-
|
|
33501
|
-
|
|
33502
|
-
|
|
33503
|
-
|
|
33504
|
-
|
|
33505
|
-
|
|
33506
|
-
|
|
33507
|
-
|
|
33508
|
-
|
|
33509
|
-
|
|
33510
|
-
|
|
33511
|
-
|
|
33512
|
-
return description === title ? subagentType : `${subagentType}: ${description}`;
|
|
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
|
+
}
|
|
33513
33477
|
}
|
|
33514
|
-
if (
|
|
33515
|
-
|
|
33516
|
-
|
|
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
|
+
}
|
|
33484
|
+
}
|
|
33485
|
+
return {
|
|
33486
|
+
status: "completed",
|
|
33487
|
+
transcriptPath,
|
|
33488
|
+
completedToolCallIds: [...completed],
|
|
33489
|
+
failedToolCallIds: [...failed]
|
|
33490
|
+
};
|
|
33517
33491
|
}
|
|
33518
|
-
function
|
|
33519
|
-
|
|
33520
|
-
|
|
33521
|
-
|
|
33522
|
-
|
|
33492
|
+
async function readJsonlDelta(path14, cursor) {
|
|
33493
|
+
let size;
|
|
33494
|
+
try {
|
|
33495
|
+
size = (await stat3(path14)).size;
|
|
33496
|
+
} catch {
|
|
33497
|
+
return [];
|
|
33498
|
+
}
|
|
33499
|
+
if (size < cursor.offset) {
|
|
33500
|
+
cursor.offset = 0;
|
|
33501
|
+
cursor.partial = "";
|
|
33502
|
+
}
|
|
33503
|
+
if (size <= cursor.offset)
|
|
33504
|
+
return [];
|
|
33505
|
+
let chunk;
|
|
33506
|
+
try {
|
|
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();
|
|
33523
33514
|
}
|
|
33515
|
+
} catch {
|
|
33516
|
+
return [];
|
|
33524
33517
|
}
|
|
33525
|
-
|
|
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;
|
|
33526
33524
|
}
|
|
33527
|
-
function
|
|
33528
|
-
|
|
33529
|
-
|
|
33530
|
-
|
|
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)
|
|
33531
33530
|
continue;
|
|
33532
|
-
|
|
33533
|
-
|
|
33534
|
-
|
|
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
33535
|
}
|
|
33536
33536
|
}
|
|
33537
|
-
|
|
33538
|
-
|
|
33539
|
-
|
|
33540
|
-
|
|
33541
|
-
|
|
33542
|
-
|
|
33543
|
-
|
|
33544
|
-
const n = asFiniteNumber(record3[key]);
|
|
33545
|
-
if (n !== undefined)
|
|
33546
|
-
return n;
|
|
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
|
+
}
|
|
33547
33544
|
}
|
|
33548
|
-
return;
|
|
33545
|
+
return -1;
|
|
33549
33546
|
}
|
|
33550
|
-
function
|
|
33551
|
-
if (
|
|
33552
|
-
return;
|
|
33553
|
-
|
|
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;
|
|
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") ?? ""));
|
|
33560
33551
|
}
|
|
33561
|
-
function
|
|
33562
|
-
|
|
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())
|
|
33563
33557
|
return;
|
|
33564
|
-
|
|
33565
|
-
|
|
33566
|
-
|
|
33558
|
+
try {
|
|
33559
|
+
return JSON.parse(line);
|
|
33560
|
+
} catch {
|
|
33567
33561
|
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
33562
|
}
|
|
33583
|
-
return out;
|
|
33584
33563
|
}
|
|
33585
|
-
function
|
|
33586
|
-
|
|
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") : [];
|
|
33587
33568
|
}
|
|
33588
|
-
function
|
|
33589
|
-
if (
|
|
33590
|
-
return;
|
|
33591
|
-
|
|
33592
|
-
|
|
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);
|
|
33593
33578
|
}
|
|
33594
|
-
function
|
|
33595
|
-
|
|
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
|
+
}
|
|
33596
33597
|
}
|
|
33597
|
-
function
|
|
33598
|
-
|
|
33599
|
-
|
|
33600
|
-
|
|
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;
|
|
33601
33608
|
}
|
|
33602
|
-
|
|
33603
|
-
|
|
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();
|
|
33604
33614
|
}
|
|
33605
|
-
|
|
33606
|
-
|
|
33615
|
+
for (const candidate of Object.values(object4)) {
|
|
33616
|
+
const found = findStringField(candidate, keys);
|
|
33617
|
+
if (found)
|
|
33618
|
+
return found;
|
|
33607
33619
|
}
|
|
33608
|
-
return
|
|
33620
|
+
return;
|
|
33609
33621
|
}
|
|
33610
|
-
|
|
33611
|
-
|
|
33612
|
-
|
|
33613
|
-
|
|
33614
|
-
|
|
33615
|
-
|
|
33616
|
-
|
|
33617
|
-
|
|
33618
|
-
|
|
33619
|
-
|
|
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;
|
|
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
|
+
});
|
|
33629
33634
|
}
|
|
33630
|
-
return
|
|
33635
|
+
return notifications;
|
|
33631
33636
|
}
|
|
33632
|
-
|
|
33633
|
-
|
|
33634
|
-
|
|
33635
|
-
|
|
33636
|
-
|
|
33637
|
-
|
|
33638
|
-
|
|
33639
|
-
|
|
33640
|
-
|
|
33641
|
-
|
|
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");
|
|
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";
|
|
33665
33650
|
}
|
|
33666
|
-
function
|
|
33667
|
-
|
|
33668
|
-
|
|
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);
|
|
33651
|
+
function isAgentToolName(name) {
|
|
33652
|
+
const normalized = name.trim().toLowerCase();
|
|
33653
|
+
return normalized === "agent" || normalized === "task";
|
|
33677
33654
|
}
|
|
33678
|
-
function
|
|
33679
|
-
|
|
33680
|
-
const
|
|
33681
|
-
|
|
33682
|
-
|
|
33683
|
-
if (cached2 !== undefined)
|
|
33684
|
-
return cached2;
|
|
33685
|
-
let result = false;
|
|
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;
|
|
33686
33660
|
try {
|
|
33687
|
-
|
|
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));
|
|
33661
|
+
entries = await readdir3(directory, { withFileTypes: true });
|
|
33698
33662
|
} catch {
|
|
33699
|
-
|
|
33663
|
+
return;
|
|
33700
33664
|
}
|
|
33701
|
-
|
|
33702
|
-
|
|
33703
|
-
|
|
33704
|
-
|
|
33705
|
-
|
|
33706
|
-
|
|
33707
|
-
...result,
|
|
33708
|
-
sessions: result.sessions.filter((session3) => {
|
|
33709
|
-
try {
|
|
33710
|
-
return !isSubagent(session3.sessionId);
|
|
33711
|
-
} catch {
|
|
33712
|
-
return true;
|
|
33713
|
-
}
|
|
33714
|
-
})
|
|
33715
|
-
};
|
|
33716
|
-
}
|
|
33717
|
-
function nodeRolloutReader(home) {
|
|
33718
|
-
const root = join21(home, "sessions");
|
|
33719
|
-
return {
|
|
33720
|
-
listRolloutPaths() {
|
|
33721
|
-
const out = [];
|
|
33722
|
-
const walk = (dir) => {
|
|
33723
|
-
let entries;
|
|
33724
|
-
try {
|
|
33725
|
-
entries = readdirSync(dir, { withFileTypes: true });
|
|
33726
|
-
} catch {
|
|
33727
|
-
return;
|
|
33728
|
-
}
|
|
33729
|
-
for (const entry of entries) {
|
|
33730
|
-
const full = join21(dir, entry.name);
|
|
33731
|
-
if (entry.isDirectory())
|
|
33732
|
-
walk(full);
|
|
33733
|
-
else if (entry.isFile() && entry.name.startsWith("rollout-") && entry.name.endsWith(".jsonl"))
|
|
33734
|
-
out.push(full);
|
|
33735
|
-
}
|
|
33736
|
-
};
|
|
33737
|
-
walk(root);
|
|
33738
|
-
return out;
|
|
33739
|
-
},
|
|
33740
|
-
readFirstLine(path14) {
|
|
33741
|
-
let fd;
|
|
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
|
-
}
|
|
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 });
|
|
33770
33671
|
}
|
|
33771
33672
|
}
|
|
33772
33673
|
};
|
|
33674
|
+
await visit(sessionDir);
|
|
33675
|
+
return found;
|
|
33773
33676
|
}
|
|
33774
|
-
function
|
|
33775
|
-
|
|
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();
|
|
33684
|
+
}
|
|
33685
|
+
return;
|
|
33776
33686
|
}
|
|
33777
|
-
|
|
33778
|
-
|
|
33779
|
-
|
|
33780
|
-
|
|
33781
|
-
|
|
33782
|
-
});
|
|
33783
|
-
|
|
33784
|
-
// src/transport/agent-session-list.ts
|
|
33785
|
-
function isUnknownFilterCwdOption(output) {
|
|
33786
|
-
return /(?:unknown|unrecognized) option/i.test(output) && output.includes("--filter-cwd");
|
|
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;
|
|
33787
33692
|
}
|
|
33788
|
-
|
|
33789
|
-
|
|
33790
|
-
let filterLocally = false;
|
|
33791
|
-
if (result.code !== 0 && options.filterCwd && isUnknownFilterCwdOption(result.stdout + result.stderr)) {
|
|
33792
|
-
result = await options.runList(false);
|
|
33793
|
-
filterLocally = true;
|
|
33794
|
-
}
|
|
33795
|
-
if (result.code !== 0) {
|
|
33796
|
-
if ((result.stdout + result.stderr).includes("sessionCapabilities.list")) {
|
|
33797
|
-
return;
|
|
33798
|
-
}
|
|
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
|
-
}
|
|
33805
|
-
return parsed;
|
|
33693
|
+
function readBoolean(object4, key) {
|
|
33694
|
+
return !!object4 && typeof object4 === "object" && object4[key] === true;
|
|
33806
33695
|
}
|
|
33807
|
-
function
|
|
33808
|
-
|
|
33696
|
+
function encodeClaudeProjectDirectory(cwd) {
|
|
33697
|
+
return cwd.replace(/[:\\/]/g, "-");
|
|
33698
|
+
}
|
|
33699
|
+
async function exists(path14) {
|
|
33809
33700
|
try {
|
|
33810
|
-
|
|
33701
|
+
await access4(path14, fsConstants.R_OK);
|
|
33702
|
+
return true;
|
|
33811
33703
|
} catch {
|
|
33812
|
-
|
|
33704
|
+
return false;
|
|
33813
33705
|
}
|
|
33814
|
-
|
|
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));
|
|
33815
33714
|
return;
|
|
33816
33715
|
}
|
|
33817
|
-
|
|
33818
|
-
|
|
33819
|
-
|
|
33820
|
-
|
|
33821
|
-
|
|
33822
|
-
|
|
33823
|
-
|
|
33824
|
-
|
|
33825
|
-
|
|
33826
|
-
|
|
33827
|
-
|
|
33828
|
-
const item = session3;
|
|
33829
|
-
return typeof item.sessionId === "string";
|
|
33716
|
+
throwIfAborted(signal);
|
|
33717
|
+
await new Promise((resolve4, reject) => {
|
|
33718
|
+
const timer = setTimeout(() => {
|
|
33719
|
+
signal.removeEventListener("abort", onAbort);
|
|
33720
|
+
resolve4();
|
|
33721
|
+
}, ms);
|
|
33722
|
+
const onAbort = () => {
|
|
33723
|
+
clearTimeout(timer);
|
|
33724
|
+
reject(new DOMException("background follow-up aborted", "AbortError"));
|
|
33725
|
+
};
|
|
33726
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
33830
33727
|
});
|
|
33831
33728
|
}
|
|
33832
|
-
|
|
33833
|
-
|
|
33834
|
-
|
|
33835
|
-
|
|
33836
|
-
};
|
|
33837
|
-
}
|
|
33838
|
-
var init_agent_session_list = __esm(() => {
|
|
33839
|
-
init_path();
|
|
33840
|
-
init_codex_subagent_filter();
|
|
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_background_followup = __esm(() => {
|
|
33731
|
+
DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
|
|
33732
|
+
ASYNC_AGENT_LAUNCH = /Async agent launched successfully|["']?status["']?\s*:\s*["']async_launched["']/i;
|
|
33841
33733
|
});
|
|
33842
33734
|
|
|
33843
|
-
// src/transport/
|
|
33844
|
-
|
|
33845
|
-
|
|
33846
|
-
|
|
33847
|
-
|
|
33848
|
-
|
|
33849
|
-
|
|
33850
|
-
|
|
33851
|
-
|
|
33852
|
-
|
|
33853
|
-
|
|
33854
|
-
|
|
33855
|
-
|
|
33856
|
-
|
|
33857
|
-
|
|
33858
|
-
|
|
33859
|
-
|
|
33860
|
-
|
|
33861
|
-
|
|
33862
|
-
|
|
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
|
|
33863
33776
|
});
|
|
33864
33777
|
}
|
|
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);
|
|
33797
|
+
}
|
|
33798
|
+
const remaining = this.rawStream ? this.buffer : this.buffer.trim();
|
|
33799
|
+
this.buffer = "";
|
|
33800
|
+
this.pendingLine = "";
|
|
33801
|
+
return remaining;
|
|
33802
|
+
}
|
|
33803
|
+
};
|
|
33865
33804
|
}
|
|
33866
|
-
|
|
33867
|
-
|
|
33868
|
-
|
|
33869
|
-
|
|
33870
|
-
|
|
33871
|
-
|
|
33872
|
-
|
|
33873
|
-
|
|
33874
|
-
if (!advertised.available.includes(value)) {
|
|
33875
|
-
throw new Error(`reasoning effort "${value}" is not advertised by the active agent`);
|
|
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);
|
|
33876
33813
|
}
|
|
33877
|
-
return advertised;
|
|
33878
33814
|
}
|
|
33879
|
-
function
|
|
33880
|
-
|
|
33815
|
+
function parseStreamingChunks(state, line) {
|
|
33816
|
+
const trimmed = line.trim();
|
|
33817
|
+
if (trimmed.length === 0)
|
|
33818
|
+
return;
|
|
33819
|
+
let event;
|
|
33881
33820
|
try {
|
|
33882
|
-
|
|
33821
|
+
event = JSON.parse(trimmed);
|
|
33883
33822
|
} catch {
|
|
33884
33823
|
return;
|
|
33885
33824
|
}
|
|
33886
|
-
if (
|
|
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);
|
|
33838
|
+
}
|
|
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);
|
|
33847
|
+
}
|
|
33848
|
+
state.segments.push(formatted);
|
|
33849
|
+
}
|
|
33850
|
+
}
|
|
33887
33851
|
return;
|
|
33888
33852
|
}
|
|
33889
|
-
|
|
33890
|
-
|
|
33891
|
-
|
|
33892
|
-
|
|
33893
|
-
|
|
33894
|
-
const available = Array.isArray(candidate.options) ? candidate.options.flatMap(effortOptionValues) : [];
|
|
33895
|
-
return {
|
|
33896
|
-
configId: candidate.id,
|
|
33897
|
-
current: typeof candidate.currentValue === "string" ? candidate.currentValue : undefined,
|
|
33898
|
-
available
|
|
33899
|
-
};
|
|
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;
|
|
33900
33858
|
}
|
|
33901
|
-
|
|
33902
|
-
|
|
33903
|
-
|
|
33904
|
-
|
|
33905
|
-
|
|
33906
|
-
|
|
33907
|
-
|
|
33908
|
-
|
|
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";
|
|
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 } : {} });
|
|
33866
|
+
}
|
|
33867
|
+
return;
|
|
33932
33868
|
}
|
|
33933
|
-
|
|
33869
|
+
if (update.sessionUpdate === "available_commands_update") {
|
|
33870
|
+
if (Array.isArray(update.availableCommands)) {
|
|
33871
|
+
state.onCommands?.(normalizeAgentCommands(update.availableCommands));
|
|
33872
|
+
}
|
|
33873
|
+
return;
|
|
33874
|
+
}
|
|
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);
|
|
33880
|
+
}
|
|
33881
|
+
return;
|
|
33882
|
+
}
|
|
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(`
|
|
33934
33895
|
|
|
33935
|
-
|
|
33936
|
-
|
|
33937
|
-
|
|
33938
|
-
|
|
33939
|
-
|
|
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
|
+
}
|
|
33940
33902
|
}
|
|
33941
|
-
return args;
|
|
33942
|
-
}
|
|
33943
|
-
function buildQueueOwnerTtlArgs(queueOwnerTtlSeconds) {
|
|
33944
|
-
if (typeof queueOwnerTtlSeconds !== "number" || !Number.isFinite(queueOwnerTtlSeconds))
|
|
33945
|
-
return [];
|
|
33946
|
-
return ["--ttl", String(queueOwnerTtlSeconds)];
|
|
33947
33903
|
}
|
|
33948
|
-
function
|
|
33949
|
-
|
|
33950
|
-
|
|
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}`;
|
|
33951
33921
|
}
|
|
33952
|
-
function
|
|
33953
|
-
if (
|
|
33954
|
-
return
|
|
33955
|
-
|
|
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;
|
|
33956
33932
|
}
|
|
33957
|
-
function
|
|
33958
|
-
const
|
|
33959
|
-
|
|
33960
|
-
|
|
33961
|
-
|
|
33962
|
-
|
|
33963
|
-
|
|
33964
|
-
|
|
33965
|
-
|
|
33966
|
-
if (
|
|
33967
|
-
|
|
33968
|
-
|
|
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;
|
|
33940
|
+
}
|
|
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 } } : {}
|
|
33956
|
+
};
|
|
33957
|
+
}
|
|
33958
|
+
merged.toolCallId = toolCallId;
|
|
33959
|
+
state.toolCalls.set(toolCallId, merged);
|
|
33960
|
+
return merged;
|
|
33969
33961
|
}
|
|
33970
|
-
function
|
|
33971
|
-
|
|
33972
|
-
|
|
33973
|
-
|
|
33974
|
-
|
|
33975
|
-
|
|
33976
|
-
|
|
33977
|
-
|
|
33978
|
-
|
|
33979
|
-
|
|
33980
|
-
|
|
33981
|
-
|
|
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 isAsyncAgentLaunch2 = update._meta?.claudeCode?.toolName === "Agent" && isRecord4(claudeToolResponse) && claudeToolResponse.status === "async_launched" || driver === "qoder" && update._meta?.qoder?.toolName === "Agent" && isAsyncAgentLaunchOutput(update.rawOutput);
|
|
33991
|
+
const status = isAsyncAgentLaunch2 ? "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
|
+
};
|
|
33982
34011
|
}
|
|
33983
|
-
function
|
|
33984
|
-
|
|
33985
|
-
return appendAgentAndTail(prefix, input, tail2);
|
|
34012
|
+
function isKimiSubagentInput(rawInput) {
|
|
34013
|
+
return isRecord4(rawInput) && readFirstString(rawInput, ["prompt"]) !== undefined && readFirstString(rawInput, ["subagent_type", "subagentType"]) !== undefined;
|
|
33986
34014
|
}
|
|
33987
|
-
function
|
|
33988
|
-
|
|
33989
|
-
${stdout2}`.toLowerCase();
|
|
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");
|
|
34015
|
+
function isCodexSubagentMeta(meta2) {
|
|
34016
|
+
return typeof meta2?.threadId === "string" && meta2.threadId.trim().length > 0 && typeof meta2.activity === "string" && meta2.activity.trim().length > 0;
|
|
33991
34017
|
}
|
|
33992
|
-
function
|
|
33993
|
-
|
|
33994
|
-
|
|
33995
|
-
|
|
33996
|
-
|
|
33997
|
-
|
|
33998
|
-
|
|
33999
|
-
|
|
34000
|
-
|
|
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);
|
|
34023
|
+
}
|
|
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(" ");
|
|
34033
|
+
}
|
|
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
|
+
}
|
|
34001
34041
|
}
|
|
34002
|
-
|
|
34003
|
-
|
|
34004
|
-
if (firstLine && /^[\w.:-]+$/.test(firstLine) && firstLine.length >= 8) {
|
|
34005
|
-
return { acpxRecordId: firstLine };
|
|
34042
|
+
if (parts.length > 0) {
|
|
34043
|
+
return parts.join(" ");
|
|
34006
34044
|
}
|
|
34007
34045
|
}
|
|
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;
|
|
34008
34071
|
return;
|
|
34009
34072
|
}
|
|
34010
|
-
|
|
34011
|
-
|
|
34012
|
-
|
|
34013
|
-
|
|
34014
|
-
|
|
34015
|
-
|
|
34016
|
-
|
|
34017
|
-
|
|
34018
|
-
return new CommandTimeoutError(options.timeoutMs, renderCommandForError(args), {
|
|
34019
|
-
stage: options.stage,
|
|
34020
|
-
...output
|
|
34021
|
-
});
|
|
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();
|
|
34078
|
+
}
|
|
34079
|
+
}
|
|
34080
|
+
return;
|
|
34022
34081
|
}
|
|
34023
|
-
|
|
34024
|
-
|
|
34025
|
-
const
|
|
34026
|
-
|
|
34027
|
-
|
|
34028
|
-
|
|
34029
|
-
|
|
34030
|
-
|
|
34031
|
-
|
|
34032
|
-
|
|
34033
|
-
|
|
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
|
-
});
|
|
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;
|
|
34090
|
+
}
|
|
34091
|
+
}
|
|
34092
|
+
return;
|
|
34059
34093
|
}
|
|
34060
|
-
|
|
34061
|
-
|
|
34062
|
-
await ensureNodePtyHelperExecutable(helperPath);
|
|
34063
|
-
return await new Promise((resolve4, reject) => {
|
|
34064
|
-
const spawnSpec = resolveSpawnCommand(command, args);
|
|
34065
|
-
const child = spawnPty(spawnSpec.command, spawnSpec.args, {
|
|
34066
|
-
name: "xterm-color",
|
|
34067
|
-
cols: 80,
|
|
34068
|
-
rows: 24,
|
|
34069
|
-
cwd: process.cwd(),
|
|
34070
|
-
env: resolveChildEnvironment(process.env, options?.env, getLocale())
|
|
34071
|
-
});
|
|
34072
|
-
let output = "";
|
|
34073
|
-
const onAbort = () => {
|
|
34074
|
-
child.kill();
|
|
34075
|
-
};
|
|
34076
|
-
options?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
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
|
-
});
|
|
34090
|
-
});
|
|
34094
|
+
function asFiniteNumber(value) {
|
|
34095
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
34091
34096
|
}
|
|
34092
|
-
|
|
34093
|
-
|
|
34094
|
-
|
|
34095
|
-
|
|
34096
|
-
|
|
34097
|
-
permissionMode;
|
|
34098
|
-
nonInteractivePermissions;
|
|
34099
|
-
permissionPolicy;
|
|
34100
|
-
queueOwnerTtlSeconds;
|
|
34101
|
-
runCommand;
|
|
34102
|
-
runPtyCommand;
|
|
34103
|
-
queueOwnerLauncher;
|
|
34104
|
-
streamingHooks;
|
|
34105
|
-
resolveSpawnEnvironment;
|
|
34106
|
-
constructor(options, runCommand = defaultRunner, runPtyCommand = defaultPtyRunner, queueOwnerLauncher, streamingHooks = {}) {
|
|
34107
|
-
this.command = options.command ?? "acpx";
|
|
34108
|
-
this.sessionInitTimeoutMs = options.sessionInitTimeoutMs ?? 120000;
|
|
34109
|
-
this.managementCommandTimeoutMs = options.managementCommandTimeoutMs ?? DEFAULT_MANAGEMENT_COMMAND_TIMEOUT_MS;
|
|
34110
|
-
this.permissionMode = options.permissionMode ?? DEFAULT_PERMISSION_MODE2;
|
|
34111
|
-
this.nonInteractivePermissions = options.nonInteractivePermissions ?? DEFAULT_NON_INTERACTIVE;
|
|
34112
|
-
this.permissionPolicy = options.permissionPolicy;
|
|
34113
|
-
this.queueOwnerTtlSeconds = options.queueOwnerTtlSeconds;
|
|
34114
|
-
this.runCommand = runCommand;
|
|
34115
|
-
this.runPtyCommand = runPtyCommand;
|
|
34116
|
-
this.queueOwnerLauncher = queueOwnerLauncher ?? new AcpxQueueOwnerLauncher({
|
|
34117
|
-
acpxCommand: this.command,
|
|
34118
|
-
...typeof this.queueOwnerTtlSeconds === "number" && Number.isFinite(this.queueOwnerTtlSeconds) ? { ttlMs: this.queueOwnerTtlSeconds * 1000 } : {}
|
|
34119
|
-
});
|
|
34120
|
-
this.streamingHooks = streamingHooks;
|
|
34121
|
-
this.resolveSpawnEnvironment = options.resolveSpawnEnvironment ?? resolveClaudeSpawnEnvironment;
|
|
34097
|
+
function firstFiniteNumber(record3, keys) {
|
|
34098
|
+
for (const key of keys) {
|
|
34099
|
+
const n = asFiniteNumber(record3[key]);
|
|
34100
|
+
if (n !== undefined)
|
|
34101
|
+
return n;
|
|
34122
34102
|
}
|
|
34123
|
-
|
|
34124
|
-
|
|
34125
|
-
|
|
34126
|
-
|
|
34127
|
-
|
|
34128
|
-
|
|
34129
|
-
|
|
34130
|
-
|
|
34131
|
-
|
|
34132
|
-
|
|
34133
|
-
throw error2;
|
|
34134
|
-
}
|
|
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;
|
|
34135
34113
|
}
|
|
34136
|
-
|
|
34137
|
-
|
|
34138
|
-
|
|
34139
|
-
|
|
34140
|
-
|
|
34141
|
-
|
|
34142
|
-
|
|
34143
|
-
|
|
34144
|
-
|
|
34145
|
-
|
|
34146
|
-
|
|
34147
|
-
|
|
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 });
|
|
34148
34137
|
}
|
|
34149
|
-
|
|
34150
|
-
|
|
34151
|
-
|
|
34152
|
-
|
|
34153
|
-
|
|
34154
|
-
|
|
34155
|
-
|
|
34156
|
-
|
|
34157
|
-
|
|
34158
|
-
|
|
34159
|
-
|
|
34160
|
-
|
|
34161
|
-
|
|
34162
|
-
|
|
34163
|
-
|
|
34164
|
-
|
|
34165
|
-
|
|
34166
|
-
|
|
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;
|
|
34167
34156
|
}
|
|
34168
|
-
|
|
34169
|
-
|
|
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);
|
|
34157
|
+
if (kind === "search" && ["grep", "rg", "search"].includes(normalizedTitle)) {
|
|
34158
|
+
return true;
|
|
34193
34159
|
}
|
|
34194
|
-
|
|
34195
|
-
|
|
34196
|
-
|
|
34197
|
-
|
|
34198
|
-
|
|
34199
|
-
|
|
34200
|
-
|
|
34201
|
-
|
|
34202
|
-
|
|
34203
|
-
|
|
34204
|
-
|
|
34205
|
-
|
|
34206
|
-
|
|
34207
|
-
|
|
34208
|
-
|
|
34209
|
-
|
|
34210
|
-
|
|
34211
|
-
|
|
34212
|
-
if (!reply) {
|
|
34213
|
-
return { text: baseText };
|
|
34214
|
-
}
|
|
34215
|
-
const summary = buildOverflowSummary(overflowCount);
|
|
34216
|
-
return { text: summary ? `${summary}
|
|
34160
|
+
if (kind === "read" && ["read", "cat"].includes(normalizedTitle)) {
|
|
34161
|
+
return true;
|
|
34162
|
+
}
|
|
34163
|
+
return false;
|
|
34164
|
+
}
|
|
34165
|
+
var USAGE_BREAKDOWN_FIELDS;
|
|
34166
|
+
var init_streaming_prompt = __esm(() => {
|
|
34167
|
+
init_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
|
+
});
|
|
34217
34178
|
|
|
34218
|
-
|
|
34219
|
-
|
|
34220
|
-
|
|
34221
|
-
|
|
34222
|
-
|
|
34223
|
-
|
|
34224
|
-
try {
|
|
34225
|
-
await structuredPrompt?.cleanup();
|
|
34226
|
-
} catch {}
|
|
34227
|
-
}
|
|
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;
|
|
34228
34185
|
}
|
|
34229
|
-
|
|
34230
|
-
|
|
34231
|
-
|
|
34232
|
-
|
|
34233
|
-
|
|
34234
|
-
modeId
|
|
34235
|
-
]), this.withSpawnEnvironment(session3, {
|
|
34236
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34237
|
-
stage: "set-mode"
|
|
34238
|
-
}));
|
|
34186
|
+
return join21(dirname13(packageJsonPath), "prebuilds", `${platform}-${arch}`, "spawn-helper");
|
|
34187
|
+
}
|
|
34188
|
+
async function ensureNodePtyHelperExecutable(helperPath, chmod5 = chmodFs) {
|
|
34189
|
+
if (!helperPath) {
|
|
34190
|
+
return;
|
|
34239
34191
|
}
|
|
34240
|
-
|
|
34241
|
-
await
|
|
34242
|
-
|
|
34243
|
-
|
|
34244
|
-
|
|
34245
|
-
"model",
|
|
34246
|
-
modelId
|
|
34247
|
-
]), this.withSpawnEnvironment({ ...session3, model: modelId }, {
|
|
34248
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34249
|
-
stage: "set-model"
|
|
34250
|
-
}));
|
|
34251
|
-
}
|
|
34252
|
-
async getSessionModel(session3) {
|
|
34253
|
-
const prefix = ["--format", "json", "--cwd", session3.cwd, ...this.buildPermissionArgs()];
|
|
34254
|
-
const tail2 = ["status", "-s", session3.transportSession];
|
|
34255
|
-
const args = session3.agentCommand ? [...prefix, "--agent", session3.agentCommand, ...tail2] : [...prefix, session3.agent, ...tail2];
|
|
34256
|
-
const result = await this.runCommandWithTimeout(this.runCommand, args, {
|
|
34257
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34258
|
-
stage: "get-session-model",
|
|
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);
|
|
34192
|
+
try {
|
|
34193
|
+
await chmod5(helperPath, 493);
|
|
34194
|
+
} catch (error2) {
|
|
34195
|
+
if (error2.code === "ENOENT") {
|
|
34196
|
+
return;
|
|
34264
34197
|
}
|
|
34198
|
+
throw error2;
|
|
34199
|
+
}
|
|
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;
|
|
34230
|
+
}
|
|
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;
|
|
34265
34242
|
try {
|
|
34266
|
-
|
|
34267
|
-
|
|
34268
|
-
|
|
34269
|
-
|
|
34270
|
-
|
|
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);
|
|
34249
|
+
}
|
|
34250
|
+
}
|
|
34251
|
+
const path14 = index.get(sessionId.toLowerCase());
|
|
34252
|
+
if (path14)
|
|
34253
|
+
result = sessionMetaLineIsSubagent(reader.readFirstLine(path14));
|
|
34271
34254
|
} catch {
|
|
34272
|
-
|
|
34255
|
+
result = false;
|
|
34273
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;
|
|
34284
|
+
}
|
|
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);
|
|
34291
|
+
}
|
|
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)
|
|
34315
|
+
return;
|
|
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;
|
|
34274
34350
|
}
|
|
34275
|
-
|
|
34276
|
-
|
|
34277
|
-
"sessions",
|
|
34278
|
-
"show",
|
|
34279
|
-
session3.transportSession
|
|
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);
|
|
34290
|
-
}
|
|
34291
|
-
async reapplySessionEffort(session3, effort) {
|
|
34292
|
-
const record3 = await this.readSessionEffortRecord(session3);
|
|
34293
|
-
const observed = parseSessionEffortRecord(record3);
|
|
34294
|
-
if (!observed?.available.includes(effort)) {
|
|
34351
|
+
if (result.code !== 0) {
|
|
34352
|
+
if ((result.stdout + result.stderr).includes("sessionCapabilities.list")) {
|
|
34295
34353
|
return;
|
|
34296
34354
|
}
|
|
34297
|
-
|
|
34355
|
+
throw new Error(options.formatError(result));
|
|
34298
34356
|
}
|
|
34299
|
-
|
|
34300
|
-
|
|
34301
|
-
|
|
34302
|
-
"show",
|
|
34303
|
-
session3.transportSession
|
|
34304
|
-
], "json"), this.withSpawnEnvironment(session3, {
|
|
34305
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34306
|
-
stage: "get-session-effort"
|
|
34307
|
-
}));
|
|
34357
|
+
const parsed = parseAgentSessionListOutput(result.stdout, filterLocally ? options.filterCwd : undefined);
|
|
34358
|
+
if (parsed && options.isSubagentSession) {
|
|
34359
|
+
return filterSubagentSessions(parsed, options.isSubagentSession);
|
|
34308
34360
|
}
|
|
34309
|
-
|
|
34310
|
-
|
|
34311
|
-
|
|
34312
|
-
|
|
34313
|
-
|
|
34314
|
-
|
|
34315
|
-
|
|
34316
|
-
|
|
34317
|
-
]), this.withSpawnEnvironment(session3, {
|
|
34318
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34319
|
-
stage: "set-session-effort"
|
|
34320
|
-
}));
|
|
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");
|
|
34321
34369
|
}
|
|
34322
|
-
|
|
34323
|
-
|
|
34324
|
-
"cancel",
|
|
34325
|
-
"-s",
|
|
34326
|
-
session3.transportSession
|
|
34327
|
-
]), this.withSpawnEnvironment(session3, {
|
|
34328
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34329
|
-
stage: "cancel"
|
|
34330
|
-
}));
|
|
34331
|
-
return {
|
|
34332
|
-
cancelled: true,
|
|
34333
|
-
message: output.trim()
|
|
34334
|
-
};
|
|
34370
|
+
if (!isAgentSessionListResult(parsed)) {
|
|
34371
|
+
return;
|
|
34335
34372
|
}
|
|
34336
|
-
|
|
34337
|
-
|
|
34338
|
-
|
|
34339
|
-
|
|
34340
|
-
|
|
34341
|
-
|
|
34342
|
-
|
|
34343
|
-
|
|
34344
|
-
|
|
34345
|
-
|
|
34346
|
-
const runResume = session3.agentCommand ? this.run : this.runWithPty;
|
|
34347
|
-
await runResume.call(this, args, {
|
|
34348
|
-
timeoutMs: this.sessionInitTimeoutMs,
|
|
34349
|
-
env: this.spawnEnvironment(session3)
|
|
34350
|
-
});
|
|
34351
|
-
}
|
|
34352
|
-
async updatePermissionPolicy(policy) {
|
|
34353
|
-
this.permissionMode = policy.permissionMode;
|
|
34354
|
-
this.nonInteractivePermissions = policy.nonInteractivePermissions;
|
|
34355
|
-
this.permissionPolicy = policy.permissionPolicy;
|
|
34356
|
-
}
|
|
34357
|
-
async removeSession(session3) {
|
|
34358
|
-
this.invalidateRecordIdCache(session3);
|
|
34359
|
-
const result = await this.runCommandWithTimeout(this.runCommand, this.buildArgs(session3, [
|
|
34360
|
-
"sessions",
|
|
34361
|
-
"close",
|
|
34362
|
-
session3.transportSession
|
|
34363
|
-
]), this.withSpawnEnvironment(session3, {
|
|
34364
|
-
timeoutMs: this.managementCommandTimeoutMs,
|
|
34365
|
-
stage: "remove-session"
|
|
34366
|
-
}));
|
|
34367
|
-
if (result.code === 0) {
|
|
34368
|
-
return;
|
|
34369
|
-
}
|
|
34370
|
-
if (isMissingAcpxSessionError(result.stderr, result.stdout)) {
|
|
34371
|
-
return;
|
|
34372
|
-
}
|
|
34373
|
-
const detail = normalizeCommandError(result) ?? `command failed with exit code ${result.code}`;
|
|
34374
|
-
throw new Error(detail);
|
|
34375
|
-
}
|
|
34376
|
-
async deleteSession(session3) {
|
|
34377
|
-
let acpxRecordId;
|
|
34378
|
-
try {
|
|
34379
|
-
({ acpxRecordId } = await this.readSessionRecord(session3));
|
|
34380
|
-
} catch {
|
|
34381
|
-
return;
|
|
34382
|
-
}
|
|
34383
|
-
await this.removeSession(session3);
|
|
34384
|
-
await deleteAcpxSessionFiles({ acpxRecordId });
|
|
34385
|
-
}
|
|
34386
|
-
async freeWarmProcess(session3) {
|
|
34387
|
-
let acpxRecordId;
|
|
34388
|
-
try {
|
|
34389
|
-
({ acpxRecordId } = await this.readSessionRecord(session3));
|
|
34390
|
-
} catch {
|
|
34391
|
-
return;
|
|
34392
|
-
}
|
|
34393
|
-
await terminateAcpxQueueOwner(acpxRecordId);
|
|
34394
|
-
}
|
|
34395
|
-
recordIdCache = new Map;
|
|
34396
|
-
recordIdCacheKey(session3) {
|
|
34397
|
-
return JSON.stringify([session3.agent, session3.agentCommand ?? null, session3.cwd, session3.transportSession]);
|
|
34398
|
-
}
|
|
34399
|
-
invalidateRecordIdCache(session3) {
|
|
34400
|
-
this.recordIdCache.delete(this.recordIdCacheKey(session3));
|
|
34401
|
-
}
|
|
34402
|
-
async isSessionWarm(session3) {
|
|
34403
|
-
const cacheKey = this.recordIdCacheKey(session3);
|
|
34404
|
-
let acpxRecordId = this.recordIdCache.get(cacheKey);
|
|
34405
|
-
if (!acpxRecordId) {
|
|
34406
|
-
try {
|
|
34407
|
-
({ acpxRecordId } = await this.readSessionRecord(session3));
|
|
34408
|
-
} catch {
|
|
34409
|
-
return false;
|
|
34410
|
-
}
|
|
34411
|
-
this.recordIdCache.set(cacheKey, acpxRecordId);
|
|
34412
|
-
}
|
|
34413
|
-
const pid = await readQueueOwnerPid(acpxRecordId);
|
|
34414
|
-
if (pid === undefined) {
|
|
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))
|
|
34415
34383
|
return false;
|
|
34416
|
-
|
|
34417
|
-
return
|
|
34418
|
-
}
|
|
34419
|
-
|
|
34420
|
-
|
|
34421
|
-
|
|
34422
|
-
|
|
34423
|
-
|
|
34424
|
-
|
|
34425
|
-
|
|
34426
|
-
|
|
34427
|
-
|
|
34428
|
-
|
|
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;
|
|
34429
34414
|
}
|
|
34430
|
-
|
|
34431
|
-
|
|
34415
|
+
const streamFiles = entries.filter((name) => name.startsWith(`${safeId}.stream.`));
|
|
34416
|
+
for (const name of streamFiles) {
|
|
34417
|
+
await unlink2(join23(dir, name)).catch(() => {
|
|
34432
34418
|
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
34419
|
});
|
|
34445
34420
|
}
|
|
34446
|
-
|
|
34447
|
-
|
|
34448
|
-
|
|
34449
|
-
|
|
34450
|
-
|
|
34451
|
-
|
|
34452
|
-
|
|
34453
|
-
|
|
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");
|
|
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");
|
|
34463
34429
|
}
|
|
34464
|
-
|
|
34465
|
-
|
|
34466
|
-
return record3.agentSessionId;
|
|
34430
|
+
if (!advertised.available.includes(value)) {
|
|
34431
|
+
throw new Error(`reasoning effort "${value}" is not advertised by the active agent`);
|
|
34467
34432
|
}
|
|
34468
|
-
|
|
34469
|
-
|
|
34470
|
-
|
|
34471
|
-
|
|
34472
|
-
|
|
34473
|
-
|
|
34474
|
-
|
|
34433
|
+
return advertised;
|
|
34434
|
+
}
|
|
34435
|
+
function parseSessionEffortRecord(raw) {
|
|
34436
|
+
let record3;
|
|
34437
|
+
try {
|
|
34438
|
+
record3 = JSON.parse(raw);
|
|
34439
|
+
} catch {
|
|
34440
|
+
return;
|
|
34475
34441
|
}
|
|
34476
|
-
|
|
34477
|
-
|
|
34478
|
-
if (result.code !== 0) {
|
|
34479
|
-
const detail = normalizeCommandError(result) ?? `command failed with exit code ${result.code}`;
|
|
34480
|
-
throw new Error(detail);
|
|
34481
|
-
}
|
|
34482
|
-
return result.stdout;
|
|
34442
|
+
if (!isRecord5(record3) || !isRecord5(record3.acpx) || !Array.isArray(record3.acpx.config_options)) {
|
|
34443
|
+
return;
|
|
34483
34444
|
}
|
|
34484
|
-
|
|
34485
|
-
|
|
34486
|
-
|
|
34487
|
-
|
|
34488
|
-
|
|
34489
|
-
const
|
|
34490
|
-
|
|
34491
|
-
|
|
34492
|
-
|
|
34493
|
-
|
|
34494
|
-
|
|
34495
|
-
}),
|
|
34496
|
-
new Promise((_, reject) => {
|
|
34497
|
-
timeoutId = setTimeout(() => {
|
|
34498
|
-
reject(managementTimeoutError(args, options));
|
|
34499
|
-
abortController.abort();
|
|
34500
|
-
}, options.timeoutMs);
|
|
34501
|
-
})
|
|
34502
|
-
]);
|
|
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) : [];
|
|
34451
|
+
return {
|
|
34452
|
+
configId: candidate.id,
|
|
34453
|
+
current: typeof candidate.currentValue === "string" ? candidate.currentValue : undefined,
|
|
34454
|
+
available
|
|
34455
|
+
};
|
|
34503
34456
|
}
|
|
34504
|
-
|
|
34505
|
-
|
|
34506
|
-
|
|
34507
|
-
|
|
34508
|
-
|
|
34509
|
-
|
|
34510
|
-
|
|
34511
|
-
|
|
34512
|
-
|
|
34513
|
-
|
|
34514
|
-
|
|
34515
|
-
|
|
34516
|
-
|
|
34517
|
-
|
|
34518
|
-
|
|
34519
|
-
|
|
34520
|
-
|
|
34521
|
-
|
|
34522
|
-
|
|
34523
|
-
|
|
34524
|
-
|
|
34525
|
-
|
|
34526
|
-
|
|
34527
|
-
|
|
34528
|
-
|
|
34529
|
-
|
|
34530
|
-
|
|
34531
|
-
|
|
34532
|
-
|
|
34533
|
-
|
|
34534
|
-
|
|
34535
|
-
|
|
34536
|
-
|
|
34537
|
-
|
|
34538
|
-
|
|
34539
|
-
|
|
34540
|
-
|
|
34541
|
-
|
|
34542
|
-
|
|
34543
|
-
|
|
34544
|
-
|
|
34545
|
-
|
|
34546
|
-
|
|
34547
|
-
|
|
34548
|
-
|
|
34549
|
-
|
|
34550
|
-
|
|
34551
|
-
|
|
34552
|
-
|
|
34553
|
-
|
|
34554
|
-
|
|
34555
|
-
|
|
34556
|
-
|
|
34557
|
-
|
|
34558
|
-
|
|
34559
|
-
|
|
34560
|
-
|
|
34561
|
-
|
|
34562
|
-
|
|
34563
|
-
|
|
34564
|
-
|
|
34565
|
-
|
|
34566
|
-
|
|
34567
|
-
|
|
34568
|
-
|
|
34569
|
-
|
|
34570
|
-
|
|
34571
|
-
|
|
34572
|
-
|
|
34573
|
-
|
|
34574
|
-
|
|
34575
|
-
|
|
34576
|
-
|
|
34577
|
-
|
|
34578
|
-
|
|
34579
|
-
|
|
34580
|
-
|
|
34581
|
-
|
|
34582
|
-
|
|
34583
|
-
|
|
34584
|
-
|
|
34585
|
-
|
|
34586
|
-
|
|
34587
|
-
|
|
34588
|
-
|
|
34589
|
-
|
|
34590
|
-
|
|
34591
|
-
|
|
34592
|
-
|
|
34593
|
-
|
|
34594
|
-
|
|
34595
|
-
|
|
34596
|
-
|
|
34597
|
-
|
|
34598
|
-
|
|
34599
|
-
|
|
34600
|
-
|
|
34601
|
-
|
|
34602
|
-
|
|
34603
|
-
|
|
34604
|
-
|
|
34605
|
-
|
|
34606
|
-
|
|
34607
|
-
|
|
34608
|
-
|
|
34609
|
-
|
|
34610
|
-
});
|
|
34611
|
-
child.stderr.on("data", (chunk) => {
|
|
34612
|
-
stderr += String(chunk);
|
|
34613
|
-
});
|
|
34614
|
-
child.on("error", (err) => {
|
|
34615
|
-
clearIntervalFn(timer);
|
|
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);
|
|
34623
|
-
}
|
|
34624
|
-
const { overflowCount } = sink2?.finalize() ?? { overflowCount: 0 };
|
|
34625
|
-
Promise.all([
|
|
34626
|
-
sink2?.drain({ timeoutMs: 30000 }) ?? Promise.resolve(),
|
|
34627
|
-
segmentChain,
|
|
34628
|
-
toolEventChain,
|
|
34629
|
-
thoughtChain,
|
|
34630
|
-
planChain,
|
|
34631
|
-
usageChain,
|
|
34632
|
-
commandsChain
|
|
34633
|
-
]).then(() => {
|
|
34634
|
-
const deferred = sink2?.getPendingError();
|
|
34635
|
-
if (deferred) {
|
|
34636
|
-
reject(deferred);
|
|
34637
|
-
return;
|
|
34638
|
-
}
|
|
34639
|
-
if (segmentError) {
|
|
34640
|
-
reject(segmentError);
|
|
34641
|
-
return;
|
|
34642
|
-
}
|
|
34643
|
-
if (toolEventError) {
|
|
34644
|
-
reject(toolEventError);
|
|
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);
|
|
34661
|
-
return;
|
|
34662
|
-
}
|
|
34663
|
-
resolve4({
|
|
34664
|
-
result: { code: code ?? 1, stdout: stdout2, stderr },
|
|
34665
|
-
overflowCount
|
|
34666
|
-
});
|
|
34667
|
-
}).catch((error2) => {
|
|
34668
|
-
reject(error2);
|
|
34669
|
-
});
|
|
34670
|
-
});
|
|
34671
|
-
});
|
|
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";
|
|
34488
|
+
}
|
|
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);
|
|
34496
|
+
}
|
|
34497
|
+
return args;
|
|
34498
|
+
}
|
|
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 };
|
|
34557
|
+
}
|
|
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 };
|
|
34562
|
+
}
|
|
34672
34563
|
}
|
|
34673
|
-
|
|
34674
|
-
|
|
34675
|
-
|
|
34676
|
-
|
|
34677
|
-
|
|
34564
|
+
return;
|
|
34565
|
+
}
|
|
34566
|
+
var DEFAULT_PERMISSION_MODE2 = "approve-all", DEFAULT_NON_INTERACTIVE = "deny";
|
|
34567
|
+
var init_acpx_command_builder = () => {};
|
|
34568
|
+
|
|
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
|
+
});
|
|
34578
|
+
}
|
|
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
|
+
});
|
|
34615
|
+
}
|
|
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();
|
|
34678
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;
|
|
34679
34678
|
}
|
|
34680
|
-
|
|
34681
|
-
|
|
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;
|
|
34690
|
+
}
|
|
34682
34691
|
}
|
|
34683
|
-
|
|
34684
|
-
const
|
|
34685
|
-
|
|
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
|
+
});
|
|
34686
34704
|
}
|
|
34687
|
-
|
|
34688
|
-
return {
|
|
34689
|
-
|
|
34690
|
-
|
|
34691
|
-
|
|
34692
|
-
|
|
34693
|
-
|
|
34694
|
-
|
|
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
|
+
});
|
|
34695
34723
|
}
|
|
34696
|
-
|
|
34697
|
-
|
|
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);
|
|
34698
34749
|
}
|
|
34699
|
-
|
|
34700
|
-
|
|
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";
|
|
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}` : "" };
|
|
34775
|
+
}
|
|
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 {}
|
|
34783
|
+
}
|
|
34701
34784
|
}
|
|
34702
|
-
|
|
34703
|
-
|
|
34704
|
-
|
|
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
|
+
}));
|
|
34705
34795
|
}
|
|
34706
|
-
|
|
34707
|
-
|
|
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
|
+
}));
|
|
34708
34807
|
}
|
|
34709
|
-
|
|
34710
|
-
|
|
34711
|
-
|
|
34712
|
-
|
|
34713
|
-
const
|
|
34714
|
-
|
|
34715
|
-
|
|
34716
|
-
|
|
34717
|
-
|
|
34718
|
-
|
|
34719
|
-
|
|
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);
|
|
34720
34820
|
}
|
|
34721
|
-
|
|
34722
|
-
|
|
34723
|
-
|
|
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: [] };
|
|
34724
34829
|
}
|
|
34725
|
-
rendered.push(/\s/.test(arg) || arg.includes(":") ? `"${arg}"` : arg);
|
|
34726
34830
|
}
|
|
34727
|
-
|
|
34728
|
-
|
|
34729
|
-
|
|
34730
|
-
|
|
34731
|
-
|
|
34732
|
-
|
|
34733
|
-
|
|
34734
|
-
|
|
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: [] };
|
|
34735
34842
|
}
|
|
34736
|
-
|
|
34737
|
-
|
|
34738
|
-
|
|
34739
|
-
|
|
34740
|
-
|
|
34741
|
-
|
|
34742
|
-
|
|
34743
|
-
|
|
34744
|
-
|
|
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
|
-
});
|
|
34760
|
-
|
|
34761
|
-
// src/transport/claude-background-followup.ts
|
|
34762
|
-
import { access as access4, open as open5, readFile as readFile14, readdir as readdir4, stat as stat3 } from "node:fs/promises";
|
|
34763
|
-
import { constants as fsConstants } from "node:fs";
|
|
34764
|
-
import { homedir as homedir12 } from "node:os";
|
|
34765
|
-
import { basename as basename3, dirname as dirname13, join as join23 } from "node:path";
|
|
34766
|
-
function isClaudeAsyncAgentLaunch(event) {
|
|
34767
|
-
return ASYNC_AGENT_LAUNCH.test(textOfUnknown(event.rawOutput));
|
|
34768
|
-
}
|
|
34769
|
-
function claudeAsyncAgentId(event) {
|
|
34770
|
-
const fromObject = findStringField(event.rawOutput, new Set(["agentId", "agent_id"]));
|
|
34771
|
-
if (fromObject)
|
|
34772
|
-
return fromObject;
|
|
34773
|
-
return /\bagent(?:Id|_id)["']?\s*[:=]\s*["']?([A-Za-z0-9_-]+)/i.exec(textOfUnknown(event.rawOutput))?.[1];
|
|
34774
|
-
}
|
|
34775
|
-
async function findClaudeTranscriptPath(input) {
|
|
34776
|
-
const projectsDir = join23(input.homeDir ?? homedir12(), ".claude", "projects");
|
|
34777
|
-
const direct = join23(projectsDir, encodeClaudeProjectDirectory(input.cwd), `${input.sessionId}.jsonl`);
|
|
34778
|
-
if (await exists(direct))
|
|
34779
|
-
return direct;
|
|
34780
|
-
try {
|
|
34781
|
-
const entries = await readdir4(projectsDir, { withFileTypes: true });
|
|
34782
|
-
for (const entry of entries) {
|
|
34783
|
-
if (!entry.isDirectory())
|
|
34784
|
-
continue;
|
|
34785
|
-
const candidate = join23(projectsDir, entry.name, `${input.sessionId}.jsonl`);
|
|
34786
|
-
if (await exists(candidate))
|
|
34787
|
-
return candidate;
|
|
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)) {
|
|
34851
|
+
return;
|
|
34788
34852
|
}
|
|
34789
|
-
|
|
34790
|
-
return;
|
|
34853
|
+
await this.applyAdvertisedSessionEffort(session3, effort, record3);
|
|
34791
34854
|
}
|
|
34792
|
-
|
|
34793
|
-
|
|
34794
|
-
|
|
34795
|
-
|
|
34796
|
-
|
|
34797
|
-
|
|
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
|
+
}));
|
|
34798
34864
|
}
|
|
34799
|
-
|
|
34800
|
-
|
|
34801
|
-
|
|
34802
|
-
|
|
34803
|
-
|
|
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
|
+
}));
|
|
34804
34877
|
}
|
|
34805
|
-
|
|
34806
|
-
|
|
34807
|
-
|
|
34808
|
-
|
|
34809
|
-
|
|
34810
|
-
|
|
34811
|
-
|
|
34812
|
-
|
|
34813
|
-
|
|
34814
|
-
|
|
34815
|
-
|
|
34816
|
-
|
|
34817
|
-
|
|
34818
|
-
toolEvents.set(event.toolCallId, event);
|
|
34819
|
-
const parentToolCallIdByAgentId = new Map;
|
|
34820
|
-
for (const [toolCallId, agentId] of options.subagentIdsByToolCallId ?? []) {
|
|
34821
|
-
if (toolCallId && agentId)
|
|
34822
|
-
parentToolCallIdByAgentId.set(agentId, toolCallId);
|
|
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
|
+
};
|
|
34823
34891
|
}
|
|
34824
|
-
|
|
34825
|
-
|
|
34826
|
-
|
|
34827
|
-
|
|
34828
|
-
|
|
34829
|
-
|
|
34830
|
-
|
|
34831
|
-
|
|
34832
|
-
|
|
34833
|
-
|
|
34834
|
-
|
|
34835
|
-
|
|
34836
|
-
|
|
34837
|
-
|
|
34838
|
-
|
|
34839
|
-
|
|
34840
|
-
|
|
34841
|
-
|
|
34842
|
-
|
|
34843
|
-
|
|
34844
|
-
|
|
34845
|
-
|
|
34846
|
-
|
|
34847
|
-
|
|
34848
|
-
|
|
34849
|
-
|
|
34850
|
-
|
|
34851
|
-
|
|
34852
|
-
|
|
34853
|
-
|
|
34854
|
-
|
|
34855
|
-
|
|
34856
|
-
}
|
|
34857
|
-
}
|
|
34858
|
-
for (const block of blocks) {
|
|
34859
|
-
if (readString2(block, "type") !== "tool_result")
|
|
34860
|
-
continue;
|
|
34861
|
-
const toolCallId = readString2(block, "tool_use_id");
|
|
34862
|
-
if (!toolCallId)
|
|
34863
|
-
continue;
|
|
34864
|
-
const output = blockText(block);
|
|
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;
|
|
34881
|
-
}
|
|
34882
|
-
if (record3.type !== "assistant" || record3.isSidechain === true)
|
|
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) {
|
|
34883
34924
|
return;
|
|
34884
|
-
for (const block of blocks) {
|
|
34885
|
-
const type = readString2(block, "type");
|
|
34886
|
-
if (type === "text") {
|
|
34887
|
-
const text = readString2(block, "text");
|
|
34888
|
-
if (text)
|
|
34889
|
-
await options.onText?.(text);
|
|
34890
|
-
} else if (type === "thinking") {
|
|
34891
|
-
const thought = readString2(block, "thinking");
|
|
34892
|
-
if (thought)
|
|
34893
|
-
await options.onThought?.(thought);
|
|
34894
|
-
} else if (type === "tool_use") {
|
|
34895
|
-
const toolCallId = readString2(block, "id");
|
|
34896
|
-
if (!toolCallId)
|
|
34897
|
-
continue;
|
|
34898
|
-
const name = readString2(block, "name") ?? "Tool";
|
|
34899
|
-
const rawInput = block.input;
|
|
34900
|
-
const event = {
|
|
34901
|
-
toolCallId,
|
|
34902
|
-
toolName: name,
|
|
34903
|
-
kind: classifyToolKind(name),
|
|
34904
|
-
...toolSummary(rawInput) ? { summary: toolSummary(rawInput) } : {},
|
|
34905
|
-
...rawInput !== undefined ? { rawInput } : {},
|
|
34906
|
-
status: "running"
|
|
34907
|
-
};
|
|
34908
|
-
await emitTool(event);
|
|
34909
|
-
}
|
|
34910
34925
|
}
|
|
34911
|
-
if (
|
|
34912
|
-
done = true;
|
|
34913
|
-
}
|
|
34914
|
-
};
|
|
34915
|
-
const processAfterBoundary = async (record3) => {
|
|
34916
|
-
if (!record3)
|
|
34917
|
-
return;
|
|
34918
|
-
if (!boundarySeen) {
|
|
34919
|
-
if (hasTrackedLaunch(record3, launched))
|
|
34920
|
-
launchSeen = true;
|
|
34921
|
-
if (launchSeen && isMainEndTurn(record3))
|
|
34922
|
-
boundarySeen = true;
|
|
34926
|
+
if (isMissingAcpxSessionError(result.stderr, result.stdout)) {
|
|
34923
34927
|
return;
|
|
34924
34928
|
}
|
|
34925
|
-
|
|
34926
|
-
|
|
34927
|
-
|
|
34928
|
-
|
|
34929
|
-
|
|
34930
|
-
|
|
34931
|
-
|
|
34932
|
-
|
|
34933
|
-
if (readString2(block, "type") !== "tool_use")
|
|
34934
|
-
continue;
|
|
34935
|
-
const toolCallId = readString2(block, "id");
|
|
34936
|
-
if (!toolCallId)
|
|
34937
|
-
continue;
|
|
34938
|
-
const name = readString2(block, "name") ?? "Tool";
|
|
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
|
-
}
|
|
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
|
-
failedToolCallIds: [...failed]
|
|
35028
|
-
};
|
|
35029
|
-
}
|
|
35030
|
-
await waitForPoll(pollIntervalMs, options.signal);
|
|
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;
|
|
35037
|
-
}
|
|
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;
|
|
35038
34985
|
}
|
|
35039
|
-
|
|
35040
|
-
|
|
35041
|
-
|
|
35042
|
-
await waitForPoll(pollIntervalMs, options.signal);
|
|
35043
|
-
stablePolls = await processSubagentTranscripts() ? 0 : stablePolls + 1;
|
|
34986
|
+
async launchMcpQueueOwnerIfNeeded(session3) {
|
|
34987
|
+
if (!session3.mcpCoordinatorSession) {
|
|
34988
|
+
return;
|
|
35044
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
|
+
});
|
|
35045
35001
|
}
|
|
35046
|
-
|
|
35047
|
-
|
|
35048
|
-
|
|
35049
|
-
|
|
35050
|
-
|
|
35051
|
-
|
|
35052
|
-
|
|
35053
|
-
|
|
35054
|
-
|
|
35055
|
-
|
|
35056
|
-
|
|
35057
|
-
|
|
35058
|
-
|
|
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);
|
|
35014
|
+
}
|
|
35015
|
+
const record3 = parseAcpxSessionRecordId(result.stdout);
|
|
35016
|
+
if (record3)
|
|
35017
|
+
return record3;
|
|
35018
|
+
throw new Error("failed to resolve acpx session record id");
|
|
35059
35019
|
}
|
|
35060
|
-
|
|
35061
|
-
|
|
35062
|
-
|
|
35020
|
+
async getAgentSessionId(session3) {
|
|
35021
|
+
const record3 = await this.readSessionRecord(session3);
|
|
35022
|
+
return record3.agentSessionId;
|
|
35063
35023
|
}
|
|
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();
|
|
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);
|
|
35075
35029
|
}
|
|
35076
|
-
|
|
35077
|
-
return [];
|
|
35030
|
+
return result.stdout;
|
|
35078
35031
|
}
|
|
35079
|
-
|
|
35080
|
-
|
|
35081
|
-
|
|
35082
|
-
`
|
|
35083
|
-
|
|
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
|
-
}
|
|
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);
|
|
35096
35037
|
}
|
|
35038
|
+
return result.stdout;
|
|
35097
35039
|
}
|
|
35098
|
-
|
|
35099
|
-
|
|
35100
|
-
|
|
35101
|
-
|
|
35102
|
-
if (record3?.type === "assistant" && record3.isSidechain !== true && record3.message?.stop_reason === "end_turn") {
|
|
35103
|
-
return index;
|
|
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);
|
|
35104
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
|
+
});
|
|
35228
|
+
}
|
|
35229
|
+
permissionInput() {
|
|
35230
|
+
return {
|
|
35231
|
+
permissionMode: this.permissionMode,
|
|
35232
|
+
nonInteractivePermissions: this.nonInteractivePermissions,
|
|
35233
|
+
permissionPolicy: this.permissionPolicy
|
|
35234
|
+
};
|
|
35235
|
+
}
|
|
35236
|
+
spawnEnvironment(input) {
|
|
35237
|
+
return this.resolveSpawnEnvironment(input);
|
|
35238
|
+
}
|
|
35239
|
+
withSpawnEnvironment(input, options) {
|
|
35240
|
+
const env = this.spawnEnvironment(input);
|
|
35241
|
+
return env ? { ...options ?? {}, env } : options;
|
|
35105
35242
|
}
|
|
35106
|
-
|
|
35107
|
-
|
|
35108
|
-
|
|
35109
|
-
|
|
35110
|
-
|
|
35111
|
-
|
|
35112
|
-
|
|
35113
|
-
|
|
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;
|
|
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
|
+
};
|
|
35123
35251
|
}
|
|
35124
|
-
|
|
35125
|
-
|
|
35126
|
-
if (typeof content === "string")
|
|
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 "";
|
|
35252
|
+
buildArgs(session3, tail2, format = "quiet") {
|
|
35253
|
+
return buildSessionArgs(this.sessionInput(session3), tail2, { format });
|
|
35157
35254
|
}
|
|
35158
|
-
|
|
35159
|
-
|
|
35160
|
-
if (!value || typeof value !== "object")
|
|
35161
|
-
return;
|
|
35162
|
-
if (Array.isArray(value)) {
|
|
35163
|
-
for (const item of value) {
|
|
35164
|
-
const found = findStringField(item, keys);
|
|
35165
|
-
if (found)
|
|
35166
|
-
return found;
|
|
35167
|
-
}
|
|
35168
|
-
return;
|
|
35255
|
+
buildAgentQueryArgs(query, format, tail2) {
|
|
35256
|
+
return buildAgentQueryArgs({ agent: query.agent, agentCommand: query.agentCommand, cwd: query.cwd, permission: this.permissionInput() }, format, tail2);
|
|
35169
35257
|
}
|
|
35170
|
-
|
|
35171
|
-
|
|
35172
|
-
|
|
35173
|
-
if (typeof candidate === "string" && candidate.trim())
|
|
35174
|
-
return candidate.trim();
|
|
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);
|
|
35175
35261
|
}
|
|
35176
|
-
|
|
35177
|
-
|
|
35178
|
-
if (found)
|
|
35179
|
-
return found;
|
|
35262
|
+
buildPermissionArgs() {
|
|
35263
|
+
return buildPermissionArgs(this.permissionInput());
|
|
35180
35264
|
}
|
|
35181
|
-
return;
|
|
35182
35265
|
}
|
|
35183
|
-
function
|
|
35184
|
-
const
|
|
35185
|
-
|
|
35186
|
-
|
|
35187
|
-
|
|
35188
|
-
if (!toolCallId)
|
|
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) {
|
|
35189
35271
|
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
|
-
});
|
|
35195
|
-
}
|
|
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
|
-
}
|
|
35216
|
-
async function findSubagentTranscripts(transcriptPath) {
|
|
35217
|
-
const sessionDir = join23(dirname13(transcriptPath), basename3(transcriptPath, ".jsonl"), "subagents");
|
|
35218
|
-
const found = [];
|
|
35219
|
-
const visit = async (directory) => {
|
|
35220
|
-
let entries;
|
|
35221
|
-
try {
|
|
35222
|
-
entries = await readdir4(directory, { withFileTypes: true });
|
|
35223
|
-
} catch {
|
|
35224
|
-
return;
|
|
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
|
-
// src/transport/
|
|
35297
|
-
function
|
|
35298
|
-
const
|
|
35317
|
+
// src/transport/background-followup-transport.ts
|
|
35318
|
+
function createBackgroundFollowupTransport(delegate, options) {
|
|
35319
|
+
const runBackgroundFollowup = options.followBackgroundTurn ?? followBackgroundTurn;
|
|
35299
35320
|
const prompt = async (session3, text, reply, replyContext, promptOptions) => {
|
|
35300
35321
|
const latestToolEvents = new Map;
|
|
35301
35322
|
const pendingToolEvents = new Map;
|
|
@@ -35308,9 +35329,9 @@ function createClaudeBackgroundFollowupTransport(delegate, options) {
|
|
|
35308
35329
|
pendingToolEvents.set(event.toolCallId, event);
|
|
35309
35330
|
else
|
|
35310
35331
|
pendingToolEvents.delete(event.toolCallId);
|
|
35311
|
-
if (
|
|
35332
|
+
if (event.isSubagent && isAsyncAgentLaunch(event)) {
|
|
35312
35333
|
asyncToolCallIds.add(event.toolCallId);
|
|
35313
|
-
const agentId =
|
|
35334
|
+
const agentId = asyncAgentId(event);
|
|
35314
35335
|
if (agentId)
|
|
35315
35336
|
subagentIdsByToolCallId.set(event.toolCallId, agentId);
|
|
35316
35337
|
}
|
|
@@ -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(
|
|
35353
|
+
await options.logger.error(`${LEGACY_LOG_EVENT_PREFIX}.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(
|
|
35345
|
-
const followup = await
|
|
35366
|
+
await options.logger.info(`${LEGACY_LOG_EVENT_PREFIX}.started`, "following background-agent continuation", { alias: session3.alias, agentSessionId, driver, taskCount: asyncToolCallIds.size });
|
|
35367
|
+
const followup = await runBackgroundFollowup({
|
|
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(
|
|
35402
|
+
await options.logger.info(`${LEGACY_LOG_EVENT_PREFIX}.${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
|
});
|
|
@@ -35393,8 +35417,9 @@ function createClaudeBackgroundFollowupTransport(delegate, options) {
|
|
|
35393
35417
|
}
|
|
35394
35418
|
});
|
|
35395
35419
|
}
|
|
35396
|
-
var
|
|
35397
|
-
|
|
35420
|
+
var LEGACY_LOG_EVENT_PREFIX = "transport.claude_background_followup";
|
|
35421
|
+
var init_background_followup_transport = __esm(() => {
|
|
35422
|
+
init_background_followup();
|
|
35398
35423
|
});
|
|
35399
35424
|
|
|
35400
35425
|
// src/util/async.ts
|
|
@@ -36758,21 +36783,28 @@ class WorkspaceGit {
|
|
|
36758
36783
|
}
|
|
36759
36784
|
return startPoint;
|
|
36760
36785
|
}
|
|
36761
|
-
async
|
|
36762
|
-
const selected = new Set(paths);
|
|
36763
|
-
const expanded = new Set(paths);
|
|
36786
|
+
async readPorcelain(root) {
|
|
36764
36787
|
const fields = (await this.runRaw(root, ["-c", "core.quotePath=false", "status", "--porcelain", "-z"])).split("\x00");
|
|
36788
|
+
const entries = [];
|
|
36765
36789
|
for (let index = 0;index < fields.length; index += 1) {
|
|
36766
36790
|
const field = fields[index];
|
|
36767
36791
|
if (!field)
|
|
36768
36792
|
continue;
|
|
36769
36793
|
const status = field.slice(0, 2);
|
|
36770
36794
|
const path14 = field.slice(3);
|
|
36771
|
-
|
|
36772
|
-
|
|
36773
|
-
|
|
36774
|
-
|
|
36775
|
-
|
|
36795
|
+
const entry = { status, path: path14 };
|
|
36796
|
+
if (status[0] === "R" || status[0] === "C")
|
|
36797
|
+
entry.originalPath = fields[++index];
|
|
36798
|
+
entries.push(entry);
|
|
36799
|
+
}
|
|
36800
|
+
return entries;
|
|
36801
|
+
}
|
|
36802
|
+
async includeRenameSources(root, paths) {
|
|
36803
|
+
const selected = new Set(paths);
|
|
36804
|
+
const expanded = new Set(paths);
|
|
36805
|
+
for (const entry of await this.readPorcelain(root)) {
|
|
36806
|
+
if (entry.originalPath && selected.has(entry.path))
|
|
36807
|
+
expanded.add(entry.originalPath);
|
|
36776
36808
|
}
|
|
36777
36809
|
return [...expanded];
|
|
36778
36810
|
}
|
|
@@ -36810,6 +36842,38 @@ class WorkspaceGit {
|
|
|
36810
36842
|
}
|
|
36811
36843
|
});
|
|
36812
36844
|
}
|
|
36845
|
+
async untrack(workspace3, paths) {
|
|
36846
|
+
await this.withWrite(workspace3, async () => {
|
|
36847
|
+
const root = await this.rootFor(workspace3);
|
|
36848
|
+
await this.run(root, ["--literal-pathspecs", "rm", "--cached", "--force", "--", ...this.validatePaths(paths)]);
|
|
36849
|
+
});
|
|
36850
|
+
}
|
|
36851
|
+
async discard(workspace3, paths) {
|
|
36852
|
+
await this.withWrite(workspace3, async () => {
|
|
36853
|
+
const root = await this.rootFor(workspace3);
|
|
36854
|
+
const selected = new Set(this.validatePaths(paths));
|
|
36855
|
+
const deletePaths = new Set;
|
|
36856
|
+
const restorePaths = new Set;
|
|
36857
|
+
for (const entry of await this.readPorcelain(root)) {
|
|
36858
|
+
if (!selected.has(entry.path))
|
|
36859
|
+
continue;
|
|
36860
|
+
if (entry.status === "??" || entry.status[0] === "A" || entry.originalPath !== undefined) {
|
|
36861
|
+
deletePaths.add(entry.path);
|
|
36862
|
+
if (entry.originalPath)
|
|
36863
|
+
restorePaths.add(entry.originalPath);
|
|
36864
|
+
} else {
|
|
36865
|
+
restorePaths.add(entry.path);
|
|
36866
|
+
}
|
|
36867
|
+
}
|
|
36868
|
+
if (deletePaths.size) {
|
|
36869
|
+
await this.run(root, ["--literal-pathspecs", "reset", "-q", "--", ...deletePaths]);
|
|
36870
|
+
await this.run(root, ["--literal-pathspecs", "clean", "-qf", "--", ...deletePaths]);
|
|
36871
|
+
}
|
|
36872
|
+
if (restorePaths.size) {
|
|
36873
|
+
await this.run(root, ["--literal-pathspecs", "restore", "--source=HEAD", "--staged", "--worktree", "--", ...restorePaths]);
|
|
36874
|
+
}
|
|
36875
|
+
});
|
|
36876
|
+
}
|
|
36813
36877
|
async commit(workspace3, message) {
|
|
36814
36878
|
return this.withWrite(workspace3, async () => {
|
|
36815
36879
|
const root = await this.rootFor(workspace3);
|
|
@@ -37540,6 +37604,12 @@ class ControlService {
|
|
|
37540
37604
|
gitUnstage(workspace3, paths) {
|
|
37541
37605
|
return this.mutateWorkspaceGit(() => this.workspaceGit.unstage(workspace3, paths));
|
|
37542
37606
|
}
|
|
37607
|
+
gitUntrack(workspace3, paths) {
|
|
37608
|
+
return this.mutateWorkspaceGit(() => this.workspaceGit.untrack(workspace3, paths));
|
|
37609
|
+
}
|
|
37610
|
+
gitDiscard(workspace3, paths) {
|
|
37611
|
+
return this.mutateWorkspaceGit(() => this.workspaceGit.discard(workspace3, paths));
|
|
37612
|
+
}
|
|
37543
37613
|
gitCommit(workspace3, message) {
|
|
37544
37614
|
return this.mutateWorkspaceGit(() => this.workspaceGit.commit(workspace3, message));
|
|
37545
37615
|
}
|
|
@@ -38570,7 +38640,7 @@ async function buildApp(paths, deps = {}) {
|
|
|
38570
38640
|
});
|
|
38571
38641
|
}
|
|
38572
38642
|
})))) : deps.createCliTransport?.(acpxCommand) ?? new AcpxCliTransport({ ...config4.transport, command: acpxCommand });
|
|
38573
|
-
const transport =
|
|
38643
|
+
const transport = createBackgroundFollowupTransport(baseTransport, {
|
|
38574
38644
|
logger,
|
|
38575
38645
|
resolveDriver: (agent4) => config4.agents[agent4]?.driver
|
|
38576
38646
|
});
|
|
@@ -39245,7 +39315,7 @@ var init_main = __esm(async () => {
|
|
|
39245
39315
|
init_acpx_bridge_client();
|
|
39246
39316
|
init_acpx_bridge_transport();
|
|
39247
39317
|
init_acpx_cli_transport();
|
|
39248
|
-
|
|
39318
|
+
init_background_followup_transport();
|
|
39249
39319
|
init_queue_owner_reaper();
|
|
39250
39320
|
init_collect_reap_targets();
|
|
39251
39321
|
init_channel_registry();
|