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