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
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
parseMemoryRestartMarker,
|
|
11
11
|
pendingContinuation,
|
|
12
12
|
rotationCooldownActive
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-N5MXHJKD.js";
|
|
14
14
|
import {
|
|
15
15
|
PERMISSION_MODES,
|
|
16
16
|
PermissionModeSchema,
|
|
@@ -1301,6 +1301,11 @@ function appendThinkingText(previous, delta) {
|
|
|
1301
1301
|
// src/ui/transcript.ts
|
|
1302
1302
|
var MAX_TRANSCRIPT_TURNS = 200;
|
|
1303
1303
|
var MAX_TRANSCRIPT_CHARS = 2e6;
|
|
1304
|
+
var MAX_ACTIVE_TRANSCRIPT_BLOCKS = 160;
|
|
1305
|
+
var MAX_ACTIVE_ASSISTANT_CHARS = 64e3;
|
|
1306
|
+
var MAX_TRANSCRIPT_BLOCK_TEXT_CHARS = 16e3;
|
|
1307
|
+
var MAX_TRANSCRIPT_TOOL_VALUE_CHARS = 16e3;
|
|
1308
|
+
var MAX_TRANSCRIPT_PRESENTATION_CHARS = 32e3;
|
|
1304
1309
|
function createTranscriptState() {
|
|
1305
1310
|
return { completed: [], nextId: 1 };
|
|
1306
1311
|
}
|
|
@@ -1661,11 +1666,9 @@ function applyTaskSnapshot(turn, snapshot4, includeTerminal = true) {
|
|
|
1661
1666
|
else blocks[index] = block;
|
|
1662
1667
|
}
|
|
1663
1668
|
return {
|
|
1664
|
-
...turn,
|
|
1669
|
+
...withBlocks(turn, blocks),
|
|
1665
1670
|
taskSnapshot: snapshot4,
|
|
1666
|
-
suppressedTaskIds: [...suppressed]
|
|
1667
|
-
blocks,
|
|
1668
|
-
statusLines: blocks.filter((block) => block.kind === "status").map((block) => block.text)
|
|
1671
|
+
suppressedTaskIds: [...suppressed]
|
|
1669
1672
|
};
|
|
1670
1673
|
}
|
|
1671
1674
|
function terminalTaskIds(snapshot4) {
|
|
@@ -1679,13 +1682,10 @@ function upsertStatus(state, block) {
|
|
|
1679
1682
|
if (state.active === void 0) return state;
|
|
1680
1683
|
const blocks = [...state.active.blocks];
|
|
1681
1684
|
const index = blocks.findIndex((item) => item.kind === "status" && item.id === block.id);
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
statusLines: blocks.filter((item) => item.kind === "status").map((item) => item.text),
|
|
1687
|
-
blocks
|
|
1688
|
-
} };
|
|
1685
|
+
const bounded2 = boundedTranscriptBlock(block);
|
|
1686
|
+
if (index < 0) blocks.push(bounded2);
|
|
1687
|
+
else blocks[index] = bounded2;
|
|
1688
|
+
return { ...state, active: withBlocks(state.active, blocks) };
|
|
1689
1689
|
}
|
|
1690
1690
|
function finishActive(state) {
|
|
1691
1691
|
if (state.active === void 0) return state;
|
|
@@ -1709,16 +1709,12 @@ function attachThinking(turn, text) {
|
|
|
1709
1709
|
...block,
|
|
1710
1710
|
thinkingText: appendThinkingText(block.thinkingText, text)
|
|
1711
1711
|
};
|
|
1712
|
-
return
|
|
1712
|
+
return withBlocks(turn, blocks);
|
|
1713
1713
|
}
|
|
1714
1714
|
function withoutModelActivity(turn, id) {
|
|
1715
1715
|
const blocks = turn.blocks.filter((block) => block.kind !== "status" || block.activity !== "model" || id !== void 0 && block.id !== id);
|
|
1716
1716
|
if (blocks.length === turn.blocks.length) return turn;
|
|
1717
|
-
return
|
|
1718
|
-
...turn,
|
|
1719
|
-
blocks,
|
|
1720
|
-
statusLines: blocks.filter((block) => block.kind === "status").map((block) => block.text)
|
|
1721
|
-
};
|
|
1717
|
+
return withBlocks(turn, blocks);
|
|
1722
1718
|
}
|
|
1723
1719
|
function restoreTranscriptState(state) {
|
|
1724
1720
|
const completed = state.completed.map(cloneTurn);
|
|
@@ -1820,15 +1816,18 @@ function cloneTurn(turn) {
|
|
|
1820
1816
|
function upsertTurnStatus(turn, block) {
|
|
1821
1817
|
const blocks = [...turn.blocks];
|
|
1822
1818
|
const index = blocks.findIndex((item) => item.kind === "status" && item.id === block.id);
|
|
1823
|
-
|
|
1824
|
-
|
|
1819
|
+
const bounded2 = boundedTranscriptBlock(block);
|
|
1820
|
+
if (index < 0) blocks.push(bounded2);
|
|
1821
|
+
else blocks[index] = bounded2;
|
|
1825
1822
|
return withBlocks(turn, blocks);
|
|
1826
1823
|
}
|
|
1827
1824
|
function withBlocks(turn, blocks) {
|
|
1825
|
+
const bounded2 = blocks.length <= MAX_ACTIVE_TRANSCRIPT_BLOCKS ? blocks : blocks.slice(-MAX_ACTIVE_TRANSCRIPT_BLOCKS);
|
|
1828
1826
|
return {
|
|
1829
1827
|
...turn,
|
|
1830
|
-
|
|
1831
|
-
|
|
1828
|
+
assistantText: tailText(turn.assistantText, MAX_ACTIVE_ASSISTANT_CHARS),
|
|
1829
|
+
blocks: bounded2,
|
|
1830
|
+
statusLines: bounded2.filter((block) => block.kind === "status").map((block) => block.text)
|
|
1832
1831
|
};
|
|
1833
1832
|
}
|
|
1834
1833
|
function appendLine(text, line) {
|
|
@@ -1842,19 +1841,95 @@ function stripRetryBlocks(turn) {
|
|
|
1842
1841
|
if (block.id.startsWith("structured-retry:")) return false;
|
|
1843
1842
|
return true;
|
|
1844
1843
|
});
|
|
1845
|
-
return
|
|
1846
|
-
...turn,
|
|
1847
|
-
blocks,
|
|
1848
|
-
statusLines: blocks.filter((item) => item.kind === "status").map((item) => item.text)
|
|
1849
|
-
};
|
|
1844
|
+
return withBlocks(turn, blocks);
|
|
1850
1845
|
}
|
|
1851
1846
|
function addText(turn, text, onNewLine = false) {
|
|
1852
|
-
const assistantText =
|
|
1847
|
+
const assistantText = tailText(
|
|
1848
|
+
onNewLine ? appendLine(turn.assistantText, text) : turn.assistantText + text,
|
|
1849
|
+
MAX_ACTIVE_ASSISTANT_CHARS
|
|
1850
|
+
);
|
|
1853
1851
|
const blocks = [...turn.blocks];
|
|
1854
1852
|
const last = blocks[blocks.length - 1];
|
|
1855
|
-
if (!onNewLine && last?.kind === "text")
|
|
1856
|
-
|
|
1857
|
-
|
|
1853
|
+
if (!onNewLine && last?.kind === "text") {
|
|
1854
|
+
blocks[blocks.length - 1] = { kind: "text", text: tailText(last.text + text, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS) };
|
|
1855
|
+
} else {
|
|
1856
|
+
blocks.push({ kind: "text", text: tailText(text, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS) });
|
|
1857
|
+
}
|
|
1858
|
+
return withBlocks({ ...turn, assistantText }, blocks);
|
|
1859
|
+
}
|
|
1860
|
+
function boundedTranscriptBlock(block) {
|
|
1861
|
+
const presentation = block.presentation === void 0 ? void 0 : boundedTranscriptPresentation(block.presentation);
|
|
1862
|
+
const tool = block.tool === void 0 ? void 0 : {
|
|
1863
|
+
name: block.tool.name,
|
|
1864
|
+
input: boundedTranscriptValue(block.tool.input),
|
|
1865
|
+
...block.tool.result === void 0 ? {} : {
|
|
1866
|
+
result: {
|
|
1867
|
+
ok: block.tool.result.ok,
|
|
1868
|
+
...block.tool.result.output === void 0 ? {} : { output: boundedTranscriptValue(block.tool.result.output) },
|
|
1869
|
+
...block.tool.result.content === void 0 ? {} : {
|
|
1870
|
+
content: tailText(block.tool.result.content, MAX_TRANSCRIPT_TOOL_VALUE_CHARS)
|
|
1871
|
+
},
|
|
1872
|
+
...block.tool.result.presentation === void 0 ? {} : {
|
|
1873
|
+
presentation: boundedTranscriptPresentation(block.tool.result.presentation)
|
|
1874
|
+
},
|
|
1875
|
+
...block.tool.result.additionalContext === void 0 ? {} : {
|
|
1876
|
+
additionalContext: block.tool.result.additionalContext.slice(-20).map((item) => tailText(item, MAX_TRANSCRIPT_TOOL_VALUE_CHARS))
|
|
1877
|
+
},
|
|
1878
|
+
...block.tool.result.error === void 0 ? {} : { error: {
|
|
1879
|
+
code: block.tool.result.error.code,
|
|
1880
|
+
message: tailText(block.tool.result.error.message, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS)
|
|
1881
|
+
} }
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
};
|
|
1885
|
+
return {
|
|
1886
|
+
...block,
|
|
1887
|
+
text: tailText(block.text, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS),
|
|
1888
|
+
...block.hint === void 0 ? {} : { hint: tailText(block.hint, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS) },
|
|
1889
|
+
...block.details === void 0 ? {} : { details: tailText(block.details, MAX_TRANSCRIPT_BLOCK_TEXT_CHARS) },
|
|
1890
|
+
...presentation === void 0 ? {} : { presentation },
|
|
1891
|
+
...tool === void 0 ? {} : { tool }
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
function boundedTranscriptPresentation(presentation) {
|
|
1895
|
+
return jsonSize(presentation) <= MAX_TRANSCRIPT_PRESENTATION_CHARS ? presentation : {
|
|
1896
|
+
kind: "generic",
|
|
1897
|
+
title: "Tool output",
|
|
1898
|
+
summary: "Large presentation omitted from the live transcript; the model-facing result remains available in context."
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
function boundedTranscriptValue(value) {
|
|
1902
|
+
const chars = jsonSize(value);
|
|
1903
|
+
if (chars <= MAX_TRANSCRIPT_TOOL_VALUE_CHARS) return value;
|
|
1904
|
+
const record = typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
1905
|
+
const summary2 = { truncated: true, originalChars: chars };
|
|
1906
|
+
for (const key of ["path", "command", "id", "name", "exitCode", "bytes", "replacements"]) {
|
|
1907
|
+
const item = record?.[key];
|
|
1908
|
+
if (typeof item === "string") summary2[key] = tailText(item, 1e3);
|
|
1909
|
+
else if (typeof item === "number" || typeof item === "boolean" || item === null) summary2[key] = item;
|
|
1910
|
+
}
|
|
1911
|
+
return summary2;
|
|
1912
|
+
}
|
|
1913
|
+
function jsonSize(value) {
|
|
1914
|
+
try {
|
|
1915
|
+
return JSON.stringify(value)?.length ?? 0;
|
|
1916
|
+
} catch {
|
|
1917
|
+
return Number.POSITIVE_INFINITY;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
function tailText(text, limit) {
|
|
1921
|
+
if (text.length <= limit) return text;
|
|
1922
|
+
const marker = `\u2026 ${text.length - limit} earlier characters omitted \u2026
|
|
1923
|
+
`;
|
|
1924
|
+
return marker.length >= limit ? text.slice(-limit) : marker + text.slice(-(limit - marker.length));
|
|
1925
|
+
}
|
|
1926
|
+
function transcriptCensus(state) {
|
|
1927
|
+
const turns = [...state.completed, ...state.active === void 0 ? [] : [state.active]];
|
|
1928
|
+
return {
|
|
1929
|
+
turns: turns.length,
|
|
1930
|
+
blocks: turns.reduce((total, turn) => total + turn.blocks.length, 0),
|
|
1931
|
+
chars: jsonSize(state)
|
|
1932
|
+
};
|
|
1858
1933
|
}
|
|
1859
1934
|
|
|
1860
1935
|
// src/session/checkpoint.ts
|
|
@@ -3621,6 +3696,11 @@ var HELP = [
|
|
|
3621
3696
|
"/co-work <pal> <goal> | status [id] | cancel <id> [reason]"
|
|
3622
3697
|
].join("\n");
|
|
3623
3698
|
var MAX_STOP_DENIALS = 2;
|
|
3699
|
+
var RESUMABLE_TURN_BOUNDARIES = /* @__PURE__ */ new Set([
|
|
3700
|
+
"iteration_limit",
|
|
3701
|
+
"output_limit",
|
|
3702
|
+
"context_overflow"
|
|
3703
|
+
]);
|
|
3624
3704
|
var FlavorSession = class {
|
|
3625
3705
|
#services;
|
|
3626
3706
|
#active;
|
|
@@ -3852,6 +3932,7 @@ var FlavorSession = class {
|
|
|
3852
3932
|
if (!initial) this.#outputQueuedSubmission(submission);
|
|
3853
3933
|
initial = false;
|
|
3854
3934
|
await this.#runSubmission(submission);
|
|
3935
|
+
if (this.#services.rotationPending?.() === true) return;
|
|
3855
3936
|
pending.push(...this.#drainMessages("steer"), ...this.#drainMessages("followUp"));
|
|
3856
3937
|
}
|
|
3857
3938
|
}
|
|
@@ -3875,6 +3956,7 @@ var FlavorSession = class {
|
|
|
3875
3956
|
this.#activeSubmission = submission;
|
|
3876
3957
|
this.#interrupted = false;
|
|
3877
3958
|
let outcome = "completed";
|
|
3959
|
+
let resumableBoundary;
|
|
3878
3960
|
let assistantSummary = "";
|
|
3879
3961
|
let deliverables = [];
|
|
3880
3962
|
try {
|
|
@@ -3911,7 +3993,10 @@ var FlavorSession = class {
|
|
|
3911
3993
|
this.#services.output(event);
|
|
3912
3994
|
if (event.type === "text") assistantSummary = `${assistantSummary}${event.text}`.slice(-2e3);
|
|
3913
3995
|
if (event.type === "deliverables") deliverables = event.files.slice(0, 100);
|
|
3914
|
-
if (event.type === "error")
|
|
3996
|
+
if (event.type === "error") {
|
|
3997
|
+
outcome = "failed";
|
|
3998
|
+
if (RESUMABLE_TURN_BOUNDARIES.has(event.error.code)) resumableBoundary = event.error.code;
|
|
3999
|
+
}
|
|
3915
4000
|
}
|
|
3916
4001
|
if (controller.signal.aborted) outcome = "cancelled";
|
|
3917
4002
|
} catch (error) {
|
|
@@ -3952,6 +4037,13 @@ var FlavorSession = class {
|
|
|
3952
4037
|
}
|
|
3953
4038
|
}
|
|
3954
4039
|
try {
|
|
4040
|
+
if (resumableBoundary !== void 0 && !this.#closed && !controller.signal.aborted) {
|
|
4041
|
+
const attempt = (submission.iterationContinuation ?? 0) + 1;
|
|
4042
|
+
const text = `[automatic continuation after ${resumableBoundary} boundary; segment ${attempt}]
|
|
4043
|
+
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.`;
|
|
4044
|
+
this.#enqueueMessage("followUp", { text, displayText: text, iterationContinuation: attempt });
|
|
4045
|
+
this.#notice(`Agent ${resumableBoundary} boundary reached; durable continuation ${attempt} queued.`);
|
|
4046
|
+
}
|
|
3955
4047
|
if (stopDecision?.decision === "deny" && typeof stopDecision.reason === "string" && stopDecision.reason.length > 0 && !this.#closed && outcome !== "cancelled" && outcome !== "denied") {
|
|
3956
4048
|
if (this.#stopDenials < MAX_STOP_DENIALS) {
|
|
3957
4049
|
this.#stopDenials += 1;
|
|
@@ -4148,7 +4240,7 @@ Address this now (for example run the required verification or fix), then finish
|
|
|
4148
4240
|
});
|
|
4149
4241
|
}
|
|
4150
4242
|
#resumeDurableQueue() {
|
|
4151
|
-
if (this.#durableResumeStarted || this.#closed || this.active || this.#pendingSubmissions > 0) return;
|
|
4243
|
+
if (this.#durableResumeStarted || this.#closed || this.active || this.#pendingSubmissions > 0 || this.#services.rotationPending?.() === true) return;
|
|
4152
4244
|
if (!this.#queue.hasPending) return;
|
|
4153
4245
|
this.#durableResumeStarted = true;
|
|
4154
4246
|
const submissions = [...this.#drainMessages("steer"), ...this.#drainMessages("followUp")];
|
|
@@ -4299,6 +4391,7 @@ function recoveredSubmission(value) {
|
|
|
4299
4391
|
if (typeof input.text !== "string" || input.text.trim().length === 0) return void 0;
|
|
4300
4392
|
if (typeof input.displayText !== "string") return void 0;
|
|
4301
4393
|
if (input.controlOnly !== void 0 && typeof input.controlOnly !== "boolean") return void 0;
|
|
4394
|
+
if (input.iterationContinuation !== void 0 && (!Number.isSafeInteger(input.iterationContinuation) || input.iterationContinuation < 1)) return void 0;
|
|
4302
4395
|
if (input.coWorkPlanningKey !== void 0 && typeof input.coWorkPlanningKey !== "string") return void 0;
|
|
4303
4396
|
if (input.remoteOrigin !== void 0) {
|
|
4304
4397
|
const origin = input.remoteOrigin;
|
|
@@ -7772,10 +7865,6 @@ var ContextManager = class _ContextManager {
|
|
|
7772
7865
|
}
|
|
7773
7866
|
return microcompact.changed;
|
|
7774
7867
|
}
|
|
7775
|
-
if (this.#consecutiveAutoCompactFailures >= 3) {
|
|
7776
|
-
rollbackMicrocompact();
|
|
7777
|
-
return false;
|
|
7778
|
-
}
|
|
7779
7868
|
try {
|
|
7780
7869
|
const compacted = await this.#compactConversation(signal);
|
|
7781
7870
|
if (compacted) {
|
|
@@ -8239,10 +8328,10 @@ function within(root, candidate) {
|
|
|
8239
8328
|
|
|
8240
8329
|
// src/context/summarizer.ts
|
|
8241
8330
|
async function summarizeWithModel(options) {
|
|
8242
|
-
const maxAttempts = options.maxPromptTooLongAttempts ?? 3;
|
|
8243
|
-
if (!Number.isInteger(maxAttempts) || maxAttempts <= 0) throw new Error("maxPromptTooLongAttempts must be positive");
|
|
8244
8331
|
options.signal?.throwIfAborted();
|
|
8245
8332
|
let groups = groupMessagesByApiRound(options.messages);
|
|
8333
|
+
const maxAttempts = options.maxPromptTooLongAttempts ?? Math.max(1, Math.ceil(Math.log2(Math.max(1, groups.length))) + 1);
|
|
8334
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts <= 0) throw new Error("maxPromptTooLongAttempts must be positive");
|
|
8246
8335
|
let lastOverflow;
|
|
8247
8336
|
let progress = 20;
|
|
8248
8337
|
reportProgress(options.onProgress, progress);
|
|
@@ -8283,7 +8372,7 @@ async function summarizeWithModel(options) {
|
|
|
8283
8372
|
if (terminalError.code !== "context_overflow") throw terminalError;
|
|
8284
8373
|
lastOverflow = terminalError;
|
|
8285
8374
|
if (attempt >= maxAttempts || groups.length <= 1) throw terminalError;
|
|
8286
|
-
groups = groups.slice(1);
|
|
8375
|
+
groups = groups.slice(Math.max(1, Math.floor(groups.length / 2)));
|
|
8287
8376
|
}
|
|
8288
8377
|
throw lastOverflow ?? new Error("Compact summary failed");
|
|
8289
8378
|
}
|
|
@@ -12663,7 +12752,7 @@ function extendBudget(input, dimensions, approvedAt) {
|
|
|
12663
12752
|
return LoopStateSchema.parse({
|
|
12664
12753
|
...state,
|
|
12665
12754
|
updatedAt: approvedAt,
|
|
12666
|
-
budget: { ...state.budget, cycleCheckpoint, tokenCheckpoint, approvals }
|
|
12755
|
+
budget: { ...state.budget, cycleCheckpoint, tokenCheckpoint, approvals: approvals.slice(-64) }
|
|
12667
12756
|
});
|
|
12668
12757
|
}
|
|
12669
12758
|
function rejectBudget(input, terminalReason) {
|
|
@@ -12790,6 +12879,7 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12790
12879
|
});
|
|
12791
12880
|
let workerError;
|
|
12792
12881
|
let workerMemoryPressure = false;
|
|
12882
|
+
let workerIterationLimit = false;
|
|
12793
12883
|
for await (const event of this.#options.runWorker({
|
|
12794
12884
|
goal,
|
|
12795
12885
|
cycle,
|
|
@@ -12802,8 +12892,9 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12802
12892
|
cycleOutputTokens += event.outputTokens;
|
|
12803
12893
|
}
|
|
12804
12894
|
if (event.type === "error") {
|
|
12805
|
-
workerError = event.error
|
|
12895
|
+
workerError = event.error;
|
|
12806
12896
|
if (event.error.code === "memory_pressure") workerMemoryPressure = true;
|
|
12897
|
+
if (event.error.code === "iteration_limit") workerIterationLimit = true;
|
|
12807
12898
|
}
|
|
12808
12899
|
if (event.type === "text") workerText = `${workerText}${event.text}`.slice(-16e3);
|
|
12809
12900
|
if (this.#options.hallucinationGuard !== void 0) {
|
|
@@ -12816,7 +12907,8 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12816
12907
|
yield { type: "worker-event", event };
|
|
12817
12908
|
}
|
|
12818
12909
|
if (workerMemoryPressure) return;
|
|
12819
|
-
if (workerError !== void 0) {
|
|
12910
|
+
if (workerError !== void 0 && !workerIterationLimit && !isResumableWorkerError(workerError)) {
|
|
12911
|
+
const status = workerError.code === "cancelled" ? "cancelled" : "failed";
|
|
12820
12912
|
state = LoopStateSchema.parse({
|
|
12821
12913
|
...state,
|
|
12822
12914
|
budget: {
|
|
@@ -12826,8 +12918,8 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12826
12918
|
outputTokens: state.budget.outputTokens + cycleOutputTokens
|
|
12827
12919
|
}
|
|
12828
12920
|
});
|
|
12829
|
-
state = await this.#terminal(state,
|
|
12830
|
-
yield { type: "loop-terminal", loopId, status
|
|
12921
|
+
state = await this.#terminal(state, status, workerError.message, now());
|
|
12922
|
+
yield { type: "loop-terminal", loopId, status, reason: workerError.message };
|
|
12831
12923
|
return;
|
|
12832
12924
|
}
|
|
12833
12925
|
state = LoopStateSchema.parse({
|
|
@@ -12870,13 +12962,7 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12870
12962
|
const report = await this.#options.hallucinationGuard.evaluate(goal, workerText);
|
|
12871
12963
|
await this.#options.onMemoryCheckpoint?.(loopId);
|
|
12872
12964
|
if (memoryRotationActive()) return;
|
|
12873
|
-
|
|
12874
|
-
const guardReason = report.blockingReasons.join("; ") || "Hallucination guard blocked completion.";
|
|
12875
|
-
state = await this.#terminal(state, "failed", guardReason, now());
|
|
12876
|
-
yield { type: "loop-terminal", loopId, status: "failed", reason: guardReason };
|
|
12877
|
-
return;
|
|
12878
|
-
}
|
|
12879
|
-
guardWarnings = report.warnings;
|
|
12965
|
+
guardWarnings = [...report.blockingReasons, ...report.warnings];
|
|
12880
12966
|
} catch {
|
|
12881
12967
|
}
|
|
12882
12968
|
}
|
|
@@ -12898,7 +12984,7 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12898
12984
|
outputTokens: cycleOutputTokens,
|
|
12899
12985
|
workspaceFingerprint: fingerprint2,
|
|
12900
12986
|
verification: evidence
|
|
12901
|
-
}],
|
|
12987
|
+
}].slice(-64),
|
|
12902
12988
|
pendingCycle: null
|
|
12903
12989
|
});
|
|
12904
12990
|
await this.#options.persistence.save(state);
|
|
@@ -12927,8 +13013,8 @@ ${evidence.summary}`;
|
|
|
12927
13013
|
repeatedFailures = failureSignature === previousFailureSignature ? repeatedFailures + 1 : 1;
|
|
12928
13014
|
previousFailureSignature = failureSignature;
|
|
12929
13015
|
previousVerification = evidence;
|
|
12930
|
-
if (repeatedFailures >=
|
|
12931
|
-
const reason =
|
|
13016
|
+
if (this.#options.maxNoProgressCycles !== void 0 && repeatedFailures >= this.#options.maxNoProgressCycles) {
|
|
13017
|
+
const reason = `The same verification failure repeated ${this.#options.maxNoProgressCycles} times without material workspace progress.`;
|
|
12932
13018
|
state = await this.#terminal(state, "no_progress", reason, now());
|
|
12933
13019
|
yield { type: "loop-terminal", loopId, status: "no_progress", reason };
|
|
12934
13020
|
return;
|
|
@@ -12989,6 +13075,9 @@ ${evidence.summary}`;
|
|
|
12989
13075
|
return state;
|
|
12990
13076
|
}
|
|
12991
13077
|
};
|
|
13078
|
+
function isResumableWorkerError(error) {
|
|
13079
|
+
return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
|
|
13080
|
+
}
|
|
12992
13081
|
function countTrailingFailureSignature(cycles, signature) {
|
|
12993
13082
|
let count = 0;
|
|
12994
13083
|
for (let index = cycles.length - 1; index >= 0; index -= 1) {
|
|
@@ -13477,26 +13566,37 @@ var GoalOrchestrator = class {
|
|
|
13477
13566
|
let plan;
|
|
13478
13567
|
let planPath;
|
|
13479
13568
|
if (state.plan === null) {
|
|
13480
|
-
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
13499
|
-
|
|
13569
|
+
let planningAttempt = 0;
|
|
13570
|
+
while (true) {
|
|
13571
|
+
try {
|
|
13572
|
+
signal.throwIfAborted();
|
|
13573
|
+
await memoryCheckpoint();
|
|
13574
|
+
plan = await runPlanner({
|
|
13575
|
+
registry: this.#options.registry,
|
|
13576
|
+
modelId: this.#options.plannerModelId,
|
|
13577
|
+
objective: state.objective,
|
|
13578
|
+
signal,
|
|
13579
|
+
onProgress: memoryCheckpoint
|
|
13580
|
+
});
|
|
13581
|
+
planPath = await writePlanFile(workspace, plan);
|
|
13582
|
+
await persistState({ phase: "executing", plan, planPath, contractHash: contractHash(state.objective, plan) });
|
|
13583
|
+
yield { type: "goal-plan-created", plan, planPath };
|
|
13584
|
+
break;
|
|
13585
|
+
} catch (error) {
|
|
13586
|
+
if (memoryRotationActive()) return;
|
|
13587
|
+
const normalized = normalizeProviderError(error);
|
|
13588
|
+
if (!isResumableStageError(normalized)) {
|
|
13589
|
+
const reason = `Goal planning failed: ${normalized.message}`;
|
|
13590
|
+
await persistState({ phase: "complete", status: "failed" });
|
|
13591
|
+
yield { type: "goal-plan-failed", reason };
|
|
13592
|
+
yield { type: "goal-failed", reason };
|
|
13593
|
+
return;
|
|
13594
|
+
}
|
|
13595
|
+
planningAttempt += 1;
|
|
13596
|
+
const delayMs = stageRetryDelay(this.#options, planningAttempt);
|
|
13597
|
+
yield { type: "goal-stage-retry", stage: "planning", attempt: planningAttempt, reason: normalized.message, delayMs };
|
|
13598
|
+
await waitForStageRetry(delayMs, signal);
|
|
13599
|
+
}
|
|
13500
13600
|
}
|
|
13501
13601
|
} else {
|
|
13502
13602
|
plan = state.plan;
|
|
@@ -13507,7 +13607,7 @@ var GoalOrchestrator = class {
|
|
|
13507
13607
|
let priorFingerprint = state.gapFingerprint;
|
|
13508
13608
|
let stallStreak = state.stallStreak;
|
|
13509
13609
|
const startRound = resumeStartRound(state);
|
|
13510
|
-
for (let round = startRound; round <= this.#options.maxRounds; round++) {
|
|
13610
|
+
for (let round = startRound; this.#options.maxRounds === void 0 || round <= this.#options.maxRounds; round++) {
|
|
13511
13611
|
signal.throwIfAborted();
|
|
13512
13612
|
await this.#options.onRoundBoundary?.(state.id);
|
|
13513
13613
|
if (memoryRotationActive()) return;
|
|
@@ -13527,6 +13627,7 @@ var GoalOrchestrator = class {
|
|
|
13527
13627
|
yield { type: "goal-worker-start", round };
|
|
13528
13628
|
let workerError;
|
|
13529
13629
|
let workerMemoryPressure = false;
|
|
13630
|
+
let workerIterationLimit = false;
|
|
13530
13631
|
try {
|
|
13531
13632
|
for await (const event of this.#options.runWorker({
|
|
13532
13633
|
goal: state.objective,
|
|
@@ -13539,18 +13640,19 @@ var GoalOrchestrator = class {
|
|
|
13539
13640
|
yield { type: "goal-worker-event", round, event };
|
|
13540
13641
|
if (event.type === "text") finalResponse = `${finalResponse}${event.text}`.slice(-16e3);
|
|
13541
13642
|
if (event.type === "error") {
|
|
13542
|
-
workerError = event.error
|
|
13643
|
+
workerError = event.error;
|
|
13543
13644
|
if (event.error.code === "memory_pressure") workerMemoryPressure = true;
|
|
13645
|
+
if (event.error.code === "iteration_limit") workerIterationLimit = true;
|
|
13544
13646
|
break;
|
|
13545
13647
|
}
|
|
13546
13648
|
}
|
|
13547
13649
|
} catch (error) {
|
|
13548
13650
|
if (memoryRotationActive()) return;
|
|
13549
|
-
workerError = message(error);
|
|
13651
|
+
workerError = { code: "unknown", message: message(error) };
|
|
13550
13652
|
}
|
|
13551
13653
|
if (workerMemoryPressure) return;
|
|
13552
|
-
if (workerError !== void 0) {
|
|
13553
|
-
const reason = `Worker error in round ${round}: ${workerError}`;
|
|
13654
|
+
if (workerError !== void 0 && !workerIterationLimit && !isResumableWorkerError2(workerError)) {
|
|
13655
|
+
const reason = `Worker error in round ${round}: ${workerError.message}`;
|
|
13554
13656
|
await persistState({ phase: "complete", status: "failed" });
|
|
13555
13657
|
yield { type: "goal-failed", reason };
|
|
13556
13658
|
return;
|
|
@@ -13580,7 +13682,7 @@ var GoalOrchestrator = class {
|
|
|
13580
13682
|
round,
|
|
13581
13683
|
workspaceDiffHash: evidence.workspaceDiffHash,
|
|
13582
13684
|
...hostVerification === void 0 ? {} : { hostVerification }
|
|
13583
|
-
}] });
|
|
13685
|
+
}].slice(-64) });
|
|
13584
13686
|
let outcome;
|
|
13585
13687
|
if (plan.kind === "code-change" && hostVerification !== void 0 && !hostVerification.passed) {
|
|
13586
13688
|
if (hostVerification.commands.length === 0) {
|
|
@@ -13594,21 +13696,32 @@ var GoalOrchestrator = class {
|
|
|
13594
13696
|
fingerprint: createHash11("sha256").update(hostVerification.summary).digest("hex").slice(0, 16)
|
|
13595
13697
|
};
|
|
13596
13698
|
}
|
|
13597
|
-
} else
|
|
13598
|
-
|
|
13599
|
-
|
|
13600
|
-
|
|
13601
|
-
|
|
13602
|
-
|
|
13603
|
-
|
|
13604
|
-
|
|
13605
|
-
|
|
13606
|
-
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13699
|
+
} else {
|
|
13700
|
+
let classifierAttempt = 0;
|
|
13701
|
+
while (true) {
|
|
13702
|
+
try {
|
|
13703
|
+
outcome = await runClassifier(evidence, plan, {
|
|
13704
|
+
registry: this.#options.registry,
|
|
13705
|
+
modelId: this.#options.classifierModelId,
|
|
13706
|
+
skepticCount: this.#options.skepticCount,
|
|
13707
|
+
workspace,
|
|
13708
|
+
signal,
|
|
13709
|
+
onProgress: memoryCheckpoint
|
|
13710
|
+
});
|
|
13711
|
+
break;
|
|
13712
|
+
} catch (error) {
|
|
13713
|
+
if (memoryRotationActive()) return;
|
|
13714
|
+
const normalized = normalizeProviderError(error);
|
|
13715
|
+
if (!isResumableStageError(normalized)) {
|
|
13716
|
+
outcome = { type: "blocked", reason: `Classifier infrastructure error: ${normalized.message}` };
|
|
13717
|
+
break;
|
|
13718
|
+
}
|
|
13719
|
+
classifierAttempt += 1;
|
|
13720
|
+
const delayMs = stageRetryDelay(this.#options, classifierAttempt);
|
|
13721
|
+
yield { type: "goal-stage-retry", stage: "classification", attempt: classifierAttempt, reason: normalized.message, delayMs };
|
|
13722
|
+
await waitForStageRetry(delayMs, signal);
|
|
13723
|
+
}
|
|
13724
|
+
}
|
|
13612
13725
|
}
|
|
13613
13726
|
await persistState({ verifyRounds: round, pendingVerification: null });
|
|
13614
13727
|
yield {
|
|
@@ -13630,7 +13743,7 @@ var GoalOrchestrator = class {
|
|
|
13630
13743
|
}
|
|
13631
13744
|
if (outcome.fingerprint === priorFingerprint) {
|
|
13632
13745
|
stallStreak++;
|
|
13633
|
-
if (stallStreak >= this.#options.maxStallStreak) {
|
|
13746
|
+
if (this.#options.maxStallStreak !== void 0 && stallStreak >= this.#options.maxStallStreak) {
|
|
13634
13747
|
await persistState({
|
|
13635
13748
|
phase: "complete",
|
|
13636
13749
|
status: "failed",
|
|
@@ -13676,6 +13789,31 @@ function resumeStartRound(state) {
|
|
|
13676
13789
|
}
|
|
13677
13790
|
return state.verifyRounds >= state.workerRounds ? state.workerRounds + 1 : Math.max(state.workerRounds, 1);
|
|
13678
13791
|
}
|
|
13792
|
+
function isResumableWorkerError2(error) {
|
|
13793
|
+
return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
|
|
13794
|
+
}
|
|
13795
|
+
function isResumableStageError(error) {
|
|
13796
|
+
return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
|
|
13797
|
+
}
|
|
13798
|
+
function stageRetryDelay(options, attempt) {
|
|
13799
|
+
const delayMs = options.stageRetryDelayMs?.(attempt) ?? Math.min(6e4, 1e3 * 2 ** Math.min(attempt - 1, 6));
|
|
13800
|
+
return Number.isSafeInteger(delayMs) && delayMs >= 0 ? delayMs : 1e3;
|
|
13801
|
+
}
|
|
13802
|
+
function waitForStageRetry(delayMs, signal) {
|
|
13803
|
+
signal.throwIfAborted();
|
|
13804
|
+
if (delayMs === 0) return Promise.resolve();
|
|
13805
|
+
return new Promise((resolvePromise, reject) => {
|
|
13806
|
+
const onAbort = () => {
|
|
13807
|
+
clearTimeout(timer);
|
|
13808
|
+
reject(signal.reason instanceof Error ? signal.reason : new Error("Goal cancelled"));
|
|
13809
|
+
};
|
|
13810
|
+
const timer = setTimeout(() => {
|
|
13811
|
+
signal.removeEventListener("abort", onAbort);
|
|
13812
|
+
resolvePromise();
|
|
13813
|
+
}, delayMs);
|
|
13814
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
13815
|
+
});
|
|
13816
|
+
}
|
|
13679
13817
|
async function writePlanFile(workspace, plan) {
|
|
13680
13818
|
const dir = join17(workspace, ".flavor");
|
|
13681
13819
|
const planPath = join17(dir, "goal-plan.md");
|
|
@@ -14056,6 +14194,7 @@ function isCode4(error, code) {
|
|
|
14056
14194
|
import { readFile as readFile14 } from "fs/promises";
|
|
14057
14195
|
import { join as join21 } from "path";
|
|
14058
14196
|
var SCRIPT_PRIORITY = ["test", "typecheck", "lint", "build", "smoke:install"];
|
|
14197
|
+
var MAX_PERSISTED_VERIFICATION_STREAM_BYTES = 1024;
|
|
14059
14198
|
async function inferVerificationPlan(workspace) {
|
|
14060
14199
|
const commands = [];
|
|
14061
14200
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -14091,9 +14230,9 @@ async function runVerificationPlan(plan, workspace, signal, executionEnvironment
|
|
|
14091
14230
|
command: item.command,
|
|
14092
14231
|
args: item.args,
|
|
14093
14232
|
exitCode: result.exitCode,
|
|
14094
|
-
stdout: result.stdout,
|
|
14095
|
-
stderr: result.stderr,
|
|
14096
|
-
truncated: result.truncated
|
|
14233
|
+
stdout: boundedEvidenceTail(result.stdout),
|
|
14234
|
+
stderr: boundedEvidenceTail(result.stderr),
|
|
14235
|
+
truncated: result.truncated || Buffer.byteLength(result.stdout, "utf8") > MAX_PERSISTED_VERIFICATION_STREAM_BYTES || Buffer.byteLength(result.stderr, "utf8") > MAX_PERSISTED_VERIFICATION_STREAM_BYTES
|
|
14097
14236
|
});
|
|
14098
14237
|
if (result.exitCode !== 0) {
|
|
14099
14238
|
return { passed: false, commands, summary: `${item.label} failed with exit code ${String(result.exitCode)}.` };
|
|
@@ -14101,6 +14240,14 @@ async function runVerificationPlan(plan, workspace, signal, executionEnvironment
|
|
|
14101
14240
|
}
|
|
14102
14241
|
return { passed: true, commands, summary: `Passed ${commands.length} deterministic verification command(s).` };
|
|
14103
14242
|
}
|
|
14243
|
+
function boundedEvidenceTail(value) {
|
|
14244
|
+
const encoded = Buffer.from(value, "utf8");
|
|
14245
|
+
if (encoded.byteLength <= MAX_PERSISTED_VERIFICATION_STREAM_BYTES) return value;
|
|
14246
|
+
const prefix = Buffer.from("\u2026\n", "utf8");
|
|
14247
|
+
let start = encoded.byteLength - (MAX_PERSISTED_VERIFICATION_STREAM_BYTES - prefix.byteLength);
|
|
14248
|
+
while (start < encoded.byteLength && (encoded[start] & 192) === 128) start += 1;
|
|
14249
|
+
return `${prefix.toString("utf8")}${encoded.subarray(start).toString("utf8")}`;
|
|
14250
|
+
}
|
|
14104
14251
|
function npmScript(name) {
|
|
14105
14252
|
return name === "test" ? { label: name, command: "npm", args: ["test"] } : { label: name, command: "npm", args: ["run", name] };
|
|
14106
14253
|
}
|
|
@@ -14194,6 +14341,35 @@ function normalizeToolCallInput(input, maxDepth = 3) {
|
|
|
14194
14341
|
throw new Error(`Tool-call input must decode to an object; received ${kind}`);
|
|
14195
14342
|
}
|
|
14196
14343
|
|
|
14344
|
+
// src/utils/abort.ts
|
|
14345
|
+
function waitWithSignal(operation, signal) {
|
|
14346
|
+
if (signal === void 0) return operation;
|
|
14347
|
+
return new Promise((resolve32, reject) => {
|
|
14348
|
+
const abort2 = () => reject(signal.reason);
|
|
14349
|
+
if (signal.aborted) abort2();
|
|
14350
|
+
else signal.addEventListener("abort", abort2, { once: true });
|
|
14351
|
+
operation.then(resolve32, reject).finally(() => signal.removeEventListener("abort", abort2));
|
|
14352
|
+
});
|
|
14353
|
+
}
|
|
14354
|
+
function createScopedAbortSignal(parent) {
|
|
14355
|
+
const controller = new AbortController();
|
|
14356
|
+
let disposed = false;
|
|
14357
|
+
const abort2 = () => {
|
|
14358
|
+
if (!controller.signal.aborted) controller.abort(parent?.reason);
|
|
14359
|
+
};
|
|
14360
|
+
if (parent?.aborted) abort2();
|
|
14361
|
+
else parent?.addEventListener("abort", abort2, { once: true });
|
|
14362
|
+
return {
|
|
14363
|
+
signal: controller.signal,
|
|
14364
|
+
dispose: () => {
|
|
14365
|
+
if (disposed) return;
|
|
14366
|
+
disposed = true;
|
|
14367
|
+
parent?.removeEventListener("abort", abort2);
|
|
14368
|
+
abort2();
|
|
14369
|
+
}
|
|
14370
|
+
};
|
|
14371
|
+
}
|
|
14372
|
+
|
|
14197
14373
|
// src/models/anthropic.ts
|
|
14198
14374
|
var CLAUDE_CLIENT_HEADERS = {
|
|
14199
14375
|
"User-Agent": "claude-cli/2.1.0 (external, cli)",
|
|
@@ -14316,6 +14492,7 @@ var AnthropicModelAdapter = class {
|
|
|
14316
14492
|
void appendUsageLog(line);
|
|
14317
14493
|
}
|
|
14318
14494
|
async *stream(request) {
|
|
14495
|
+
const requestAbort = createScopedAbortSignal(request.signal);
|
|
14319
14496
|
let inputTokens = 0;
|
|
14320
14497
|
let outputTokens = 0;
|
|
14321
14498
|
let hasUsage = false;
|
|
@@ -14439,13 +14616,13 @@ var AnthropicModelAdapter = class {
|
|
|
14439
14616
|
};
|
|
14440
14617
|
let stream;
|
|
14441
14618
|
try {
|
|
14442
|
-
stream = await this.client.messages.create(body, { signal:
|
|
14619
|
+
stream = await this.client.messages.create(body, { signal: requestAbort.signal });
|
|
14443
14620
|
} catch (error) {
|
|
14444
14621
|
if (this.thinkingBudget > 0 && !this.#thinkingRejected && isThinkingParamRejected(error)) {
|
|
14445
14622
|
this.#thinkingRejected = true;
|
|
14446
14623
|
delete body.thinking;
|
|
14447
14624
|
stripThinkingBlocks(body.messages);
|
|
14448
|
-
stream = await this.client.messages.create(body, { signal:
|
|
14625
|
+
stream = await this.client.messages.create(body, { signal: requestAbort.signal });
|
|
14449
14626
|
} else {
|
|
14450
14627
|
throw error;
|
|
14451
14628
|
}
|
|
@@ -14557,6 +14734,8 @@ var AnthropicModelAdapter = class {
|
|
|
14557
14734
|
};
|
|
14558
14735
|
}
|
|
14559
14736
|
yield { type: "error", error: normalizeProviderError(error) };
|
|
14737
|
+
} finally {
|
|
14738
|
+
requestAbort.dispose();
|
|
14560
14739
|
}
|
|
14561
14740
|
}
|
|
14562
14741
|
};
|
|
@@ -14701,6 +14880,7 @@ var OpenAIModelAdapter = class {
|
|
|
14701
14880
|
void appendUsageLog(line);
|
|
14702
14881
|
}
|
|
14703
14882
|
async *stream(request) {
|
|
14883
|
+
const requestAbort = createScopedAbortSignal(request.signal);
|
|
14704
14884
|
const callIds = /* @__PURE__ */ new Map();
|
|
14705
14885
|
const pendingCalls = /* @__PURE__ */ new Map();
|
|
14706
14886
|
const emittedCalls = /* @__PURE__ */ new Set();
|
|
@@ -14717,7 +14897,7 @@ var OpenAIModelAdapter = class {
|
|
|
14717
14897
|
strict: tool.strict ?? true
|
|
14718
14898
|
}))
|
|
14719
14899
|
};
|
|
14720
|
-
const stream = this.client.responses.stream(body, { signal:
|
|
14900
|
+
const stream = this.client.responses.stream(body, { signal: requestAbort.signal });
|
|
14721
14901
|
for await (const event of stream) {
|
|
14722
14902
|
if (event.type === "response.output_item.added" && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
|
|
14723
14903
|
callIds.set(event.output_index, event.item.call_id);
|
|
@@ -14811,6 +14991,8 @@ var OpenAIModelAdapter = class {
|
|
|
14811
14991
|
}
|
|
14812
14992
|
} catch (error) {
|
|
14813
14993
|
yield { type: "error", error: normalizeProviderError(error) };
|
|
14994
|
+
} finally {
|
|
14995
|
+
requestAbort.dispose();
|
|
14814
14996
|
}
|
|
14815
14997
|
}
|
|
14816
14998
|
};
|
|
@@ -18219,19 +18401,6 @@ import { isIP } from "net";
|
|
|
18219
18401
|
import { request as httpRequest } from "http";
|
|
18220
18402
|
import { request as httpsRequest } from "https";
|
|
18221
18403
|
import { z as z25 } from "zod";
|
|
18222
|
-
|
|
18223
|
-
// src/utils/abort.ts
|
|
18224
|
-
function waitWithSignal(operation, signal) {
|
|
18225
|
-
if (signal === void 0) return operation;
|
|
18226
|
-
return new Promise((resolve32, reject) => {
|
|
18227
|
-
const abort2 = () => reject(signal.reason);
|
|
18228
|
-
if (signal.aborted) abort2();
|
|
18229
|
-
else signal.addEventListener("abort", abort2, { once: true });
|
|
18230
|
-
operation.then(resolve32, reject).finally(() => signal.removeEventListener("abort", abort2));
|
|
18231
|
-
});
|
|
18232
|
-
}
|
|
18233
|
-
|
|
18234
|
-
// src/tools/web.ts
|
|
18235
18404
|
var WebFetchInput = z25.object({
|
|
18236
18405
|
url: z25.string().url().max(8192),
|
|
18237
18406
|
timeoutMs: z25.coerce.number().int().positive().max(12e4).optional(),
|
|
@@ -24063,6 +24232,12 @@ async function createProductionRuntime(options) {
|
|
|
24063
24232
|
holders.sessionTree = { entries: sessionHistory.nodeCount };
|
|
24064
24233
|
} catch {
|
|
24065
24234
|
}
|
|
24235
|
+
try {
|
|
24236
|
+
const transcript = transcriptCensus(timelineState);
|
|
24237
|
+
holders.transcript = { entries: transcript.blocks, chars: transcript.chars };
|
|
24238
|
+
holders.transcriptTurns = { entries: transcript.turns };
|
|
24239
|
+
} catch {
|
|
24240
|
+
}
|
|
24066
24241
|
return holders;
|
|
24067
24242
|
};
|
|
24068
24243
|
const rotateForHeap = (continuation, reading) => {
|
|
@@ -24120,21 +24295,9 @@ async function createProductionRuntime(options) {
|
|
|
24120
24295
|
await verifierEnvironment?.dispose();
|
|
24121
24296
|
}
|
|
24122
24297
|
},
|
|
24123
|
-
|
|
24124
|
-
|
|
24125
|
-
|
|
24126
|
-
const next = dimensions.map((dimension) => dimension === "cycles" ? `${state.budget.cycleCheckpoint + state.config.cycleStep} cycles` : `${state.budget.tokenCheckpoint + state.config.tokenStep} tokens`).join(" and ");
|
|
24127
|
-
const latestVerification = state.cycles.at(-1)?.verification.summary ?? "No host verification evidence yet.";
|
|
24128
|
-
const answers = await questions.ask([{
|
|
24129
|
-
header: "Loop budget",
|
|
24130
|
-
question: `Loop ${state.loopId} reached ${reached}. Latest verification: ${latestVerification} Continue until the next checkpoint (${next})?`,
|
|
24131
|
-
options: [
|
|
24132
|
-
{ label: "Continue", description: "Extend only the reached budget tranche and keep looping." },
|
|
24133
|
-
{ label: "Stop", description: "End this loop as budget exhausted." }
|
|
24134
|
-
]
|
|
24135
|
-
}], signal);
|
|
24136
|
-
return answers[0] === "Continue" ? "approved" : "rejected";
|
|
24137
|
-
},
|
|
24298
|
+
// Cycle/token values are telemetry checkpoint cadence, not an unattended
|
|
24299
|
+
// execution cap. The user can still cancel explicitly at any time.
|
|
24300
|
+
confirmBudget: async () => "approved",
|
|
24138
24301
|
fingerprint: workspaceFingerprint,
|
|
24139
24302
|
idFactory: () => `loop-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${randomUUID20().slice(0, 8)}`
|
|
24140
24303
|
});
|
|
@@ -24145,8 +24308,9 @@ async function createProductionRuntime(options) {
|
|
|
24145
24308
|
plannerModelId: mainModel,
|
|
24146
24309
|
classifierModelId: mainModel,
|
|
24147
24310
|
skepticCount: 3,
|
|
24148
|
-
|
|
24149
|
-
|
|
24311
|
+
// Production goals run until verified, explicitly cancelled, or blocked
|
|
24312
|
+
// by a non-recoverable external condition. Numeric config values remain
|
|
24313
|
+
// accepted for compatibility but no longer terminate autonomous work.
|
|
24150
24314
|
persistence: goalStore,
|
|
24151
24315
|
onRoundBoundary: (goalId) => maybeRotateAtBoundary({ kind: "goal", id: goalId }),
|
|
24152
24316
|
onMemoryCheckpoint: (goalId) => maybeRotateAtBoundary({ kind: "goal", id: goalId }),
|
|
@@ -24287,6 +24451,7 @@ async function createProductionRuntime(options) {
|
|
|
24287
24451
|
() => rotateForHeap(activeLongTask ?? { kind: "goal", id: goalId }, currentPressureReading())
|
|
24288
24452
|
),
|
|
24289
24453
|
continuation: () => consumePendingContinuation(),
|
|
24454
|
+
rotationPending: () => memoryRotationActive(),
|
|
24290
24455
|
mcp: async (command, signal) => {
|
|
24291
24456
|
signal.throwIfAborted();
|
|
24292
24457
|
const manager = await mcpReady;
|
|
@@ -24844,6 +25009,8 @@ async function* loopSessionEvents(events, hooks) {
|
|
|
24844
25009
|
totalInputTokens,
|
|
24845
25010
|
totalOutputTokens
|
|
24846
25011
|
};
|
|
25012
|
+
} else if (event.event.type === "error" && isResumableLongTaskError(event.event.error.code)) {
|
|
25013
|
+
yield { type: "warning", message: `Loop worker segment ended at ${event.event.error.code}; checkpointing and verifying before continuing.` };
|
|
24847
25014
|
} else if (event.event.type !== "done") yield event.event;
|
|
24848
25015
|
continue;
|
|
24849
25016
|
}
|
|
@@ -24898,7 +25065,7 @@ function loopProgressEvent(event) {
|
|
|
24898
25065
|
loopId: event.loopId,
|
|
24899
25066
|
phase: "budget",
|
|
24900
25067
|
state: "info",
|
|
24901
|
-
message:
|
|
25068
|
+
message: `${event.dimensions.join(" and ")} checkpoint reached; continuing automatically.`
|
|
24902
25069
|
};
|
|
24903
25070
|
}
|
|
24904
25071
|
return {
|
|
@@ -24915,6 +25082,9 @@ function terminalProgressState(status) {
|
|
|
24915
25082
|
if (status === "needs_human") return "info";
|
|
24916
25083
|
return "failed";
|
|
24917
25084
|
}
|
|
25085
|
+
function isResumableLongTaskError(code) {
|
|
25086
|
+
return code !== "authentication" && code !== "model_not_found" && code !== "cancelled" && code !== "memory_pressure";
|
|
25087
|
+
}
|
|
24918
25088
|
async function workspaceFingerprint(workspace) {
|
|
24919
25089
|
const hash = createHash18("sha256");
|
|
24920
25090
|
const diff = await execFileNoThrow(
|
|
@@ -25574,6 +25744,13 @@ async function* goalSessionEvents(events) {
|
|
|
25574
25744
|
yield { type: "notice", message: `Resuming goal ${event.goalId} at round ${event.round} after a heap rotation.` };
|
|
25575
25745
|
continue;
|
|
25576
25746
|
}
|
|
25747
|
+
if (event.type === "goal-stage-retry") {
|
|
25748
|
+
yield {
|
|
25749
|
+
type: "warning",
|
|
25750
|
+
message: `Goal ${event.stage} attempt ${event.attempt} hit a recoverable boundary (${event.reason}); retrying in ${event.delayMs}ms.`
|
|
25751
|
+
};
|
|
25752
|
+
continue;
|
|
25753
|
+
}
|
|
25577
25754
|
if (event.type === "goal-plan-created") {
|
|
25578
25755
|
yield { type: "notice", message: `Goal plan created (${event.plan.kind}) with ${event.plan.criteria.length} acceptance criteria.` };
|
|
25579
25756
|
yield { type: "notice", message: `Plan file: ${event.planPath}` };
|
|
@@ -25600,6 +25777,8 @@ async function* goalSessionEvents(events) {
|
|
|
25600
25777
|
totalInputTokens: event.event.usage.inputTokens,
|
|
25601
25778
|
totalOutputTokens: event.event.usage.outputTokens
|
|
25602
25779
|
};
|
|
25780
|
+
} else if (event.event.type === "error" && isResumableLongTaskError(event.event.error.code)) {
|
|
25781
|
+
yield { type: "warning", message: `Goal worker segment ended at ${event.event.error.code}; checkpointing and verifying before continuing.` };
|
|
25603
25782
|
} else {
|
|
25604
25783
|
yield event.event;
|
|
25605
25784
|
}
|