flavor-code 1.4.0-beta.3 → 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/agent/loop.d.ts +4 -2
- package/dist/{app-H7RYDMD3.js → app-SXNJDSI2.js} +3 -3
- package/dist/{chunk-NIKCPCJG.js → chunk-J7TLT6LR.js} +1098 -366
- package/dist/{chunk-3BHKW5A7.js → chunk-JZVC4477.js} +8 -2
- package/dist/{chunk-KBHWS7M6.js → chunk-KQMKY7C5.js} +4 -0
- package/dist/chunk-N5MXHJKD.js +107 -0
- package/dist/cli-main.js +20 -13
- package/dist/cli.js +51 -10
- package/dist/config/schema.d.ts +4 -0
- package/dist/context/manager.d.ts +9 -0
- package/dist/desktop/main.js +1442 -625
- package/dist/desktop-renderer/assets/index-nR67Z0XT.js +154 -0
- package/dist/desktop-renderer/assets/{interactive-terminal-j52Ty3QO.js → interactive-terminal-D2J4feTJ.js} +1 -1
- package/dist/desktop-renderer/index.html +1 -1
- package/dist/goal/classifier.d.ts +2 -0
- package/dist/goal/orchestrator.d.ts +23 -2
- package/dist/goal/planner.d.ts +2 -0
- package/dist/goal/store.d.ts +2 -0
- package/dist/goal/types.d.ts +14 -0
- package/dist/harness/journal.d.ts +2 -0
- package/dist/jobs/registry.d.ts +6 -0
- package/dist/{load-SLSL3IWR.js → load-F4AYLCF6.js} +1 -1
- package/dist/loop/orchestrator.d.ts +20 -0
- package/dist/loop/types.d.ts +7 -0
- package/dist/loop/verifier.d.ts +2 -0
- package/dist/production.d.ts +17 -0
- package/dist/sdk/index.js +4 -4
- package/dist/session/tree.d.ts +2 -0
- package/dist/ui/session.d.ts +11 -0
- package/dist/ui/transcript.d.ts +9 -0
- package/dist/utils/abort.d.ts +16 -0
- package/dist/utils/heap.d.ts +58 -0
- package/dist/utils/memory-restart.d.ts +42 -3
- package/dist/utils/rotation-census.d.ts +36 -0
- package/package.json +1 -1
- package/dist/chunk-CIVPKHF4.js +0 -53
- package/dist/desktop-renderer/assets/index-CYd5JkTR.js +0 -154
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
message,
|
|
5
5
|
redactErrorText,
|
|
6
6
|
redactSecrets
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-J7TLT6LR.js";
|
|
8
8
|
|
|
9
9
|
// src/rpc/server.ts
|
|
10
10
|
import { createInterface } from "readline";
|
|
@@ -44,7 +44,13 @@ var FlavorRpcServer = class {
|
|
|
44
44
|
this.#runtime = await this.#options.createRuntime({
|
|
45
45
|
workspace: this.#options.workspace,
|
|
46
46
|
output: (event) => {
|
|
47
|
-
|
|
47
|
+
const emitted = this.#emit({ type: "event", sessionId: this.#runtime?.sessionId, event }, "output");
|
|
48
|
+
if (event.type === "exit") {
|
|
49
|
+
void emitted.finally(() => {
|
|
50
|
+
this.#closing = true;
|
|
51
|
+
this.#lines?.close();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
48
54
|
}
|
|
49
55
|
});
|
|
50
56
|
await this.#runtime.session.start();
|
|
@@ -127,6 +127,10 @@ var FlavorConfigSchema = z.object({
|
|
|
127
127
|
maxTokens: z.number().int().positive().max(Number.MAX_SAFE_INTEGER).default(5e5),
|
|
128
128
|
isolation: z.literal("auto").default("auto")
|
|
129
129
|
}).prefault({}),
|
|
130
|
+
goal: z.object({
|
|
131
|
+
maxRounds: z.number().int().positive().max(1e4).default(100),
|
|
132
|
+
maxStallStreak: z.number().int().positive().max(100).default(3)
|
|
133
|
+
}).prefault({}),
|
|
130
134
|
context: z.object({
|
|
131
135
|
windowTokens: z.number().int().positive().default(2e5),
|
|
132
136
|
reservedOutputTokens: z.number().int().nonnegative().default(2e4),
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module"; const require = createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/utils/memory-restart.ts
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
var MEMORY_RESTART_EXIT_CODE = 75;
|
|
7
|
+
var MEMORY_RESTART_MARKER_FILE = "memory-restart.json";
|
|
8
|
+
var MEMORY_RESTART_MAX_ATTEMPTS = 24;
|
|
9
|
+
var MEMORY_RESTART_WINDOW_MS = 60 * 60 * 1e3;
|
|
10
|
+
var MEMORY_RESTART_MIN_GAP_MS = 5 * 60 * 1e3;
|
|
11
|
+
var MEMORY_RESTART_CONTINUATION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
12
|
+
var SESSION_ID_PATTERN = /^session-[A-Za-z0-9_-]+$/u;
|
|
13
|
+
var rotationActive = false;
|
|
14
|
+
function markMemoryRotation() {
|
|
15
|
+
rotationActive = true;
|
|
16
|
+
}
|
|
17
|
+
function memoryRotationActive() {
|
|
18
|
+
return rotationActive;
|
|
19
|
+
}
|
|
20
|
+
function memoryRestartMarkerPath(workspace) {
|
|
21
|
+
return join(workspace, ".flavor", "tmp", MEMORY_RESTART_MARKER_FILE);
|
|
22
|
+
}
|
|
23
|
+
function nextMemoryRestartMarker(previous, sessionId, now, continuation) {
|
|
24
|
+
const previousWindowStart = previous?.windowStartedAt ?? previous?.requestedAt;
|
|
25
|
+
const reusable = previous !== void 0 && previous.sessionId === sessionId && previousWindowStart !== void 0 && now.getTime() - Date.parse(previousWindowStart) < MEMORY_RESTART_WINDOW_MS && Number.isInteger(previous.attempts) && previous.attempts > 0;
|
|
26
|
+
return {
|
|
27
|
+
sessionId,
|
|
28
|
+
windowStartedAt: reusable ? previousWindowStart : now.toISOString(),
|
|
29
|
+
requestedAt: now.toISOString(),
|
|
30
|
+
attempts: reusable ? previous.attempts + 1 : 1,
|
|
31
|
+
...continuation === void 0 ? {} : { continuation }
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function consumedMemoryRestartMarker(marker) {
|
|
35
|
+
return {
|
|
36
|
+
sessionId: marker.sessionId,
|
|
37
|
+
...marker.windowStartedAt === void 0 ? {} : { windowStartedAt: marker.windowStartedAt },
|
|
38
|
+
requestedAt: marker.requestedAt,
|
|
39
|
+
attempts: marker.attempts
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function rotationCooldownActive(marker, sessionId, now) {
|
|
43
|
+
return marker !== void 0 && marker.sessionId === sessionId && now.getTime() - Date.parse(marker.requestedAt) < MEMORY_RESTART_MIN_GAP_MS;
|
|
44
|
+
}
|
|
45
|
+
function pendingContinuation(marker, sessionId, now) {
|
|
46
|
+
if (marker === void 0 || marker.sessionId !== sessionId) return void 0;
|
|
47
|
+
if (now.getTime() - Date.parse(marker.requestedAt) > MEMORY_RESTART_CONTINUATION_TTL_MS) return void 0;
|
|
48
|
+
const continuation = marker.continuation;
|
|
49
|
+
if (continuation === void 0) return void 0;
|
|
50
|
+
if (continuation.kind !== "loop" && continuation.kind !== "goal") return void 0;
|
|
51
|
+
if (typeof continuation.id !== "string" || continuation.id.length === 0) return void 0;
|
|
52
|
+
return continuation;
|
|
53
|
+
}
|
|
54
|
+
function shouldRelaunchForMemoryRestart(marker) {
|
|
55
|
+
return marker !== void 0 && SESSION_ID_PATTERN.test(marker.sessionId) && Number.isInteger(marker.attempts) && marker.attempts >= 1 && marker.attempts <= MEMORY_RESTART_MAX_ATTEMPTS;
|
|
56
|
+
}
|
|
57
|
+
function memoryRestartArgs(argv, marker) {
|
|
58
|
+
if (!shouldRelaunchForMemoryRestart(marker)) return void 0;
|
|
59
|
+
const stripped = [];
|
|
60
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
61
|
+
const argument = argv[index];
|
|
62
|
+
if (argument === "--resume") {
|
|
63
|
+
if (index + 1 < argv.length && !argv[index + 1].startsWith("-")) index += 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (argument.startsWith("--resume=")) continue;
|
|
67
|
+
if (argument === "--memory-restart") continue;
|
|
68
|
+
stripped.push(argument);
|
|
69
|
+
}
|
|
70
|
+
return [...stripped, "--resume", marker.sessionId, "--memory-restart"];
|
|
71
|
+
}
|
|
72
|
+
function parseMemoryRestartMarker(json) {
|
|
73
|
+
try {
|
|
74
|
+
const value = JSON.parse(json);
|
|
75
|
+
if (typeof value.sessionId !== "string" || typeof value.requestedAt !== "string" || typeof value.attempts !== "number") {
|
|
76
|
+
return void 0;
|
|
77
|
+
}
|
|
78
|
+
const continuation = value.continuation;
|
|
79
|
+
if (continuation !== void 0 && (typeof continuation !== "object" || continuation === null || continuation.kind !== "loop" && continuation.kind !== "goal" || typeof continuation.id !== "string")) {
|
|
80
|
+
return void 0;
|
|
81
|
+
}
|
|
82
|
+
const windowStartedAt = value.windowStartedAt;
|
|
83
|
+
if (windowStartedAt !== void 0 && typeof windowStartedAt !== "string") return void 0;
|
|
84
|
+
return {
|
|
85
|
+
sessionId: value.sessionId,
|
|
86
|
+
...windowStartedAt === void 0 ? {} : { windowStartedAt },
|
|
87
|
+
requestedAt: value.requestedAt,
|
|
88
|
+
attempts: value.attempts,
|
|
89
|
+
...continuation === void 0 ? {} : { continuation }
|
|
90
|
+
};
|
|
91
|
+
} catch {
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export {
|
|
97
|
+
MEMORY_RESTART_EXIT_CODE,
|
|
98
|
+
markMemoryRotation,
|
|
99
|
+
memoryRotationActive,
|
|
100
|
+
memoryRestartMarkerPath,
|
|
101
|
+
nextMemoryRestartMarker,
|
|
102
|
+
consumedMemoryRestartMarker,
|
|
103
|
+
rotationCooldownActive,
|
|
104
|
+
pendingContinuation,
|
|
105
|
+
memoryRestartArgs,
|
|
106
|
+
parseMemoryRestartMarker
|
|
107
|
+
};
|
package/dist/cli-main.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire } from "node:module"; const require = createRequire(impor
|
|
|
3
3
|
import {
|
|
4
4
|
FlavorRpcServer,
|
|
5
5
|
TraceRecorder
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JZVC4477.js";
|
|
7
7
|
import {
|
|
8
8
|
staticTaskLines
|
|
9
9
|
} from "./chunk-2BF7CVWZ.js";
|
|
@@ -29,8 +29,10 @@ import {
|
|
|
29
29
|
redactErrorText,
|
|
30
30
|
runDoctor,
|
|
31
31
|
runPalBroker
|
|
32
|
-
} from "./chunk-
|
|
33
|
-
import
|
|
32
|
+
} from "./chunk-J7TLT6LR.js";
|
|
33
|
+
import {
|
|
34
|
+
MEMORY_RESTART_EXIT_CODE
|
|
35
|
+
} from "./chunk-N5MXHJKD.js";
|
|
34
36
|
import {
|
|
35
37
|
McpServerConfigSchema,
|
|
36
38
|
McpServerNameSchema,
|
|
@@ -39,7 +41,7 @@ import {
|
|
|
39
41
|
readRecoverableFile,
|
|
40
42
|
setProjectSkillDisabled,
|
|
41
43
|
updateProtectedFile
|
|
42
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-KQMKY7C5.js";
|
|
43
45
|
import {
|
|
44
46
|
gt,
|
|
45
47
|
isValidVersion
|
|
@@ -728,7 +730,7 @@ async function runEvaluationFile(path, outputPath) {
|
|
|
728
730
|
})),
|
|
729
731
|
...parsed.maxTokens === void 0 ? {} : { maxTokens: parsed.maxTokens }
|
|
730
732
|
};
|
|
731
|
-
const configured = await import("./load-
|
|
733
|
+
const configured = await import("./load-F4AYLCF6.js").then(({ loadConfig: loadConfig2 }) => loadConfig2({ cwd: workspace, home: process.env.USERPROFILE ?? process.env.HOME ?? workspace }));
|
|
732
734
|
const environment = createExecutionEnvironment(workspace, configured.config.execution) ?? new LocalExecutionEnvironment();
|
|
733
735
|
let report;
|
|
734
736
|
try {
|
|
@@ -752,7 +754,7 @@ async function runEvaluationFile(path, outputPath) {
|
|
|
752
754
|
|
|
753
755
|
// src/cli.tsx
|
|
754
756
|
function createProgram(dependencies = {}) {
|
|
755
|
-
const program = new Command().name("flavor").description("Interactive coding agent").version(packageVersion()).option("-p, --print <prompt>", "run one prompt without the interactive UI").option("--resume [session-id]", "resume a saved session (latest when id is omitted)").option("--mode <mode>", "runtime mode: interactive or rpc").option("--workspace <path>", "workspace path (RPC mode)").option("--rpc-approvals", "allow an RPC client to resolve interactive tool approvals").option("--rpc-streamed-writes", "stream proposed file writes to an RPC client before committing them").option("--trace <path>", "write a redacted JSONL execution trace").option("--pal-name <alias>", "name this interactive Flavor instance for /pals and /chat").addOption(new Option("--pals-broker <address>").hideHelp());
|
|
757
|
+
const program = new Command().name("flavor").description("Interactive coding agent").version(packageVersion()).option("-p, --print <prompt>", "run one prompt without the interactive UI").option("--resume [session-id]", "resume a saved session (latest when id is omitted)").option("--mode <mode>", "runtime mode: interactive or rpc").option("--workspace <path>", "workspace path (RPC mode)").option("--rpc-approvals", "allow an RPC client to resolve interactive tool approvals").option("--rpc-streamed-writes", "stream proposed file writes to an RPC client before committing them").option("--trace <path>", "write a redacted JSONL execution trace").option("--pal-name <alias>", "name this interactive Flavor instance for /pals and /chat").addOption(new Option("--memory-restart").hideHelp()).addOption(new Option("--pals-broker <address>").hideHelp());
|
|
756
758
|
program.command("init [directory]").description("Initialize Flavor project files in a directory (defaults to cwd)").action(async (directory) => {
|
|
757
759
|
const cwd = directory ? resolve3(directory) : process.cwd();
|
|
758
760
|
try {
|
|
@@ -869,7 +871,7 @@ function createProgram(dependencies = {}) {
|
|
|
869
871
|
return;
|
|
870
872
|
}
|
|
871
873
|
if (options.print !== void 0) {
|
|
872
|
-
process.exitCode = await runPrint(options.print, {}, resumeSession);
|
|
874
|
+
process.exitCode = await runPrint(options.print, {}, resumeSession, options.memoryRestart === true);
|
|
873
875
|
return;
|
|
874
876
|
}
|
|
875
877
|
if (!(dependencies.isTTY?.() ?? process.stdin.isTTY)) {
|
|
@@ -898,7 +900,7 @@ async function runInteractiveCli(props) {
|
|
|
898
900
|
const [{ render, AlternateScreen }, { createElement }, { App }] = await Promise.all([
|
|
899
901
|
import("./claude-ink-ECZ6QF3P.js"),
|
|
900
902
|
import("react"),
|
|
901
|
-
import("./app-
|
|
903
|
+
import("./app-SXNJDSI2.js")
|
|
902
904
|
]);
|
|
903
905
|
const instance = await render(createElement(
|
|
904
906
|
AlternateScreen,
|
|
@@ -961,7 +963,7 @@ async function runRpcMode(options) {
|
|
|
961
963
|
});
|
|
962
964
|
await server.start();
|
|
963
965
|
await recorder?.close();
|
|
964
|
-
return 0;
|
|
966
|
+
return process.exitCode === MEMORY_RESTART_EXIT_CODE ? MEMORY_RESTART_EXIT_CODE : 0;
|
|
965
967
|
} catch (error) {
|
|
966
968
|
await recorder?.close().catch(() => void 0);
|
|
967
969
|
process.stderr.write(`rpc: ${safeError(error)}
|
|
@@ -972,7 +974,7 @@ async function runRpcMode(options) {
|
|
|
972
974
|
function setInteractiveProcessTitle(target = process) {
|
|
973
975
|
target.title = "Flavor Code";
|
|
974
976
|
}
|
|
975
|
-
async function runPrint(prompt, dependencies = {}, resumeSession) {
|
|
977
|
+
async function runPrint(prompt, dependencies = {}, resumeSession, memoryRestart = false) {
|
|
976
978
|
let code = 0;
|
|
977
979
|
let runtime;
|
|
978
980
|
const stdout = dependencies.stdout ?? ((text) => process.stdout.write(text));
|
|
@@ -1004,7 +1006,11 @@ async function runPrint(prompt, dependencies = {}, resumeSession) {
|
|
|
1004
1006
|
}
|
|
1005
1007
|
try {
|
|
1006
1008
|
await runtime.session.start();
|
|
1007
|
-
|
|
1009
|
+
if (runtime.session.rotationContinuationResumed) {
|
|
1010
|
+
await runtime.session.whenIdle();
|
|
1011
|
+
} else if (!memoryRestart) {
|
|
1012
|
+
await runtime.session.submit(prompt);
|
|
1013
|
+
}
|
|
1008
1014
|
} catch (error) {
|
|
1009
1015
|
stderr(`runtime: ${safeError(error)}
|
|
1010
1016
|
`);
|
|
@@ -1025,8 +1031,9 @@ async function runPrint(prompt, dependencies = {}, resumeSession) {
|
|
|
1025
1031
|
code = 1;
|
|
1026
1032
|
}
|
|
1027
1033
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1034
|
+
const restarting = process.exitCode === MEMORY_RESTART_EXIT_CODE;
|
|
1035
|
+
if (code === 0 && !restarting) stdout("\n");
|
|
1036
|
+
return restarting ? MEMORY_RESTART_EXIT_CODE : code;
|
|
1030
1037
|
}
|
|
1031
1038
|
function safeError(error) {
|
|
1032
1039
|
return redactErrorText(message(error));
|
package/dist/cli.js
CHANGED
|
@@ -5,19 +5,25 @@ import {
|
|
|
5
5
|
memoryRestartArgs,
|
|
6
6
|
memoryRestartMarkerPath,
|
|
7
7
|
parseMemoryRestartMarker
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-N5MXHJKD.js";
|
|
9
9
|
import "./chunk-S32JRDZK.js";
|
|
10
10
|
|
|
11
11
|
// src/launcher.ts
|
|
12
12
|
import { spawn } from "child_process";
|
|
13
|
-
import { realpathSync, readFileSync } from "fs";
|
|
13
|
+
import { mkdirSync, realpathSync, readFileSync, rmSync } from "fs";
|
|
14
|
+
import { totalmem } from "os";
|
|
15
|
+
import { join } from "path";
|
|
14
16
|
import { fileURLToPath } from "url";
|
|
15
17
|
function needsRelaunch(runtime) {
|
|
16
18
|
if (!runtime.execArgv.some((argument) => argument === "--report-on-fatalerror")) return true;
|
|
17
|
-
|
|
19
|
+
if (!runtime.execArgv.some((argument) => argument.startsWith("--heapsnapshot-near-heap-limit"))) return true;
|
|
20
|
+
if (!runtime.execArgv.some((argument) => argument === "--heap-prof")) return true;
|
|
21
|
+
return !runtime.execArgv.some((argument) => argument === "--expose-gc");
|
|
18
22
|
}
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
var HEAP_HEADROOM_MB = 8192;
|
|
24
|
+
var HEAP_HEADROOM_MIN_TOTALMEM = 12 * 1024 * 1024 * 1024;
|
|
25
|
+
function cliMainArguments(mainPath, argv, heapProfile) {
|
|
26
|
+
const flags = [
|
|
21
27
|
// Fatal V8 errors (heap OOM, native crashes) bypass crash-guard.ts and
|
|
22
28
|
// leave only an unusable native stack. Ask Node to dump a diagnostic
|
|
23
29
|
// report next to the working directory so the next crash has a scene.
|
|
@@ -27,9 +33,33 @@ function cliMainArguments(mainPath, argv) {
|
|
|
27
33
|
// Capture one heap snapshot as the heap nears its limit so the next
|
|
28
34
|
// crash leaves a .heapsnapshot retainer trail next to the report.
|
|
29
35
|
"--heapsnapshot-near-heap-limit=1",
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
// A full snapshot is intentionally reserved for a hard OOM. Sparse
|
|
37
|
+
// allocation sampling has much lower overhead and still records the
|
|
38
|
+
// allocating call stacks responsible for a controlled watermark
|
|
39
|
+
// restart, where --heapsnapshot-near-heap-limit never fires.
|
|
40
|
+
"--heap-prof",
|
|
41
|
+
"--heap-prof-interval=1048576",
|
|
42
|
+
// The heap watermarks are GC-verified: heapUsed counts uncollected
|
|
43
|
+
// garbage, and stopping turns or rotating on garbage alone would waste
|
|
44
|
+
// work. Exposing gc lets the watermark measure the live set instead.
|
|
45
|
+
"--expose-gc"
|
|
32
46
|
];
|
|
47
|
+
if (heapProfile !== void 0) {
|
|
48
|
+
flags.push(`--heap-prof-dir=${heapProfile.directory}`, `--heap-prof-name=${heapProfile.name}`);
|
|
49
|
+
}
|
|
50
|
+
const processHeapFlag = process.execArgv.find((argument) => argument.startsWith("--max-old-space-size"));
|
|
51
|
+
const argvHeapFlag = argv.find((argument) => argument.startsWith("--max-old-space-size"));
|
|
52
|
+
const userHeapFlag = processHeapFlag ?? argvHeapFlag;
|
|
53
|
+
if (userHeapFlag !== void 0) {
|
|
54
|
+
flags.push(userHeapFlag);
|
|
55
|
+
} else {
|
|
56
|
+
const constrained = process.constrainedMemory?.() ?? 0;
|
|
57
|
+
const availableLimit = constrained > 0 ? Math.min(totalmem(), constrained) : totalmem();
|
|
58
|
+
if (availableLimit >= HEAP_HEADROOM_MIN_TOTALMEM) {
|
|
59
|
+
flags.push(`--max-old-space-size=${HEAP_HEADROOM_MB}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return [...flags, mainPath, ...argv.filter((argument) => argument !== argvHeapFlag)];
|
|
33
63
|
}
|
|
34
64
|
async function launchCli() {
|
|
35
65
|
const mainUrl = new URL("./cli-main.js", import.meta.url);
|
|
@@ -43,8 +73,19 @@ async function launchCli() {
|
|
|
43
73
|
}
|
|
44
74
|
const mainPath = fileURLToPath(mainUrl);
|
|
45
75
|
let argv = process.argv.slice(2);
|
|
76
|
+
let childSequence = 0;
|
|
46
77
|
for (; ; ) {
|
|
47
|
-
const
|
|
78
|
+
const profileDirectory = join(process.cwd(), ".flavor", "tmp");
|
|
79
|
+
mkdirSync(profileDirectory, { recursive: true });
|
|
80
|
+
const profileName = `heap-profile-${Date.now()}-${process.pid}-${childSequence++}.heapprofile`;
|
|
81
|
+
const profilePath = join(profileDirectory, profileName);
|
|
82
|
+
const code = await spawnAndWait(mainPath, argv, { directory: profileDirectory, name: profileName });
|
|
83
|
+
if (code === 0) {
|
|
84
|
+
rmSync(profilePath, { force: true });
|
|
85
|
+
} else {
|
|
86
|
+
process.stderr.write(`flavor launcher: retained allocation profile ${profilePath}
|
|
87
|
+
`);
|
|
88
|
+
}
|
|
48
89
|
if (code === MEMORY_RESTART_EXIT_CODE) {
|
|
49
90
|
let marker;
|
|
50
91
|
try {
|
|
@@ -67,8 +108,8 @@ async function launchCli() {
|
|
|
67
108
|
return;
|
|
68
109
|
}
|
|
69
110
|
}
|
|
70
|
-
async function spawnAndWait(mainPath, argv) {
|
|
71
|
-
const child = spawn(process.execPath, cliMainArguments(mainPath, argv), { stdio: "inherit" });
|
|
111
|
+
async function spawnAndWait(mainPath, argv, heapProfile) {
|
|
112
|
+
const child = spawn(process.execPath, cliMainArguments(mainPath, argv, heapProfile), { stdio: "inherit" });
|
|
72
113
|
const ignoreSignal = () => {
|
|
73
114
|
};
|
|
74
115
|
process.on("SIGINT", ignoreSignal);
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -164,6 +164,10 @@ export declare const FlavorConfigSchema: z.ZodObject<{
|
|
|
164
164
|
maxTokens: z.ZodDefault<z.ZodNumber>;
|
|
165
165
|
isolation: z.ZodDefault<z.ZodLiteral<"auto">>;
|
|
166
166
|
}, z.core.$strip>>;
|
|
167
|
+
goal: z.ZodPrefault<z.ZodObject<{
|
|
168
|
+
maxRounds: z.ZodDefault<z.ZodNumber>;
|
|
169
|
+
maxStallStreak: z.ZodDefault<z.ZodNumber>;
|
|
170
|
+
}, z.core.$strip>>;
|
|
167
171
|
context: z.ZodPrefault<z.ZodObject<{
|
|
168
172
|
windowTokens: z.ZodDefault<z.ZodNumber>;
|
|
169
173
|
reservedOutputTokens: z.ZodDefault<z.ZodNumber>;
|
|
@@ -97,6 +97,15 @@ export declare class ContextManager {
|
|
|
97
97
|
restore(snapshot: ContextSnapshot): void;
|
|
98
98
|
messagesForModel(): ModelMessage[];
|
|
99
99
|
estimatedTokens(): number;
|
|
100
|
+
/** Retained sizes for the rotation census: what this context holds right now. */
|
|
101
|
+
census(): {
|
|
102
|
+
messages: number;
|
|
103
|
+
messageChars: number;
|
|
104
|
+
visibilityEntries: number;
|
|
105
|
+
visibilityChars: number;
|
|
106
|
+
transientEntries: number;
|
|
107
|
+
transientChars: number;
|
|
108
|
+
};
|
|
100
109
|
needsCompaction(): boolean;
|
|
101
110
|
get lastRecordedInputTokens(): number | undefined;
|
|
102
111
|
get consecutiveAutoCompactFailures(): number;
|