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
|
@@ -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;
|
|
@@ -6763,6 +6856,7 @@ import { mkdirSync as mkdirSync4, readFileSync as readFileSync3, renameSync as r
|
|
|
6763
6856
|
import { createHash as createHash18, randomUUID as randomUUID20 } from "crypto";
|
|
6764
6857
|
import { homedir as homedir3, release as osRelease, tmpdir as tmpdir4, version as osVersion } from "os";
|
|
6765
6858
|
import { basename as basename7, dirname as dirname17, join as join30, relative as relative22, resolve as resolve31, sep as sep22 } from "path";
|
|
6859
|
+
import { performance } from "perf_hooks";
|
|
6766
6860
|
|
|
6767
6861
|
// src/agent/subagents.ts
|
|
6768
6862
|
import { z as z9 } from "zod";
|
|
@@ -7772,10 +7866,6 @@ var ContextManager = class _ContextManager {
|
|
|
7772
7866
|
}
|
|
7773
7867
|
return microcompact.changed;
|
|
7774
7868
|
}
|
|
7775
|
-
if (this.#consecutiveAutoCompactFailures >= 3) {
|
|
7776
|
-
rollbackMicrocompact();
|
|
7777
|
-
return false;
|
|
7778
|
-
}
|
|
7779
7869
|
try {
|
|
7780
7870
|
const compacted = await this.#compactConversation(signal);
|
|
7781
7871
|
if (compacted) {
|
|
@@ -8239,10 +8329,10 @@ function within(root, candidate) {
|
|
|
8239
8329
|
|
|
8240
8330
|
// src/context/summarizer.ts
|
|
8241
8331
|
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
8332
|
options.signal?.throwIfAborted();
|
|
8245
8333
|
let groups = groupMessagesByApiRound(options.messages);
|
|
8334
|
+
const maxAttempts = options.maxPromptTooLongAttempts ?? Math.max(1, Math.ceil(Math.log2(Math.max(1, groups.length))) + 1);
|
|
8335
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts <= 0) throw new Error("maxPromptTooLongAttempts must be positive");
|
|
8246
8336
|
let lastOverflow;
|
|
8247
8337
|
let progress = 20;
|
|
8248
8338
|
reportProgress(options.onProgress, progress);
|
|
@@ -8283,7 +8373,7 @@ async function summarizeWithModel(options) {
|
|
|
8283
8373
|
if (terminalError.code !== "context_overflow") throw terminalError;
|
|
8284
8374
|
lastOverflow = terminalError;
|
|
8285
8375
|
if (attempt >= maxAttempts || groups.length <= 1) throw terminalError;
|
|
8286
|
-
groups = groups.slice(1);
|
|
8376
|
+
groups = groups.slice(Math.max(1, Math.floor(groups.length / 2)));
|
|
8287
8377
|
}
|
|
8288
8378
|
throw lastOverflow ?? new Error("Compact summary failed");
|
|
8289
8379
|
}
|
|
@@ -12663,7 +12753,7 @@ function extendBudget(input, dimensions, approvedAt) {
|
|
|
12663
12753
|
return LoopStateSchema.parse({
|
|
12664
12754
|
...state,
|
|
12665
12755
|
updatedAt: approvedAt,
|
|
12666
|
-
budget: { ...state.budget, cycleCheckpoint, tokenCheckpoint, approvals }
|
|
12756
|
+
budget: { ...state.budget, cycleCheckpoint, tokenCheckpoint, approvals: approvals.slice(-64) }
|
|
12667
12757
|
});
|
|
12668
12758
|
}
|
|
12669
12759
|
function rejectBudget(input, terminalReason) {
|
|
@@ -12790,6 +12880,7 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12790
12880
|
});
|
|
12791
12881
|
let workerError;
|
|
12792
12882
|
let workerMemoryPressure = false;
|
|
12883
|
+
let workerIterationLimit = false;
|
|
12793
12884
|
for await (const event of this.#options.runWorker({
|
|
12794
12885
|
goal,
|
|
12795
12886
|
cycle,
|
|
@@ -12802,8 +12893,9 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12802
12893
|
cycleOutputTokens += event.outputTokens;
|
|
12803
12894
|
}
|
|
12804
12895
|
if (event.type === "error") {
|
|
12805
|
-
workerError = event.error
|
|
12896
|
+
workerError = event.error;
|
|
12806
12897
|
if (event.error.code === "memory_pressure") workerMemoryPressure = true;
|
|
12898
|
+
if (event.error.code === "iteration_limit") workerIterationLimit = true;
|
|
12807
12899
|
}
|
|
12808
12900
|
if (event.type === "text") workerText = `${workerText}${event.text}`.slice(-16e3);
|
|
12809
12901
|
if (this.#options.hallucinationGuard !== void 0) {
|
|
@@ -12816,7 +12908,8 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12816
12908
|
yield { type: "worker-event", event };
|
|
12817
12909
|
}
|
|
12818
12910
|
if (workerMemoryPressure) return;
|
|
12819
|
-
if (workerError !== void 0) {
|
|
12911
|
+
if (workerError !== void 0 && !workerIterationLimit && !isResumableWorkerError(workerError)) {
|
|
12912
|
+
const status = workerError.code === "cancelled" ? "cancelled" : "failed";
|
|
12820
12913
|
state = LoopStateSchema.parse({
|
|
12821
12914
|
...state,
|
|
12822
12915
|
budget: {
|
|
@@ -12826,8 +12919,8 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12826
12919
|
outputTokens: state.budget.outputTokens + cycleOutputTokens
|
|
12827
12920
|
}
|
|
12828
12921
|
});
|
|
12829
|
-
state = await this.#terminal(state,
|
|
12830
|
-
yield { type: "loop-terminal", loopId, status
|
|
12922
|
+
state = await this.#terminal(state, status, workerError.message, now());
|
|
12923
|
+
yield { type: "loop-terminal", loopId, status, reason: workerError.message };
|
|
12831
12924
|
return;
|
|
12832
12925
|
}
|
|
12833
12926
|
state = LoopStateSchema.parse({
|
|
@@ -12870,13 +12963,7 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12870
12963
|
const report = await this.#options.hallucinationGuard.evaluate(goal, workerText);
|
|
12871
12964
|
await this.#options.onMemoryCheckpoint?.(loopId);
|
|
12872
12965
|
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;
|
|
12966
|
+
guardWarnings = [...report.blockingReasons, ...report.warnings];
|
|
12880
12967
|
} catch {
|
|
12881
12968
|
}
|
|
12882
12969
|
}
|
|
@@ -12898,7 +12985,7 @@ ${lastCompletedCycle.verification.summary}`;
|
|
|
12898
12985
|
outputTokens: cycleOutputTokens,
|
|
12899
12986
|
workspaceFingerprint: fingerprint2,
|
|
12900
12987
|
verification: evidence
|
|
12901
|
-
}],
|
|
12988
|
+
}].slice(-64),
|
|
12902
12989
|
pendingCycle: null
|
|
12903
12990
|
});
|
|
12904
12991
|
await this.#options.persistence.save(state);
|
|
@@ -12927,8 +13014,8 @@ ${evidence.summary}`;
|
|
|
12927
13014
|
repeatedFailures = failureSignature === previousFailureSignature ? repeatedFailures + 1 : 1;
|
|
12928
13015
|
previousFailureSignature = failureSignature;
|
|
12929
13016
|
previousVerification = evidence;
|
|
12930
|
-
if (repeatedFailures >=
|
|
12931
|
-
const reason =
|
|
13017
|
+
if (this.#options.maxNoProgressCycles !== void 0 && repeatedFailures >= this.#options.maxNoProgressCycles) {
|
|
13018
|
+
const reason = `The same verification failure repeated ${this.#options.maxNoProgressCycles} times without material workspace progress.`;
|
|
12932
13019
|
state = await this.#terminal(state, "no_progress", reason, now());
|
|
12933
13020
|
yield { type: "loop-terminal", loopId, status: "no_progress", reason };
|
|
12934
13021
|
return;
|
|
@@ -12989,6 +13076,9 @@ ${evidence.summary}`;
|
|
|
12989
13076
|
return state;
|
|
12990
13077
|
}
|
|
12991
13078
|
};
|
|
13079
|
+
function isResumableWorkerError(error) {
|
|
13080
|
+
return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
|
|
13081
|
+
}
|
|
12992
13082
|
function countTrailingFailureSignature(cycles, signature) {
|
|
12993
13083
|
let count = 0;
|
|
12994
13084
|
for (let index = cycles.length - 1; index >= 0; index -= 1) {
|
|
@@ -13477,26 +13567,37 @@ var GoalOrchestrator = class {
|
|
|
13477
13567
|
let plan;
|
|
13478
13568
|
let planPath;
|
|
13479
13569
|
if (state.plan === null) {
|
|
13480
|
-
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
13499
|
-
|
|
13570
|
+
let planningAttempt = 0;
|
|
13571
|
+
while (true) {
|
|
13572
|
+
try {
|
|
13573
|
+
signal.throwIfAborted();
|
|
13574
|
+
await memoryCheckpoint();
|
|
13575
|
+
plan = await runPlanner({
|
|
13576
|
+
registry: this.#options.registry,
|
|
13577
|
+
modelId: this.#options.plannerModelId,
|
|
13578
|
+
objective: state.objective,
|
|
13579
|
+
signal,
|
|
13580
|
+
onProgress: memoryCheckpoint
|
|
13581
|
+
});
|
|
13582
|
+
planPath = await writePlanFile(workspace, plan);
|
|
13583
|
+
await persistState({ phase: "executing", plan, planPath, contractHash: contractHash(state.objective, plan) });
|
|
13584
|
+
yield { type: "goal-plan-created", plan, planPath };
|
|
13585
|
+
break;
|
|
13586
|
+
} catch (error) {
|
|
13587
|
+
if (memoryRotationActive()) return;
|
|
13588
|
+
const normalized = normalizeProviderError(error);
|
|
13589
|
+
if (!isResumableStageError(normalized)) {
|
|
13590
|
+
const reason = `Goal planning failed: ${normalized.message}`;
|
|
13591
|
+
await persistState({ phase: "complete", status: "failed" });
|
|
13592
|
+
yield { type: "goal-plan-failed", reason };
|
|
13593
|
+
yield { type: "goal-failed", reason };
|
|
13594
|
+
return;
|
|
13595
|
+
}
|
|
13596
|
+
planningAttempt += 1;
|
|
13597
|
+
const delayMs = stageRetryDelay(this.#options, planningAttempt);
|
|
13598
|
+
yield { type: "goal-stage-retry", stage: "planning", attempt: planningAttempt, reason: normalized.message, delayMs };
|
|
13599
|
+
await waitForStageRetry(delayMs, signal);
|
|
13600
|
+
}
|
|
13500
13601
|
}
|
|
13501
13602
|
} else {
|
|
13502
13603
|
plan = state.plan;
|
|
@@ -13507,7 +13608,7 @@ var GoalOrchestrator = class {
|
|
|
13507
13608
|
let priorFingerprint = state.gapFingerprint;
|
|
13508
13609
|
let stallStreak = state.stallStreak;
|
|
13509
13610
|
const startRound = resumeStartRound(state);
|
|
13510
|
-
for (let round = startRound; round <= this.#options.maxRounds; round++) {
|
|
13611
|
+
for (let round = startRound; this.#options.maxRounds === void 0 || round <= this.#options.maxRounds; round++) {
|
|
13511
13612
|
signal.throwIfAborted();
|
|
13512
13613
|
await this.#options.onRoundBoundary?.(state.id);
|
|
13513
13614
|
if (memoryRotationActive()) return;
|
|
@@ -13527,6 +13628,7 @@ var GoalOrchestrator = class {
|
|
|
13527
13628
|
yield { type: "goal-worker-start", round };
|
|
13528
13629
|
let workerError;
|
|
13529
13630
|
let workerMemoryPressure = false;
|
|
13631
|
+
let workerIterationLimit = false;
|
|
13530
13632
|
try {
|
|
13531
13633
|
for await (const event of this.#options.runWorker({
|
|
13532
13634
|
goal: state.objective,
|
|
@@ -13539,18 +13641,19 @@ var GoalOrchestrator = class {
|
|
|
13539
13641
|
yield { type: "goal-worker-event", round, event };
|
|
13540
13642
|
if (event.type === "text") finalResponse = `${finalResponse}${event.text}`.slice(-16e3);
|
|
13541
13643
|
if (event.type === "error") {
|
|
13542
|
-
workerError = event.error
|
|
13644
|
+
workerError = event.error;
|
|
13543
13645
|
if (event.error.code === "memory_pressure") workerMemoryPressure = true;
|
|
13646
|
+
if (event.error.code === "iteration_limit") workerIterationLimit = true;
|
|
13544
13647
|
break;
|
|
13545
13648
|
}
|
|
13546
13649
|
}
|
|
13547
13650
|
} catch (error) {
|
|
13548
13651
|
if (memoryRotationActive()) return;
|
|
13549
|
-
workerError = message(error);
|
|
13652
|
+
workerError = { code: "unknown", message: message(error) };
|
|
13550
13653
|
}
|
|
13551
13654
|
if (workerMemoryPressure) return;
|
|
13552
|
-
if (workerError !== void 0) {
|
|
13553
|
-
const reason = `Worker error in round ${round}: ${workerError}`;
|
|
13655
|
+
if (workerError !== void 0 && !workerIterationLimit && !isResumableWorkerError2(workerError)) {
|
|
13656
|
+
const reason = `Worker error in round ${round}: ${workerError.message}`;
|
|
13554
13657
|
await persistState({ phase: "complete", status: "failed" });
|
|
13555
13658
|
yield { type: "goal-failed", reason };
|
|
13556
13659
|
return;
|
|
@@ -13580,7 +13683,7 @@ var GoalOrchestrator = class {
|
|
|
13580
13683
|
round,
|
|
13581
13684
|
workspaceDiffHash: evidence.workspaceDiffHash,
|
|
13582
13685
|
...hostVerification === void 0 ? {} : { hostVerification }
|
|
13583
|
-
}] });
|
|
13686
|
+
}].slice(-64) });
|
|
13584
13687
|
let outcome;
|
|
13585
13688
|
if (plan.kind === "code-change" && hostVerification !== void 0 && !hostVerification.passed) {
|
|
13586
13689
|
if (hostVerification.commands.length === 0) {
|
|
@@ -13594,21 +13697,32 @@ var GoalOrchestrator = class {
|
|
|
13594
13697
|
fingerprint: createHash11("sha256").update(hostVerification.summary).digest("hex").slice(0, 16)
|
|
13595
13698
|
};
|
|
13596
13699
|
}
|
|
13597
|
-
} else
|
|
13598
|
-
|
|
13599
|
-
|
|
13600
|
-
|
|
13601
|
-
|
|
13602
|
-
|
|
13603
|
-
|
|
13604
|
-
|
|
13605
|
-
|
|
13606
|
-
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13700
|
+
} else {
|
|
13701
|
+
let classifierAttempt = 0;
|
|
13702
|
+
while (true) {
|
|
13703
|
+
try {
|
|
13704
|
+
outcome = await runClassifier(evidence, plan, {
|
|
13705
|
+
registry: this.#options.registry,
|
|
13706
|
+
modelId: this.#options.classifierModelId,
|
|
13707
|
+
skepticCount: this.#options.skepticCount,
|
|
13708
|
+
workspace,
|
|
13709
|
+
signal,
|
|
13710
|
+
onProgress: memoryCheckpoint
|
|
13711
|
+
});
|
|
13712
|
+
break;
|
|
13713
|
+
} catch (error) {
|
|
13714
|
+
if (memoryRotationActive()) return;
|
|
13715
|
+
const normalized = normalizeProviderError(error);
|
|
13716
|
+
if (!isResumableStageError(normalized)) {
|
|
13717
|
+
outcome = { type: "blocked", reason: `Classifier infrastructure error: ${normalized.message}` };
|
|
13718
|
+
break;
|
|
13719
|
+
}
|
|
13720
|
+
classifierAttempt += 1;
|
|
13721
|
+
const delayMs = stageRetryDelay(this.#options, classifierAttempt);
|
|
13722
|
+
yield { type: "goal-stage-retry", stage: "classification", attempt: classifierAttempt, reason: normalized.message, delayMs };
|
|
13723
|
+
await waitForStageRetry(delayMs, signal);
|
|
13724
|
+
}
|
|
13725
|
+
}
|
|
13612
13726
|
}
|
|
13613
13727
|
await persistState({ verifyRounds: round, pendingVerification: null });
|
|
13614
13728
|
yield {
|
|
@@ -13630,7 +13744,7 @@ var GoalOrchestrator = class {
|
|
|
13630
13744
|
}
|
|
13631
13745
|
if (outcome.fingerprint === priorFingerprint) {
|
|
13632
13746
|
stallStreak++;
|
|
13633
|
-
if (stallStreak >= this.#options.maxStallStreak) {
|
|
13747
|
+
if (this.#options.maxStallStreak !== void 0 && stallStreak >= this.#options.maxStallStreak) {
|
|
13634
13748
|
await persistState({
|
|
13635
13749
|
phase: "complete",
|
|
13636
13750
|
status: "failed",
|
|
@@ -13676,6 +13790,31 @@ function resumeStartRound(state) {
|
|
|
13676
13790
|
}
|
|
13677
13791
|
return state.verifyRounds >= state.workerRounds ? state.workerRounds + 1 : Math.max(state.workerRounds, 1);
|
|
13678
13792
|
}
|
|
13793
|
+
function isResumableWorkerError2(error) {
|
|
13794
|
+
return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
|
|
13795
|
+
}
|
|
13796
|
+
function isResumableStageError(error) {
|
|
13797
|
+
return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
|
|
13798
|
+
}
|
|
13799
|
+
function stageRetryDelay(options, attempt) {
|
|
13800
|
+
const delayMs = options.stageRetryDelayMs?.(attempt) ?? Math.min(6e4, 1e3 * 2 ** Math.min(attempt - 1, 6));
|
|
13801
|
+
return Number.isSafeInteger(delayMs) && delayMs >= 0 ? delayMs : 1e3;
|
|
13802
|
+
}
|
|
13803
|
+
function waitForStageRetry(delayMs, signal) {
|
|
13804
|
+
signal.throwIfAborted();
|
|
13805
|
+
if (delayMs === 0) return Promise.resolve();
|
|
13806
|
+
return new Promise((resolvePromise, reject) => {
|
|
13807
|
+
const onAbort = () => {
|
|
13808
|
+
clearTimeout(timer);
|
|
13809
|
+
reject(signal.reason instanceof Error ? signal.reason : new Error("Goal cancelled"));
|
|
13810
|
+
};
|
|
13811
|
+
const timer = setTimeout(() => {
|
|
13812
|
+
signal.removeEventListener("abort", onAbort);
|
|
13813
|
+
resolvePromise();
|
|
13814
|
+
}, delayMs);
|
|
13815
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
13816
|
+
});
|
|
13817
|
+
}
|
|
13679
13818
|
async function writePlanFile(workspace, plan) {
|
|
13680
13819
|
const dir = join17(workspace, ".flavor");
|
|
13681
13820
|
const planPath = join17(dir, "goal-plan.md");
|
|
@@ -14056,6 +14195,7 @@ function isCode4(error, code) {
|
|
|
14056
14195
|
import { readFile as readFile14 } from "fs/promises";
|
|
14057
14196
|
import { join as join21 } from "path";
|
|
14058
14197
|
var SCRIPT_PRIORITY = ["test", "typecheck", "lint", "build", "smoke:install"];
|
|
14198
|
+
var MAX_PERSISTED_VERIFICATION_STREAM_BYTES = 1024;
|
|
14059
14199
|
async function inferVerificationPlan(workspace) {
|
|
14060
14200
|
const commands = [];
|
|
14061
14201
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -14091,9 +14231,9 @@ async function runVerificationPlan(plan, workspace, signal, executionEnvironment
|
|
|
14091
14231
|
command: item.command,
|
|
14092
14232
|
args: item.args,
|
|
14093
14233
|
exitCode: result.exitCode,
|
|
14094
|
-
stdout: result.stdout,
|
|
14095
|
-
stderr: result.stderr,
|
|
14096
|
-
truncated: result.truncated
|
|
14234
|
+
stdout: boundedEvidenceTail(result.stdout),
|
|
14235
|
+
stderr: boundedEvidenceTail(result.stderr),
|
|
14236
|
+
truncated: result.truncated || Buffer.byteLength(result.stdout, "utf8") > MAX_PERSISTED_VERIFICATION_STREAM_BYTES || Buffer.byteLength(result.stderr, "utf8") > MAX_PERSISTED_VERIFICATION_STREAM_BYTES
|
|
14097
14237
|
});
|
|
14098
14238
|
if (result.exitCode !== 0) {
|
|
14099
14239
|
return { passed: false, commands, summary: `${item.label} failed with exit code ${String(result.exitCode)}.` };
|
|
@@ -14101,6 +14241,14 @@ async function runVerificationPlan(plan, workspace, signal, executionEnvironment
|
|
|
14101
14241
|
}
|
|
14102
14242
|
return { passed: true, commands, summary: `Passed ${commands.length} deterministic verification command(s).` };
|
|
14103
14243
|
}
|
|
14244
|
+
function boundedEvidenceTail(value) {
|
|
14245
|
+
const encoded = Buffer.from(value, "utf8");
|
|
14246
|
+
if (encoded.byteLength <= MAX_PERSISTED_VERIFICATION_STREAM_BYTES) return value;
|
|
14247
|
+
const prefix = Buffer.from("\u2026\n", "utf8");
|
|
14248
|
+
let start = encoded.byteLength - (MAX_PERSISTED_VERIFICATION_STREAM_BYTES - prefix.byteLength);
|
|
14249
|
+
while (start < encoded.byteLength && (encoded[start] & 192) === 128) start += 1;
|
|
14250
|
+
return `${prefix.toString("utf8")}${encoded.subarray(start).toString("utf8")}`;
|
|
14251
|
+
}
|
|
14104
14252
|
function npmScript(name) {
|
|
14105
14253
|
return name === "test" ? { label: name, command: "npm", args: ["test"] } : { label: name, command: "npm", args: ["run", name] };
|
|
14106
14254
|
}
|
|
@@ -14194,6 +14342,35 @@ function normalizeToolCallInput(input, maxDepth = 3) {
|
|
|
14194
14342
|
throw new Error(`Tool-call input must decode to an object; received ${kind}`);
|
|
14195
14343
|
}
|
|
14196
14344
|
|
|
14345
|
+
// src/utils/abort.ts
|
|
14346
|
+
function waitWithSignal(operation, signal) {
|
|
14347
|
+
if (signal === void 0) return operation;
|
|
14348
|
+
return new Promise((resolve32, reject) => {
|
|
14349
|
+
const abort2 = () => reject(signal.reason);
|
|
14350
|
+
if (signal.aborted) abort2();
|
|
14351
|
+
else signal.addEventListener("abort", abort2, { once: true });
|
|
14352
|
+
operation.then(resolve32, reject).finally(() => signal.removeEventListener("abort", abort2));
|
|
14353
|
+
});
|
|
14354
|
+
}
|
|
14355
|
+
function createScopedAbortSignal(parent) {
|
|
14356
|
+
const controller = new AbortController();
|
|
14357
|
+
let disposed = false;
|
|
14358
|
+
const abort2 = () => {
|
|
14359
|
+
if (!controller.signal.aborted) controller.abort(parent?.reason);
|
|
14360
|
+
};
|
|
14361
|
+
if (parent?.aborted) abort2();
|
|
14362
|
+
else parent?.addEventListener("abort", abort2, { once: true });
|
|
14363
|
+
return {
|
|
14364
|
+
signal: controller.signal,
|
|
14365
|
+
dispose: () => {
|
|
14366
|
+
if (disposed) return;
|
|
14367
|
+
disposed = true;
|
|
14368
|
+
parent?.removeEventListener("abort", abort2);
|
|
14369
|
+
abort2();
|
|
14370
|
+
}
|
|
14371
|
+
};
|
|
14372
|
+
}
|
|
14373
|
+
|
|
14197
14374
|
// src/models/anthropic.ts
|
|
14198
14375
|
var CLAUDE_CLIENT_HEADERS = {
|
|
14199
14376
|
"User-Agent": "claude-cli/2.1.0 (external, cli)",
|
|
@@ -14316,6 +14493,7 @@ var AnthropicModelAdapter = class {
|
|
|
14316
14493
|
void appendUsageLog(line);
|
|
14317
14494
|
}
|
|
14318
14495
|
async *stream(request) {
|
|
14496
|
+
const requestAbort = createScopedAbortSignal(request.signal);
|
|
14319
14497
|
let inputTokens = 0;
|
|
14320
14498
|
let outputTokens = 0;
|
|
14321
14499
|
let hasUsage = false;
|
|
@@ -14439,13 +14617,13 @@ var AnthropicModelAdapter = class {
|
|
|
14439
14617
|
};
|
|
14440
14618
|
let stream;
|
|
14441
14619
|
try {
|
|
14442
|
-
stream = await this.client.messages.create(body, { signal:
|
|
14620
|
+
stream = await this.client.messages.create(body, { signal: requestAbort.signal });
|
|
14443
14621
|
} catch (error) {
|
|
14444
14622
|
if (this.thinkingBudget > 0 && !this.#thinkingRejected && isThinkingParamRejected(error)) {
|
|
14445
14623
|
this.#thinkingRejected = true;
|
|
14446
14624
|
delete body.thinking;
|
|
14447
14625
|
stripThinkingBlocks(body.messages);
|
|
14448
|
-
stream = await this.client.messages.create(body, { signal:
|
|
14626
|
+
stream = await this.client.messages.create(body, { signal: requestAbort.signal });
|
|
14449
14627
|
} else {
|
|
14450
14628
|
throw error;
|
|
14451
14629
|
}
|
|
@@ -14557,6 +14735,8 @@ var AnthropicModelAdapter = class {
|
|
|
14557
14735
|
};
|
|
14558
14736
|
}
|
|
14559
14737
|
yield { type: "error", error: normalizeProviderError(error) };
|
|
14738
|
+
} finally {
|
|
14739
|
+
requestAbort.dispose();
|
|
14560
14740
|
}
|
|
14561
14741
|
}
|
|
14562
14742
|
};
|
|
@@ -14701,6 +14881,7 @@ var OpenAIModelAdapter = class {
|
|
|
14701
14881
|
void appendUsageLog(line);
|
|
14702
14882
|
}
|
|
14703
14883
|
async *stream(request) {
|
|
14884
|
+
const requestAbort = createScopedAbortSignal(request.signal);
|
|
14704
14885
|
const callIds = /* @__PURE__ */ new Map();
|
|
14705
14886
|
const pendingCalls = /* @__PURE__ */ new Map();
|
|
14706
14887
|
const emittedCalls = /* @__PURE__ */ new Set();
|
|
@@ -14717,7 +14898,7 @@ var OpenAIModelAdapter = class {
|
|
|
14717
14898
|
strict: tool.strict ?? true
|
|
14718
14899
|
}))
|
|
14719
14900
|
};
|
|
14720
|
-
const stream = this.client.responses.stream(body, { signal:
|
|
14901
|
+
const stream = this.client.responses.stream(body, { signal: requestAbort.signal });
|
|
14721
14902
|
for await (const event of stream) {
|
|
14722
14903
|
if (event.type === "response.output_item.added" && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
|
|
14723
14904
|
callIds.set(event.output_index, event.item.call_id);
|
|
@@ -14811,6 +14992,8 @@ var OpenAIModelAdapter = class {
|
|
|
14811
14992
|
}
|
|
14812
14993
|
} catch (error) {
|
|
14813
14994
|
yield { type: "error", error: normalizeProviderError(error) };
|
|
14995
|
+
} finally {
|
|
14996
|
+
requestAbort.dispose();
|
|
14814
14997
|
}
|
|
14815
14998
|
}
|
|
14816
14999
|
};
|
|
@@ -18219,19 +18402,6 @@ import { isIP } from "net";
|
|
|
18219
18402
|
import { request as httpRequest } from "http";
|
|
18220
18403
|
import { request as httpsRequest } from "https";
|
|
18221
18404
|
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
18405
|
var WebFetchInput = z25.object({
|
|
18236
18406
|
url: z25.string().url().max(8192),
|
|
18237
18407
|
timeoutMs: z25.coerce.number().int().positive().max(12e4).optional(),
|
|
@@ -24063,6 +24233,18 @@ async function createProductionRuntime(options) {
|
|
|
24063
24233
|
holders.sessionTree = { entries: sessionHistory.nodeCount };
|
|
24064
24234
|
} catch {
|
|
24065
24235
|
}
|
|
24236
|
+
try {
|
|
24237
|
+
const transcript = transcriptCensus(timelineState);
|
|
24238
|
+
holders.transcript = { entries: transcript.blocks, chars: transcript.chars };
|
|
24239
|
+
holders.transcriptTurns = { entries: transcript.turns };
|
|
24240
|
+
} catch {
|
|
24241
|
+
}
|
|
24242
|
+
try {
|
|
24243
|
+
holders.userTiming = {
|
|
24244
|
+
entries: performance.getEntriesByType("measure").length + performance.getEntriesByType("mark").length
|
|
24245
|
+
};
|
|
24246
|
+
} catch {
|
|
24247
|
+
}
|
|
24066
24248
|
return holders;
|
|
24067
24249
|
};
|
|
24068
24250
|
const rotateForHeap = (continuation, reading) => {
|
|
@@ -24120,21 +24302,9 @@ async function createProductionRuntime(options) {
|
|
|
24120
24302
|
await verifierEnvironment?.dispose();
|
|
24121
24303
|
}
|
|
24122
24304
|
},
|
|
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
|
-
},
|
|
24305
|
+
// Cycle/token values are telemetry checkpoint cadence, not an unattended
|
|
24306
|
+
// execution cap. The user can still cancel explicitly at any time.
|
|
24307
|
+
confirmBudget: async () => "approved",
|
|
24138
24308
|
fingerprint: workspaceFingerprint,
|
|
24139
24309
|
idFactory: () => `loop-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "").slice(0, 17)}-${randomUUID20().slice(0, 8)}`
|
|
24140
24310
|
});
|
|
@@ -24145,8 +24315,9 @@ async function createProductionRuntime(options) {
|
|
|
24145
24315
|
plannerModelId: mainModel,
|
|
24146
24316
|
classifierModelId: mainModel,
|
|
24147
24317
|
skepticCount: 3,
|
|
24148
|
-
|
|
24149
|
-
|
|
24318
|
+
// Production goals run until verified, explicitly cancelled, or blocked
|
|
24319
|
+
// by a non-recoverable external condition. Numeric config values remain
|
|
24320
|
+
// accepted for compatibility but no longer terminate autonomous work.
|
|
24150
24321
|
persistence: goalStore,
|
|
24151
24322
|
onRoundBoundary: (goalId) => maybeRotateAtBoundary({ kind: "goal", id: goalId }),
|
|
24152
24323
|
onMemoryCheckpoint: (goalId) => maybeRotateAtBoundary({ kind: "goal", id: goalId }),
|
|
@@ -24287,6 +24458,7 @@ async function createProductionRuntime(options) {
|
|
|
24287
24458
|
() => rotateForHeap(activeLongTask ?? { kind: "goal", id: goalId }, currentPressureReading())
|
|
24288
24459
|
),
|
|
24289
24460
|
continuation: () => consumePendingContinuation(),
|
|
24461
|
+
rotationPending: () => memoryRotationActive(),
|
|
24290
24462
|
mcp: async (command, signal) => {
|
|
24291
24463
|
signal.throwIfAborted();
|
|
24292
24464
|
const manager = await mcpReady;
|
|
@@ -24844,6 +25016,8 @@ async function* loopSessionEvents(events, hooks) {
|
|
|
24844
25016
|
totalInputTokens,
|
|
24845
25017
|
totalOutputTokens
|
|
24846
25018
|
};
|
|
25019
|
+
} else if (event.event.type === "error" && isResumableLongTaskError(event.event.error.code)) {
|
|
25020
|
+
yield { type: "warning", message: `Loop worker segment ended at ${event.event.error.code}; checkpointing and verifying before continuing.` };
|
|
24847
25021
|
} else if (event.event.type !== "done") yield event.event;
|
|
24848
25022
|
continue;
|
|
24849
25023
|
}
|
|
@@ -24898,7 +25072,7 @@ function loopProgressEvent(event) {
|
|
|
24898
25072
|
loopId: event.loopId,
|
|
24899
25073
|
phase: "budget",
|
|
24900
25074
|
state: "info",
|
|
24901
|
-
message:
|
|
25075
|
+
message: `${event.dimensions.join(" and ")} checkpoint reached; continuing automatically.`
|
|
24902
25076
|
};
|
|
24903
25077
|
}
|
|
24904
25078
|
return {
|
|
@@ -24915,6 +25089,9 @@ function terminalProgressState(status) {
|
|
|
24915
25089
|
if (status === "needs_human") return "info";
|
|
24916
25090
|
return "failed";
|
|
24917
25091
|
}
|
|
25092
|
+
function isResumableLongTaskError(code) {
|
|
25093
|
+
return code !== "authentication" && code !== "model_not_found" && code !== "cancelled" && code !== "memory_pressure";
|
|
25094
|
+
}
|
|
24918
25095
|
async function workspaceFingerprint(workspace) {
|
|
24919
25096
|
const hash = createHash18("sha256");
|
|
24920
25097
|
const diff = await execFileNoThrow(
|
|
@@ -25574,6 +25751,13 @@ async function* goalSessionEvents(events) {
|
|
|
25574
25751
|
yield { type: "notice", message: `Resuming goal ${event.goalId} at round ${event.round} after a heap rotation.` };
|
|
25575
25752
|
continue;
|
|
25576
25753
|
}
|
|
25754
|
+
if (event.type === "goal-stage-retry") {
|
|
25755
|
+
yield {
|
|
25756
|
+
type: "warning",
|
|
25757
|
+
message: `Goal ${event.stage} attempt ${event.attempt} hit a recoverable boundary (${event.reason}); retrying in ${event.delayMs}ms.`
|
|
25758
|
+
};
|
|
25759
|
+
continue;
|
|
25760
|
+
}
|
|
25577
25761
|
if (event.type === "goal-plan-created") {
|
|
25578
25762
|
yield { type: "notice", message: `Goal plan created (${event.plan.kind}) with ${event.plan.criteria.length} acceptance criteria.` };
|
|
25579
25763
|
yield { type: "notice", message: `Plan file: ${event.planPath}` };
|
|
@@ -25600,6 +25784,8 @@ async function* goalSessionEvents(events) {
|
|
|
25600
25784
|
totalInputTokens: event.event.usage.inputTokens,
|
|
25601
25785
|
totalOutputTokens: event.event.usage.outputTokens
|
|
25602
25786
|
};
|
|
25787
|
+
} else if (event.event.type === "error" && isResumableLongTaskError(event.event.error.code)) {
|
|
25788
|
+
yield { type: "warning", message: `Goal worker segment ended at ${event.event.error.code}; checkpointing and verifying before continuing.` };
|
|
25603
25789
|
} else {
|
|
25604
25790
|
yield event.event;
|
|
25605
25791
|
}
|