flavor-code 1.4.0-beta.4 → 1.4.0-beta.5
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/{app-UWIEIWBQ.js → app-SXNJDSI2.js} +2 -2
- package/dist/{chunk-DCNUBQCH.js → chunk-J7TLT6LR.js} +313 -134
- package/dist/{chunk-4RR5VVX4.js → chunk-JZVC4477.js} +1 -1
- package/dist/{chunk-LKQTBL3R.js → chunk-N5MXHJKD.js} +1 -1
- package/dist/cli-main.js +4 -4
- package/dist/cli.js +28 -6
- package/dist/desktop/main.js +313 -134
- package/dist/desktop-renderer/assets/index-nR67Z0XT.js +154 -0
- package/dist/desktop-renderer/assets/{interactive-terminal-BJqe96mZ.js → interactive-terminal-D2J4feTJ.js} +1 -1
- package/dist/desktop-renderer/index.html +1 -1
- package/dist/goal/orchestrator.d.ts +5 -2
- package/dist/goal/types.d.ts +6 -0
- package/dist/loop/orchestrator.d.ts +2 -0
- package/dist/loop/verifier.d.ts +2 -0
- package/dist/sdk/index.js +3 -3
- package/dist/ui/session.d.ts +2 -0
- package/dist/ui/transcript.d.ts +9 -0
- package/dist/utils/abort.d.ts +16 -0
- package/dist/utils/memory-restart.d.ts +5 -1
- package/package.json +1 -1
- package/dist/desktop-renderer/assets/index-C0t1nGih.js +0 -154
package/dist/desktop/main.js
CHANGED
|
@@ -5628,10 +5628,6 @@ var ContextManager = class _ContextManager {
|
|
|
5628
5628
|
}
|
|
5629
5629
|
return microcompact.changed;
|
|
5630
5630
|
}
|
|
5631
|
-
if (this.#consecutiveAutoCompactFailures >= 3) {
|
|
5632
|
-
rollbackMicrocompact();
|
|
5633
|
-
return false;
|
|
5634
|
-
}
|
|
5635
5631
|
try {
|
|
5636
5632
|
const compacted = await this.#compactConversation(signal);
|
|
5637
5633
|
if (compacted) {
|
|
@@ -6095,10 +6091,10 @@ function within(root, candidate) {
|
|
|
6095
6091
|
|
|
6096
6092
|
// src/context/summarizer.ts
|
|
6097
6093
|
async function summarizeWithModel(options) {
|
|
6098
|
-
const maxAttempts = options.maxPromptTooLongAttempts ?? 3;
|
|
6099
|
-
if (!Number.isInteger(maxAttempts) || maxAttempts <= 0) throw new Error("maxPromptTooLongAttempts must be positive");
|
|
6100
6094
|
options.signal?.throwIfAborted();
|
|
6101
6095
|
let groups = groupMessagesByApiRound(options.messages);
|
|
6096
|
+
const maxAttempts = options.maxPromptTooLongAttempts ?? Math.max(1, Math.ceil(Math.log2(Math.max(1, groups.length))) + 1);
|
|
6097
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts <= 0) throw new Error("maxPromptTooLongAttempts must be positive");
|
|
6102
6098
|
let lastOverflow;
|
|
6103
6099
|
let progress = 20;
|
|
6104
6100
|
reportProgress(options.onProgress, progress);
|
|
@@ -6139,7 +6135,7 @@ async function summarizeWithModel(options) {
|
|
|
6139
6135
|
if (terminalError.code !== "context_overflow") throw terminalError;
|
|
6140
6136
|
lastOverflow = terminalError;
|
|
6141
6137
|
if (attempt >= maxAttempts || groups.length <= 1) throw terminalError;
|
|
6142
|
-
groups = groups.slice(1);
|
|
6138
|
+
groups = groups.slice(Math.max(1, Math.floor(groups.length / 2)));
|
|
6143
6139
|
}
|
|
6144
6140
|
throw lastOverflow ?? new Error("Compact summary failed");
|
|
6145
6141
|
}
|
|
@@ -11503,7 +11499,7 @@ var MEMORY_RESTART_EXIT_CODE = 75;
|
|
|
11503
11499
|
var MEMORY_RESTART_MARKER_FILE = "memory-restart.json";
|
|
11504
11500
|
var MEMORY_RESTART_WINDOW_MS = 60 * 60 * 1e3;
|
|
11505
11501
|
var MEMORY_RESTART_MIN_GAP_MS = 5 * 60 * 1e3;
|
|
11506
|
-
var MEMORY_RESTART_CONTINUATION_TTL_MS =
|
|
11502
|
+
var MEMORY_RESTART_CONTINUATION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
11507
11503
|
var rotationActive = false;
|
|
11508
11504
|
function markMemoryRotation() {
|
|
11509
11505
|
rotationActive = true;
|
|
@@ -11709,7 +11705,7 @@ function extendBudget(input, dimensions, approvedAt) {
|
|
|
11709
11705
|
return LoopStateSchema.parse({
|
|
11710
11706
|
...state,
|
|
11711
11707
|
updatedAt: approvedAt,
|
|
11712
|
-
budget: { ...state.budget, cycleCheckpoint, tokenCheckpoint, approvals }
|
|
11708
|
+
budget: { ...state.budget, cycleCheckpoint, tokenCheckpoint, approvals: approvals.slice(-64) }
|
|
11713
11709
|
});
|
|
11714
11710
|
}
|
|
11715
11711
|
function rejectBudget(input, terminalReason) {
|
|
@@ -11836,6 +11832,7 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
11836
11832
|
});
|
|
11837
11833
|
let workerError;
|
|
11838
11834
|
let workerMemoryPressure = false;
|
|
11835
|
+
let workerIterationLimit = false;
|
|
11839
11836
|
for await (const event of this.#options.runWorker({
|
|
11840
11837
|
goal,
|
|
11841
11838
|
cycle,
|
|
@@ -11848,8 +11845,9 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
11848
11845
|
cycleOutputTokens += event.outputTokens;
|
|
11849
11846
|
}
|
|
11850
11847
|
if (event.type === "error") {
|
|
11851
|
-
workerError = event.error
|
|
11848
|
+
workerError = event.error;
|
|
11852
11849
|
if (event.error.code === "memory_pressure") workerMemoryPressure = true;
|
|
11850
|
+
if (event.error.code === "iteration_limit") workerIterationLimit = true;
|
|
11853
11851
|
}
|
|
11854
11852
|
if (event.type === "text") workerText = `${workerText}${event.text}`.slice(-16e3);
|
|
11855
11853
|
if (this.#options.hallucinationGuard !== void 0) {
|
|
@@ -11862,7 +11860,8 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
11862
11860
|
yield { type: "worker-event", event };
|
|
11863
11861
|
}
|
|
11864
11862
|
if (workerMemoryPressure) return;
|
|
11865
|
-
if (workerError !== void 0) {
|
|
11863
|
+
if (workerError !== void 0 && !workerIterationLimit && !isResumableWorkerError(workerError)) {
|
|
11864
|
+
const status = workerError.code === "cancelled" ? "cancelled" : "failed";
|
|
11866
11865
|
state = LoopStateSchema.parse({
|
|
11867
11866
|
...state,
|
|
11868
11867
|
budget: {
|
|
@@ -11872,8 +11871,8 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
11872
11871
|
outputTokens: state.budget.outputTokens + cycleOutputTokens
|
|
11873
11872
|
}
|
|
11874
11873
|
});
|
|
11875
|
-
state = await this.#terminal(state,
|
|
11876
|
-
yield { type: "loop-terminal", loopId, status
|
|
11874
|
+
state = await this.#terminal(state, status, workerError.message, now());
|
|
11875
|
+
yield { type: "loop-terminal", loopId, status, reason: workerError.message };
|
|
11877
11876
|
return;
|
|
11878
11877
|
}
|
|
11879
11878
|
state = LoopStateSchema.parse({
|
|
@@ -11916,13 +11915,7 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
11916
11915
|
const report = await this.#options.hallucinationGuard.evaluate(goal, workerText);
|
|
11917
11916
|
await this.#options.onMemoryCheckpoint?.(loopId);
|
|
11918
11917
|
if (memoryRotationActive()) return;
|
|
11919
|
-
|
|
11920
|
-
const guardReason = report.blockingReasons.join("; ") || "Hallucination guard blocked completion.";
|
|
11921
|
-
state = await this.#terminal(state, "failed", guardReason, now());
|
|
11922
|
-
yield { type: "loop-terminal", loopId, status: "failed", reason: guardReason };
|
|
11923
|
-
return;
|
|
11924
|
-
}
|
|
11925
|
-
guardWarnings = report.warnings;
|
|
11918
|
+
guardWarnings = [...report.blockingReasons, ...report.warnings];
|
|
11926
11919
|
} catch {
|
|
11927
11920
|
}
|
|
11928
11921
|
}
|
|
@@ -11944,7 +11937,7 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
11944
11937
|
outputTokens: cycleOutputTokens,
|
|
11945
11938
|
workspaceFingerprint: fingerprint2,
|
|
11946
11939
|
verification: evidence
|
|
11947
|
-
}],
|
|
11940
|
+
}].slice(-64),
|
|
11948
11941
|
pendingCycle: null
|
|
11949
11942
|
});
|
|
11950
11943
|
await this.#options.persistence.save(state);
|
|
@@ -11973,8 +11966,8 @@ ${evidence.summary}`;
|
|
|
11973
11966
|
repeatedFailures = failureSignature === previousFailureSignature ? repeatedFailures + 1 : 1;
|
|
11974
11967
|
previousFailureSignature = failureSignature;
|
|
11975
11968
|
previousVerification = evidence;
|
|
11976
|
-
if (repeatedFailures >=
|
|
11977
|
-
const reason =
|
|
11969
|
+
if (this.#options.maxNoProgressCycles !== void 0 && repeatedFailures >= this.#options.maxNoProgressCycles) {
|
|
11970
|
+
const reason = `The same verification failure repeated ${this.#options.maxNoProgressCycles} times without material workspace progress.`;
|
|
11978
11971
|
state = await this.#terminal(state, "no_progress", reason, now());
|
|
11979
11972
|
yield { type: "loop-terminal", loopId, status: "no_progress", reason };
|
|
11980
11973
|
return;
|
|
@@ -12035,6 +12028,9 @@ ${evidence.summary}`;
|
|
|
12035
12028
|
return state;
|
|
12036
12029
|
}
|
|
12037
12030
|
};
|
|
12031
|
+
function isResumableWorkerError(error) {
|
|
12032
|
+
return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
|
|
12033
|
+
}
|
|
12038
12034
|
function countTrailingFailureSignature(cycles, signature) {
|
|
12039
12035
|
let count = 0;
|
|
12040
12036
|
for (let index = cycles.length - 1; index >= 0; index -= 1) {
|
|
@@ -12523,26 +12519,37 @@ var GoalOrchestrator = class {
|
|
|
12523
12519
|
let plan;
|
|
12524
12520
|
let planPath2;
|
|
12525
12521
|
if (state.plan === null) {
|
|
12526
|
-
|
|
12527
|
-
|
|
12528
|
-
|
|
12529
|
-
|
|
12530
|
-
|
|
12531
|
-
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
|
|
12535
|
-
|
|
12536
|
-
|
|
12537
|
-
|
|
12538
|
-
|
|
12539
|
-
|
|
12540
|
-
|
|
12541
|
-
|
|
12542
|
-
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12522
|
+
let planningAttempt = 0;
|
|
12523
|
+
while (true) {
|
|
12524
|
+
try {
|
|
12525
|
+
signal.throwIfAborted();
|
|
12526
|
+
await memoryCheckpoint();
|
|
12527
|
+
plan = await runPlanner({
|
|
12528
|
+
registry: this.#options.registry,
|
|
12529
|
+
modelId: this.#options.plannerModelId,
|
|
12530
|
+
objective: state.objective,
|
|
12531
|
+
signal,
|
|
12532
|
+
onProgress: memoryCheckpoint
|
|
12533
|
+
});
|
|
12534
|
+
planPath2 = await writePlanFile(workspace, plan);
|
|
12535
|
+
await persistState({ phase: "executing", plan, planPath: planPath2, contractHash: contractHash(state.objective, plan) });
|
|
12536
|
+
yield { type: "goal-plan-created", plan, planPath: planPath2 };
|
|
12537
|
+
break;
|
|
12538
|
+
} catch (error) {
|
|
12539
|
+
if (memoryRotationActive()) return;
|
|
12540
|
+
const normalized = normalizeProviderError(error);
|
|
12541
|
+
if (!isResumableStageError(normalized)) {
|
|
12542
|
+
const reason = `Goal planning failed: ${normalized.message}`;
|
|
12543
|
+
await persistState({ phase: "complete", status: "failed" });
|
|
12544
|
+
yield { type: "goal-plan-failed", reason };
|
|
12545
|
+
yield { type: "goal-failed", reason };
|
|
12546
|
+
return;
|
|
12547
|
+
}
|
|
12548
|
+
planningAttempt += 1;
|
|
12549
|
+
const delayMs = stageRetryDelay(this.#options, planningAttempt);
|
|
12550
|
+
yield { type: "goal-stage-retry", stage: "planning", attempt: planningAttempt, reason: normalized.message, delayMs };
|
|
12551
|
+
await waitForStageRetry(delayMs, signal);
|
|
12552
|
+
}
|
|
12546
12553
|
}
|
|
12547
12554
|
} else {
|
|
12548
12555
|
plan = state.plan;
|
|
@@ -12553,7 +12560,7 @@ var GoalOrchestrator = class {
|
|
|
12553
12560
|
let priorFingerprint = state.gapFingerprint;
|
|
12554
12561
|
let stallStreak = state.stallStreak;
|
|
12555
12562
|
const startRound = resumeStartRound(state);
|
|
12556
|
-
for (let round = startRound; round <= this.#options.maxRounds; round++) {
|
|
12563
|
+
for (let round = startRound; this.#options.maxRounds === void 0 || round <= this.#options.maxRounds; round++) {
|
|
12557
12564
|
signal.throwIfAborted();
|
|
12558
12565
|
await this.#options.onRoundBoundary?.(state.id);
|
|
12559
12566
|
if (memoryRotationActive()) return;
|
|
@@ -12573,6 +12580,7 @@ var GoalOrchestrator = class {
|
|
|
12573
12580
|
yield { type: "goal-worker-start", round };
|
|
12574
12581
|
let workerError;
|
|
12575
12582
|
let workerMemoryPressure = false;
|
|
12583
|
+
let workerIterationLimit = false;
|
|
12576
12584
|
try {
|
|
12577
12585
|
for await (const event of this.#options.runWorker({
|
|
12578
12586
|
goal: state.objective,
|
|
@@ -12585,18 +12593,19 @@ var GoalOrchestrator = class {
|
|
|
12585
12593
|
yield { type: "goal-worker-event", round, event };
|
|
12586
12594
|
if (event.type === "text") finalResponse = `${finalResponse}${event.text}`.slice(-16e3);
|
|
12587
12595
|
if (event.type === "error") {
|
|
12588
|
-
workerError = event.error
|
|
12596
|
+
workerError = event.error;
|
|
12589
12597
|
if (event.error.code === "memory_pressure") workerMemoryPressure = true;
|
|
12598
|
+
if (event.error.code === "iteration_limit") workerIterationLimit = true;
|
|
12590
12599
|
break;
|
|
12591
12600
|
}
|
|
12592
12601
|
}
|
|
12593
12602
|
} catch (error) {
|
|
12594
12603
|
if (memoryRotationActive()) return;
|
|
12595
|
-
workerError = message(error);
|
|
12604
|
+
workerError = { code: "unknown", message: message(error) };
|
|
12596
12605
|
}
|
|
12597
12606
|
if (workerMemoryPressure) return;
|
|
12598
|
-
if (workerError !== void 0) {
|
|
12599
|
-
const reason = `Worker error in round ${round}: ${workerError}`;
|
|
12607
|
+
if (workerError !== void 0 && !workerIterationLimit && !isResumableWorkerError2(workerError)) {
|
|
12608
|
+
const reason = `Worker error in round ${round}: ${workerError.message}`;
|
|
12600
12609
|
await persistState({ phase: "complete", status: "failed" });
|
|
12601
12610
|
yield { type: "goal-failed", reason };
|
|
12602
12611
|
return;
|
|
@@ -12626,7 +12635,7 @@ var GoalOrchestrator = class {
|
|
|
12626
12635
|
round,
|
|
12627
12636
|
workspaceDiffHash: evidence.workspaceDiffHash,
|
|
12628
12637
|
...hostVerification === void 0 ? {} : { hostVerification }
|
|
12629
|
-
}] });
|
|
12638
|
+
}].slice(-64) });
|
|
12630
12639
|
let outcome;
|
|
12631
12640
|
if (plan.kind === "code-change" && hostVerification !== void 0 && !hostVerification.passed) {
|
|
12632
12641
|
if (hostVerification.commands.length === 0) {
|
|
@@ -12640,21 +12649,32 @@ var GoalOrchestrator = class {
|
|
|
12640
12649
|
fingerprint: createHash11("sha256").update(hostVerification.summary).digest("hex").slice(0, 16)
|
|
12641
12650
|
};
|
|
12642
12651
|
}
|
|
12643
|
-
} else
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12654
|
-
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12652
|
+
} else {
|
|
12653
|
+
let classifierAttempt = 0;
|
|
12654
|
+
while (true) {
|
|
12655
|
+
try {
|
|
12656
|
+
outcome = await runClassifier(evidence, plan, {
|
|
12657
|
+
registry: this.#options.registry,
|
|
12658
|
+
modelId: this.#options.classifierModelId,
|
|
12659
|
+
skepticCount: this.#options.skepticCount,
|
|
12660
|
+
workspace,
|
|
12661
|
+
signal,
|
|
12662
|
+
onProgress: memoryCheckpoint
|
|
12663
|
+
});
|
|
12664
|
+
break;
|
|
12665
|
+
} catch (error) {
|
|
12666
|
+
if (memoryRotationActive()) return;
|
|
12667
|
+
const normalized = normalizeProviderError(error);
|
|
12668
|
+
if (!isResumableStageError(normalized)) {
|
|
12669
|
+
outcome = { type: "blocked", reason: `Classifier infrastructure error: ${normalized.message}` };
|
|
12670
|
+
break;
|
|
12671
|
+
}
|
|
12672
|
+
classifierAttempt += 1;
|
|
12673
|
+
const delayMs = stageRetryDelay(this.#options, classifierAttempt);
|
|
12674
|
+
yield { type: "goal-stage-retry", stage: "classification", attempt: classifierAttempt, reason: normalized.message, delayMs };
|
|
12675
|
+
await waitForStageRetry(delayMs, signal);
|
|
12676
|
+
}
|
|
12677
|
+
}
|
|
12658
12678
|
}
|
|
12659
12679
|
await persistState({ verifyRounds: round, pendingVerification: null });
|
|
12660
12680
|
yield {
|
|
@@ -12676,7 +12696,7 @@ var GoalOrchestrator = class {
|
|
|
12676
12696
|
}
|
|
12677
12697
|
if (outcome.fingerprint === priorFingerprint) {
|
|
12678
12698
|
stallStreak++;
|
|
12679
|
-
if (stallStreak >= this.#options.maxStallStreak) {
|
|
12699
|
+
if (this.#options.maxStallStreak !== void 0 && stallStreak >= this.#options.maxStallStreak) {
|
|
12680
12700
|
await persistState({
|
|
12681
12701
|
phase: "complete",
|
|
12682
12702
|
status: "failed",
|
|
@@ -12722,6 +12742,31 @@ function resumeStartRound(state) {
|
|
|
12722
12742
|
}
|
|
12723
12743
|
return state.verifyRounds >= state.workerRounds ? state.workerRounds + 1 : Math.max(state.workerRounds, 1);
|
|
12724
12744
|
}
|
|
12745
|
+
function isResumableWorkerError2(error) {
|
|
12746
|
+
return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
|
|
12747
|
+
}
|
|
12748
|
+
function isResumableStageError(error) {
|
|
12749
|
+
return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
|
|
12750
|
+
}
|
|
12751
|
+
function stageRetryDelay(options, attempt) {
|
|
12752
|
+
const delayMs = options.stageRetryDelayMs?.(attempt) ?? Math.min(6e4, 1e3 * 2 ** Math.min(attempt - 1, 6));
|
|
12753
|
+
return Number.isSafeInteger(delayMs) && delayMs >= 0 ? delayMs : 1e3;
|
|
12754
|
+
}
|
|
12755
|
+
function waitForStageRetry(delayMs, signal) {
|
|
12756
|
+
signal.throwIfAborted();
|
|
12757
|
+
if (delayMs === 0) return Promise.resolve();
|
|
12758
|
+
return new Promise((resolvePromise, reject) => {
|
|
12759
|
+
const onAbort = () => {
|
|
12760
|
+
clearTimeout(timer);
|
|
12761
|
+
reject(signal.reason instanceof Error ? signal.reason : new Error("Goal cancelled"));
|
|
12762
|
+
};
|
|
12763
|
+
const timer = setTimeout(() => {
|
|
12764
|
+
signal.removeEventListener("abort", onAbort);
|
|
12765
|
+
resolvePromise();
|
|
12766
|
+
}, delayMs);
|
|
12767
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
12768
|
+
});
|
|
12769
|
+
}
|
|
12725
12770
|
async function writePlanFile(workspace, plan) {
|
|
12726
12771
|
const dir = join16(workspace, ".flavor");
|
|
12727
12772
|
const planPath2 = join16(dir, "goal-plan.md");
|
|
@@ -13868,6 +13913,7 @@ function incompleteUtf8SuffixLength(buffer) {
|
|
|
13868
13913
|
|
|
13869
13914
|
// src/loop/verifier.ts
|
|
13870
13915
|
var SCRIPT_PRIORITY = ["test", "typecheck", "lint", "build", "smoke:install"];
|
|
13916
|
+
var MAX_PERSISTED_VERIFICATION_STREAM_BYTES = 1024;
|
|
13871
13917
|
async function inferVerificationPlan(workspace) {
|
|
13872
13918
|
const commands = [];
|
|
13873
13919
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -13903,9 +13949,9 @@ async function runVerificationPlan(plan, workspace, signal, executionEnvironment
|
|
|
13903
13949
|
command: item.command,
|
|
13904
13950
|
args: item.args,
|
|
13905
13951
|
exitCode: result.exitCode,
|
|
13906
|
-
stdout: result.stdout,
|
|
13907
|
-
stderr: result.stderr,
|
|
13908
|
-
truncated: result.truncated
|
|
13952
|
+
stdout: boundedEvidenceTail(result.stdout),
|
|
13953
|
+
stderr: boundedEvidenceTail(result.stderr),
|
|
13954
|
+
truncated: result.truncated || Buffer.byteLength(result.stdout, "utf8") > MAX_PERSISTED_VERIFICATION_STREAM_BYTES || Buffer.byteLength(result.stderr, "utf8") > MAX_PERSISTED_VERIFICATION_STREAM_BYTES
|
|
13909
13955
|
});
|
|
13910
13956
|
if (result.exitCode !== 0) {
|
|
13911
13957
|
return { passed: false, commands, summary: `${item.label} failed with exit code ${String(result.exitCode)}.` };
|
|
@@ -13913,6 +13959,14 @@ async function runVerificationPlan(plan, workspace, signal, executionEnvironment
|
|
|
13913
13959
|
}
|
|
13914
13960
|
return { passed: true, commands, summary: `Passed ${commands.length} deterministic verification command(s).` };
|
|
13915
13961
|
}
|
|
13962
|
+
function boundedEvidenceTail(value) {
|
|
13963
|
+
const encoded = Buffer.from(value, "utf8");
|
|
13964
|
+
if (encoded.byteLength <= MAX_PERSISTED_VERIFICATION_STREAM_BYTES) return value;
|
|
13965
|
+
const prefix = Buffer.from("\u2026\n", "utf8");
|
|
13966
|
+
let start = encoded.byteLength - (MAX_PERSISTED_VERIFICATION_STREAM_BYTES - prefix.byteLength);
|
|
13967
|
+
while (start < encoded.byteLength && (encoded[start] & 192) === 128) start += 1;
|
|
13968
|
+
return `${prefix.toString("utf8")}${encoded.subarray(start).toString("utf8")}`;
|
|
13969
|
+
}
|
|
13916
13970
|
function npmScript(name) {
|
|
13917
13971
|
return name === "test" ? { label: name, command: "npm", args: ["test"] } : { label: name, command: "npm", args: ["run", name] };
|
|
13918
13972
|
}
|
|
@@ -14071,6 +14125,35 @@ var AuditLogger = class {
|
|
|
14071
14125
|
}
|
|
14072
14126
|
};
|
|
14073
14127
|
|
|
14128
|
+
// src/utils/abort.ts
|
|
14129
|
+
function waitWithSignal(operation, signal) {
|
|
14130
|
+
if (signal === void 0) return operation;
|
|
14131
|
+
return new Promise((resolve44, reject) => {
|
|
14132
|
+
const abort2 = () => reject(signal.reason);
|
|
14133
|
+
if (signal.aborted) abort2();
|
|
14134
|
+
else signal.addEventListener("abort", abort2, { once: true });
|
|
14135
|
+
operation.then(resolve44, reject).finally(() => signal.removeEventListener("abort", abort2));
|
|
14136
|
+
});
|
|
14137
|
+
}
|
|
14138
|
+
function createScopedAbortSignal(parent) {
|
|
14139
|
+
const controller2 = new AbortController();
|
|
14140
|
+
let disposed = false;
|
|
14141
|
+
const abort2 = () => {
|
|
14142
|
+
if (!controller2.signal.aborted) controller2.abort(parent?.reason);
|
|
14143
|
+
};
|
|
14144
|
+
if (parent?.aborted) abort2();
|
|
14145
|
+
else parent?.addEventListener("abort", abort2, { once: true });
|
|
14146
|
+
return {
|
|
14147
|
+
signal: controller2.signal,
|
|
14148
|
+
dispose: () => {
|
|
14149
|
+
if (disposed) return;
|
|
14150
|
+
disposed = true;
|
|
14151
|
+
parent?.removeEventListener("abort", abort2);
|
|
14152
|
+
abort2();
|
|
14153
|
+
}
|
|
14154
|
+
};
|
|
14155
|
+
}
|
|
14156
|
+
|
|
14074
14157
|
// src/models/anthropic.ts
|
|
14075
14158
|
var CLAUDE_CLIENT_HEADERS = {
|
|
14076
14159
|
"User-Agent": "claude-cli/2.1.0 (external, cli)",
|
|
@@ -14193,6 +14276,7 @@ var AnthropicModelAdapter = class {
|
|
|
14193
14276
|
void appendUsageLog(line);
|
|
14194
14277
|
}
|
|
14195
14278
|
async *stream(request) {
|
|
14279
|
+
const requestAbort = createScopedAbortSignal(request.signal);
|
|
14196
14280
|
let inputTokens = 0;
|
|
14197
14281
|
let outputTokens = 0;
|
|
14198
14282
|
let hasUsage = false;
|
|
@@ -14316,13 +14400,13 @@ var AnthropicModelAdapter = class {
|
|
|
14316
14400
|
};
|
|
14317
14401
|
let stream;
|
|
14318
14402
|
try {
|
|
14319
|
-
stream = await this.client.messages.create(body, { signal:
|
|
14403
|
+
stream = await this.client.messages.create(body, { signal: requestAbort.signal });
|
|
14320
14404
|
} catch (error) {
|
|
14321
14405
|
if (this.thinkingBudget > 0 && !this.#thinkingRejected && isThinkingParamRejected(error)) {
|
|
14322
14406
|
this.#thinkingRejected = true;
|
|
14323
14407
|
delete body.thinking;
|
|
14324
14408
|
stripThinkingBlocks(body.messages);
|
|
14325
|
-
stream = await this.client.messages.create(body, { signal:
|
|
14409
|
+
stream = await this.client.messages.create(body, { signal: requestAbort.signal });
|
|
14326
14410
|
} else {
|
|
14327
14411
|
throw error;
|
|
14328
14412
|
}
|
|
@@ -14434,6 +14518,8 @@ var AnthropicModelAdapter = class {
|
|
|
14434
14518
|
};
|
|
14435
14519
|
}
|
|
14436
14520
|
yield { type: "error", error: normalizeProviderError(error) };
|
|
14521
|
+
} finally {
|
|
14522
|
+
requestAbort.dispose();
|
|
14437
14523
|
}
|
|
14438
14524
|
}
|
|
14439
14525
|
};
|
|
@@ -14578,6 +14664,7 @@ var OpenAIModelAdapter = class {
|
|
|
14578
14664
|
void appendUsageLog(line);
|
|
14579
14665
|
}
|
|
14580
14666
|
async *stream(request) {
|
|
14667
|
+
const requestAbort = createScopedAbortSignal(request.signal);
|
|
14581
14668
|
const callIds = /* @__PURE__ */ new Map();
|
|
14582
14669
|
const pendingCalls = /* @__PURE__ */ new Map();
|
|
14583
14670
|
const emittedCalls = /* @__PURE__ */ new Set();
|
|
@@ -14594,7 +14681,7 @@ var OpenAIModelAdapter = class {
|
|
|
14594
14681
|
strict: tool.strict ?? true
|
|
14595
14682
|
}))
|
|
14596
14683
|
};
|
|
14597
|
-
const stream = this.client.responses.stream(body, { signal:
|
|
14684
|
+
const stream = this.client.responses.stream(body, { signal: requestAbort.signal });
|
|
14598
14685
|
for await (const event of stream) {
|
|
14599
14686
|
if (event.type === "response.output_item.added" && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
|
|
14600
14687
|
callIds.set(event.output_index, event.item.call_id);
|
|
@@ -14688,6 +14775,8 @@ var OpenAIModelAdapter = class {
|
|
|
14688
14775
|
}
|
|
14689
14776
|
} catch (error) {
|
|
14690
14777
|
yield { type: "error", error: normalizeProviderError(error) };
|
|
14778
|
+
} finally {
|
|
14779
|
+
requestAbort.dispose();
|
|
14691
14780
|
}
|
|
14692
14781
|
}
|
|
14693
14782
|
};
|
|
@@ -16183,6 +16272,11 @@ function appendThinkingText(previous, delta) {
|
|
|
16183
16272
|
// src/ui/transcript.ts
|
|
16184
16273
|
var MAX_TRANSCRIPT_TURNS = 200;
|
|
16185
16274
|
var MAX_TRANSCRIPT_CHARS = 2e6;
|
|
16275
|
+
var MAX_ACTIVE_TRANSCRIPT_BLOCKS = 160;
|
|
16276
|
+
var MAX_ACTIVE_ASSISTANT_CHARS = 64e3;
|
|
16277
|
+
var MAX_TRANSCRIPT_BLOCK_TEXT_CHARS = 16e3;
|
|
16278
|
+
var MAX_TRANSCRIPT_TOOL_VALUE_CHARS = 16e3;
|
|
16279
|
+
var MAX_TRANSCRIPT_PRESENTATION_CHARS = 32e3;
|
|
16186
16280
|
function createTranscriptState() {
|
|
16187
16281
|
return { completed: [], nextId: 1 };
|
|
16188
16282
|
}
|
|
@@ -16543,11 +16637,9 @@ function applyTaskSnapshot(turn, snapshot4, includeTerminal = true) {
|
|
|
16543
16637
|
else blocks[index] = block;
|
|
16544
16638
|
}
|
|
16545
16639
|
return {
|
|
16546
|
-
...turn,
|
|
16640
|
+
...withBlocks(turn, blocks),
|
|
16547
16641
|
taskSnapshot: snapshot4,
|
|
16548
|
-
suppressedTaskIds: [...suppressed]
|
|
16549
|
-
blocks,
|
|
16550
|
-
statusLines: blocks.filter((block) => block.kind === "status").map((block) => block.text)
|
|
16642
|
+
suppressedTaskIds: [...suppressed]
|
|
16551
16643
|
};
|
|
16552
16644
|
}
|
|
16553
16645
|
function terminalTaskIds(snapshot4) {
|
|
@@ -16561,13 +16653,10 @@ function upsertStatus(state, block) {
|
|
|
16561
16653
|
if (state.active === void 0) return state;
|
|
16562
16654
|
const blocks = [...state.active.blocks];
|
|
16563
16655
|
const index = blocks.findIndex((item) => item.kind === "status" && item.id === block.id);
|
|
16564
|
-
|
|
16565
|
-
|
|
16566
|
-
|
|
16567
|
-
|
|
16568
|
-
statusLines: blocks.filter((item) => item.kind === "status").map((item) => item.text),
|
|
16569
|
-
blocks
|
|
16570
|
-
} };
|
|
16656
|
+
const bounded2 = boundedTranscriptBlock(block);
|
|
16657
|
+
if (index < 0) blocks.push(bounded2);
|
|
16658
|
+
else blocks[index] = bounded2;
|
|
16659
|
+
return { ...state, active: withBlocks(state.active, blocks) };
|
|
16571
16660
|
}
|
|
16572
16661
|
function finishActive(state) {
|
|
16573
16662
|
if (state.active === void 0) return state;
|
|
@@ -16591,16 +16680,12 @@ function attachThinking(turn, text) {
|
|
|
16591
16680
|
...block,
|
|
16592
16681
|
thinkingText: appendThinkingText(block.thinkingText, text)
|
|
16593
16682
|
};
|
|
16594
|
-
return
|
|
16683
|
+
return withBlocks(turn, blocks);
|
|
16595
16684
|
}
|
|
16596
16685
|
function withoutModelActivity(turn, id) {
|
|
16597
16686
|
const blocks = turn.blocks.filter((block) => block.kind !== "status" || block.activity !== "model" || id !== void 0 && block.id !== id);
|
|
16598
16687
|
if (blocks.length === turn.blocks.length) return turn;
|
|
16599
|
-
return
|
|
16600
|
-
...turn,
|
|
16601
|
-
blocks,
|
|
16602
|
-
statusLines: blocks.filter((block) => block.kind === "status").map((block) => block.text)
|
|
16603
|
-
};
|
|
16688
|
+
return withBlocks(turn, blocks);
|
|
16604
16689
|
}
|
|
16605
16690
|
function restoreTranscriptState(state) {
|
|
16606
16691
|
const completed = state.completed.map(cloneTurn);
|
|
@@ -16702,15 +16787,18 @@ function cloneTurn(turn) {
|
|
|
16702
16787
|
function upsertTurnStatus(turn, block) {
|
|
16703
16788
|
const blocks = [...turn.blocks];
|
|
16704
16789
|
const index = blocks.findIndex((item) => item.kind === "status" && item.id === block.id);
|
|
16705
|
-
|
|
16706
|
-
|
|
16790
|
+
const bounded2 = boundedTranscriptBlock(block);
|
|
16791
|
+
if (index < 0) blocks.push(bounded2);
|
|
16792
|
+
else blocks[index] = bounded2;
|
|
16707
16793
|
return withBlocks(turn, blocks);
|
|
16708
16794
|
}
|
|
16709
16795
|
function withBlocks(turn, blocks) {
|
|
16796
|
+
const bounded2 = blocks.length <= MAX_ACTIVE_TRANSCRIPT_BLOCKS ? blocks : blocks.slice(-MAX_ACTIVE_TRANSCRIPT_BLOCKS);
|
|
16710
16797
|
return {
|
|
16711
16798
|
...turn,
|
|
16712
|
-
|
|
16713
|
-
|
|
16799
|
+
assistantText: tailText(turn.assistantText, MAX_ACTIVE_ASSISTANT_CHARS),
|
|
16800
|
+
blocks: bounded2,
|
|
16801
|
+
statusLines: bounded2.filter((block) => block.kind === "status").map((block) => block.text)
|
|
16714
16802
|
};
|
|
16715
16803
|
}
|
|
16716
16804
|
function appendLine(text, line) {
|
|
@@ -16724,19 +16812,95 @@ function stripRetryBlocks(turn) {
|
|
|
16724
16812
|
if (block.id.startsWith("structured-retry:")) return false;
|
|
16725
16813
|
return true;
|
|
16726
16814
|
});
|
|
16727
|
-
return
|
|
16728
|
-
...turn,
|
|
16729
|
-
blocks,
|
|
16730
|
-
statusLines: blocks.filter((item) => item.kind === "status").map((item) => item.text)
|
|
16731
|
-
};
|
|
16815
|
+
return withBlocks(turn, blocks);
|
|
16732
16816
|
}
|
|
16733
16817
|
function addText(turn, text, onNewLine = false) {
|
|
16734
|
-
const assistantText =
|
|
16818
|
+
const assistantText = tailText(
|
|
16819
|
+
onNewLine ? appendLine(turn.assistantText, text) : turn.assistantText + text,
|
|
16820
|
+
MAX_ACTIVE_ASSISTANT_CHARS
|
|
16821
|
+
);
|
|
16735
16822
|
const blocks = [...turn.blocks];
|
|
16736
16823
|
const last = blocks[blocks.length - 1];
|
|
16737
|
-
if (!onNewLine && last?.kind === "text")
|
|
16738
|
-
|
|
16739
|
-
|
|
16824
|
+
if (!onNewLine && last?.kind === "text") {
|
|
16825
|
+
blocks[blocks.length - 1] = { kind: "text", text: tailText(last.text + text, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS) };
|
|
16826
|
+
} else {
|
|
16827
|
+
blocks.push({ kind: "text", text: tailText(text, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS) });
|
|
16828
|
+
}
|
|
16829
|
+
return withBlocks({ ...turn, assistantText }, blocks);
|
|
16830
|
+
}
|
|
16831
|
+
function boundedTranscriptBlock(block) {
|
|
16832
|
+
const presentation = block.presentation === void 0 ? void 0 : boundedTranscriptPresentation(block.presentation);
|
|
16833
|
+
const tool = block.tool === void 0 ? void 0 : {
|
|
16834
|
+
name: block.tool.name,
|
|
16835
|
+
input: boundedTranscriptValue(block.tool.input),
|
|
16836
|
+
...block.tool.result === void 0 ? {} : {
|
|
16837
|
+
result: {
|
|
16838
|
+
ok: block.tool.result.ok,
|
|
16839
|
+
...block.tool.result.output === void 0 ? {} : { output: boundedTranscriptValue(block.tool.result.output) },
|
|
16840
|
+
...block.tool.result.content === void 0 ? {} : {
|
|
16841
|
+
content: tailText(block.tool.result.content, MAX_TRANSCRIPT_TOOL_VALUE_CHARS)
|
|
16842
|
+
},
|
|
16843
|
+
...block.tool.result.presentation === void 0 ? {} : {
|
|
16844
|
+
presentation: boundedTranscriptPresentation(block.tool.result.presentation)
|
|
16845
|
+
},
|
|
16846
|
+
...block.tool.result.additionalContext === void 0 ? {} : {
|
|
16847
|
+
additionalContext: block.tool.result.additionalContext.slice(-20).map((item) => tailText(item, MAX_TRANSCRIPT_TOOL_VALUE_CHARS))
|
|
16848
|
+
},
|
|
16849
|
+
...block.tool.result.error === void 0 ? {} : { error: {
|
|
16850
|
+
code: block.tool.result.error.code,
|
|
16851
|
+
message: tailText(block.tool.result.error.message, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS)
|
|
16852
|
+
} }
|
|
16853
|
+
}
|
|
16854
|
+
}
|
|
16855
|
+
};
|
|
16856
|
+
return {
|
|
16857
|
+
...block,
|
|
16858
|
+
text: tailText(block.text, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS),
|
|
16859
|
+
...block.hint === void 0 ? {} : { hint: tailText(block.hint, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS) },
|
|
16860
|
+
...block.details === void 0 ? {} : { details: tailText(block.details, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS) },
|
|
16861
|
+
...presentation === void 0 ? {} : { presentation },
|
|
16862
|
+
...tool === void 0 ? {} : { tool }
|
|
16863
|
+
};
|
|
16864
|
+
}
|
|
16865
|
+
function boundedTranscriptPresentation(presentation) {
|
|
16866
|
+
return jsonSize(presentation) <= MAX_TRANSCRIPT_PRESENTATION_CHARS ? presentation : {
|
|
16867
|
+
kind: "generic",
|
|
16868
|
+
title: "Tool output",
|
|
16869
|
+
summary: "Large presentation omitted from the live transcript; the model-facing result remains available in context."
|
|
16870
|
+
};
|
|
16871
|
+
}
|
|
16872
|
+
function boundedTranscriptValue(value) {
|
|
16873
|
+
const chars = jsonSize(value);
|
|
16874
|
+
if (chars <= MAX_TRANSCRIPT_TOOL_VALUE_CHARS) return value;
|
|
16875
|
+
const record3 = typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
16876
|
+
const summary2 = { truncated: true, originalChars: chars };
|
|
16877
|
+
for (const key of ["path", "command", "id", "name", "exitCode", "bytes", "replacements"]) {
|
|
16878
|
+
const item = record3?.[key];
|
|
16879
|
+
if (typeof item === "string") summary2[key] = tailText(item, 1e3);
|
|
16880
|
+
else if (typeof item === "number" || typeof item === "boolean" || item === null) summary2[key] = item;
|
|
16881
|
+
}
|
|
16882
|
+
return summary2;
|
|
16883
|
+
}
|
|
16884
|
+
function jsonSize(value) {
|
|
16885
|
+
try {
|
|
16886
|
+
return JSON.stringify(value)?.length ?? 0;
|
|
16887
|
+
} catch {
|
|
16888
|
+
return Number.POSITIVE_INFINITY;
|
|
16889
|
+
}
|
|
16890
|
+
}
|
|
16891
|
+
function tailText(text, limit) {
|
|
16892
|
+
if (text.length <= limit) return text;
|
|
16893
|
+
const marker = `\u2026 ${text.length - limit} earlier characters omitted \u2026
|
|
16894
|
+
`;
|
|
16895
|
+
return marker.length >= limit ? text.slice(-limit) : marker + text.slice(-(limit - marker.length));
|
|
16896
|
+
}
|
|
16897
|
+
function transcriptCensus(state) {
|
|
16898
|
+
const turns = [...state.completed, ...state.active === void 0 ? [] : [state.active]];
|
|
16899
|
+
return {
|
|
16900
|
+
turns: turns.length,
|
|
16901
|
+
blocks: turns.reduce((total, turn) => total + turn.blocks.length, 0),
|
|
16902
|
+
chars: jsonSize(state)
|
|
16903
|
+
};
|
|
16740
16904
|
}
|
|
16741
16905
|
|
|
16742
16906
|
// src/session/store.ts
|
|
@@ -19721,19 +19885,6 @@ import { isIP } from "net";
|
|
|
19721
19885
|
import { request as httpRequest } from "http";
|
|
19722
19886
|
import { request as httpsRequest } from "https";
|
|
19723
19887
|
import { z as z31 } from "zod";
|
|
19724
|
-
|
|
19725
|
-
// src/utils/abort.ts
|
|
19726
|
-
function waitWithSignal(operation, signal) {
|
|
19727
|
-
if (signal === void 0) return operation;
|
|
19728
|
-
return new Promise((resolve44, reject) => {
|
|
19729
|
-
const abort2 = () => reject(signal.reason);
|
|
19730
|
-
if (signal.aborted) abort2();
|
|
19731
|
-
else signal.addEventListener("abort", abort2, { once: true });
|
|
19732
|
-
operation.then(resolve44, reject).finally(() => signal.removeEventListener("abort", abort2));
|
|
19733
|
-
});
|
|
19734
|
-
}
|
|
19735
|
-
|
|
19736
|
-
// src/tools/web.ts
|
|
19737
19888
|
var WebFetchInput = z31.object({
|
|
19738
19889
|
url: z31.string().url().max(8192),
|
|
19739
19890
|
timeoutMs: z31.coerce.number().int().positive().max(12e4).optional(),
|
|
@@ -22246,6 +22397,11 @@ var HELP = [
|
|
|
22246
22397
|
"/co-work <pal> <goal> | status [id] | cancel <id> [reason]"
|
|
22247
22398
|
].join("\n");
|
|
22248
22399
|
var MAX_STOP_DENIALS = 2;
|
|
22400
|
+
var RESUMABLE_TURN_BOUNDARIES = /* @__PURE__ */ new Set([
|
|
22401
|
+
"iteration_limit",
|
|
22402
|
+
"output_limit",
|
|
22403
|
+
"context_overflow"
|
|
22404
|
+
]);
|
|
22249
22405
|
var FlavorSession = class {
|
|
22250
22406
|
#services;
|
|
22251
22407
|
#active;
|
|
@@ -22477,6 +22633,7 @@ var FlavorSession = class {
|
|
|
22477
22633
|
if (!initial) this.#outputQueuedSubmission(submission);
|
|
22478
22634
|
initial = false;
|
|
22479
22635
|
await this.#runSubmission(submission);
|
|
22636
|
+
if (this.#services.rotationPending?.() === true) return;
|
|
22480
22637
|
pending2.push(...this.#drainMessages("steer"), ...this.#drainMessages("followUp"));
|
|
22481
22638
|
}
|
|
22482
22639
|
}
|
|
@@ -22500,6 +22657,7 @@ var FlavorSession = class {
|
|
|
22500
22657
|
this.#activeSubmission = submission;
|
|
22501
22658
|
this.#interrupted = false;
|
|
22502
22659
|
let outcome = "completed";
|
|
22660
|
+
let resumableBoundary;
|
|
22503
22661
|
let assistantSummary = "";
|
|
22504
22662
|
let deliverables = [];
|
|
22505
22663
|
try {
|
|
@@ -22536,7 +22694,10 @@ var FlavorSession = class {
|
|
|
22536
22694
|
this.#services.output(event);
|
|
22537
22695
|
if (event.type === "text") assistantSummary = `${assistantSummary}${event.text}`.slice(-2e3);
|
|
22538
22696
|
if (event.type === "deliverables") deliverables = event.files.slice(0, 100);
|
|
22539
|
-
if (event.type === "error")
|
|
22697
|
+
if (event.type === "error") {
|
|
22698
|
+
outcome = "failed";
|
|
22699
|
+
if (RESUMABLE_TURN_BOUNDARIES.has(event.error.code)) resumableBoundary = event.error.code;
|
|
22700
|
+
}
|
|
22540
22701
|
}
|
|
22541
22702
|
if (controller2.signal.aborted) outcome = "cancelled";
|
|
22542
22703
|
} catch (error) {
|
|
@@ -22577,6 +22738,13 @@ var FlavorSession = class {
|
|
|
22577
22738
|
}
|
|
22578
22739
|
}
|
|
22579
22740
|
try {
|
|
22741
|
+
if (resumableBoundary !== void 0 && !this.#closed && !controller2.signal.aborted) {
|
|
22742
|
+
const attempt = (submission.iterationContinuation ?? 0) + 1;
|
|
22743
|
+
const text = `[automatic continuation after ${resumableBoundary} boundary; segment ${attempt}]
|
|
22744
|
+
Continue the unfinished task from the current conversation and workspace state. Do not repeat completed operations. Inspect existing results, finish the remaining work, and verify it before stopping.`;
|
|
22745
|
+
this.#enqueueMessage("followUp", { text, displayText: text, iterationContinuation: attempt });
|
|
22746
|
+
this.#notice(`Agent ${resumableBoundary} boundary reached; durable continuation ${attempt} queued.`);
|
|
22747
|
+
}
|
|
22580
22748
|
if (stopDecision?.decision === "deny" && typeof stopDecision.reason === "string" && stopDecision.reason.length > 0 && !this.#closed && outcome !== "cancelled" && outcome !== "denied") {
|
|
22581
22749
|
if (this.#stopDenials < MAX_STOP_DENIALS) {
|
|
22582
22750
|
this.#stopDenials += 1;
|
|
@@ -22773,7 +22941,7 @@ Address this now (for example run the required verification or fix), then finish
|
|
|
22773
22941
|
});
|
|
22774
22942
|
}
|
|
22775
22943
|
#resumeDurableQueue() {
|
|
22776
|
-
if (this.#durableResumeStarted || this.#closed || this.active || this.#pendingSubmissions > 0) return;
|
|
22944
|
+
if (this.#durableResumeStarted || this.#closed || this.active || this.#pendingSubmissions > 0 || this.#services.rotationPending?.() === true) return;
|
|
22777
22945
|
if (!this.#queue.hasPending) return;
|
|
22778
22946
|
this.#durableResumeStarted = true;
|
|
22779
22947
|
const submissions = [...this.#drainMessages("steer"), ...this.#drainMessages("followUp")];
|
|
@@ -22924,6 +23092,7 @@ function recoveredSubmission(value) {
|
|
|
22924
23092
|
if (typeof input.text !== "string" || input.text.trim().length === 0) return void 0;
|
|
22925
23093
|
if (typeof input.displayText !== "string") return void 0;
|
|
22926
23094
|
if (input.controlOnly !== void 0 && typeof input.controlOnly !== "boolean") return void 0;
|
|
23095
|
+
if (input.iterationContinuation !== void 0 && (!Number.isSafeInteger(input.iterationContinuation) || input.iterationContinuation < 1)) return void 0;
|
|
22927
23096
|
if (input.coWorkPlanningKey !== void 0 && typeof input.coWorkPlanningKey !== "string") return void 0;
|
|
22928
23097
|
if (input.remoteOrigin !== void 0) {
|
|
22929
23098
|
const origin = input.remoteOrigin;
|
|
@@ -27701,6 +27870,12 @@ async function createProductionRuntime(options) {
|
|
|
27701
27870
|
holders.sessionTree = { entries: sessionHistory.nodeCount };
|
|
27702
27871
|
} catch {
|
|
27703
27872
|
}
|
|
27873
|
+
try {
|
|
27874
|
+
const transcript = transcriptCensus(timelineState);
|
|
27875
|
+
holders.transcript = { entries: transcript.blocks, chars: transcript.chars };
|
|
27876
|
+
holders.transcriptTurns = { entries: transcript.turns };
|
|
27877
|
+
} catch {
|
|
27878
|
+
}
|
|
27704
27879
|
return holders;
|
|
27705
27880
|
};
|
|
27706
27881
|
const rotateForHeap = (continuation, reading) => {
|
|
@@ -27758,21 +27933,9 @@ async function createProductionRuntime(options) {
|
|
|
27758
27933
|
await verifierEnvironment?.dispose();
|
|
27759
27934
|
}
|
|
27760
27935
|
},
|
|
27761
|
-
|
|
27762
|
-
|
|
27763
|
-
|
|
27764
|
-
const next = dimensions.map((dimension) => dimension === "cycles" ? `${state.budget.cycleCheckpoint + state.config.cycleStep} cycles` : `${state.budget.tokenCheckpoint + state.config.tokenStep} tokens`).join(" and ");
|
|
27765
|
-
const latestVerification = state.cycles.at(-1)?.verification.summary ?? "No host verification evidence yet.";
|
|
27766
|
-
const answers = await questions.ask([{
|
|
27767
|
-
header: "Loop budget",
|
|
27768
|
-
question: `Loop ${state.loopId} reached ${reached}. Latest verification: ${latestVerification} Continue until the next checkpoint (${next})?`,
|
|
27769
|
-
options: [
|
|
27770
|
-
{ label: "Continue", description: "Extend only the reached budget tranche and keep looping." },
|
|
27771
|
-
{ label: "Stop", description: "End this loop as budget exhausted." }
|
|
27772
|
-
]
|
|
27773
|
-
}], signal);
|
|
27774
|
-
return answers[0] === "Continue" ? "approved" : "rejected";
|
|
27775
|
-
},
|
|
27936
|
+
// Cycle/token values are telemetry checkpoint cadence, not an unattended
|
|
27937
|
+
// execution cap. The user can still cancel explicitly at any time.
|
|
27938
|
+
confirmBudget: async () => "approved",
|
|
27776
27939
|
fingerprint: workspaceFingerprint,
|
|
27777
27940
|
idFactory: () => `loop-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${randomUUID25().slice(0, 8)}`
|
|
27778
27941
|
});
|
|
@@ -27783,8 +27946,9 @@ async function createProductionRuntime(options) {
|
|
|
27783
27946
|
plannerModelId: mainModel,
|
|
27784
27947
|
classifierModelId: mainModel,
|
|
27785
27948
|
skepticCount: 3,
|
|
27786
|
-
|
|
27787
|
-
|
|
27949
|
+
// Production goals run until verified, explicitly cancelled, or blocked
|
|
27950
|
+
// by a non-recoverable external condition. Numeric config values remain
|
|
27951
|
+
// accepted for compatibility but no longer terminate autonomous work.
|
|
27788
27952
|
persistence: goalStore,
|
|
27789
27953
|
onRoundBoundary: (goalId) => maybeRotateAtBoundary({ kind: "goal", id: goalId }),
|
|
27790
27954
|
onMemoryCheckpoint: (goalId) => maybeRotateAtBoundary({ kind: "goal", id: goalId }),
|
|
@@ -27925,6 +28089,7 @@ async function createProductionRuntime(options) {
|
|
|
27925
28089
|
() => rotateForHeap(activeLongTask ?? { kind: "goal", id: goalId }, currentPressureReading())
|
|
27926
28090
|
),
|
|
27927
28091
|
continuation: () => consumePendingContinuation(),
|
|
28092
|
+
rotationPending: () => memoryRotationActive(),
|
|
27928
28093
|
mcp: async (command, signal) => {
|
|
27929
28094
|
signal.throwIfAborted();
|
|
27930
28095
|
const manager = await mcpReady;
|
|
@@ -28482,6 +28647,8 @@ async function* loopSessionEvents(events, hooks) {
|
|
|
28482
28647
|
totalInputTokens,
|
|
28483
28648
|
totalOutputTokens
|
|
28484
28649
|
};
|
|
28650
|
+
} else if (event.event.type === "error" && isResumableLongTaskError(event.event.error.code)) {
|
|
28651
|
+
yield { type: "warning", message: `Loop worker segment ended at ${event.event.error.code}; checkpointing and verifying before continuing.` };
|
|
28485
28652
|
} else if (event.event.type !== "done") yield event.event;
|
|
28486
28653
|
continue;
|
|
28487
28654
|
}
|
|
@@ -28536,7 +28703,7 @@ function loopProgressEvent(event) {
|
|
|
28536
28703
|
loopId: event.loopId,
|
|
28537
28704
|
phase: "budget",
|
|
28538
28705
|
state: "info",
|
|
28539
|
-
message:
|
|
28706
|
+
message: `${event.dimensions.join(" and ")} checkpoint reached; continuing automatically.`
|
|
28540
28707
|
};
|
|
28541
28708
|
}
|
|
28542
28709
|
return {
|
|
@@ -28553,6 +28720,9 @@ function terminalProgressState(status) {
|
|
|
28553
28720
|
if (status === "needs_human") return "info";
|
|
28554
28721
|
return "failed";
|
|
28555
28722
|
}
|
|
28723
|
+
function isResumableLongTaskError(code) {
|
|
28724
|
+
return code !== "authentication" && code !== "model_not_found" && code !== "cancelled" && code !== "memory_pressure";
|
|
28725
|
+
}
|
|
28556
28726
|
async function workspaceFingerprint(workspace) {
|
|
28557
28727
|
const hash = createHash21("sha256");
|
|
28558
28728
|
const diff = await execFileNoThrow(
|
|
@@ -29212,6 +29382,13 @@ async function* goalSessionEvents(events) {
|
|
|
29212
29382
|
yield { type: "notice", message: `Resuming goal ${event.goalId} at round ${event.round} after a heap rotation.` };
|
|
29213
29383
|
continue;
|
|
29214
29384
|
}
|
|
29385
|
+
if (event.type === "goal-stage-retry") {
|
|
29386
|
+
yield {
|
|
29387
|
+
type: "warning",
|
|
29388
|
+
message: `Goal ${event.stage} attempt ${event.attempt} hit a recoverable boundary (${event.reason}); retrying in ${event.delayMs}ms.`
|
|
29389
|
+
};
|
|
29390
|
+
continue;
|
|
29391
|
+
}
|
|
29215
29392
|
if (event.type === "goal-plan-created") {
|
|
29216
29393
|
yield { type: "notice", message: `Goal plan created (${event.plan.kind}) with ${event.plan.criteria.length} acceptance criteria.` };
|
|
29217
29394
|
yield { type: "notice", message: `Plan file: ${event.planPath}` };
|
|
@@ -29238,6 +29415,8 @@ async function* goalSessionEvents(events) {
|
|
|
29238
29415
|
totalInputTokens: event.event.usage.inputTokens,
|
|
29239
29416
|
totalOutputTokens: event.event.usage.outputTokens
|
|
29240
29417
|
};
|
|
29418
|
+
} else if (event.event.type === "error" && isResumableLongTaskError(event.event.error.code)) {
|
|
29419
|
+
yield { type: "warning", message: `Goal worker segment ended at ${event.event.error.code}; checkpointing and verifying before continuing.` };
|
|
29241
29420
|
} else {
|
|
29242
29421
|
yield event.event;
|
|
29243
29422
|
}
|