@draht/rlm 2026.7.13 → 2026.9.5-1
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/session.d.ts +2 -2
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +13 -7
- package/dist/session.js.map +1 -1
- package/package.json +4 -4
package/dist/session.d.ts
CHANGED
|
@@ -135,8 +135,8 @@ export declare class RlmSession {
|
|
|
135
135
|
* report both a network connect attempt and an out-of-workdir file read
|
|
136
136
|
* failing. Throws `RlmSandboxViolationError` (fail-closed, refusing to run
|
|
137
137
|
* at all) if:
|
|
138
|
-
* - the driver never responds (crash/hang -- guarded by the
|
|
139
|
-
* wall-clock timeout
|
|
138
|
+
* - the driver never responds (crash/hang -- guarded by the step
|
|
139
|
+
* wall-clock timeout, floored at `MIN_SELF_TEST_TIMEOUT_MS`),
|
|
140
140
|
* - the response isn't a well-formed `self_test_result`, or
|
|
141
141
|
* - either check reports the sandbox did NOT block the attempt.
|
|
142
142
|
*
|
package/dist/session.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAkHhF;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI1D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIpE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASvD;AAoND,qBAAa,UAAU;IAwBV,OAAO,CAAC,QAAQ,CAAC,IAAI;IAvBjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA6B;IACnE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IAEtC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,gBAAgB,CAAsB;IAC9C,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,eAAe,CAAS;IAEhC,YAA6B,IAAI,EAAE,iBAAiB,EAyEnD;IAED,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,cAAc;IAatB;;;;;;;;;OASG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;YAST,OAAO;IAoBrB;;;;;;;;;OASG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IAYvB;;;;;;;;;OASG;IACH,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,IAAI;IAOZ;;;;OAIG;YACW,OAAO;IAKrB,sHAAsH;YACxG,iBAAiB;YA4BjB,WAAW;IAOzB;;;;;;;;;;;;;;;;;;;;;OAqBG;YACW,WAAW;IA4BzB,OAAO,CAAC,YAAY;IAWpB,iFAAiF;IAC3E,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC,CAyBrC;IAED,iGAAiG;IAC3F,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC,CAoD9B;IAED,4GAA4G;IAC5G,OAAO,IAAI,IAAI,CAUd;CACD"}
|
package/dist/session.js
CHANGED
|
@@ -25,6 +25,12 @@ const DEFAULT_STDOUT_TRUNCATE_CHARS = 2000;
|
|
|
25
25
|
// which is explicitly a backstop, not the primary mechanism, and isn't used
|
|
26
26
|
// on macOS at all per the plan).
|
|
27
27
|
const DEFAULT_STEP_TIMEOUT_MS = 30_000;
|
|
28
|
+
/**
|
|
29
|
+
* The startup self-test spawns python3 and drives a 2 s socket probe, so it
|
|
30
|
+
* is bounded by at least this much even when a caller sets a tiny step
|
|
31
|
+
* budget -- otherwise a slow start would be reported as a sandbox violation.
|
|
32
|
+
*/
|
|
33
|
+
const MIN_SELF_TEST_TIMEOUT_MS = 10_000;
|
|
28
34
|
const DEFAULT_MAX_RSS_BYTES = 256 * 1024 * 1024;
|
|
29
35
|
const DEFAULT_RSS_POLL_INTERVAL_MS = 250;
|
|
30
36
|
/**
|
|
@@ -574,15 +580,15 @@ export class RlmSession {
|
|
|
574
580
|
* `nextMessage()` wait) -- the explicit `reject` here is what actually
|
|
575
581
|
* unblocks the caller in that case, not just a formality.
|
|
576
582
|
*/
|
|
577
|
-
withStepTimeout(promise) {
|
|
578
|
-
if (!(
|
|
583
|
+
withStepTimeout(promise, timeoutMs = this.stepTimeoutMs) {
|
|
584
|
+
if (!(timeoutMs > 0))
|
|
579
585
|
return promise;
|
|
580
586
|
return new Promise((resolve, reject) => {
|
|
581
587
|
const timer = setTimeout(() => {
|
|
582
|
-
const error = new RlmStepTimeoutError(`RlmSession: step exceeded the configured wall-clock timeout of ${
|
|
588
|
+
const error = new RlmStepTimeoutError(`RlmSession: step exceeded the configured wall-clock timeout of ${timeoutMs}ms -- killed.`);
|
|
583
589
|
this.killAndTerminate(error);
|
|
584
590
|
reject(error);
|
|
585
|
-
},
|
|
591
|
+
}, timeoutMs);
|
|
586
592
|
timer.unref();
|
|
587
593
|
promise.then((value) => {
|
|
588
594
|
clearTimeout(timer);
|
|
@@ -658,8 +664,8 @@ export class RlmSession {
|
|
|
658
664
|
* report both a network connect attempt and an out-of-workdir file read
|
|
659
665
|
* failing. Throws `RlmSandboxViolationError` (fail-closed, refusing to run
|
|
660
666
|
* at all) if:
|
|
661
|
-
* - the driver never responds (crash/hang -- guarded by the
|
|
662
|
-
* wall-clock timeout
|
|
667
|
+
* - the driver never responds (crash/hang -- guarded by the step
|
|
668
|
+
* wall-clock timeout, floored at `MIN_SELF_TEST_TIMEOUT_MS`),
|
|
663
669
|
* - the response isn't a well-formed `self_test_result`, or
|
|
664
670
|
* - either check reports the sandbox did NOT block the attempt.
|
|
665
671
|
*
|
|
@@ -677,7 +683,7 @@ export class RlmSession {
|
|
|
677
683
|
this.send({ type: "self_test" });
|
|
678
684
|
let message;
|
|
679
685
|
try {
|
|
680
|
-
message = await this.withStepTimeout(this.nextMessage());
|
|
686
|
+
message = await this.withStepTimeout(this.nextMessage(), this.stepTimeoutMs > 0 ? Math.max(this.stepTimeoutMs, MIN_SELF_TEST_TIMEOUT_MS) : 0);
|
|
681
687
|
}
|
|
682
688
|
catch (err) {
|
|
683
689
|
throw new RlmSandboxViolationError("RlmSession: OS-level sandbox startup self-test did not complete " +
|
package/dist/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `RlmSession` — the RLM root loop.\n *\n * root-LLM-produces-code -> REPL-executes -> truncated-stdout ->\n * history-append -> FINAL-check, per\n * .planning/phases/26-rlm-core-primitives/26-01-PLAN.md, Architecture\n * section 4. Talks to `../python/repl_driver.py` over the newline-delimited\n * JSON wire protocol documented in that file's module docstring (and\n * section 2-3 of the plan).\n */\n\nimport { type ChildProcess, execFile } from \"node:child_process\";\nimport { mkdtempSync, rmSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { spawnSandboxed } from \"./sandbox.js\";\nimport type { RlmHistoryEntry, RlmResult, RlmSessionOptions } from \"./types.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst DRIVER_PATH = join(__dirname, \"..\", \"python\", \"repl_driver.py\");\n\nconst DEFAULT_MAX_ITERATIONS = 24;\nconst DEFAULT_STDOUT_TRUNCATE_CHARS = 2000;\n\n// Resource-limit defaults (Phase 28, Architecture section 3). These are the\n// REAL enforcement mechanisms -- Node-side wall-clock + RSS polling, not any\n// Python-level RLIMIT/timer (see repl_driver.py's Linux-only RLIMIT_AS,\n// which is explicitly a backstop, not the primary mechanism, and isn't used\n// on macOS at all per the plan).\nconst DEFAULT_STEP_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RSS_BYTES = 256 * 1024 * 1024;\nconst DEFAULT_RSS_POLL_INTERVAL_MS = 250;\n\n/**\n * Thrown internally when a step's Node-side wall-clock timeout fires and the\n * driver subprocess is hard-killed. Caught in `run()` and mapped to\n * `RlmResult.kind === \"timeout\"` -- never surfaced to callers directly.\n */\nclass RlmStepTimeoutError extends Error {}\n\n/**\n * Thrown internally when a `maxSubCalls`/`maxTotalCostUsd` pre-check fails\n * and the driver subprocess is hard-killed as a result. Caught in `run()`\n * and mapped to `RlmResult.kind === \"budget_exhausted\"` -- never surfaced to\n * callers directly.\n */\nclass RlmBudgetExhaustedError extends Error {}\n\n/**\n * Thrown internally when the OS-level sandbox's runtime startup self-test\n * (Phase 28 Architecture section 1) doesn't confirm the sandbox is actually\n * enforcing for this process -- either the driver never answered, answered\n * with something other than a well-formed `self_test_result`, or reported\n * that a network connect or an out-of-workdir file read *succeeded*. Caught\n * in `run()` and mapped to `RlmResult.kind === \"sandbox_violation\"`. This is\n * distinct from the synchronous `SandboxUnavailableError` thrown by\n * `spawnSandboxed` itself (missing wrapper binary/profile/interpreter) --\n * that one fails closed before any process exists; this one fails closed\n * after a process exists but before it's ever trusted with real\n * root-LLM-authored code.\n */\nclass RlmSandboxViolationError extends Error {}\n\n/**\n * Reads the driver subprocess's current resident-set size in bytes, or\n * `null` if it can't be determined right now (process already exited,\n * `ps`/`/proc` unavailable, a transient read race, etc.). `null` always\n * means \"skip this poll\" -- never treated as \"assume 0 bytes\" or \"assume\n * over the limit\", since either guess could produce a wrong kill/no-kill\n * decision.\n *\n * Linux: reads `/proc/<pid>/status`'s `VmRSS` line directly (no subprocess\n * spawn needed). Every other platform (macOS in practice): shells out to\n * `ps -o rss= -p <pid>` (BSD `ps` reports RSS in KiB) since there's no\n * `/proc` to read. See Phase 28 Architecture section 3.\n */\nfunction readRssBytes(pid: number): Promise<number | null> {\n\tif (process.platform === \"linux\") {\n\t\treturn readFile(`/proc/${pid}/status`, \"utf8\").then(\n\t\t\t(status) => {\n\t\t\t\tconst match = /^VmRSS:\\s*(\\d+)\\s*kB$/m.exec(status);\n\t\t\t\treturn match ? Number(match[1]) * 1024 : null;\n\t\t\t},\n\t\t\t() => null,\n\t\t);\n\t}\n\treturn new Promise((resolve) => {\n\t\texecFile(\"ps\", [\"-o\", \"rss=\", \"-p\", String(pid)], { encoding: \"utf8\" }, (err, stdout) => {\n\t\t\tif (err) {\n\t\t\t\tresolve(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst trimmed = stdout.trim().split(\"\\n\")[0]?.trim();\n\t\t\tif (!trimmed) {\n\t\t\t\tresolve(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst kb = Number(trimmed);\n\t\t\tresolve(Number.isFinite(kb) ? kb * 1024 : null);\n\t\t});\n\t});\n}\n\n/** One newline-delimited-JSON message in either direction of the wire protocol. */\ninterface DriverMessage {\n\ttype: string;\n\t[key: string]: unknown;\n}\n\n/** The `exec_result.final` payload shape (see repl_driver.py). */\ninterface DriverFinalPayload {\n\tkind: \"value\" | \"var\";\n\t/** For \"value\": `str(answer)`. For \"var\": `repr(globals_dict[name])`. */\n\tvalue: string;\n\tname?: string;\n}\n\ninterface DriverExecResult extends DriverMessage {\n\ttype: \"exec_result\";\n\tstdout: string;\n\terror: string | null;\n\tfinal: DriverFinalPayload | null;\n}\n\n/**\n * Extracts Python source from a root-LLM response.\n *\n * Per R26-RLM.4, the response is expected to contain a ```repl or ```python\n * fenced block (possibly surrounded by prose explaining the plan). Falls\n * back to the whole (trimmed) response when no fence is present, so mocked\n * `rootLlm` callbacks in tests can return raw code directly.\n */\nexport function extractPythonCode(response: string): string {\n\tconst match = /```(?:repl|python)[ \\t]*\\r?\\n([\\s\\S]*?)```/.exec(response);\n\tif (!match) return response.trim();\n\treturn match[1].replace(/\\r?\\n$/, \"\");\n}\n\n/**\n * Truncates captured stdout to `limit` characters, appending an explicit\n * marker for how many characters were cut — matching the `[truncated N\n * chars]` format R28-SBX.4 (Phase 28) will enforce as a hard cap. This phase\n * only applies it as a plain formatting rule, not a safety mechanism.\n */\nexport function truncateStdout(stdout: string, limit: number): string {\n\tif (stdout.length <= limit) return stdout;\n\tconst omitted = stdout.length - limit;\n\treturn `${stdout.slice(0, limit)}\\n[truncated ${omitted} chars]`;\n}\n\n/**\n * Restricted Python-literal parser used to turn a `FINAL_VAR`-produced\n * `repr()` string back into a real JS value.\n *\n * Handles the JSON-safe subset the plan calls out: `None`/`True`/`False`,\n * int/float, single- or double-quoted strings (with the common backslash\n * escapes), lists, tuples (mapped to arrays — JS has no tuple type), and\n * dicts (mapped to plain objects; keys are coerced with `String(...)`).\n * Anything it can't parse (custom object reprs like `<Foo object at\n * 0x...>`, sets, NaN/Infinity, etc.) falls back to the raw repr string\n * rather than throwing, so a result is never lost — see the module-level\n * note in this file's neighboring test for why raw-string fallback beats\n * failing the whole run.\n */\nexport function pythonReprToValue(repr: string): unknown {\n\ttry {\n\t\tconst parser = new PyReprParser(repr);\n\t\tconst value = parser.parseValue();\n\t\tparser.expectEnd();\n\t\treturn value;\n\t} catch {\n\t\treturn repr;\n\t}\n}\n\nclass PyReprParseError extends Error {}\n\n/** Minimal recursive-descent parser for a subset of Python literal syntax. */\nclass PyReprParser {\n\tprivate i = 0;\n\tconstructor(private readonly src: string) {}\n\n\tprivate skipWs(): void {\n\t\twhile (this.i < this.src.length && /\\s/.test(this.src[this.i])) this.i++;\n\t}\n\n\texpectEnd(): void {\n\t\tthis.skipWs();\n\t\tif (this.i !== this.src.length) {\n\t\t\tthrow new PyReprParseError(`unexpected trailing characters at ${this.i}`);\n\t\t}\n\t}\n\n\tparseValue(): unknown {\n\t\tthis.skipWs();\n\t\tconst c = this.src[this.i];\n\t\tif (c === undefined) throw new PyReprParseError(\"unexpected end of repr\");\n\t\tif (c === \"'\" || c === '\"') return this.parseString();\n\t\tif (c === \"[\") return this.parseSequence(\"[\", \"]\");\n\t\tif (c === \"(\") return this.parseSequence(\"(\", \")\");\n\t\tif (c === \"{\") return this.parseDictOrSet();\n\t\tif (this.src.startsWith(\"None\", this.i)) {\n\t\t\tthis.i += 4;\n\t\t\treturn null;\n\t\t}\n\t\tif (this.src.startsWith(\"True\", this.i)) {\n\t\t\tthis.i += 4;\n\t\t\treturn true;\n\t\t}\n\t\tif (this.src.startsWith(\"False\", this.i)) {\n\t\t\tthis.i += 5;\n\t\t\treturn false;\n\t\t}\n\t\treturn this.parseNumber();\n\t}\n\n\tprivate parseString(): string {\n\t\tconst quote = this.src[this.i];\n\t\tthis.i++;\n\t\tlet out = \"\";\n\t\twhile (this.i < this.src.length && this.src[this.i] !== quote) {\n\t\t\tconst ch = this.src[this.i];\n\t\t\tif (ch === \"\\\\\") {\n\t\t\t\tthis.i++;\n\t\t\t\tconst esc = this.src[this.i];\n\t\t\t\tswitch (esc) {\n\t\t\t\t\tcase \"n\":\n\t\t\t\t\t\tout += \"\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"t\":\n\t\t\t\t\t\tout += \"\\t\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"r\":\n\t\t\t\t\t\tout += \"\\r\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"b\":\n\t\t\t\t\t\tout += \"\\b\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"f\":\n\t\t\t\t\t\tout += \"\\f\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"v\":\n\t\t\t\t\t\tout += \"\\v\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"0\":\n\t\t\t\t\t\tout += \"\\0\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"\\\\\":\n\t\t\t\t\t\tout += \"\\\\\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tout += \"'\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase '\"':\n\t\t\t\t\t\tout += '\"';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"x\": {\n\t\t\t\t\t\tout += String.fromCharCode(Number.parseInt(this.src.slice(this.i + 1, this.i + 3), 16));\n\t\t\t\t\t\tthis.i += 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"u\": {\n\t\t\t\t\t\tout += String.fromCharCode(Number.parseInt(this.src.slice(this.i + 1, this.i + 5), 16));\n\t\t\t\t\t\tthis.i += 4;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"U\": {\n\t\t\t\t\t\tout += String.fromCodePoint(Number.parseInt(this.src.slice(this.i + 1, this.i + 9), 16));\n\t\t\t\t\t\tthis.i += 8;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tout += esc ?? \"\";\n\t\t\t\t}\n\t\t\t\tthis.i++;\n\t\t\t} else {\n\t\t\t\tout += ch;\n\t\t\t\tthis.i++;\n\t\t\t}\n\t\t}\n\t\tif (this.src[this.i] !== quote) throw new PyReprParseError(\"unterminated string literal\");\n\t\tthis.i++;\n\t\treturn out;\n\t}\n\n\tprivate parseNumber(): number {\n\t\tconst start = this.i;\n\t\tif (this.src[this.i] === \"-\" || this.src[this.i] === \"+\") this.i++;\n\t\twhile (this.i < this.src.length && /[0-9]/.test(this.src[this.i])) this.i++;\n\t\tif (this.src[this.i] === \".\") {\n\t\t\tthis.i++;\n\t\t\twhile (this.i < this.src.length && /[0-9]/.test(this.src[this.i])) this.i++;\n\t\t}\n\t\tif (this.src[this.i] === \"e\" || this.src[this.i] === \"E\") {\n\t\t\tthis.i++;\n\t\t\tif (this.src[this.i] === \"-\" || this.src[this.i] === \"+\") this.i++;\n\t\t\twhile (this.i < this.src.length && /[0-9]/.test(this.src[this.i])) this.i++;\n\t\t}\n\t\tconst numStr = this.src.slice(start, this.i);\n\t\tif (!/^[+-]?[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?$/.test(numStr)) {\n\t\t\tthrow new PyReprParseError(`invalid number literal at ${start}`);\n\t\t}\n\t\treturn Number(numStr);\n\t}\n\n\t/** Parses `[...]` (list) or `(...)` (tuple) into a JS array. */\n\tprivate parseSequence(_open: string, close: string): unknown[] {\n\t\tthis.i++; // opening bracket\n\t\tconst out: unknown[] = [];\n\t\tthis.skipWs();\n\t\tif (this.src[this.i] === close) {\n\t\t\tthis.i++;\n\t\t\treturn out;\n\t\t}\n\t\twhile (true) {\n\t\t\tout.push(this.parseValue());\n\t\t\tthis.skipWs();\n\t\t\tif (this.src[this.i] === \",\") {\n\t\t\t\tthis.i++;\n\t\t\t\tthis.skipWs();\n\t\t\t\tif (this.src[this.i] === close) {\n\t\t\t\t\tthis.i++;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (this.src[this.i] === close) {\n\t\t\t\tthis.i++;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthrow new PyReprParseError(`expected ',' or '${close}' at ${this.i}`);\n\t\t}\n\t\treturn out;\n\t}\n\n\t/** Parses `{...}` as a dict (if any `key: value` pair is found) or a set (mapped to an array). */\n\tprivate parseDictOrSet(): unknown {\n\t\tthis.i++; // {\n\t\tthis.skipWs();\n\t\tif (this.src[this.i] === \"}\") {\n\t\t\tthis.i++;\n\t\t\treturn {};\n\t\t}\n\t\tconst firstKeyOrValue = this.parseValue();\n\t\tthis.skipWs();\n\t\tif (this.src[this.i] === \":\") {\n\t\t\tthis.i++;\n\t\t\tconst out: Record<string, unknown> = {};\n\t\t\tout[String(firstKeyOrValue)] = this.parseValue();\n\t\t\tthis.skipWs();\n\t\t\twhile (this.src[this.i] === \",\") {\n\t\t\t\tthis.i++;\n\t\t\t\tthis.skipWs();\n\t\t\t\tif (this.src[this.i] === \"}\") break;\n\t\t\t\tconst key = this.parseValue();\n\t\t\t\tthis.skipWs();\n\t\t\t\tif (this.src[this.i] !== \":\") throw new PyReprParseError(`expected ':' at ${this.i}`);\n\t\t\t\tthis.i++;\n\t\t\t\tout[String(key)] = this.parseValue();\n\t\t\t\tthis.skipWs();\n\t\t\t}\n\t\t\tif (this.src[this.i] !== \"}\") throw new PyReprParseError(\"expected '}' to close dict\");\n\t\t\tthis.i++;\n\t\t\treturn out;\n\t\t}\n\t\tconst out: unknown[] = [firstKeyOrValue];\n\t\tthis.skipWs();\n\t\twhile (this.src[this.i] === \",\") {\n\t\t\tthis.i++;\n\t\t\tthis.skipWs();\n\t\t\tif (this.src[this.i] === \"}\") break;\n\t\t\tout.push(this.parseValue());\n\t\t\tthis.skipWs();\n\t\t}\n\t\tif (this.src[this.i] !== \"}\") throw new PyReprParseError(\"expected '}' to close set\");\n\t\tthis.i++;\n\t\treturn out;\n\t}\n}\n\ninterface PendingWaiter {\n\tresolve: (message: DriverMessage) => void;\n\treject: (error: Error) => void;\n}\n\nexport class RlmSession {\n\tprivate readonly child: ChildProcess;\n\tprivate readonly workdir: string;\n\tprivate readonly stdoutTruncateChars: number;\n\tprivate readonly maxIterations: number;\n\tprivate readonly stepTimeoutMs: number;\n\tprivate readonly maxRssBytes: number;\n\tprivate readonly rssPollIntervalMs: number;\n\tprivate readonly maxSubCalls: number | undefined;\n\tprivate readonly maxTotalCostUsd: number | undefined;\n\tprivate readonly getAccumulatedCostUsd: (() => number) | undefined;\n\tprivate readonly history: RlmHistoryEntry[] = [];\n\tprivate readonly ready: Promise<void>;\n\n\tprivate buffer = \"\";\n\tprivate messageQueue: DriverMessage[] = [];\n\tprivate waiters: PendingWaiter[] = [];\n\tprivate terminated = false;\n\tprivate terminationError: Error | null = null;\n\tprivate lastFinal: DriverFinalPayload | null = null;\n\tprivate subCallCount = 0;\n\tprivate rssPollTimer: NodeJS.Timeout | undefined;\n\tprivate rssPollInFlight = false;\n\n\tconstructor(private readonly opts: RlmSessionOptions) {\n\t\tthis.stdoutTruncateChars = opts.stdoutTruncateChars ?? DEFAULT_STDOUT_TRUNCATE_CHARS;\n\t\tthis.maxIterations = opts.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n\t\tthis.stepTimeoutMs = opts.stepTimeoutMs ?? DEFAULT_STEP_TIMEOUT_MS;\n\t\tthis.maxRssBytes = opts.maxRssBytes ?? DEFAULT_MAX_RSS_BYTES;\n\t\tthis.rssPollIntervalMs = opts.rssPollIntervalMs ?? DEFAULT_RSS_POLL_INTERVAL_MS;\n\t\tthis.maxSubCalls = opts.maxSubCalls;\n\t\tthis.maxTotalCostUsd = opts.maxTotalCostUsd;\n\t\tthis.getAccumulatedCostUsd = opts.getAccumulatedCostUsd;\n\n\t\t// The session's scratch workdir -- the only place the OS-sandboxed\n\t\t// driver process may read *and* write freely (see sandbox.ts /\n\t\t// ../sandbox/macos.sb). Created fresh per session and cleaned up in\n\t\t// dispose(). Not caller-configurable (yet): Phase 28 scopes the\n\t\t// sandbox to this session-owned directory, not an arbitrary\n\t\t// caller-supplied path.\n\t\tthis.workdir = mkdtempSync(join(tmpdir(), \"rlm-session-\"));\n\n\t\t// spawnSandboxed wraps python3/repl_driver.py in the platform's\n\t\t// OS-level sandbox (sandbox-exec on macOS, unshare/bwrap on Linux) --\n\t\t// see sandbox.ts's module docstring for why this, and not\n\t\t// repl_driver.py's Python-level guardrails, is the real security\n\t\t// boundary. It throws SandboxUnavailableError synchronously (never\n\t\t// returns a fallback unwrapped command) if the sandbox can't be\n\t\t// established, which is exactly what should happen here: this\n\t\t// constructor must fail closed, not silently spawn the driver\n\t\t// unsandboxed.\n\t\tthis.child = spawnSandboxed({ driverPath: DRIVER_PATH, workdir: this.workdir });\n\n\t\tthis.child.stdout?.setEncoding(\"utf8\");\n\t\tthis.child.stdout?.on(\"data\", (chunk: string) => this.onStdoutChunk(chunk));\n\n\t\tthis.child.stderr?.setEncoding(\"utf8\");\n\t\tthis.child.stderr?.on(\"data\", (chunk: string) => {\n\t\t\t// Driver-side crashes (as opposed to in-REPL exceptions, which are\n\t\t\t// reported via exec_result.error) surface here. Don't throw on\n\t\t\t// stray stderr output alone -- just make it visible for debugging.\n\t\t\tconsole.error(`[rlm repl_driver stderr] ${chunk}`);\n\t\t});\n\n\t\tthis.child.once(\"exit\", (code, signal) => {\n\t\t\tthis.markTerminated(new Error(`RlmSession: python3 driver exited (code=${code}, signal=${signal})`));\n\t\t});\n\t\tthis.child.once(\"error\", (err) => {\n\t\t\tthis.markTerminated(new Error(`RlmSession: failed to spawn python3 driver: ${err.message}`));\n\t\t});\n\n\t\t// Node-side RSS polling (Phase 28 Architecture section 3) -- the real\n\t\t// memory enforcement mechanism, running for the whole lifetime of the\n\t\t// child process, independent of any single step's wall-clock timeout.\n\t\tthis.startRssPolling();\n\n\t\t// Tell the driver how aggressively to cap captured stdout *before* any\n\t\t// real step runs (see repl_driver.py's `configure` handling / Phase 28\n\t\t// Architecture section 5) -- fire-and-forget: writes to child.stdin are\n\t\t// delivered strictly in order, so this is guaranteed to be processed\n\t\t// before the `self_test`/`exec` messages sent next.\n\t\tthis.send({ type: \"configure\", stdoutTruncateChars: this.stdoutTruncateChars });\n\n\t\t// Runtime startup self-test (Phase 28 Architecture section 1) -- runs\n\t\t// before `context` is even seeded, let alone before any root-LLM-\n\t\t// authored `exec`. If the OS sandbox isn't actually enforcing for this\n\t\t// process, `runSelfTest()` throws and `seedContext()` never runs, so no\n\t\t// step ever executes against an unconfined driver. See\n\t\t// `RlmSandboxViolationError`'s doc comment for how this differs from\n\t\t// `spawnSandboxed`'s synchronous fail-closed throw.\n\t\tthis.ready = this.runSelfTest().then(() => this.seedContext());\n\t\t// Attach a no-op rejection handler so Node doesn't report this as an\n\t\t// unhandled rejection when the failure path is exercised without every\n\t\t// caller immediately awaiting `run()`/`step()` -- `await this.ready`\n\t\t// elsewhere still observes the same rejection (a promise notifies every\n\t\t// attached reaction, not just the first).\n\t\tthis.ready.catch(() => {});\n\t}\n\n\tprivate onStdoutChunk(chunk: string): void {\n\t\tthis.buffer += chunk;\n\t\tlet newlineIndex = this.buffer.indexOf(\"\\n\");\n\t\twhile (newlineIndex !== -1) {\n\t\t\tconst line = this.buffer.slice(0, newlineIndex);\n\t\t\tthis.buffer = this.buffer.slice(newlineIndex + 1);\n\t\t\tnewlineIndex = this.buffer.indexOf(\"\\n\");\n\t\t\tif (!line.trim()) continue;\n\t\t\tlet message: DriverMessage;\n\t\t\ttry {\n\t\t\t\tmessage = JSON.parse(line) as DriverMessage;\n\t\t\t} catch {\n\t\t\t\tthis.markTerminated(new Error(`RlmSession: driver emitted non-JSON output: ${line}`));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst waiter = this.waiters.shift();\n\t\t\tif (waiter) waiter.resolve(message);\n\t\t\telse this.messageQueue.push(message);\n\t\t}\n\t}\n\n\tprivate markTerminated(error: Error): void {\n\t\tif (this.terminated) return;\n\t\tthis.terminated = true;\n\t\tthis.terminationError = error;\n\t\tif (this.rssPollTimer) {\n\t\t\tclearInterval(this.rssPollTimer);\n\t\t\tthis.rssPollTimer = undefined;\n\t\t}\n\t\tconst waiters = this.waiters;\n\t\tthis.waiters = [];\n\t\tfor (const waiter of waiters) waiter.reject(error);\n\t}\n\n\t/**\n\t * Hard-kills the driver subprocess and marks the session terminated with\n\t * `error` in one step. Used by every resource-limit enforcement path (RSS\n\t * ceiling, wall-clock timeout, budget exhaustion) -- these are Node-side\n\t * hard kills, not attempts at graceful in-process recovery (Phase 28\n\t * Architecture sections 3 and 6). `markTerminated`'s first-write-wins\n\t * guard means whichever of these fires first supplies the message callers\n\t * actually see, even though the child's own `exit` handler will also fire\n\t * shortly after and try to (harmlessly, redundantly) mark terminated too.\n\t */\n\tprivate killAndTerminate(error: Error): void {\n\t\tthis.markTerminated(error);\n\t\tthis.child.kill(\"SIGKILL\");\n\t}\n\n\t/**\n\t * Starts the Node-side RSS poll loop (Phase 28 Architecture section 3) --\n\t * the real memory enforcement mechanism, not any Python-level\n\t * `RLIMIT_AS`. Runs for the child process's whole lifetime; `unref()`d so\n\t * it never by itself keeps the host Node process alive past everything\n\t * else finishing. A `maxRssBytes <= 0` disables polling entirely.\n\t */\n\tprivate startRssPolling(): void {\n\t\tif (!(this.maxRssBytes > 0)) return;\n\t\tconst timer = setInterval(() => {\n\t\t\tvoid this.pollRss();\n\t\t}, this.rssPollIntervalMs);\n\t\ttimer.unref();\n\t\tthis.rssPollTimer = timer;\n\t}\n\n\tprivate async pollRss(): Promise<void> {\n\t\tif (this.terminated || this.rssPollInFlight) return;\n\t\tconst pid = this.child.pid;\n\t\tif (!pid) return;\n\t\tthis.rssPollInFlight = true;\n\t\ttry {\n\t\t\tconst rssBytes = await readRssBytes(pid);\n\t\t\tif (rssBytes === null || rssBytes <= this.maxRssBytes) return;\n\t\t\tthis.killAndTerminate(\n\t\t\t\tnew Error(\n\t\t\t\t\t`RlmSession: python3 driver exceeded the configured RSS ceiling of ${this.maxRssBytes} bytes ` +\n\t\t\t\t\t\t`(observed ${rssBytes} bytes) -- killed. This is a resource-limit kill (Phase 28 Architecture ` +\n\t\t\t\t\t\t\"section 3), not the OS sandbox itself failing.\",\n\t\t\t\t),\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.rssPollInFlight = false;\n\t\t}\n\t}\n\n\t/**\n\t * Pre-dispatch sub-call budget check (Phase 28 Architecture section 6,\n\t * R28-SBX.5): called *before* an `llm_query_request` is ever forwarded to\n\t * `opts.llmQuery`, so the (budget+1)th attempted sub-call never actually\n\t * dispatches -- the session is killed right here instead. Deliberately\n\t * NOT also checked before dispatching a whole step: a step that never\n\t * attempts another sub-call can still legitimately finish (e.g. call\n\t * FINAL immediately) even after the budget is otherwise exhausted, and\n\t * pre-emptively killing such a step here would be wrong.\n\t */\n\tprivate checkSubCallBudget(): void {\n\t\tif (this.maxSubCalls === undefined) return;\n\t\tif (this.subCallCount < this.maxSubCalls) return;\n\t\tconst error = new RlmBudgetExhaustedError(\n\t\t\t`RlmSession: llm_query sub-call budget exhausted (maxSubCalls=${this.maxSubCalls}) -- refusing to ` +\n\t\t\t\t`dispatch sub-call #${this.subCallCount + 1} and killing the driver subprocess.`,\n\t\t);\n\t\tthis.killAndTerminate(error);\n\t\tthrow error;\n\t}\n\n\t/**\n\t * Pre-dispatch cost budget check (Phase 28 Architecture section 6,\n\t * R28-SBX.5): called before dispatching a step's `rootLlm` turn and\n\t * before forwarding a sub-call to `opts.llmQuery`. No-ops unless both\n\t * `maxTotalCostUsd` and `getAccumulatedCostUsd` are supplied -- see\n\t * `RlmSessionOptions.maxTotalCostUsd`'s doc comment for why an unpaired\n\t * option is a no-op rather than a guess.\n\t */\n\tprivate checkCostBudget(): void {\n\t\tif (this.maxTotalCostUsd === undefined || !this.getAccumulatedCostUsd) return;\n\t\tconst accumulated = this.getAccumulatedCostUsd();\n\t\tif (accumulated < this.maxTotalCostUsd) return;\n\t\tconst error = new RlmBudgetExhaustedError(\n\t\t\t`RlmSession: cost budget exhausted (maxTotalCostUsd=$${this.maxTotalCostUsd}, accumulated=$${accumulated}) ` +\n\t\t\t\t\"-- killing the driver subprocess.\",\n\t\t);\n\t\tthis.killAndTerminate(error);\n\t\tthrow error;\n\t}\n\n\t/**\n\t * Races `promise` against the configured wall-clock step timeout\n\t * (Phase 28 Architecture section 3, R28-SBX.3) -- the real timeout\n\t * enforcement mechanism. On expiry, hard-kills the driver subprocess and\n\t * rejects with `RlmStepTimeoutError`, even if `promise` itself is stuck\n\t * awaiting something that `markTerminated`'s waiter-rejection can't reach\n\t * (e.g. a slow/hung `opts.llmQuery` callback, as opposed to a pending\n\t * `nextMessage()` wait) -- the explicit `reject` here is what actually\n\t * unblocks the caller in that case, not just a formality.\n\t */\n\tprivate withStepTimeout<T>(promise: Promise<T>): Promise<T> {\n\t\tif (!(this.stepTimeoutMs > 0)) return promise;\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tconst error = new RlmStepTimeoutError(\n\t\t\t\t\t`RlmSession: step exceeded the configured wall-clock timeout of ${this.stepTimeoutMs}ms -- killed.`,\n\t\t\t\t);\n\t\t\t\tthis.killAndTerminate(error);\n\t\t\t\treject(error);\n\t\t\t}, this.stepTimeoutMs);\n\t\t\ttimer.unref();\n\t\t\tpromise.then(\n\t\t\t\t(value) => {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tresolve(value);\n\t\t\t\t},\n\t\t\t\t(err) => {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\treject(err);\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate nextMessage(): Promise<DriverMessage> {\n\t\tconst queued = this.messageQueue.shift();\n\t\tif (queued) return Promise.resolve(queued);\n\t\tif (this.terminated) {\n\t\t\treturn Promise.reject(this.terminationError ?? new Error(\"RlmSession: driver process is no longer running\"));\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.waiters.push({ resolve, reject });\n\t\t});\n\t}\n\n\tprivate send(message: Record<string, unknown>): void {\n\t\tif (this.terminated) {\n\t\t\tthrow this.terminationError ?? new Error(\"RlmSession: cannot send to a terminated driver process\");\n\t\t}\n\t\tthis.child.stdin?.write(`${JSON.stringify(message)}\\n`);\n\t}\n\n\t/**\n\t * Sends one `exec` message and handles any `llm_query_request` round-trips\n\t * until the matching `exec_result`, all under the wall-clock step timeout\n\t * (`withStepTimeout`, Phase 28 Architecture section 3).\n\t */\n\tprivate async runExec(code: string): Promise<DriverExecResult> {\n\t\tthis.send({ type: \"exec\", code });\n\t\treturn this.withStepTimeout(this.collectExecResult());\n\t}\n\n\t/** The message loop `runExec` races against the step timeout -- split out so `withStepTimeout` can wrap just this. */\n\tprivate async collectExecResult(): Promise<DriverExecResult> {\n\t\twhile (true) {\n\t\t\tconst message = await this.nextMessage();\n\t\t\tif (message.type === \"llm_query_request\") {\n\t\t\t\tconst id = message.id as string;\n\t\t\t\tif (!this.opts.llmQuery) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"RlmSession: REPL code called llm_query(...) but no `llmQuery` callback was provided in RlmSessionOptions.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// Budget pre-checks (Phase 28 Architecture section 6, R28-SBX.5) --\n\t\t\t\t// before this sub-call is dispatched, not after: either check can\n\t\t\t\t// throw (and kill the driver), in which case opts.llmQuery is never\n\t\t\t\t// called for this attempt at all.\n\t\t\t\tthis.checkSubCallBudget();\n\t\t\t\tthis.checkCostBudget();\n\t\t\t\tthis.subCallCount++;\n\t\t\t\tconst text = await this.opts.llmQuery(message.prompt as string);\n\t\t\t\tthis.send({ type: \"llm_query_response\", id, text });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (message.type === \"exec_result\") {\n\t\t\t\treturn message as DriverExecResult;\n\t\t\t}\n\t\t\tthrow new Error(`RlmSession: unexpected message from driver: ${JSON.stringify(message)}`);\n\t\t}\n\t}\n\n\tprivate async seedContext(): Promise<void> {\n\t\t// JSON string escaping and Python double-quoted string literal escaping\n\t\t// agree on the escapes that matter here (\\\", \\\\, \\n, \\t, \\r, and\n\t\t// \\uXXXX), so JSON.stringify produces a valid Python string literal.\n\t\tawait this.runExec(`context = ${JSON.stringify(this.opts.prompt)}`);\n\t}\n\n\t/**\n\t * Runtime proof the OS-level sandbox is actually enforcing for *this*\n\t * process (Phase 28 Architecture section 1) -- sends `{\"type\":\n\t * \"self_test\"}` and requires the driver's `self_test_result` response to\n\t * report both a network connect attempt and an out-of-workdir file read\n\t * failing. Throws `RlmSandboxViolationError` (fail-closed, refusing to run\n\t * at all) if:\n\t * - the driver never responds (crash/hang -- guarded by the same\n\t * wall-clock timeout as a normal step, via `withStepTimeout`),\n\t * - the response isn't a well-formed `self_test_result`, or\n\t * - either check reports the sandbox did NOT block the attempt.\n\t *\n\t * Deliberately does not go through `runExec`/the guarded `exec()` wire\n\t * message: `repl_driver.py`'s `_run_self_test` handles `self_test`\n\t * on a route that bypasses its own Python-level guardrails (restricted\n\t * builtins, import allowlist, AST screen) entirely, because a self-test\n\t * *routed through* those guardrails would be a false positive -- e.g.\n\t * `import socket` failing on the guardrail import allowlist looks\n\t * identical to `import socket` failing because the OS sandbox denied the\n\t * connection, even with the OS sandbox completely disabled. See\n\t * `_run_self_test`'s docstring in repl_driver.py for the full reasoning.\n\t */\n\tprivate async runSelfTest(): Promise<void> {\n\t\tthis.send({ type: \"self_test\" });\n\t\tlet message: DriverMessage;\n\t\ttry {\n\t\t\tmessage = await this.withStepTimeout(this.nextMessage());\n\t\t} catch (err) {\n\t\t\tthrow new RlmSandboxViolationError(\n\t\t\t\t\"RlmSession: OS-level sandbox startup self-test did not complete \" +\n\t\t\t\t\t`(refusing to run -- fail-closed): ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t}\n\t\tconst networkBlocked = message.type === \"self_test_result\" && message.networkBlocked === true;\n\t\tconst fileReadBlocked = message.type === \"self_test_result\" && message.fileReadBlocked === true;\n\t\tif (!networkBlocked || !fileReadBlocked) {\n\t\t\tconst error = new RlmSandboxViolationError(\n\t\t\t\t\"RlmSession: OS-level sandbox startup self-test failed -- the sandbox is not confining this \" +\n\t\t\t\t\t`process (networkBlocked=${networkBlocked}, fileReadBlocked=${fileReadBlocked}, ` +\n\t\t\t\t\t`response=${JSON.stringify(message)}). Refusing to run rather than executing unconfined ` +\n\t\t\t\t\t\"root-LLM-authored code (fail-closed).\",\n\t\t\t);\n\t\t\tthis.killAndTerminate(error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate resolveFinal(final: DriverFinalPayload): unknown {\n\t\tif (final.kind === \"value\") {\n\t\t\t// FINAL(answer) already sent `str(answer)` -- use as-is.\n\t\t\treturn final.value;\n\t\t}\n\t\t// FINAL_VAR(name) sent `repr(globals_dict[name])`. Parse it back into a\n\t\t// real JS value for JSON-safe types; fall back to the raw repr string\n\t\t// for anything else. See `pythonReprToValue`'s doc comment for why.\n\t\treturn pythonReprToValue(final.value);\n\t}\n\n\t/** One root-LLM turn: get code, exec it, append history, may resolve a final. */\n\tasync step(): Promise<RlmHistoryEntry> {\n\t\tawait this.ready;\n\t\t// Pre-dispatch cost budget check (Phase 28 Architecture section 6,\n\t\t// R28-SBX.5) -- before the root LLM is even asked for this step's code,\n\t\t// not just before a sub-call within it.\n\t\tthis.checkCostBudget();\n\t\tconst response = await this.opts.rootLlm(this.history.slice());\n\t\tconst code = extractPythonCode(response);\n\t\tconst result = await this.runExec(code);\n\t\tconst entry: RlmHistoryEntry = {\n\t\t\tstep: this.history.length + 1,\n\t\t\tcode,\n\t\t\t// Already capped+marked incrementally by the driver's\n\t\t\t// `_TruncatingStdout` (Phase 28 Architecture section 5) -- no\n\t\t\t// second Node-side truncation pass here (Phase 26's original\n\t\t\t// post-hoc `truncateStdout` call is exactly the OOM-via-print gap\n\t\t\t// this phase closes; re-applying it here on top of the driver's\n\t\t\t// own `[truncated N chars]` marker would risk mangling it).\n\t\t\ttruncatedStdout: result.stdout,\n\t\t\terror: result.error ?? null,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\t\tthis.history.push(entry);\n\t\tthis.lastFinal = result.final ?? null;\n\t\treturn entry;\n\t}\n\n\t/** Loops `step()` until a FINAL/FINAL_VAR, `maxIterations`, or an unrecoverable driver error. */\n\tasync run(): Promise<RlmResult> {\n\t\ttry {\n\t\t\twhile (this.history.length < this.maxIterations) {\n\t\t\t\tawait this.step();\n\t\t\t\tif (this.lastFinal) {\n\t\t\t\t\tconst final = this.lastFinal;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tkind: final.kind === \"var\" ? \"final_var\" : \"final\",\n\t\t\t\t\t\tvalue: this.resolveFinal(final),\n\t\t\t\t\t\tsteps: this.history.length,\n\t\t\t\t\t\thistory: this.history.slice(),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { kind: \"max_iterations\", steps: this.history.length, history: this.history.slice() };\n\t\t} catch (err) {\n\t\t\t// Typed stop reasons (Phase 28 Architecture section 6, R28-SBX.6):\n\t\t\t// a hard-killed step surfaces here as one of these internal error\n\t\t\t// classes; anything else (a genuine driver crash, a step\n\t\t\t// referencing llm_query with no callback configured, etc.) falls\n\t\t\t// through to the generic \"error\" kind, same as Phase 26.\n\t\t\tif (err instanceof RlmStepTimeoutError) {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"timeout\",\n\t\t\t\t\tvalue: err.message,\n\t\t\t\t\tsteps: this.history.length,\n\t\t\t\t\thistory: this.history.slice(),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (err instanceof RlmBudgetExhaustedError) {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"budget_exhausted\",\n\t\t\t\t\tvalue: err.message,\n\t\t\t\t\tsteps: this.history.length,\n\t\t\t\t\thistory: this.history.slice(),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (err instanceof RlmSandboxViolationError) {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"sandbox_violation\",\n\t\t\t\t\tvalue: err.message,\n\t\t\t\t\tsteps: this.history.length,\n\t\t\t\t\thistory: this.history.slice(),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tkind: \"error\",\n\t\t\t\tvalue: err instanceof Error ? err.message : String(err),\n\t\t\t\tsteps: this.history.length,\n\t\t\t\thistory: this.history.slice(),\n\t\t\t};\n\t\t}\n\t}\n\n\t/** Kills the underlying python3 subprocess and removes its scratch workdir. Safe to call more than once. */\n\tdispose(): void {\n\t\tthis.markTerminated(new Error(\"RlmSession: disposed\"));\n\t\tthis.child.stdin?.end();\n\t\tthis.child.kill();\n\t\ttry {\n\t\t\trmSync(this.workdir, { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Best-effort cleanup only -- a leftover empty-ish tmp dir isn't\n\t\t\t// worth failing dispose() over.\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAqB,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AAEtE,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAClC,MAAM,6BAA6B,GAAG,IAAI,CAAC;AAE3C,4EAA4E;AAC5E,6EAA6E;AAC7E,wEAAwE;AACxE,4EAA4E;AAC5E,iCAAiC;AACjC,MAAM,uBAAuB,GAAG,MAAM,CAAC;AACvC;;;;GAIG;AACH,MAAM,wBAAwB,GAAG,MAAM,CAAC;AACxC,MAAM,qBAAqB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAChD,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEzC;;;;GAIG;AACH,MAAM,mBAAoB,SAAQ,KAAK;CAAG;AAE1C;;;;;GAKG;AACH,MAAM,uBAAwB,SAAQ,KAAK;CAAG;AAE9C;;;;;;;;;;;;GAYG;AACH,MAAM,wBAAyB,SAAQ,KAAK;CAAG;AAE/C;;;;;;;;;;;;GAYG;AACH,SAAS,YAAY,CAAC,GAAW;IAChC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,OAAO,QAAQ,CAAC,SAAS,GAAG,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,CAClD,CAAC,MAAM,EAAE,EAAE;YACV,MAAM,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpD,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/C,CAAC,EACD,GAAG,EAAE,CAAC,IAAI,CACV,CAAC;IACH,CAAC;IACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACvF,IAAI,GAAG,EAAE,CAAC;gBACT,OAAO,CAAC,IAAI,CAAC,CAAC;gBACd,OAAO;YACR,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YACrD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,CAAC;gBACd,OAAO;YACR,CAAC;YACD,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC;AAuBD;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IACjD,MAAM,KAAK,GAAG,4CAA4C,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1E,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,KAAa;IAC3D,IAAI,MAAM,CAAC,MAAM,IAAI,KAAK;QAAE,OAAO,MAAM,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;IACtC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,gBAAgB,OAAO,SAAS,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC7C,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QAClC,MAAM,CAAC,SAAS,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,MAAM,gBAAiB,SAAQ,KAAK;CAAG;AAEvC,8EAA8E;AAC9E,MAAM,YAAY;IAEjB,YAA6B,GAAW;QAAX,QAAG,GAAH,GAAG,CAAQ;QADhC,MAAC,GAAG,CAAC,CAAC;IAC6B,CAAC;IAEpC,MAAM;QACb,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,CAAC,EAAE,CAAC;IAC1E,CAAC;IAED,SAAS;QACR,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,IAAI,gBAAgB,CAAC,qCAAqC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3E,CAAC;IACF,CAAC;IAED,UAAU;QACT,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,SAAS;YAAE,MAAM,IAAI,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;QAC1E,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;QACtD,IAAI,CAAC,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;QAC5C,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;YACZ,OAAO,IAAI,CAAC;QACb,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;YACZ,OAAO,IAAI,CAAC;QACb,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;YACZ,OAAO,KAAK,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAC3B,CAAC;IAEO,WAAW;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,CAAC,CAAC,EAAE,CAAC;QACT,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;YAC/D,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;gBACjB,IAAI,CAAC,CAAC,EAAE,CAAC;gBACT,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC7B,QAAQ,GAAG,EAAE,CAAC;oBACb,KAAK,GAAG;wBACP,GAAG,IAAI,IAAI,CAAC;wBACZ,MAAM;oBACP,KAAK,GAAG;wBACP,GAAG,IAAI,IAAI,CAAC;wBACZ,MAAM;oBACP,KAAK,GAAG;wBACP,GAAG,IAAI,IAAI,CAAC;wBACZ,MAAM;oBACP,KAAK,GAAG;wBACP,GAAG,IAAI,IAAI,CAAC;wBACZ,MAAM;oBACP,KAAK,GAAG;wBACP,GAAG,IAAI,IAAI,CAAC;wBACZ,MAAM;oBACP,KAAK,GAAG;wBACP,GAAG,IAAI,IAAI,CAAC;wBACZ,MAAM;oBACP,KAAK,GAAG;wBACP,GAAG,IAAI,IAAI,CAAC;wBACZ,MAAM;oBACP,KAAK,IAAI;wBACR,GAAG,IAAI,IAAI,CAAC;wBACZ,MAAM;oBACP,KAAK,GAAG;wBACP,GAAG,IAAI,GAAG,CAAC;wBACX,MAAM;oBACP,KAAK,GAAG;wBACP,GAAG,IAAI,GAAG,CAAC;wBACX,MAAM;oBACP,KAAK,GAAG,EAAE,CAAC;wBACV,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;wBACxF,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;wBACZ,MAAM;oBACP,CAAC;oBACD,KAAK,GAAG,EAAE,CAAC;wBACV,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;wBACxF,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;wBACZ,MAAM;oBACP,CAAC;oBACD,KAAK,GAAG,EAAE,CAAC;wBACV,GAAG,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;wBACzF,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;wBACZ,MAAM;oBACP,CAAC;oBACD;wBACC,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;gBACnB,CAAC;gBACD,IAAI,CAAC,CAAC,EAAE,CAAC;YACV,CAAC;iBAAM,CAAC;gBACP,GAAG,IAAI,EAAE,CAAC;gBACV,IAAI,CAAC,CAAC,EAAE,CAAC;YACV,CAAC;QACF,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK;YAAE,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,CAAC,CAAC;QAC1F,IAAI,CAAC,CAAC,EAAE,CAAC;QACT,OAAO,GAAG,CAAC;IACZ,CAAC;IAEO,WAAW;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC;QACrB,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QACnE,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QAC5E,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;YACT,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QAC7E,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC1D,IAAI,CAAC,CAAC,EAAE,CAAC;YACT,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YACnE,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QAC7E,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,4CAA4C,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,gBAAgB,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,gEAAgE;IACxD,aAAa,CAAC,KAAa,EAAE,KAAa;QACjD,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,kBAAkB;QAC5B,MAAM,GAAG,GAAc,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,EAAE,CAAC;YACT,OAAO,GAAG,CAAC;QACZ,CAAC;QACD,OAAO,IAAI,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;gBACT,IAAI,CAAC,MAAM,EAAE,CAAC;gBACd,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;oBAChC,IAAI,CAAC,CAAC,EAAE,CAAC;oBACT,MAAM;gBACP,CAAC;gBACD,SAAS;YACV,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;gBAChC,IAAI,CAAC,CAAC,EAAE,CAAC;gBACT,MAAM;YACP,CAAC;YACD,MAAM,IAAI,gBAAgB,CAAC,oBAAoB,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,kGAAkG;IAC1F,cAAc;QACrB,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI;QACd,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;QACX,CAAC;QACD,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;YACT,MAAM,GAAG,GAA4B,EAAE,CAAC;YACxC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YACjD,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACjC,IAAI,CAAC,CAAC,EAAE,CAAC;gBACT,IAAI,CAAC,MAAM,EAAE,CAAC;gBACd,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;oBAAE,MAAM;gBACpC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;gBAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;gBACd,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;oBAAE,MAAM,IAAI,gBAAgB,CAAC,mBAAmB,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;gBACtF,IAAI,CAAC,CAAC,EAAE,CAAC;gBACT,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;gBACrC,IAAI,CAAC,MAAM,EAAE,CAAC;YACf,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,MAAM,IAAI,gBAAgB,CAAC,4BAA4B,CAAC,CAAC;YACvF,IAAI,CAAC,CAAC,EAAE,CAAC;YACT,OAAO,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,GAAG,GAAc,CAAC,eAAe,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACjC,IAAI,CAAC,CAAC,EAAE,CAAC;YACT,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,MAAM;YACpC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACf,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,MAAM,IAAI,gBAAgB,CAAC,2BAA2B,CAAC,CAAC;QACtF,IAAI,CAAC,CAAC,EAAE,CAAC;QACT,OAAO,GAAG,CAAC;IACZ,CAAC;CACD;AAOD,MAAM,OAAO,UAAU;IAwBtB,YAA6B,IAAuB;QAAvB,SAAI,GAAJ,IAAI,CAAmB;QAbnC,YAAO,GAAsB,EAAE,CAAC;QAGzC,WAAM,GAAG,EAAE,CAAC;QACZ,iBAAY,GAAoB,EAAE,CAAC;QACnC,YAAO,GAAoB,EAAE,CAAC;QAC9B,eAAU,GAAG,KAAK,CAAC;QACnB,qBAAgB,GAAiB,IAAI,CAAC;QACtC,cAAS,GAA8B,IAAI,CAAC;QAC5C,iBAAY,GAAG,CAAC,CAAC;QAEjB,oBAAe,GAAG,KAAK,CAAC;QAG/B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,IAAI,6BAA6B,CAAC;QACrF,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,sBAAsB,CAAC;QAClE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,uBAAuB,CAAC;QACnE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,qBAAqB,CAAC;QAC7D,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,IAAI,4BAA4B,CAAC;QAChF,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACpC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;QAC5C,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAAC;QAExD,mEAAmE;QACnE,+DAA+D;QAC/D,oEAAoE;QACpE,gEAAgE;QAChE,4DAA4D;QAC5D,wBAAwB;QACxB,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;QAE3D,gEAAgE;QAChE,sEAAsE;QACtE,0DAA0D;QAC1D,iEAAiE;QACjE,mEAAmE;QACnE,gEAAgE;QAChE,8DAA8D;QAC9D,8DAA8D;QAC9D,eAAe;QACf,IAAI,CAAC,KAAK,GAAG,cAAc,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAEhF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;QAE5E,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAC/C,mEAAmE;YACnE,+DAA+D;YAC/D,mEAAmE;YACnE,OAAO,CAAC,KAAK,CAAC,4BAA4B,KAAK,EAAE,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACxC,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,2CAA2C,IAAI,YAAY,MAAM,GAAG,CAAC,CAAC,CAAC;QACtG,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAChC,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,+CAA+C,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC9F,CAAC,CAAC,CAAC;QAEH,sEAAsE;QACtE,sEAAsE;QACtE,sEAAsE;QACtE,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,uEAAuE;QACvE,uEAAuE;QACvE,wEAAwE;QACxE,qEAAqE;QACrE,oDAAoD;QACpD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC;QAEhF,sEAAsE;QACtE,kEAAkE;QAClE,uEAAuE;QACvE,wEAAwE;QACxE,uDAAuD;QACvD,qEAAqE;QACrE,oDAAoD;QACpD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC/D,qEAAqE;QACrE,uEAAuE;QACvE,qEAAqE;QACrE,wEAAwE;QACxE,0CAA0C;QAC1C,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC5B,CAAC;IAEO,aAAa,CAAC,KAAa;QAClC,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;QACrB,IAAI,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7C,OAAO,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;YAChD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;YAClD,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAAE,SAAS;YAC3B,IAAI,OAAsB,CAAC;YAC3B,IAAI,CAAC;gBACJ,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAkB,CAAC;YAC7C,CAAC;YAAC,MAAM,CAAC;gBACR,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,+CAA+C,IAAI,EAAE,CAAC,CAAC,CAAC;gBACtF,SAAS;YACV,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACpC,IAAI,MAAM;gBAAE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;;gBAC/B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;IACF,CAAC;IAEO,cAAc,CAAC,KAAY;QAClC,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAC5B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAC9B,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAC/B,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,KAAK,MAAM,MAAM,IAAI,OAAO;YAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC;IAED;;;;;;;;;OASG;IACK,gBAAgB,CAAC,KAAY;QACpC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC;IAED;;;;;;OAMG;IACK,eAAe;QACtB,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;YAAE,OAAO;QACpC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC9B,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;QACrB,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC3B,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,OAAO;QACpB,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;QAC3B,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;YACzC,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,IAAI,IAAI,CAAC,WAAW;gBAAE,OAAO;YAC9D,IAAI,CAAC,gBAAgB,CACpB,IAAI,KAAK,CACR,qEAAqE,IAAI,CAAC,WAAW,SAAS;gBAC7F,aAAa,QAAQ,0EAA0E;gBAC/F,gDAAgD,CACjD,CACD,CAAC;QACH,CAAC;gBAAS,CAAC;YACV,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC9B,CAAC;IACF,CAAC;IAED;;;;;;;;;OASG;IACK,kBAAkB;QACzB,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS;YAAE,OAAO;QAC3C,IAAI,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,WAAW;YAAE,OAAO;QACjD,MAAM,KAAK,GAAG,IAAI,uBAAuB,CACxC,gEAAgE,IAAI,CAAC,WAAW,mBAAmB;YAClG,sBAAsB,IAAI,CAAC,YAAY,GAAG,CAAC,qCAAqC,CACjF,CAAC;QACF,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC7B,MAAM,KAAK,CAAC;IACb,CAAC;IAED;;;;;;;OAOG;IACK,eAAe;QACtB,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,qBAAqB;YAAE,OAAO;QAC9E,MAAM,WAAW,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;QACjD,IAAI,WAAW,GAAG,IAAI,CAAC,eAAe;YAAE,OAAO;QAC/C,MAAM,KAAK,GAAG,IAAI,uBAAuB,CACxC,uDAAuD,IAAI,CAAC,eAAe,kBAAkB,WAAW,IAAI;YAC3G,mCAAmC,CACpC,CAAC;QACF,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC7B,MAAM,KAAK,CAAC;IACb,CAAC;IAED;;;;;;;;;OASG;IACK,eAAe,CAAI,OAAmB,EAAE,SAAS,GAAG,IAAI,CAAC,aAAa;QAC7E,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC;YAAE,OAAO,OAAO,CAAC;QACrC,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC7B,MAAM,KAAK,GAAG,IAAI,mBAAmB,CACpC,kEAAkE,SAAS,eAAe,CAC1F,CAAC;gBACF,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;gBAC7B,MAAM,CAAC,KAAK,CAAC,CAAC;YACf,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,OAAO,CAAC,IAAI,CACX,CAAC,KAAK,EAAE,EAAE;gBACT,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,EACD,CAAC,GAAG,EAAE,EAAE;gBACP,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,MAAM,CAAC,GAAG,CAAC,CAAC;YACb,CAAC,CACD,CAAC;QACH,CAAC,CAAC,CAAC;IACJ,CAAC;IAEO,WAAW;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QACzC,IAAI,MAAM;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC,CAAC;QAC9G,CAAC;QACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;IACJ,CAAC;IAEO,IAAI,CAAC,OAAgC;QAC5C,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,gBAAgB,IAAI,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACpG,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,OAAO,CAAC,IAAY;QACjC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,sHAAsH;IAC9G,KAAK,CAAC,iBAAiB;QAC9B,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YACzC,IAAI,OAAO,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;gBAC1C,MAAM,EAAE,GAAG,OAAO,CAAC,EAAY,CAAC;gBAChC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACzB,MAAM,IAAI,KAAK,CACd,2GAA2G,CAC3G,CAAC;gBACH,CAAC;gBACD,oEAAoE;gBACpE,kEAAkE;gBAClE,oEAAoE;gBACpE,kCAAkC;gBAClC,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAC1B,IAAI,CAAC,eAAe,EAAE,CAAC;gBACvB,IAAI,CAAC,YAAY,EAAE,CAAC;gBACpB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAgB,CAAC,CAAC;gBAChE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;gBACpD,SAAS;YACV,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;gBACpC,OAAO,OAA2B,CAAC;YACpC,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,+CAA+C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3F,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,WAAW;QACxB,wEAAwE;QACxE,iEAAiE;QACjE,qEAAqE;QACrE,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACK,KAAK,CAAC,WAAW;QACxB,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QACjC,IAAI,OAAsB,CAAC;QAC3B,IAAI,CAAC;YACJ,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CACnC,IAAI,CAAC,WAAW,EAAE,EAClB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC,CACnF,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,wBAAwB,CACjC,kEAAkE;gBACjE,qCAAqC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACxF,CAAC;QACH,CAAC;QACD,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,KAAK,kBAAkB,IAAI,OAAO,CAAC,cAAc,KAAK,IAAI,CAAC;QAC9F,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,KAAK,kBAAkB,IAAI,OAAO,CAAC,eAAe,KAAK,IAAI,CAAC;QAChG,IAAI,CAAC,cAAc,IAAI,CAAC,eAAe,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,IAAI,wBAAwB,CACzC,6FAA6F;gBAC5F,2BAA2B,cAAc,qBAAqB,eAAe,IAAI;gBACjF,YAAY,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,sDAAsD;gBACzF,uCAAuC,CACxC,CAAC;YACF,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAC7B,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAEO,YAAY,CAAC,KAAyB;QAC7C,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC5B,yDAAyD;YACzD,OAAO,KAAK,CAAC,KAAK,CAAC;QACpB,CAAC;QACD,wEAAwE;QACxE,sEAAsE;QACtE,oEAAoE;QACpE,OAAO,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,IAAI;QACT,MAAM,IAAI,CAAC,KAAK,CAAC;QACjB,mEAAmE;QACnE,wEAAwE;QACxE,wCAAwC;QACxC,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAC/D,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,KAAK,GAAoB;YAC9B,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAC7B,IAAI;YACJ,sDAAsD;YACtD,8DAA8D;YAC9D,6DAA6D;YAC7D,kEAAkE;YAClE,gEAAgE;YAChE,4DAA4D;YAC5D,eAAe,EAAE,MAAM,CAAC,MAAM;YAC9B,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI;YAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACnC,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC;QACtC,OAAO,KAAK,CAAC;IACd,CAAC;IAED,iGAAiG;IACjG,KAAK,CAAC,GAAG;QACR,IAAI,CAAC;YACJ,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;gBACjD,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;gBAClB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACpB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC;oBAC7B,OAAO;wBACN,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO;wBAClD,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;wBAC/B,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;wBAC1B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;qBAC7B,CAAC;gBACH,CAAC;YACF,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;QAC9F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,mEAAmE;YACnE,kEAAkE;YAClE,yDAAyD;YACzD,iEAAiE;YACjE,yDAAyD;YACzD,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;gBACxC,OAAO;oBACN,IAAI,EAAE,SAAS;oBACf,KAAK,EAAE,GAAG,CAAC,OAAO;oBAClB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;oBAC1B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;iBAC7B,CAAC;YACH,CAAC;YACD,IAAI,GAAG,YAAY,uBAAuB,EAAE,CAAC;gBAC5C,OAAO;oBACN,IAAI,EAAE,kBAAkB;oBACxB,KAAK,EAAE,GAAG,CAAC,OAAO;oBAClB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;oBAC1B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;iBAC7B,CAAC;YACH,CAAC;YACD,IAAI,GAAG,YAAY,wBAAwB,EAAE,CAAC;gBAC7C,OAAO;oBACN,IAAI,EAAE,mBAAmB;oBACzB,KAAK,EAAE,GAAG,CAAC,OAAO;oBAClB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;oBAC1B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;iBAC7B,CAAC;YACH,CAAC;YACD,OAAO;gBACN,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;gBACvD,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;gBAC1B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;aAC7B,CAAC;QACH,CAAC;IACF,CAAC;IAED,4GAA4G;IAC5G,OAAO;QACN,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAClB,IAAI,CAAC;YACJ,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACR,iEAAiE;YACjE,gCAAgC;QACjC,CAAC;IACF,CAAC;CACD","sourcesContent":["/**\n * `RlmSession` — the RLM root loop.\n *\n * root-LLM-produces-code -> REPL-executes -> truncated-stdout ->\n * history-append -> FINAL-check, per\n * .planning/phases/26-rlm-core-primitives/26-01-PLAN.md, Architecture\n * section 4. Talks to `../python/repl_driver.py` over the newline-delimited\n * JSON wire protocol documented in that file's module docstring (and\n * section 2-3 of the plan).\n */\n\nimport { type ChildProcess, execFile } from \"node:child_process\";\nimport { mkdtempSync, rmSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { spawnSandboxed } from \"./sandbox.js\";\nimport type { RlmHistoryEntry, RlmResult, RlmSessionOptions } from \"./types.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst DRIVER_PATH = join(__dirname, \"..\", \"python\", \"repl_driver.py\");\n\nconst DEFAULT_MAX_ITERATIONS = 24;\nconst DEFAULT_STDOUT_TRUNCATE_CHARS = 2000;\n\n// Resource-limit defaults (Phase 28, Architecture section 3). These are the\n// REAL enforcement mechanisms -- Node-side wall-clock + RSS polling, not any\n// Python-level RLIMIT/timer (see repl_driver.py's Linux-only RLIMIT_AS,\n// which is explicitly a backstop, not the primary mechanism, and isn't used\n// on macOS at all per the plan).\nconst DEFAULT_STEP_TIMEOUT_MS = 30_000;\n/**\n * The startup self-test spawns python3 and drives a 2 s socket probe, so it\n * is bounded by at least this much even when a caller sets a tiny step\n * budget -- otherwise a slow start would be reported as a sandbox violation.\n */\nconst MIN_SELF_TEST_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_RSS_BYTES = 256 * 1024 * 1024;\nconst DEFAULT_RSS_POLL_INTERVAL_MS = 250;\n\n/**\n * Thrown internally when a step's Node-side wall-clock timeout fires and the\n * driver subprocess is hard-killed. Caught in `run()` and mapped to\n * `RlmResult.kind === \"timeout\"` -- never surfaced to callers directly.\n */\nclass RlmStepTimeoutError extends Error {}\n\n/**\n * Thrown internally when a `maxSubCalls`/`maxTotalCostUsd` pre-check fails\n * and the driver subprocess is hard-killed as a result. Caught in `run()`\n * and mapped to `RlmResult.kind === \"budget_exhausted\"` -- never surfaced to\n * callers directly.\n */\nclass RlmBudgetExhaustedError extends Error {}\n\n/**\n * Thrown internally when the OS-level sandbox's runtime startup self-test\n * (Phase 28 Architecture section 1) doesn't confirm the sandbox is actually\n * enforcing for this process -- either the driver never answered, answered\n * with something other than a well-formed `self_test_result`, or reported\n * that a network connect or an out-of-workdir file read *succeeded*. Caught\n * in `run()` and mapped to `RlmResult.kind === \"sandbox_violation\"`. This is\n * distinct from the synchronous `SandboxUnavailableError` thrown by\n * `spawnSandboxed` itself (missing wrapper binary/profile/interpreter) --\n * that one fails closed before any process exists; this one fails closed\n * after a process exists but before it's ever trusted with real\n * root-LLM-authored code.\n */\nclass RlmSandboxViolationError extends Error {}\n\n/**\n * Reads the driver subprocess's current resident-set size in bytes, or\n * `null` if it can't be determined right now (process already exited,\n * `ps`/`/proc` unavailable, a transient read race, etc.). `null` always\n * means \"skip this poll\" -- never treated as \"assume 0 bytes\" or \"assume\n * over the limit\", since either guess could produce a wrong kill/no-kill\n * decision.\n *\n * Linux: reads `/proc/<pid>/status`'s `VmRSS` line directly (no subprocess\n * spawn needed). Every other platform (macOS in practice): shells out to\n * `ps -o rss= -p <pid>` (BSD `ps` reports RSS in KiB) since there's no\n * `/proc` to read. See Phase 28 Architecture section 3.\n */\nfunction readRssBytes(pid: number): Promise<number | null> {\n\tif (process.platform === \"linux\") {\n\t\treturn readFile(`/proc/${pid}/status`, \"utf8\").then(\n\t\t\t(status) => {\n\t\t\t\tconst match = /^VmRSS:\\s*(\\d+)\\s*kB$/m.exec(status);\n\t\t\t\treturn match ? Number(match[1]) * 1024 : null;\n\t\t\t},\n\t\t\t() => null,\n\t\t);\n\t}\n\treturn new Promise((resolve) => {\n\t\texecFile(\"ps\", [\"-o\", \"rss=\", \"-p\", String(pid)], { encoding: \"utf8\" }, (err, stdout) => {\n\t\t\tif (err) {\n\t\t\t\tresolve(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst trimmed = stdout.trim().split(\"\\n\")[0]?.trim();\n\t\t\tif (!trimmed) {\n\t\t\t\tresolve(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst kb = Number(trimmed);\n\t\t\tresolve(Number.isFinite(kb) ? kb * 1024 : null);\n\t\t});\n\t});\n}\n\n/** One newline-delimited-JSON message in either direction of the wire protocol. */\ninterface DriverMessage {\n\ttype: string;\n\t[key: string]: unknown;\n}\n\n/** The `exec_result.final` payload shape (see repl_driver.py). */\ninterface DriverFinalPayload {\n\tkind: \"value\" | \"var\";\n\t/** For \"value\": `str(answer)`. For \"var\": `repr(globals_dict[name])`. */\n\tvalue: string;\n\tname?: string;\n}\n\ninterface DriverExecResult extends DriverMessage {\n\ttype: \"exec_result\";\n\tstdout: string;\n\terror: string | null;\n\tfinal: DriverFinalPayload | null;\n}\n\n/**\n * Extracts Python source from a root-LLM response.\n *\n * Per R26-RLM.4, the response is expected to contain a ```repl or ```python\n * fenced block (possibly surrounded by prose explaining the plan). Falls\n * back to the whole (trimmed) response when no fence is present, so mocked\n * `rootLlm` callbacks in tests can return raw code directly.\n */\nexport function extractPythonCode(response: string): string {\n\tconst match = /```(?:repl|python)[ \\t]*\\r?\\n([\\s\\S]*?)```/.exec(response);\n\tif (!match) return response.trim();\n\treturn match[1].replace(/\\r?\\n$/, \"\");\n}\n\n/**\n * Truncates captured stdout to `limit` characters, appending an explicit\n * marker for how many characters were cut — matching the `[truncated N\n * chars]` format R28-SBX.4 (Phase 28) will enforce as a hard cap. This phase\n * only applies it as a plain formatting rule, not a safety mechanism.\n */\nexport function truncateStdout(stdout: string, limit: number): string {\n\tif (stdout.length <= limit) return stdout;\n\tconst omitted = stdout.length - limit;\n\treturn `${stdout.slice(0, limit)}\\n[truncated ${omitted} chars]`;\n}\n\n/**\n * Restricted Python-literal parser used to turn a `FINAL_VAR`-produced\n * `repr()` string back into a real JS value.\n *\n * Handles the JSON-safe subset the plan calls out: `None`/`True`/`False`,\n * int/float, single- or double-quoted strings (with the common backslash\n * escapes), lists, tuples (mapped to arrays — JS has no tuple type), and\n * dicts (mapped to plain objects; keys are coerced with `String(...)`).\n * Anything it can't parse (custom object reprs like `<Foo object at\n * 0x...>`, sets, NaN/Infinity, etc.) falls back to the raw repr string\n * rather than throwing, so a result is never lost — see the module-level\n * note in this file's neighboring test for why raw-string fallback beats\n * failing the whole run.\n */\nexport function pythonReprToValue(repr: string): unknown {\n\ttry {\n\t\tconst parser = new PyReprParser(repr);\n\t\tconst value = parser.parseValue();\n\t\tparser.expectEnd();\n\t\treturn value;\n\t} catch {\n\t\treturn repr;\n\t}\n}\n\nclass PyReprParseError extends Error {}\n\n/** Minimal recursive-descent parser for a subset of Python literal syntax. */\nclass PyReprParser {\n\tprivate i = 0;\n\tconstructor(private readonly src: string) {}\n\n\tprivate skipWs(): void {\n\t\twhile (this.i < this.src.length && /\\s/.test(this.src[this.i])) this.i++;\n\t}\n\n\texpectEnd(): void {\n\t\tthis.skipWs();\n\t\tif (this.i !== this.src.length) {\n\t\t\tthrow new PyReprParseError(`unexpected trailing characters at ${this.i}`);\n\t\t}\n\t}\n\n\tparseValue(): unknown {\n\t\tthis.skipWs();\n\t\tconst c = this.src[this.i];\n\t\tif (c === undefined) throw new PyReprParseError(\"unexpected end of repr\");\n\t\tif (c === \"'\" || c === '\"') return this.parseString();\n\t\tif (c === \"[\") return this.parseSequence(\"[\", \"]\");\n\t\tif (c === \"(\") return this.parseSequence(\"(\", \")\");\n\t\tif (c === \"{\") return this.parseDictOrSet();\n\t\tif (this.src.startsWith(\"None\", this.i)) {\n\t\t\tthis.i += 4;\n\t\t\treturn null;\n\t\t}\n\t\tif (this.src.startsWith(\"True\", this.i)) {\n\t\t\tthis.i += 4;\n\t\t\treturn true;\n\t\t}\n\t\tif (this.src.startsWith(\"False\", this.i)) {\n\t\t\tthis.i += 5;\n\t\t\treturn false;\n\t\t}\n\t\treturn this.parseNumber();\n\t}\n\n\tprivate parseString(): string {\n\t\tconst quote = this.src[this.i];\n\t\tthis.i++;\n\t\tlet out = \"\";\n\t\twhile (this.i < this.src.length && this.src[this.i] !== quote) {\n\t\t\tconst ch = this.src[this.i];\n\t\t\tif (ch === \"\\\\\") {\n\t\t\t\tthis.i++;\n\t\t\t\tconst esc = this.src[this.i];\n\t\t\t\tswitch (esc) {\n\t\t\t\t\tcase \"n\":\n\t\t\t\t\t\tout += \"\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"t\":\n\t\t\t\t\t\tout += \"\\t\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"r\":\n\t\t\t\t\t\tout += \"\\r\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"b\":\n\t\t\t\t\t\tout += \"\\b\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"f\":\n\t\t\t\t\t\tout += \"\\f\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"v\":\n\t\t\t\t\t\tout += \"\\v\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"0\":\n\t\t\t\t\t\tout += \"\\0\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"\\\\\":\n\t\t\t\t\t\tout += \"\\\\\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tout += \"'\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase '\"':\n\t\t\t\t\t\tout += '\"';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"x\": {\n\t\t\t\t\t\tout += String.fromCharCode(Number.parseInt(this.src.slice(this.i + 1, this.i + 3), 16));\n\t\t\t\t\t\tthis.i += 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"u\": {\n\t\t\t\t\t\tout += String.fromCharCode(Number.parseInt(this.src.slice(this.i + 1, this.i + 5), 16));\n\t\t\t\t\t\tthis.i += 4;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"U\": {\n\t\t\t\t\t\tout += String.fromCodePoint(Number.parseInt(this.src.slice(this.i + 1, this.i + 9), 16));\n\t\t\t\t\t\tthis.i += 8;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tout += esc ?? \"\";\n\t\t\t\t}\n\t\t\t\tthis.i++;\n\t\t\t} else {\n\t\t\t\tout += ch;\n\t\t\t\tthis.i++;\n\t\t\t}\n\t\t}\n\t\tif (this.src[this.i] !== quote) throw new PyReprParseError(\"unterminated string literal\");\n\t\tthis.i++;\n\t\treturn out;\n\t}\n\n\tprivate parseNumber(): number {\n\t\tconst start = this.i;\n\t\tif (this.src[this.i] === \"-\" || this.src[this.i] === \"+\") this.i++;\n\t\twhile (this.i < this.src.length && /[0-9]/.test(this.src[this.i])) this.i++;\n\t\tif (this.src[this.i] === \".\") {\n\t\t\tthis.i++;\n\t\t\twhile (this.i < this.src.length && /[0-9]/.test(this.src[this.i])) this.i++;\n\t\t}\n\t\tif (this.src[this.i] === \"e\" || this.src[this.i] === \"E\") {\n\t\t\tthis.i++;\n\t\t\tif (this.src[this.i] === \"-\" || this.src[this.i] === \"+\") this.i++;\n\t\t\twhile (this.i < this.src.length && /[0-9]/.test(this.src[this.i])) this.i++;\n\t\t}\n\t\tconst numStr = this.src.slice(start, this.i);\n\t\tif (!/^[+-]?[0-9]+(\\.[0-9]+)?([eE][+-]?[0-9]+)?$/.test(numStr)) {\n\t\t\tthrow new PyReprParseError(`invalid number literal at ${start}`);\n\t\t}\n\t\treturn Number(numStr);\n\t}\n\n\t/** Parses `[...]` (list) or `(...)` (tuple) into a JS array. */\n\tprivate parseSequence(_open: string, close: string): unknown[] {\n\t\tthis.i++; // opening bracket\n\t\tconst out: unknown[] = [];\n\t\tthis.skipWs();\n\t\tif (this.src[this.i] === close) {\n\t\t\tthis.i++;\n\t\t\treturn out;\n\t\t}\n\t\twhile (true) {\n\t\t\tout.push(this.parseValue());\n\t\t\tthis.skipWs();\n\t\t\tif (this.src[this.i] === \",\") {\n\t\t\t\tthis.i++;\n\t\t\t\tthis.skipWs();\n\t\t\t\tif (this.src[this.i] === close) {\n\t\t\t\t\tthis.i++;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (this.src[this.i] === close) {\n\t\t\t\tthis.i++;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthrow new PyReprParseError(`expected ',' or '${close}' at ${this.i}`);\n\t\t}\n\t\treturn out;\n\t}\n\n\t/** Parses `{...}` as a dict (if any `key: value` pair is found) or a set (mapped to an array). */\n\tprivate parseDictOrSet(): unknown {\n\t\tthis.i++; // {\n\t\tthis.skipWs();\n\t\tif (this.src[this.i] === \"}\") {\n\t\t\tthis.i++;\n\t\t\treturn {};\n\t\t}\n\t\tconst firstKeyOrValue = this.parseValue();\n\t\tthis.skipWs();\n\t\tif (this.src[this.i] === \":\") {\n\t\t\tthis.i++;\n\t\t\tconst out: Record<string, unknown> = {};\n\t\t\tout[String(firstKeyOrValue)] = this.parseValue();\n\t\t\tthis.skipWs();\n\t\t\twhile (this.src[this.i] === \",\") {\n\t\t\t\tthis.i++;\n\t\t\t\tthis.skipWs();\n\t\t\t\tif (this.src[this.i] === \"}\") break;\n\t\t\t\tconst key = this.parseValue();\n\t\t\t\tthis.skipWs();\n\t\t\t\tif (this.src[this.i] !== \":\") throw new PyReprParseError(`expected ':' at ${this.i}`);\n\t\t\t\tthis.i++;\n\t\t\t\tout[String(key)] = this.parseValue();\n\t\t\t\tthis.skipWs();\n\t\t\t}\n\t\t\tif (this.src[this.i] !== \"}\") throw new PyReprParseError(\"expected '}' to close dict\");\n\t\t\tthis.i++;\n\t\t\treturn out;\n\t\t}\n\t\tconst out: unknown[] = [firstKeyOrValue];\n\t\tthis.skipWs();\n\t\twhile (this.src[this.i] === \",\") {\n\t\t\tthis.i++;\n\t\t\tthis.skipWs();\n\t\t\tif (this.src[this.i] === \"}\") break;\n\t\t\tout.push(this.parseValue());\n\t\t\tthis.skipWs();\n\t\t}\n\t\tif (this.src[this.i] !== \"}\") throw new PyReprParseError(\"expected '}' to close set\");\n\t\tthis.i++;\n\t\treturn out;\n\t}\n}\n\ninterface PendingWaiter {\n\tresolve: (message: DriverMessage) => void;\n\treject: (error: Error) => void;\n}\n\nexport class RlmSession {\n\tprivate readonly child: ChildProcess;\n\tprivate readonly workdir: string;\n\tprivate readonly stdoutTruncateChars: number;\n\tprivate readonly maxIterations: number;\n\tprivate readonly stepTimeoutMs: number;\n\tprivate readonly maxRssBytes: number;\n\tprivate readonly rssPollIntervalMs: number;\n\tprivate readonly maxSubCalls: number | undefined;\n\tprivate readonly maxTotalCostUsd: number | undefined;\n\tprivate readonly getAccumulatedCostUsd: (() => number) | undefined;\n\tprivate readonly history: RlmHistoryEntry[] = [];\n\tprivate readonly ready: Promise<void>;\n\n\tprivate buffer = \"\";\n\tprivate messageQueue: DriverMessage[] = [];\n\tprivate waiters: PendingWaiter[] = [];\n\tprivate terminated = false;\n\tprivate terminationError: Error | null = null;\n\tprivate lastFinal: DriverFinalPayload | null = null;\n\tprivate subCallCount = 0;\n\tprivate rssPollTimer: NodeJS.Timeout | undefined;\n\tprivate rssPollInFlight = false;\n\n\tconstructor(private readonly opts: RlmSessionOptions) {\n\t\tthis.stdoutTruncateChars = opts.stdoutTruncateChars ?? DEFAULT_STDOUT_TRUNCATE_CHARS;\n\t\tthis.maxIterations = opts.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n\t\tthis.stepTimeoutMs = opts.stepTimeoutMs ?? DEFAULT_STEP_TIMEOUT_MS;\n\t\tthis.maxRssBytes = opts.maxRssBytes ?? DEFAULT_MAX_RSS_BYTES;\n\t\tthis.rssPollIntervalMs = opts.rssPollIntervalMs ?? DEFAULT_RSS_POLL_INTERVAL_MS;\n\t\tthis.maxSubCalls = opts.maxSubCalls;\n\t\tthis.maxTotalCostUsd = opts.maxTotalCostUsd;\n\t\tthis.getAccumulatedCostUsd = opts.getAccumulatedCostUsd;\n\n\t\t// The session's scratch workdir -- the only place the OS-sandboxed\n\t\t// driver process may read *and* write freely (see sandbox.ts /\n\t\t// ../sandbox/macos.sb). Created fresh per session and cleaned up in\n\t\t// dispose(). Not caller-configurable (yet): Phase 28 scopes the\n\t\t// sandbox to this session-owned directory, not an arbitrary\n\t\t// caller-supplied path.\n\t\tthis.workdir = mkdtempSync(join(tmpdir(), \"rlm-session-\"));\n\n\t\t// spawnSandboxed wraps python3/repl_driver.py in the platform's\n\t\t// OS-level sandbox (sandbox-exec on macOS, unshare/bwrap on Linux) --\n\t\t// see sandbox.ts's module docstring for why this, and not\n\t\t// repl_driver.py's Python-level guardrails, is the real security\n\t\t// boundary. It throws SandboxUnavailableError synchronously (never\n\t\t// returns a fallback unwrapped command) if the sandbox can't be\n\t\t// established, which is exactly what should happen here: this\n\t\t// constructor must fail closed, not silently spawn the driver\n\t\t// unsandboxed.\n\t\tthis.child = spawnSandboxed({ driverPath: DRIVER_PATH, workdir: this.workdir });\n\n\t\tthis.child.stdout?.setEncoding(\"utf8\");\n\t\tthis.child.stdout?.on(\"data\", (chunk: string) => this.onStdoutChunk(chunk));\n\n\t\tthis.child.stderr?.setEncoding(\"utf8\");\n\t\tthis.child.stderr?.on(\"data\", (chunk: string) => {\n\t\t\t// Driver-side crashes (as opposed to in-REPL exceptions, which are\n\t\t\t// reported via exec_result.error) surface here. Don't throw on\n\t\t\t// stray stderr output alone -- just make it visible for debugging.\n\t\t\tconsole.error(`[rlm repl_driver stderr] ${chunk}`);\n\t\t});\n\n\t\tthis.child.once(\"exit\", (code, signal) => {\n\t\t\tthis.markTerminated(new Error(`RlmSession: python3 driver exited (code=${code}, signal=${signal})`));\n\t\t});\n\t\tthis.child.once(\"error\", (err) => {\n\t\t\tthis.markTerminated(new Error(`RlmSession: failed to spawn python3 driver: ${err.message}`));\n\t\t});\n\n\t\t// Node-side RSS polling (Phase 28 Architecture section 3) -- the real\n\t\t// memory enforcement mechanism, running for the whole lifetime of the\n\t\t// child process, independent of any single step's wall-clock timeout.\n\t\tthis.startRssPolling();\n\n\t\t// Tell the driver how aggressively to cap captured stdout *before* any\n\t\t// real step runs (see repl_driver.py's `configure` handling / Phase 28\n\t\t// Architecture section 5) -- fire-and-forget: writes to child.stdin are\n\t\t// delivered strictly in order, so this is guaranteed to be processed\n\t\t// before the `self_test`/`exec` messages sent next.\n\t\tthis.send({ type: \"configure\", stdoutTruncateChars: this.stdoutTruncateChars });\n\n\t\t// Runtime startup self-test (Phase 28 Architecture section 1) -- runs\n\t\t// before `context` is even seeded, let alone before any root-LLM-\n\t\t// authored `exec`. If the OS sandbox isn't actually enforcing for this\n\t\t// process, `runSelfTest()` throws and `seedContext()` never runs, so no\n\t\t// step ever executes against an unconfined driver. See\n\t\t// `RlmSandboxViolationError`'s doc comment for how this differs from\n\t\t// `spawnSandboxed`'s synchronous fail-closed throw.\n\t\tthis.ready = this.runSelfTest().then(() => this.seedContext());\n\t\t// Attach a no-op rejection handler so Node doesn't report this as an\n\t\t// unhandled rejection when the failure path is exercised without every\n\t\t// caller immediately awaiting `run()`/`step()` -- `await this.ready`\n\t\t// elsewhere still observes the same rejection (a promise notifies every\n\t\t// attached reaction, not just the first).\n\t\tthis.ready.catch(() => {});\n\t}\n\n\tprivate onStdoutChunk(chunk: string): void {\n\t\tthis.buffer += chunk;\n\t\tlet newlineIndex = this.buffer.indexOf(\"\\n\");\n\t\twhile (newlineIndex !== -1) {\n\t\t\tconst line = this.buffer.slice(0, newlineIndex);\n\t\t\tthis.buffer = this.buffer.slice(newlineIndex + 1);\n\t\t\tnewlineIndex = this.buffer.indexOf(\"\\n\");\n\t\t\tif (!line.trim()) continue;\n\t\t\tlet message: DriverMessage;\n\t\t\ttry {\n\t\t\t\tmessage = JSON.parse(line) as DriverMessage;\n\t\t\t} catch {\n\t\t\t\tthis.markTerminated(new Error(`RlmSession: driver emitted non-JSON output: ${line}`));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst waiter = this.waiters.shift();\n\t\t\tif (waiter) waiter.resolve(message);\n\t\t\telse this.messageQueue.push(message);\n\t\t}\n\t}\n\n\tprivate markTerminated(error: Error): void {\n\t\tif (this.terminated) return;\n\t\tthis.terminated = true;\n\t\tthis.terminationError = error;\n\t\tif (this.rssPollTimer) {\n\t\t\tclearInterval(this.rssPollTimer);\n\t\t\tthis.rssPollTimer = undefined;\n\t\t}\n\t\tconst waiters = this.waiters;\n\t\tthis.waiters = [];\n\t\tfor (const waiter of waiters) waiter.reject(error);\n\t}\n\n\t/**\n\t * Hard-kills the driver subprocess and marks the session terminated with\n\t * `error` in one step. Used by every resource-limit enforcement path (RSS\n\t * ceiling, wall-clock timeout, budget exhaustion) -- these are Node-side\n\t * hard kills, not attempts at graceful in-process recovery (Phase 28\n\t * Architecture sections 3 and 6). `markTerminated`'s first-write-wins\n\t * guard means whichever of these fires first supplies the message callers\n\t * actually see, even though the child's own `exit` handler will also fire\n\t * shortly after and try to (harmlessly, redundantly) mark terminated too.\n\t */\n\tprivate killAndTerminate(error: Error): void {\n\t\tthis.markTerminated(error);\n\t\tthis.child.kill(\"SIGKILL\");\n\t}\n\n\t/**\n\t * Starts the Node-side RSS poll loop (Phase 28 Architecture section 3) --\n\t * the real memory enforcement mechanism, not any Python-level\n\t * `RLIMIT_AS`. Runs for the child process's whole lifetime; `unref()`d so\n\t * it never by itself keeps the host Node process alive past everything\n\t * else finishing. A `maxRssBytes <= 0` disables polling entirely.\n\t */\n\tprivate startRssPolling(): void {\n\t\tif (!(this.maxRssBytes > 0)) return;\n\t\tconst timer = setInterval(() => {\n\t\t\tvoid this.pollRss();\n\t\t}, this.rssPollIntervalMs);\n\t\ttimer.unref();\n\t\tthis.rssPollTimer = timer;\n\t}\n\n\tprivate async pollRss(): Promise<void> {\n\t\tif (this.terminated || this.rssPollInFlight) return;\n\t\tconst pid = this.child.pid;\n\t\tif (!pid) return;\n\t\tthis.rssPollInFlight = true;\n\t\ttry {\n\t\t\tconst rssBytes = await readRssBytes(pid);\n\t\t\tif (rssBytes === null || rssBytes <= this.maxRssBytes) return;\n\t\t\tthis.killAndTerminate(\n\t\t\t\tnew Error(\n\t\t\t\t\t`RlmSession: python3 driver exceeded the configured RSS ceiling of ${this.maxRssBytes} bytes ` +\n\t\t\t\t\t\t`(observed ${rssBytes} bytes) -- killed. This is a resource-limit kill (Phase 28 Architecture ` +\n\t\t\t\t\t\t\"section 3), not the OS sandbox itself failing.\",\n\t\t\t\t),\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.rssPollInFlight = false;\n\t\t}\n\t}\n\n\t/**\n\t * Pre-dispatch sub-call budget check (Phase 28 Architecture section 6,\n\t * R28-SBX.5): called *before* an `llm_query_request` is ever forwarded to\n\t * `opts.llmQuery`, so the (budget+1)th attempted sub-call never actually\n\t * dispatches -- the session is killed right here instead. Deliberately\n\t * NOT also checked before dispatching a whole step: a step that never\n\t * attempts another sub-call can still legitimately finish (e.g. call\n\t * FINAL immediately) even after the budget is otherwise exhausted, and\n\t * pre-emptively killing such a step here would be wrong.\n\t */\n\tprivate checkSubCallBudget(): void {\n\t\tif (this.maxSubCalls === undefined) return;\n\t\tif (this.subCallCount < this.maxSubCalls) return;\n\t\tconst error = new RlmBudgetExhaustedError(\n\t\t\t`RlmSession: llm_query sub-call budget exhausted (maxSubCalls=${this.maxSubCalls}) -- refusing to ` +\n\t\t\t\t`dispatch sub-call #${this.subCallCount + 1} and killing the driver subprocess.`,\n\t\t);\n\t\tthis.killAndTerminate(error);\n\t\tthrow error;\n\t}\n\n\t/**\n\t * Pre-dispatch cost budget check (Phase 28 Architecture section 6,\n\t * R28-SBX.5): called before dispatching a step's `rootLlm` turn and\n\t * before forwarding a sub-call to `opts.llmQuery`. No-ops unless both\n\t * `maxTotalCostUsd` and `getAccumulatedCostUsd` are supplied -- see\n\t * `RlmSessionOptions.maxTotalCostUsd`'s doc comment for why an unpaired\n\t * option is a no-op rather than a guess.\n\t */\n\tprivate checkCostBudget(): void {\n\t\tif (this.maxTotalCostUsd === undefined || !this.getAccumulatedCostUsd) return;\n\t\tconst accumulated = this.getAccumulatedCostUsd();\n\t\tif (accumulated < this.maxTotalCostUsd) return;\n\t\tconst error = new RlmBudgetExhaustedError(\n\t\t\t`RlmSession: cost budget exhausted (maxTotalCostUsd=$${this.maxTotalCostUsd}, accumulated=$${accumulated}) ` +\n\t\t\t\t\"-- killing the driver subprocess.\",\n\t\t);\n\t\tthis.killAndTerminate(error);\n\t\tthrow error;\n\t}\n\n\t/**\n\t * Races `promise` against the configured wall-clock step timeout\n\t * (Phase 28 Architecture section 3, R28-SBX.3) -- the real timeout\n\t * enforcement mechanism. On expiry, hard-kills the driver subprocess and\n\t * rejects with `RlmStepTimeoutError`, even if `promise` itself is stuck\n\t * awaiting something that `markTerminated`'s waiter-rejection can't reach\n\t * (e.g. a slow/hung `opts.llmQuery` callback, as opposed to a pending\n\t * `nextMessage()` wait) -- the explicit `reject` here is what actually\n\t * unblocks the caller in that case, not just a formality.\n\t */\n\tprivate withStepTimeout<T>(promise: Promise<T>, timeoutMs = this.stepTimeoutMs): Promise<T> {\n\t\tif (!(timeoutMs > 0)) return promise;\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tconst error = new RlmStepTimeoutError(\n\t\t\t\t\t`RlmSession: step exceeded the configured wall-clock timeout of ${timeoutMs}ms -- killed.`,\n\t\t\t\t);\n\t\t\t\tthis.killAndTerminate(error);\n\t\t\t\treject(error);\n\t\t\t}, timeoutMs);\n\t\t\ttimer.unref();\n\t\t\tpromise.then(\n\t\t\t\t(value) => {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tresolve(value);\n\t\t\t\t},\n\t\t\t\t(err) => {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\treject(err);\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate nextMessage(): Promise<DriverMessage> {\n\t\tconst queued = this.messageQueue.shift();\n\t\tif (queued) return Promise.resolve(queued);\n\t\tif (this.terminated) {\n\t\t\treturn Promise.reject(this.terminationError ?? new Error(\"RlmSession: driver process is no longer running\"));\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.waiters.push({ resolve, reject });\n\t\t});\n\t}\n\n\tprivate send(message: Record<string, unknown>): void {\n\t\tif (this.terminated) {\n\t\t\tthrow this.terminationError ?? new Error(\"RlmSession: cannot send to a terminated driver process\");\n\t\t}\n\t\tthis.child.stdin?.write(`${JSON.stringify(message)}\\n`);\n\t}\n\n\t/**\n\t * Sends one `exec` message and handles any `llm_query_request` round-trips\n\t * until the matching `exec_result`, all under the wall-clock step timeout\n\t * (`withStepTimeout`, Phase 28 Architecture section 3).\n\t */\n\tprivate async runExec(code: string): Promise<DriverExecResult> {\n\t\tthis.send({ type: \"exec\", code });\n\t\treturn this.withStepTimeout(this.collectExecResult());\n\t}\n\n\t/** The message loop `runExec` races against the step timeout -- split out so `withStepTimeout` can wrap just this. */\n\tprivate async collectExecResult(): Promise<DriverExecResult> {\n\t\twhile (true) {\n\t\t\tconst message = await this.nextMessage();\n\t\t\tif (message.type === \"llm_query_request\") {\n\t\t\t\tconst id = message.id as string;\n\t\t\t\tif (!this.opts.llmQuery) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"RlmSession: REPL code called llm_query(...) but no `llmQuery` callback was provided in RlmSessionOptions.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// Budget pre-checks (Phase 28 Architecture section 6, R28-SBX.5) --\n\t\t\t\t// before this sub-call is dispatched, not after: either check can\n\t\t\t\t// throw (and kill the driver), in which case opts.llmQuery is never\n\t\t\t\t// called for this attempt at all.\n\t\t\t\tthis.checkSubCallBudget();\n\t\t\t\tthis.checkCostBudget();\n\t\t\t\tthis.subCallCount++;\n\t\t\t\tconst text = await this.opts.llmQuery(message.prompt as string);\n\t\t\t\tthis.send({ type: \"llm_query_response\", id, text });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (message.type === \"exec_result\") {\n\t\t\t\treturn message as DriverExecResult;\n\t\t\t}\n\t\t\tthrow new Error(`RlmSession: unexpected message from driver: ${JSON.stringify(message)}`);\n\t\t}\n\t}\n\n\tprivate async seedContext(): Promise<void> {\n\t\t// JSON string escaping and Python double-quoted string literal escaping\n\t\t// agree on the escapes that matter here (\\\", \\\\, \\n, \\t, \\r, and\n\t\t// \\uXXXX), so JSON.stringify produces a valid Python string literal.\n\t\tawait this.runExec(`context = ${JSON.stringify(this.opts.prompt)}`);\n\t}\n\n\t/**\n\t * Runtime proof the OS-level sandbox is actually enforcing for *this*\n\t * process (Phase 28 Architecture section 1) -- sends `{\"type\":\n\t * \"self_test\"}` and requires the driver's `self_test_result` response to\n\t * report both a network connect attempt and an out-of-workdir file read\n\t * failing. Throws `RlmSandboxViolationError` (fail-closed, refusing to run\n\t * at all) if:\n\t * - the driver never responds (crash/hang -- guarded by the step\n\t * wall-clock timeout, floored at `MIN_SELF_TEST_TIMEOUT_MS`),\n\t * - the response isn't a well-formed `self_test_result`, or\n\t * - either check reports the sandbox did NOT block the attempt.\n\t *\n\t * Deliberately does not go through `runExec`/the guarded `exec()` wire\n\t * message: `repl_driver.py`'s `_run_self_test` handles `self_test`\n\t * on a route that bypasses its own Python-level guardrails (restricted\n\t * builtins, import allowlist, AST screen) entirely, because a self-test\n\t * *routed through* those guardrails would be a false positive -- e.g.\n\t * `import socket` failing on the guardrail import allowlist looks\n\t * identical to `import socket` failing because the OS sandbox denied the\n\t * connection, even with the OS sandbox completely disabled. See\n\t * `_run_self_test`'s docstring in repl_driver.py for the full reasoning.\n\t */\n\tprivate async runSelfTest(): Promise<void> {\n\t\tthis.send({ type: \"self_test\" });\n\t\tlet message: DriverMessage;\n\t\ttry {\n\t\t\tmessage = await this.withStepTimeout(\n\t\t\t\tthis.nextMessage(),\n\t\t\t\tthis.stepTimeoutMs > 0 ? Math.max(this.stepTimeoutMs, MIN_SELF_TEST_TIMEOUT_MS) : 0,\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow new RlmSandboxViolationError(\n\t\t\t\t\"RlmSession: OS-level sandbox startup self-test did not complete \" +\n\t\t\t\t\t`(refusing to run -- fail-closed): ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t}\n\t\tconst networkBlocked = message.type === \"self_test_result\" && message.networkBlocked === true;\n\t\tconst fileReadBlocked = message.type === \"self_test_result\" && message.fileReadBlocked === true;\n\t\tif (!networkBlocked || !fileReadBlocked) {\n\t\t\tconst error = new RlmSandboxViolationError(\n\t\t\t\t\"RlmSession: OS-level sandbox startup self-test failed -- the sandbox is not confining this \" +\n\t\t\t\t\t`process (networkBlocked=${networkBlocked}, fileReadBlocked=${fileReadBlocked}, ` +\n\t\t\t\t\t`response=${JSON.stringify(message)}). Refusing to run rather than executing unconfined ` +\n\t\t\t\t\t\"root-LLM-authored code (fail-closed).\",\n\t\t\t);\n\t\t\tthis.killAndTerminate(error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate resolveFinal(final: DriverFinalPayload): unknown {\n\t\tif (final.kind === \"value\") {\n\t\t\t// FINAL(answer) already sent `str(answer)` -- use as-is.\n\t\t\treturn final.value;\n\t\t}\n\t\t// FINAL_VAR(name) sent `repr(globals_dict[name])`. Parse it back into a\n\t\t// real JS value for JSON-safe types; fall back to the raw repr string\n\t\t// for anything else. See `pythonReprToValue`'s doc comment for why.\n\t\treturn pythonReprToValue(final.value);\n\t}\n\n\t/** One root-LLM turn: get code, exec it, append history, may resolve a final. */\n\tasync step(): Promise<RlmHistoryEntry> {\n\t\tawait this.ready;\n\t\t// Pre-dispatch cost budget check (Phase 28 Architecture section 6,\n\t\t// R28-SBX.5) -- before the root LLM is even asked for this step's code,\n\t\t// not just before a sub-call within it.\n\t\tthis.checkCostBudget();\n\t\tconst response = await this.opts.rootLlm(this.history.slice());\n\t\tconst code = extractPythonCode(response);\n\t\tconst result = await this.runExec(code);\n\t\tconst entry: RlmHistoryEntry = {\n\t\t\tstep: this.history.length + 1,\n\t\t\tcode,\n\t\t\t// Already capped+marked incrementally by the driver's\n\t\t\t// `_TruncatingStdout` (Phase 28 Architecture section 5) -- no\n\t\t\t// second Node-side truncation pass here (Phase 26's original\n\t\t\t// post-hoc `truncateStdout` call is exactly the OOM-via-print gap\n\t\t\t// this phase closes; re-applying it here on top of the driver's\n\t\t\t// own `[truncated N chars]` marker would risk mangling it).\n\t\t\ttruncatedStdout: result.stdout,\n\t\t\terror: result.error ?? null,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t};\n\t\tthis.history.push(entry);\n\t\tthis.lastFinal = result.final ?? null;\n\t\treturn entry;\n\t}\n\n\t/** Loops `step()` until a FINAL/FINAL_VAR, `maxIterations`, or an unrecoverable driver error. */\n\tasync run(): Promise<RlmResult> {\n\t\ttry {\n\t\t\twhile (this.history.length < this.maxIterations) {\n\t\t\t\tawait this.step();\n\t\t\t\tif (this.lastFinal) {\n\t\t\t\t\tconst final = this.lastFinal;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tkind: final.kind === \"var\" ? \"final_var\" : \"final\",\n\t\t\t\t\t\tvalue: this.resolveFinal(final),\n\t\t\t\t\t\tsteps: this.history.length,\n\t\t\t\t\t\thistory: this.history.slice(),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { kind: \"max_iterations\", steps: this.history.length, history: this.history.slice() };\n\t\t} catch (err) {\n\t\t\t// Typed stop reasons (Phase 28 Architecture section 6, R28-SBX.6):\n\t\t\t// a hard-killed step surfaces here as one of these internal error\n\t\t\t// classes; anything else (a genuine driver crash, a step\n\t\t\t// referencing llm_query with no callback configured, etc.) falls\n\t\t\t// through to the generic \"error\" kind, same as Phase 26.\n\t\t\tif (err instanceof RlmStepTimeoutError) {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"timeout\",\n\t\t\t\t\tvalue: err.message,\n\t\t\t\t\tsteps: this.history.length,\n\t\t\t\t\thistory: this.history.slice(),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (err instanceof RlmBudgetExhaustedError) {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"budget_exhausted\",\n\t\t\t\t\tvalue: err.message,\n\t\t\t\t\tsteps: this.history.length,\n\t\t\t\t\thistory: this.history.slice(),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (err instanceof RlmSandboxViolationError) {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"sandbox_violation\",\n\t\t\t\t\tvalue: err.message,\n\t\t\t\t\tsteps: this.history.length,\n\t\t\t\t\thistory: this.history.slice(),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tkind: \"error\",\n\t\t\t\tvalue: err instanceof Error ? err.message : String(err),\n\t\t\t\tsteps: this.history.length,\n\t\t\t\thistory: this.history.slice(),\n\t\t\t};\n\t\t}\n\t}\n\n\t/** Kills the underlying python3 subprocess and removes its scratch workdir. Safe to call more than once. */\n\tdispose(): void {\n\t\tthis.markTerminated(new Error(\"RlmSession: disposed\"));\n\t\tthis.child.stdin?.end();\n\t\tthis.child.kill();\n\t\ttry {\n\t\t\trmSync(this.workdir, { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Best-effort cleanup only -- a leftover empty-ish tmp dir isn't\n\t\t\t// worth failing dispose() over.\n\t\t}\n\t}\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@draht/rlm",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.9.5-1",
|
|
4
4
|
"description": "Recursive Language Models — root-LLM-produces-code / REPL-executes / truncated-stdout scaffold",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"clean": "rm -rf dist"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@draht/ai": "2026.
|
|
27
|
-
"@draht/knowledge": "2026.
|
|
28
|
-
"@draht/router": "2026.
|
|
26
|
+
"@draht/ai": "2026.9.5-1",
|
|
27
|
+
"@draht/knowledge": "2026.9.5-1",
|
|
28
|
+
"@draht/router": "2026.9.5-1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"vitest": "^3.2.4",
|