@rallycry/conveyor-agent 10.4.0 → 10.5.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/{chunk-TZYEU4QE.js → chunk-MSDYMAG3.js} +190 -91
- package/dist/chunk-MSDYMAG3.js.map +1 -0
- package/dist/cli.js +381 -47
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +25 -3
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-TZYEU4QE.js.map +0 -1
|
@@ -197,6 +197,8 @@ var AgentConnection = class _AgentConnection {
|
|
|
197
197
|
earlyPullBranches = [];
|
|
198
198
|
spawnReviewCallback = null;
|
|
199
199
|
earlySpawnReviews = [];
|
|
200
|
+
spawnTuiCallback = null;
|
|
201
|
+
earlySpawnTuis = [];
|
|
200
202
|
// PTY relay (S5 terminal). Single-slot callbacks, set per PtySession run.
|
|
201
203
|
ptyInputCallback = null;
|
|
202
204
|
ptyResizeCallback = null;
|
|
@@ -404,6 +406,10 @@ var AgentConnection = class _AgentConnection {
|
|
|
404
406
|
if (this.spawnReviewCallback) this.spawnReviewCallback(data);
|
|
405
407
|
else this.earlySpawnReviews.push(data);
|
|
406
408
|
});
|
|
409
|
+
this.socket.on("session:spawnTui", (data) => {
|
|
410
|
+
if (this.spawnTuiCallback) this.spawnTuiCallback(data);
|
|
411
|
+
else this.earlySpawnTuis.push(data);
|
|
412
|
+
});
|
|
407
413
|
this.socket.on("session:finalizeSnapshot", () => {
|
|
408
414
|
this.finalizeSnapshotCallback?.();
|
|
409
415
|
});
|
|
@@ -659,6 +665,25 @@ var AgentConnection = class _AgentConnection {
|
|
|
659
665
|
}).catch(() => {
|
|
660
666
|
});
|
|
661
667
|
}
|
|
668
|
+
onSpawnTui(callback) {
|
|
669
|
+
this.spawnTuiCallback = callback;
|
|
670
|
+
for (const data of this.earlySpawnTuis) callback(data);
|
|
671
|
+
this.earlySpawnTuis = [];
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Report that a same-pod TUI/shell child failed to spawn (fire-and-forget).
|
|
675
|
+
* The server Ends the orphaned session — no fallback pod (unlike review).
|
|
676
|
+
* sessionId is OUR (builder) session — the SEC-9 guard runs on it.
|
|
677
|
+
*/
|
|
678
|
+
reportSessionSpawnFailure(spawnedSessionId, error) {
|
|
679
|
+
if (!this.socket) return;
|
|
680
|
+
void this.call("reportSessionSpawnFailure", {
|
|
681
|
+
sessionId: this.config.sessionId,
|
|
682
|
+
spawnedSessionId,
|
|
683
|
+
...error ? { error: error.slice(0, 2e3) } : {}
|
|
684
|
+
}).catch(() => {
|
|
685
|
+
});
|
|
686
|
+
}
|
|
662
687
|
onFinalizeSnapshot(callback) {
|
|
663
688
|
this.finalizeSnapshotCallback = callback;
|
|
664
689
|
}
|
|
@@ -719,13 +744,16 @@ var AgentConnection = class _AgentConnection {
|
|
|
719
744
|
};
|
|
720
745
|
}
|
|
721
746
|
// ── Convenience methods (thin wrappers around call / emit) ─────────
|
|
722
|
-
async emitStatus(status, reason) {
|
|
747
|
+
async emitStatus(status, reason, questionText) {
|
|
723
748
|
this.lastEmittedStatus = status;
|
|
724
749
|
await this.flushEvents();
|
|
725
750
|
const payload = {
|
|
726
751
|
sessionId: this.config.sessionId,
|
|
727
752
|
status,
|
|
728
|
-
...reason ? { reason } : {}
|
|
753
|
+
...reason ? { reason } : {},
|
|
754
|
+
// Only sent with a pending TUI questionnaire (reason "user_question") so
|
|
755
|
+
// the server can surface the real question text in the notification.
|
|
756
|
+
...questionText ? { questionText } : {}
|
|
729
757
|
};
|
|
730
758
|
const AWAIT_STATUSES = ["idle", "waiting_for_input", "connected"];
|
|
731
759
|
if (AWAIT_STATUSES.includes(status)) {
|
|
@@ -2046,7 +2074,14 @@ var ReportAgentStatusRequestSchema = z.object({
|
|
|
2046
2074
|
sessionId: z.string(),
|
|
2047
2075
|
status: z.string(),
|
|
2048
2076
|
/** Why the agent reports this status (e.g. "user_question" while an AskUserQuestion questionnaire is pending in the TUI). */
|
|
2049
|
-
reason: z.string().optional()
|
|
2077
|
+
reason: z.string().optional(),
|
|
2078
|
+
/**
|
|
2079
|
+
* The pending question text, sent only alongside `reason: "user_question"`
|
|
2080
|
+
* so the server can surface it in the user-question notification body (and
|
|
2081
|
+
* thus the Attention feed) instead of a generic string. Optional: older
|
|
2082
|
+
* agents omit it and the server falls back to the generic wording.
|
|
2083
|
+
*/
|
|
2084
|
+
questionText: z.string().optional()
|
|
2050
2085
|
});
|
|
2051
2086
|
var NotifyAgentVersionRequestSchema = z.object({
|
|
2052
2087
|
sessionId: z.string(),
|
|
@@ -2069,7 +2104,10 @@ var CreateSubtaskRequestSchema = z.object({
|
|
|
2069
2104
|
plan: z.string().optional(),
|
|
2070
2105
|
storyPointValue: z.number().int().positive().optional(),
|
|
2071
2106
|
ordinal: z.number().int().nonnegative().optional(),
|
|
2072
|
-
followParentStatus: z.boolean().optional()
|
|
2107
|
+
followParentStatus: z.boolean().optional(),
|
|
2108
|
+
/** Sibling subtask ids or slugs this subtask blocks on (explicit dependency
|
|
2109
|
+
* metadata — preferred over encoding order in plan text / ordinal). */
|
|
2110
|
+
dependsOn: z.array(z.string().min(1)).max(32).optional()
|
|
2073
2111
|
});
|
|
2074
2112
|
var UpdateSubtaskRequestSchema = z.object({
|
|
2075
2113
|
sessionId: z.string(),
|
|
@@ -2079,7 +2117,10 @@ var UpdateSubtaskRequestSchema = z.object({
|
|
|
2079
2117
|
plan: z.string().optional(),
|
|
2080
2118
|
status: z.string().optional(),
|
|
2081
2119
|
storyPointValue: z.number().int().positive().optional(),
|
|
2082
|
-
followParentStatus: z.boolean().optional()
|
|
2120
|
+
followParentStatus: z.boolean().optional(),
|
|
2121
|
+
/** Replace this subtask's dependency edges with these sibling ids/slugs.
|
|
2122
|
+
* Empty array clears all. Omit to leave dependencies unchanged. */
|
|
2123
|
+
dependsOn: z.array(z.string().min(1)).max(32).optional()
|
|
2083
2124
|
});
|
|
2084
2125
|
var DeleteSubtaskRequestSchema = z.object({
|
|
2085
2126
|
sessionId: z.string(),
|
|
@@ -2263,6 +2304,15 @@ var ReportReviewSpawnFailureRequestSchema = z.object({
|
|
|
2263
2304
|
reviewSessionId: z.string(),
|
|
2264
2305
|
error: z.string().max(2e3).optional()
|
|
2265
2306
|
});
|
|
2307
|
+
var SpawnTaskSessionRequestSchema = z.object({
|
|
2308
|
+
taskId: z.string(),
|
|
2309
|
+
kind: z.enum(["tui", "shell"])
|
|
2310
|
+
});
|
|
2311
|
+
var ReportSessionSpawnFailureRequestSchema = z.object({
|
|
2312
|
+
sessionId: z.string(),
|
|
2313
|
+
spawnedSessionId: z.string(),
|
|
2314
|
+
error: z.string().max(2e3).optional()
|
|
2315
|
+
});
|
|
2266
2316
|
var RefreshGithubTokenResponseSchema = z.object({
|
|
2267
2317
|
token: z.string()
|
|
2268
2318
|
});
|
|
@@ -2500,6 +2550,9 @@ var CreateProjectSubtaskRequestSchema = z2.object({
|
|
|
2500
2550
|
ordinal: z2.number().int().nonnegative().optional(),
|
|
2501
2551
|
storyPointValue: z2.number().int().positive().optional(),
|
|
2502
2552
|
followParentStatus: z2.boolean().optional(),
|
|
2553
|
+
/** Sibling subtask ids or slugs this subtask blocks on (explicit dependency
|
|
2554
|
+
* metadata — preferred over encoding order in plan text / ordinal). */
|
|
2555
|
+
dependsOn: z2.array(z2.string().min(1)).max(32).optional(),
|
|
2503
2556
|
requestingUserId: z2.string().optional()
|
|
2504
2557
|
});
|
|
2505
2558
|
var UpdateProjectSubtaskRequestSchema = z2.object({
|
|
@@ -3950,6 +4003,9 @@ async function startToolServers(mcpServers, tempDir) {
|
|
|
3950
4003
|
}
|
|
3951
4004
|
|
|
3952
4005
|
// src/harness/pty/spawn-args.ts
|
|
4006
|
+
function resolveClaudeBinary() {
|
|
4007
|
+
return process.env.CONVEYOR_CLAUDE_BIN ?? "claude";
|
|
4008
|
+
}
|
|
3953
4009
|
function buildSpawnArgs(input) {
|
|
3954
4010
|
const args = [];
|
|
3955
4011
|
if (input.resume) {
|
|
@@ -4239,9 +4295,9 @@ function extractSpawn(mod) {
|
|
|
4239
4295
|
}
|
|
4240
4296
|
async function loadPtySpawn() {
|
|
4241
4297
|
const mod = await import("node-pty");
|
|
4242
|
-
const
|
|
4243
|
-
if (!
|
|
4244
|
-
return
|
|
4298
|
+
const spawn3 = extractSpawn(mod);
|
|
4299
|
+
if (!spawn3) throw new Error("node-pty: spawn export not found");
|
|
4300
|
+
return spawn3;
|
|
4245
4301
|
}
|
|
4246
4302
|
function inheritedEnv(socketPath) {
|
|
4247
4303
|
const env = {};
|
|
@@ -4740,8 +4796,8 @@ var PtySession = class {
|
|
|
4740
4796
|
// server doesn't load).
|
|
4741
4797
|
...this.mcpConfigPath ? { mcpConfigPath: this.mcpConfigPath } : {}
|
|
4742
4798
|
});
|
|
4743
|
-
const
|
|
4744
|
-
const pty =
|
|
4799
|
+
const spawn3 = await loadPtySpawn();
|
|
4800
|
+
const pty = spawn3(spec.file, spec.args, {
|
|
4745
4801
|
name: "xterm-color",
|
|
4746
4802
|
cols: this.cols,
|
|
4747
4803
|
rows: this.rows,
|
|
@@ -5195,7 +5251,7 @@ function buildPackRunnerSystemPrompt(context, config, setupLog) {
|
|
|
5195
5251
|
``,
|
|
5196
5252
|
`## Important Rules`,
|
|
5197
5253
|
`- When dependencies are set on children, use them to determine execution order. Fire all ready tasks in parallel (up to the PACK_CHILD_LIMIT backpressure \u2014 see the loop above).`,
|
|
5198
|
-
`- When NO dependencies are set on any children, fall back to ordinal order (one at a time)
|
|
5254
|
+
`- Dependencies are explicit card metadata (set at creation via create_subtask's dependsOn, or rewired with update_subtask). Prefer them over reading order out of plan text. When NO dependencies are set on any children, fall back to ordinal order (one at a time) \u2014 this is legacy behavior; set dependsOn when a child truly blocks on another.`,
|
|
5199
5255
|
`- After firing builds OR when waiting on CI, explicitly state you are going idle. Go idle when waiting \u2014 the system wakes you (or relaunches this environment) when a child changes status.`,
|
|
5200
5256
|
`- Do NOT attempt to write code yourself. Your role is coordination only.`,
|
|
5201
5257
|
`- If a child is stuck in "InProgress" for an unusually long time, use get_execution_logs(childTaskId) to check its logs and escalate to the team if it appears stuck.`,
|
|
@@ -5816,7 +5872,8 @@ function buildDiscoveryPrompt(context, runnerMode) {
|
|
|
5816
5872
|
`### Parent Task Coordination`,
|
|
5817
5873
|
`You are a parent task with child tasks. Focus on breaking work into child tasks with detailed plans, not planning implementation for yourself.`,
|
|
5818
5874
|
`- Use \`list_subtasks\` to review existing children. Create or update child tasks using \`create_subtask\` / \`update_subtask\`.`,
|
|
5819
|
-
`- Each child task should be a self-contained unit of work with a clear plan
|
|
5875
|
+
`- Each child task should be a self-contained unit of work with a clear plan.`,
|
|
5876
|
+
`- Set ordering as explicit **card metadata**, not prose: pass \`dependsOn\` (sibling ids/slugs) on \`create_subtask\` for any child that blocks on another. Leave independent children with no dependencies so the pack runner fans them out in parallel. Do NOT encode "do X after Y" only in the plan text \u2014 the runner schedules off dependsOn, not narrative.`
|
|
5820
5877
|
] : [
|
|
5821
5878
|
`### Self-Update vs Subtasks`,
|
|
5822
5879
|
`- If the work fits in a single task (1-3 SP), update YOUR OWN plan and properties \u2014 do not create subtasks`,
|
|
@@ -5830,6 +5887,7 @@ function buildDiscoveryPrompt(context, runnerMode) {
|
|
|
5830
5887
|
`- Reference existing implementations when relevant (e.g., "follow the pattern in src/services/foo.ts")`,
|
|
5831
5888
|
`- Include testing requirements and acceptance criteria`,
|
|
5832
5889
|
`- Set \`storyPointValue\` based on estimated complexity`,
|
|
5890
|
+
`- Express cross-child ordering as \`dependsOn\` (sibling ids/slugs) on \`create_subtask\` \u2014 explicit dependency metadata, not "after task 2" phrasing in the plan. Independent children get no dependencies so they run in parallel.`,
|
|
5833
5891
|
``,
|
|
5834
5892
|
`### Plan Verification Requirements`,
|
|
5835
5893
|
`Every plan MUST include a **Testing / Verification** section so the build agent has a clear definition of "done". Enumerate:`,
|
|
@@ -5876,6 +5934,7 @@ function buildAutoPrompt(context, runnerMode) {
|
|
|
5876
5934
|
`- Reference existing implementations when relevant`,
|
|
5877
5935
|
`- Include testing requirements and acceptance criteria`,
|
|
5878
5936
|
`- Set \`storyPointValue\` based on estimated complexity`,
|
|
5937
|
+
`- Express cross-child ordering as \`dependsOn\` (sibling ids/slugs) on \`create_subtask\` \u2014 explicit dependency metadata, not "after task 2" phrasing in the plan. Independent children get no dependencies so they run in parallel.`,
|
|
5879
5938
|
``,
|
|
5880
5939
|
...buildPlanCitationFormat(),
|
|
5881
5940
|
``,
|
|
@@ -5884,7 +5943,8 @@ function buildAutoPrompt(context, runnerMode) {
|
|
|
5884
5943
|
`### Parent Task Guidance`,
|
|
5885
5944
|
`You are a parent task. Your plan should define child tasks with detailed plans, not direct implementation steps.`,
|
|
5886
5945
|
`After ExitPlanMode, you'll transition to Review mode to coordinate child task execution.`,
|
|
5887
|
-
`Child task status lifecycle: Open \u2192 InProgress \u2192 ReviewPR \u2192 ReviewDev \u2192 Complete
|
|
5946
|
+
`Child task status lifecycle: Open \u2192 InProgress \u2192 ReviewPR \u2192 ReviewDev \u2192 Complete.`,
|
|
5947
|
+
`Set child ordering with \`dependsOn\` (sibling ids/slugs) on \`create_subtask\` \u2014 explicit metadata the pack runner schedules off, not order described in plan text. Independent children get none and run in parallel.`
|
|
5888
5948
|
] : [],
|
|
5889
5949
|
``,
|
|
5890
5950
|
`### Autonomous Guidelines:`,
|
|
@@ -7359,6 +7419,7 @@ function buildCommonTools(connection, config) {
|
|
|
7359
7419
|
import { z as z9 } from "zod";
|
|
7360
7420
|
var SP_DESCRIPTION = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
|
|
7361
7421
|
var FOLLOW_PARENT_STATUS_DESCRIPTION = "Child mirrors the parent task's status automatically \u2014 for subtasks that ship on the parent's branch/PR with no build or PR of their own. Manual status writes on a follower stick only until the parent's next transition.";
|
|
7422
|
+
var DEPENDS_ON_DESCRIPTION = "Sibling subtask ids or slugs this subtask blocks on (it won't start until they merge to dev). Set explicit dependency metadata here instead of describing order in the plan text \u2014 the pack runner schedules children off these edges. Omit / leave empty for independent children so they run in parallel.";
|
|
7362
7423
|
function buildUpdateTaskTool(connection) {
|
|
7363
7424
|
return defineTool(
|
|
7364
7425
|
"update_task_plan",
|
|
@@ -7391,9 +7452,18 @@ function buildCreateSubtaskTool(connection) {
|
|
|
7391
7452
|
plan: z9.string().optional().describe("Implementation plan in markdown"),
|
|
7392
7453
|
ordinal: z9.number().optional().describe("Step/order number (0-based)"),
|
|
7393
7454
|
storyPointValue: z9.number().optional().describe(SP_DESCRIPTION),
|
|
7394
|
-
followParentStatus: z9.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION)
|
|
7455
|
+
followParentStatus: z9.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION),
|
|
7456
|
+
dependsOn: z9.array(z9.string()).optional().describe(DEPENDS_ON_DESCRIPTION)
|
|
7395
7457
|
},
|
|
7396
|
-
async ({
|
|
7458
|
+
async ({
|
|
7459
|
+
title,
|
|
7460
|
+
description,
|
|
7461
|
+
plan,
|
|
7462
|
+
ordinal,
|
|
7463
|
+
storyPointValue,
|
|
7464
|
+
followParentStatus,
|
|
7465
|
+
dependsOn
|
|
7466
|
+
}) => {
|
|
7397
7467
|
try {
|
|
7398
7468
|
const result = await connection.call("createSubtask", {
|
|
7399
7469
|
sessionId: connection.sessionId,
|
|
@@ -7402,9 +7472,10 @@ function buildCreateSubtaskTool(connection) {
|
|
|
7402
7472
|
...plan !== void 0 && { plan },
|
|
7403
7473
|
...storyPointValue !== void 0 && { storyPointValue },
|
|
7404
7474
|
...ordinal !== void 0 && { ordinal },
|
|
7405
|
-
...followParentStatus !== void 0 && { followParentStatus }
|
|
7475
|
+
...followParentStatus !== void 0 && { followParentStatus },
|
|
7476
|
+
...dependsOn !== void 0 && { dependsOn }
|
|
7406
7477
|
});
|
|
7407
|
-
return textResult(`Subtask created with ID: ${result.id}`);
|
|
7478
|
+
return textResult(`Subtask created with ID: ${result.id} (slug: ${result.slug})`);
|
|
7408
7479
|
} catch (error) {
|
|
7409
7480
|
return textResult(
|
|
7410
7481
|
`Failed to create subtask: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -7416,7 +7487,7 @@ function buildCreateSubtaskTool(connection) {
|
|
|
7416
7487
|
function buildUpdateSubtaskTool(connection) {
|
|
7417
7488
|
return defineTool(
|
|
7418
7489
|
"update_subtask",
|
|
7419
|
-
"Update an existing subtask's fields (title, description, plan, ordinal, storyPointValue). Use when refining a child's plan or
|
|
7490
|
+
"Update an existing subtask's fields (title, description, plan, ordinal, storyPointValue, dependsOn). Use when refining a child's plan, reordering, or rewiring dependencies. For the current task use update_task_plan.",
|
|
7420
7491
|
{
|
|
7421
7492
|
subtaskId: z9.string().describe("The subtask ID to update"),
|
|
7422
7493
|
title: z9.string().optional(),
|
|
@@ -7424,9 +7495,20 @@ function buildUpdateSubtaskTool(connection) {
|
|
|
7424
7495
|
plan: z9.string().optional(),
|
|
7425
7496
|
ordinal: z9.number().optional(),
|
|
7426
7497
|
storyPointValue: z9.number().optional().describe(SP_DESCRIPTION),
|
|
7427
|
-
followParentStatus: z9.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION)
|
|
7498
|
+
followParentStatus: z9.boolean().optional().describe(FOLLOW_PARENT_STATUS_DESCRIPTION),
|
|
7499
|
+
dependsOn: z9.array(z9.string()).optional().describe(
|
|
7500
|
+
`${DEPENDS_ON_DESCRIPTION} Replaces the full dependency set \u2014 pass [] to clear all, omit to leave unchanged.`
|
|
7501
|
+
)
|
|
7428
7502
|
},
|
|
7429
|
-
async ({
|
|
7503
|
+
async ({
|
|
7504
|
+
subtaskId,
|
|
7505
|
+
title,
|
|
7506
|
+
description,
|
|
7507
|
+
plan,
|
|
7508
|
+
storyPointValue,
|
|
7509
|
+
followParentStatus,
|
|
7510
|
+
dependsOn
|
|
7511
|
+
}) => {
|
|
7430
7512
|
try {
|
|
7431
7513
|
await connection.call("updateSubtask", {
|
|
7432
7514
|
sessionId: connection.sessionId,
|
|
@@ -7435,7 +7517,8 @@ function buildUpdateSubtaskTool(connection) {
|
|
|
7435
7517
|
...description !== void 0 && { description },
|
|
7436
7518
|
...plan !== void 0 && { plan },
|
|
7437
7519
|
...storyPointValue !== void 0 && { storyPointValue },
|
|
7438
|
-
...followParentStatus !== void 0 && { followParentStatus }
|
|
7520
|
+
...followParentStatus !== void 0 && { followParentStatus },
|
|
7521
|
+
...dependsOn !== void 0 && { dependsOn }
|
|
7439
7522
|
});
|
|
7440
7523
|
return textResult("Subtask updated.");
|
|
7441
7524
|
} catch (error) {
|
|
@@ -8040,9 +8123,17 @@ async function handleResultCase(event, host, context, startTime, isTyping, lastA
|
|
|
8040
8123
|
function hasAskUserQuestionBlock(event) {
|
|
8041
8124
|
return event.message.content.some((b) => b.type === "tool_use" && b.name === "AskUserQuestion");
|
|
8042
8125
|
}
|
|
8043
|
-
|
|
8126
|
+
function questionTextFromEvent(event) {
|
|
8127
|
+
const text = event.questions.map((q) => q.question.trim()).filter((q) => q.length > 0).join("\n");
|
|
8128
|
+
return text.length > 0 ? text : void 0;
|
|
8129
|
+
}
|
|
8130
|
+
async function armQuestionPending(host, state, event) {
|
|
8044
8131
|
state.questionPending = true;
|
|
8045
|
-
await host.connection.emitStatus(
|
|
8132
|
+
await host.connection.emitStatus(
|
|
8133
|
+
"waiting_for_input",
|
|
8134
|
+
AGENT_STATUS_REASON_USER_QUESTION,
|
|
8135
|
+
questionTextFromEvent(event)
|
|
8136
|
+
);
|
|
8046
8137
|
await host.callbacks.onStatusChange("waiting_for_input");
|
|
8047
8138
|
}
|
|
8048
8139
|
async function clearQuestionPending(host, state, options) {
|
|
@@ -8056,7 +8147,7 @@ async function clearQuestionPending(host, state, options) {
|
|
|
8056
8147
|
async function applyQuestionTransitions(event, host, state) {
|
|
8057
8148
|
switch (event.type) {
|
|
8058
8149
|
case "user_question":
|
|
8059
|
-
await armQuestionPending(host, state);
|
|
8150
|
+
await armQuestionPending(host, state, event);
|
|
8060
8151
|
return;
|
|
8061
8152
|
case "assistant":
|
|
8062
8153
|
if (!hasAskUserQuestionBlock(event)) {
|
|
@@ -9493,74 +9584,77 @@ function readAgentVersion() {
|
|
|
9493
9584
|
return null;
|
|
9494
9585
|
}
|
|
9495
9586
|
|
|
9496
|
-
// src/
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
|
|
9503
|
-
|
|
9504
|
-
"seven_day_sonnet"
|
|
9505
|
-
];
|
|
9506
|
-
function normalizeUtilization(raw) {
|
|
9507
|
-
if (typeof raw !== "number" || !Number.isFinite(raw)) return null;
|
|
9508
|
-
const fraction = raw > 1 ? raw / 100 : raw;
|
|
9509
|
-
return Math.max(0, Math.min(1, fraction));
|
|
9510
|
-
}
|
|
9511
|
-
function extractBucket(value) {
|
|
9512
|
-
if (typeof value === "number") {
|
|
9513
|
-
const utilization = normalizeUtilization(value);
|
|
9514
|
-
return utilization === null ? null : { utilization, status: "allowed" };
|
|
9515
|
-
}
|
|
9516
|
-
if (value && typeof value === "object") {
|
|
9517
|
-
const obj = value;
|
|
9518
|
-
const utilization = normalizeUtilization(
|
|
9519
|
-
obj.utilization ?? obj.used ?? obj.percent ?? obj.percentage
|
|
9520
|
-
);
|
|
9521
|
-
if (utilization === null) return null;
|
|
9522
|
-
const status = typeof obj.status === "string" ? obj.status : "allowed";
|
|
9523
|
-
return { utilization, status };
|
|
9524
|
-
}
|
|
9525
|
-
return null;
|
|
9587
|
+
// src/usage/parse-usage.ts
|
|
9588
|
+
function parseUsageGauges(stdout) {
|
|
9589
|
+
const session = stdout.match(/Current session:\s*(\d+(?:\.\d+)?)%\s*used/i);
|
|
9590
|
+
const weekly = [...stdout.matchAll(/Current week[^:\n]*:\s*(\d+(?:\.\d+)?)%\s*used/gi)];
|
|
9591
|
+
return {
|
|
9592
|
+
sessionUsage: session ? Number(session[1]) / 100 : null,
|
|
9593
|
+
weeklyUsage: weekly.length ? Math.max(...weekly.map((m) => Number(m[1]))) / 100 : null
|
|
9594
|
+
};
|
|
9526
9595
|
}
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
|
|
9533
|
-
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
|
|
9537
|
-
|
|
9538
|
-
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
|
|
9596
|
+
|
|
9597
|
+
// src/usage/run-probe.ts
|
|
9598
|
+
import { spawn } from "child_process";
|
|
9599
|
+
var PROBE_TIMEOUT_MS = 15e3;
|
|
9600
|
+
function runUsageProbe(binary = resolveClaudeBinary(), args = ["-p", "/usage"]) {
|
|
9601
|
+
return new Promise((resolve) => {
|
|
9602
|
+
let stdout = "";
|
|
9603
|
+
let settled = false;
|
|
9604
|
+
const finish = (out) => {
|
|
9605
|
+
if (settled) return;
|
|
9606
|
+
settled = true;
|
|
9607
|
+
resolve(out);
|
|
9608
|
+
};
|
|
9609
|
+
let child;
|
|
9610
|
+
try {
|
|
9611
|
+
child = spawn(binary, args, { stdio: ["ignore", "pipe", "ignore"] });
|
|
9612
|
+
} catch {
|
|
9613
|
+
finish("");
|
|
9614
|
+
return;
|
|
9542
9615
|
}
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9616
|
+
const timer = setTimeout(() => {
|
|
9617
|
+
try {
|
|
9618
|
+
child.kill("SIGKILL");
|
|
9619
|
+
} catch {
|
|
9620
|
+
}
|
|
9621
|
+
finish("");
|
|
9622
|
+
}, PROBE_TIMEOUT_MS);
|
|
9623
|
+
timer.unref?.();
|
|
9624
|
+
child.stdout?.on("data", (d) => {
|
|
9625
|
+
stdout += d.toString();
|
|
9626
|
+
});
|
|
9627
|
+
child.on("error", () => {
|
|
9628
|
+
clearTimeout(timer);
|
|
9629
|
+
finish("");
|
|
9630
|
+
});
|
|
9631
|
+
child.on("close", (code) => {
|
|
9632
|
+
clearTimeout(timer);
|
|
9633
|
+
finish(code === 0 ? stdout : "");
|
|
9634
|
+
});
|
|
9635
|
+
});
|
|
9546
9636
|
}
|
|
9547
|
-
|
|
9637
|
+
|
|
9638
|
+
// src/execution/usage-sampler.ts
|
|
9639
|
+
var logger4 = createServiceLogger("usage-sampler");
|
|
9640
|
+
async function sampleKeyUsage(token, probe = runUsageProbe) {
|
|
9548
9641
|
if (!token) return [];
|
|
9549
9642
|
try {
|
|
9550
|
-
const
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
}
|
|
9555
|
-
});
|
|
9556
|
-
if (!res.ok) {
|
|
9557
|
-
logger4.info("OAuth usage endpoint returned non-200", { status: res.status });
|
|
9558
|
-
return [];
|
|
9643
|
+
const stdout = await probe();
|
|
9644
|
+
const { sessionUsage, weeklyUsage } = parseUsageGauges(stdout);
|
|
9645
|
+
const samples = [];
|
|
9646
|
+
if (sessionUsage !== null) {
|
|
9647
|
+
samples.push({ rateLimitType: "five_hour", utilization: sessionUsage, status: "allowed" });
|
|
9559
9648
|
}
|
|
9560
|
-
|
|
9561
|
-
|
|
9649
|
+
if (weeklyUsage !== null) {
|
|
9650
|
+
samples.push({ rateLimitType: "seven_day", utilization: weeklyUsage, status: "allowed" });
|
|
9651
|
+
}
|
|
9652
|
+
if (samples.length === 0) {
|
|
9653
|
+
logger4.info("usage sample produced no gauges", { stdoutLength: stdout.length });
|
|
9654
|
+
}
|
|
9655
|
+
return samples;
|
|
9562
9656
|
} catch (error) {
|
|
9563
|
-
logger4.info("
|
|
9657
|
+
logger4.info("usage sample failed", {
|
|
9564
9658
|
error: error instanceof Error ? error.message : String(error)
|
|
9565
9659
|
});
|
|
9566
9660
|
return [];
|
|
@@ -10080,7 +10174,11 @@ var SessionRunner = class _SessionRunner {
|
|
|
10080
10174
|
const staleBatch = [...this.pendingMessages];
|
|
10081
10175
|
const didExecuteInitialQuery = await this.executeInitialMode();
|
|
10082
10176
|
if (staleBatch.length > 0 && didExecuteInitialQuery) {
|
|
10177
|
+
const historyContents = new Set(
|
|
10178
|
+
(this.fullContext?.chatHistory ?? []).filter((m) => m.role !== "assistant" && m.content.trim()).map((m) => m.content.trim())
|
|
10179
|
+
);
|
|
10083
10180
|
for (const stale of staleBatch) {
|
|
10181
|
+
if (stale.content.trim() && !historyContents.has(stale.content.trim())) continue;
|
|
10084
10182
|
const idx = this.pendingMessages.indexOf(stale);
|
|
10085
10183
|
if (idx !== -1) this.pendingMessages.splice(idx, 1);
|
|
10086
10184
|
}
|
|
@@ -10437,8 +10535,8 @@ var SessionRunner = class _SessionRunner {
|
|
|
10437
10535
|
this.periodicFlushInFlight = false;
|
|
10438
10536
|
}
|
|
10439
10537
|
}
|
|
10440
|
-
/** Sample the running Claude subscription key's rate-limit utilization from
|
|
10441
|
-
*
|
|
10538
|
+
/** Sample the running Claude subscription key's rate-limit utilization from
|
|
10539
|
+
* the Claude CLI `/usage` command and report it as `rate_limit_update` events.
|
|
10442
10540
|
* The API (`persistRateLimitSnapshot`) attributes them to the key this session
|
|
10443
10541
|
* launched under, keeping User Settings + the PtY-tab usage widget fresh and
|
|
10444
10542
|
* `selectBestKey` rotation honest. Best-effort — never throws, no-op when the
|
|
@@ -10933,10 +11031,10 @@ function loadConveyorConfig() {
|
|
|
10933
11031
|
}
|
|
10934
11032
|
|
|
10935
11033
|
// src/setup/commands.ts
|
|
10936
|
-
import { spawn, execSync } from "child_process";
|
|
11034
|
+
import { spawn as spawn2, execSync } from "child_process";
|
|
10937
11035
|
function runSetupCommand(cmd, cwd, onOutput) {
|
|
10938
11036
|
return new Promise((resolve, reject) => {
|
|
10939
|
-
const child =
|
|
11037
|
+
const child = spawn2("sh", ["-c", cmd], {
|
|
10940
11038
|
cwd,
|
|
10941
11039
|
stdio: ["ignore", "pipe", "pipe"],
|
|
10942
11040
|
env: { ...process.env }
|
|
@@ -10975,7 +11073,7 @@ function runAuthTokenCommand(cmd, userEmail, cwd) {
|
|
|
10975
11073
|
}
|
|
10976
11074
|
}
|
|
10977
11075
|
function runStartCommand(cmd, cwd, onOutput) {
|
|
10978
|
-
const child =
|
|
11076
|
+
const child = spawn2("sh", ["-c", cmd], {
|
|
10979
11077
|
cwd,
|
|
10980
11078
|
stdio: ["ignore", "pipe", "pipe"],
|
|
10981
11079
|
detached: true,
|
|
@@ -11013,6 +11111,7 @@ export {
|
|
|
11013
11111
|
DEFAULT_LIFECYCLE_CONFIG,
|
|
11014
11112
|
Lifecycle,
|
|
11015
11113
|
cleanTerminalOutput,
|
|
11114
|
+
loadPtySpawn,
|
|
11016
11115
|
inheritedEnv,
|
|
11017
11116
|
buildPromptBytes,
|
|
11018
11117
|
ClaudeTuiAdapter,
|
|
@@ -11046,4 +11145,4 @@ export {
|
|
|
11046
11145
|
runStartCommand,
|
|
11047
11146
|
unshallowRepo
|
|
11048
11147
|
};
|
|
11049
|
-
//# sourceMappingURL=chunk-
|
|
11148
|
+
//# sourceMappingURL=chunk-MSDYMAG3.js.map
|