open-agents-ai 0.105.7 → 0.106.0

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.
Files changed (2) hide show
  1. package/dist/index.js +783 -449
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5639,8 +5639,8 @@ function deleteCustomToolDefinition(name, scope, repoRoot) {
5639
5639
  const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
5640
5640
  const filePath = join13(dir, `${name}.json`);
5641
5641
  if (existsSync10(filePath)) {
5642
- const { unlinkSync: unlinkSync10 } = __require("node:fs");
5643
- unlinkSync10(filePath);
5642
+ const { unlinkSync: unlinkSync11 } = __require("node:fs");
5643
+ unlinkSync11(filePath);
5644
5644
  return true;
5645
5645
  }
5646
5646
  return false;
@@ -7511,6 +7511,315 @@ ${result.filesCreated.join("\n")}`);
7511
7511
  }
7512
7512
  });
7513
7513
 
7514
+ // packages/execution/dist/tools/repl.js
7515
+ import { spawn as spawn6 } from "node:child_process";
7516
+ import { createServer } from "node:net";
7517
+ import { join as join18 } from "node:path";
7518
+ import { tmpdir as tmpdir3 } from "node:os";
7519
+ import { randomBytes as randomBytes2 } from "node:crypto";
7520
+ import { unlinkSync as unlinkSync2 } from "node:fs";
7521
+ var ReplTool;
7522
+ var init_repl = __esm({
7523
+ "packages/execution/dist/tools/repl.js"() {
7524
+ "use strict";
7525
+ ReplTool = class {
7526
+ name = "repl_exec";
7527
+ description = "Execute Python code in a persistent REPL environment. Variables, imports, and functions persist between calls within the same task. Use for data processing, analysis, and building up results across multiple steps. A special function llm_query(prompt, context='') is available to invoke the language model from within Python code for semantic analysis of text chunks. Write results to files or print them to see output.";
7528
+ parameters = {
7529
+ type: "object",
7530
+ properties: {
7531
+ code: {
7532
+ type: "string",
7533
+ description: "Python code to execute in the persistent REPL"
7534
+ },
7535
+ reset: {
7536
+ type: "boolean",
7537
+ description: "Reset the REPL state (kill process, clear all variables). Default: false"
7538
+ }
7539
+ },
7540
+ required: ["code"]
7541
+ };
7542
+ proc = null;
7543
+ ipcServer = null;
7544
+ ipcPath = null;
7545
+ cwd;
7546
+ llmQueryHandler = null;
7547
+ subCallCount = 0;
7548
+ maxSubCalls;
7549
+ execTimeout;
7550
+ constructor(cwd4, options) {
7551
+ this.cwd = cwd4;
7552
+ this.llmQueryHandler = options?.llmQueryHandler ?? null;
7553
+ this.maxSubCalls = options?.maxSubCalls ?? 50;
7554
+ this.execTimeout = options?.execTimeout ?? 6e4;
7555
+ }
7556
+ /** Set the llm_query handler (called after construction when backend is available) */
7557
+ setLlmQueryHandler(handler) {
7558
+ this.llmQueryHandler = handler;
7559
+ }
7560
+ /** Get the number of sub-calls made this session */
7561
+ getSubCallCount() {
7562
+ return this.subCallCount;
7563
+ }
7564
+ async execute(args) {
7565
+ const code = String(args.code ?? "");
7566
+ const reset = Boolean(args.reset);
7567
+ if (reset) {
7568
+ await this.dispose();
7569
+ return { success: true, output: "REPL state cleared.", durationMs: 0 };
7570
+ }
7571
+ if (!code.trim()) {
7572
+ return { success: false, output: "No code provided.", error: "Empty code", durationMs: 0 };
7573
+ }
7574
+ const start = performance.now();
7575
+ try {
7576
+ if (!this.proc || this.proc.killed || this.proc.exitCode !== null) {
7577
+ await this.startProcess();
7578
+ }
7579
+ const result = await this.executeCode(code);
7580
+ return { ...result, durationMs: performance.now() - start };
7581
+ } catch (err) {
7582
+ const msg = err instanceof Error ? err.message : String(err);
7583
+ return { success: false, output: `REPL error: ${msg}`, error: msg, durationMs: performance.now() - start };
7584
+ }
7585
+ }
7586
+ // ── Process lifecycle ────────────────────────────────────────────────────
7587
+ async startProcess() {
7588
+ await this.startIpcServer();
7589
+ this.proc = spawn6("python3", ["-u", "-i", "-q"], {
7590
+ cwd: this.cwd,
7591
+ stdio: ["pipe", "pipe", "pipe"],
7592
+ env: {
7593
+ ...process.env,
7594
+ PYTHONUNBUFFERED: "1",
7595
+ PYTHONDONTWRITEBYTECODE: "1",
7596
+ OA_LLM_QUERY_SOCKET: this.ipcPath ?? ""
7597
+ }
7598
+ });
7599
+ this.proc.on("error", () => {
7600
+ });
7601
+ const initCode = this.buildInitCode();
7602
+ await this.executeCode(initCode, true);
7603
+ }
7604
+ buildInitCode() {
7605
+ return `
7606
+ import sys, os, json, socket
7607
+
7608
+ def llm_query(prompt, context=""):
7609
+ """Invoke the language model on a sub-prompt. Returns the model's text response.
7610
+ Use for semantic analysis, summarization, or reasoning about text chunks.
7611
+ Args:
7612
+ prompt: The question/instruction for the model
7613
+ context: Additional text context (max ~500K chars)
7614
+ Returns: Model's text response as a string
7615
+ """
7616
+ sock_path = os.environ.get("OA_LLM_QUERY_SOCKET", "")
7617
+ if not sock_path:
7618
+ return "[llm_query unavailable: no IPC socket]"
7619
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
7620
+ try:
7621
+ sock.connect(sock_path)
7622
+ request = json.dumps({"prompt": str(prompt), "context": str(context)[:500000]})
7623
+ # Send length-prefixed message
7624
+ data = request.encode("utf-8")
7625
+ sock.sendall(len(data).to_bytes(4, "big") + data)
7626
+ # Read length-prefixed response
7627
+ length_bytes = b""
7628
+ while len(length_bytes) < 4:
7629
+ chunk = sock.recv(4 - len(length_bytes))
7630
+ if not chunk:
7631
+ return "[llm_query: connection closed]"
7632
+ length_bytes += chunk
7633
+ resp_len = int.from_bytes(length_bytes, "big")
7634
+ resp_data = b""
7635
+ while len(resp_data) < resp_len:
7636
+ chunk = sock.recv(min(resp_len - len(resp_data), 65536))
7637
+ if not chunk:
7638
+ break
7639
+ resp_data += chunk
7640
+ result = json.loads(resp_data.decode("utf-8"))
7641
+ if "error" in result:
7642
+ return f"[llm_query error: {result['error']}]"
7643
+ return result.get("response", "")
7644
+ except Exception as e:
7645
+ return f"[llm_query error: {e}]"
7646
+ finally:
7647
+ sock.close()
7648
+
7649
+ # Signal REPL ready
7650
+ print("__OA_REPL_READY__")
7651
+ `.trim();
7652
+ }
7653
+ // ── IPC Server (for llm_query bridge) ──────────────────────────────────
7654
+ async startIpcServer() {
7655
+ if (this.ipcServer)
7656
+ return;
7657
+ const sockId = randomBytes2(8).toString("hex");
7658
+ this.ipcPath = join18(tmpdir3(), `oa-repl-ipc-${sockId}.sock`);
7659
+ return new Promise((resolve32, reject) => {
7660
+ this.ipcServer = createServer((conn) => {
7661
+ let buffer = new Uint8Array(0);
7662
+ conn.on("data", (chunk) => {
7663
+ const combined = new Uint8Array(buffer.length + chunk.length);
7664
+ combined.set(buffer, 0);
7665
+ combined.set(chunk, buffer.length);
7666
+ buffer = combined;
7667
+ this.processIpcBuffer(conn, buffer).then((remaining) => {
7668
+ buffer = remaining;
7669
+ });
7670
+ });
7671
+ conn.on("error", () => {
7672
+ });
7673
+ });
7674
+ this.ipcServer.on("error", reject);
7675
+ this.ipcServer.listen(this.ipcPath, () => resolve32());
7676
+ });
7677
+ }
7678
+ async processIpcBuffer(conn, input) {
7679
+ let buffer = input;
7680
+ while (buffer.length >= 4) {
7681
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
7682
+ const msgLen = view.getUint32(0, false);
7683
+ if (buffer.length < 4 + msgLen)
7684
+ break;
7685
+ const msgData = new TextDecoder().decode(buffer.subarray(4, 4 + msgLen));
7686
+ buffer = buffer.subarray(4 + msgLen);
7687
+ let response;
7688
+ try {
7689
+ const req = JSON.parse(msgData);
7690
+ if (!this.llmQueryHandler) {
7691
+ response = { error: "llm_query handler not configured" };
7692
+ } else if (this.subCallCount >= this.maxSubCalls) {
7693
+ response = { error: `Sub-call limit reached (${this.maxSubCalls})` };
7694
+ } else {
7695
+ this.subCallCount++;
7696
+ const result = await this.llmQueryHandler(req.prompt, req.context);
7697
+ response = { response: result };
7698
+ }
7699
+ } catch (err) {
7700
+ response = { error: err instanceof Error ? err.message : String(err) };
7701
+ }
7702
+ const respBytes = new TextEncoder().encode(JSON.stringify(response));
7703
+ const header = new Uint8Array(4);
7704
+ new DataView(header.buffer).setUint32(0, respBytes.length, false);
7705
+ const packet = new Uint8Array(4 + respBytes.length);
7706
+ packet.set(header, 0);
7707
+ packet.set(respBytes, 4);
7708
+ try {
7709
+ conn.write(packet);
7710
+ } catch {
7711
+ }
7712
+ }
7713
+ return buffer;
7714
+ }
7715
+ // ── Code execution ─────────────────────────────────────────────────────
7716
+ executeCode(code, isInit = false) {
7717
+ return new Promise((resolve32) => {
7718
+ if (!this.proc?.stdin || !this.proc?.stdout || !this.proc?.stderr) {
7719
+ resolve32({ success: false, output: "REPL process not available", error: "No process", durationMs: 0 });
7720
+ return;
7721
+ }
7722
+ const sentinel = `__OA_SENTINEL_${randomBytes2(6).toString("hex")}__`;
7723
+ let stdout = "";
7724
+ let stderr = "";
7725
+ let resolved = false;
7726
+ const timeout = setTimeout(() => {
7727
+ if (!resolved) {
7728
+ resolved = true;
7729
+ resolve32({
7730
+ success: false,
7731
+ output: stdout || "Execution timed out",
7732
+ error: `Timeout after ${this.execTimeout / 1e3}s`,
7733
+ durationMs: this.execTimeout
7734
+ });
7735
+ }
7736
+ }, this.execTimeout);
7737
+ const onStdout = (data) => {
7738
+ const text = data.toString();
7739
+ stdout += text;
7740
+ if (stdout.includes(sentinel)) {
7741
+ cleanup();
7742
+ const cleanOutput = stdout.split(sentinel)[0].trim();
7743
+ if (isInit) {
7744
+ const ready = cleanOutput.includes("__OA_REPL_READY__");
7745
+ const displayOutput = cleanOutput.replace("__OA_REPL_READY__", "").trim();
7746
+ resolve32({
7747
+ success: ready,
7748
+ output: displayOutput || "REPL initialized",
7749
+ durationMs: 0
7750
+ });
7751
+ } else {
7752
+ resolve32({
7753
+ success: true,
7754
+ output: cleanOutput || "(no output)",
7755
+ durationMs: 0
7756
+ });
7757
+ }
7758
+ }
7759
+ if (stdout.length > 2e5) {
7760
+ cleanup();
7761
+ resolve32({
7762
+ success: true,
7763
+ output: stdout.slice(0, 2e5) + "\n[output truncated at 200KB]",
7764
+ durationMs: 0
7765
+ });
7766
+ }
7767
+ };
7768
+ const onStderr = (data) => {
7769
+ stderr += data.toString();
7770
+ if (stderr.length > 5e4) {
7771
+ stderr = stderr.slice(0, 5e4) + "\n[stderr truncated]";
7772
+ }
7773
+ };
7774
+ const cleanup = () => {
7775
+ if (resolved)
7776
+ return;
7777
+ resolved = true;
7778
+ clearTimeout(timeout);
7779
+ this.proc?.stdout?.removeListener("data", onStdout);
7780
+ this.proc?.stderr?.removeListener("data", onStderr);
7781
+ };
7782
+ this.proc.stdout.on("data", onStdout);
7783
+ this.proc.stderr.on("data", onStderr);
7784
+ const wrappedCode = `
7785
+ try:
7786
+ exec(${JSON.stringify(code)})
7787
+ except Exception as __oa_e:
7788
+ import traceback as __oa_tb
7789
+ print(f"Error: {__oa_e}")
7790
+ __oa_tb.print_exc()
7791
+ print("${sentinel}")
7792
+ `;
7793
+ this.proc.stdin.write(wrappedCode + "\n");
7794
+ });
7795
+ }
7796
+ // ── Cleanup ────────────────────────────────────────────────────────────
7797
+ async dispose() {
7798
+ if (this.proc && !this.proc.killed) {
7799
+ try {
7800
+ this.proc.stdin?.end();
7801
+ this.proc.kill("SIGTERM");
7802
+ } catch {
7803
+ }
7804
+ this.proc = null;
7805
+ }
7806
+ if (this.ipcServer) {
7807
+ this.ipcServer.close();
7808
+ this.ipcServer = null;
7809
+ }
7810
+ if (this.ipcPath) {
7811
+ try {
7812
+ unlinkSync2(this.ipcPath);
7813
+ } catch {
7814
+ }
7815
+ this.ipcPath = null;
7816
+ }
7817
+ this.subCallCount = 0;
7818
+ }
7819
+ };
7820
+ }
7821
+ });
7822
+
7514
7823
  // packages/execution/dist/tools/structured-read.js
7515
7824
  import { readFile as readFile8, stat as stat2 } from "node:fs/promises";
7516
7825
  import { resolve as resolve15, extname as extname5 } from "node:path";
@@ -7848,8 +8157,8 @@ ${parts.join("\n\n")}`,
7848
8157
 
7849
8158
  // packages/execution/dist/tools/vision.js
7850
8159
  import { readFileSync as readFileSync11, existsSync as existsSync14, statSync as statSync5 } from "node:fs";
7851
- import { execSync as execSync11, spawn as spawn6 } from "node:child_process";
7852
- import { resolve as resolve16, extname as extname6, basename as basename5, dirname as dirname6, join as join18 } from "node:path";
8160
+ import { execSync as execSync11, spawn as spawn7 } from "node:child_process";
8161
+ import { resolve as resolve16, extname as extname6, basename as basename5, dirname as dirname6, join as join19 } from "node:path";
7853
8162
  import { fileURLToPath as fileURLToPath2 } from "node:url";
7854
8163
  async function probeStation(endpoint) {
7855
8164
  try {
@@ -7864,7 +8173,7 @@ async function probeStation(endpoint) {
7864
8173
  }
7865
8174
  }
7866
8175
  function findStationBinary() {
7867
- const oaVenvPython = join18(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "python");
8176
+ const oaVenvPython = join19(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "python");
7868
8177
  if (existsSync14(oaVenvPython)) {
7869
8178
  try {
7870
8179
  execSync11(`${JSON.stringify(oaVenvPython)} -c "import moondream_station"`, { stdio: "pipe", timeout: 5e3 });
@@ -7872,7 +8181,7 @@ function findStationBinary() {
7872
8181
  } catch {
7873
8182
  }
7874
8183
  }
7875
- const oaVenvBin = join18(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "moondream-station");
8184
+ const oaVenvBin = join19(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "moondream-station");
7876
8185
  if (existsSync14(oaVenvBin))
7877
8186
  return oaVenvBin;
7878
8187
  const thisDir = dirname6(fileURLToPath2(import.meta.url));
@@ -7906,7 +8215,7 @@ async function autoLaunchStation(port = 2020) {
7906
8215
  if (!existsSync14(launcherScript))
7907
8216
  return false;
7908
8217
  return new Promise((resolvePromise) => {
7909
- const child = spawn6(pythonBin, [launcherScript, "--port", String(port)], {
8218
+ const child = spawn7(pythonBin, [launcherScript, "--port", String(port)], {
7910
8219
  stdio: ["ignore", "pipe", "pipe"],
7911
8220
  detached: true
7912
8221
  });
@@ -8223,8 +8532,8 @@ ${response}`, durationMs: performance.now() - start };
8223
8532
  // packages/execution/dist/tools/desktop-click.js
8224
8533
  import { readFileSync as readFileSync12, existsSync as existsSync15 } from "node:fs";
8225
8534
  import { execSync as execSync12 } from "node:child_process";
8226
- import { tmpdir as tmpdir3 } from "node:os";
8227
- import { join as join19, dirname as dirname7 } from "node:path";
8535
+ import { tmpdir as tmpdir4 } from "node:os";
8536
+ import { join as join20, dirname as dirname7 } from "node:path";
8228
8537
  import { fileURLToPath as fileURLToPath3 } from "node:url";
8229
8538
  function hasCommand2(cmd) {
8230
8539
  try {
@@ -8348,7 +8657,7 @@ for i in range(${clicks}):
8348
8657
  } catch {
8349
8658
  }
8350
8659
  try {
8351
- const venvPy = join19(__dirname2, "../../../../.moondream-venv/bin/python");
8660
+ const venvPy = join20(__dirname2, "../../../../.moondream-venv/bin/python");
8352
8661
  execSync12(`DISPLAY=:0 ${JSON.stringify(venvPy)} -c "${pyScript}"`, { stdio: "pipe", timeout: 5e3 });
8353
8662
  return;
8354
8663
  } catch {
@@ -8440,7 +8749,7 @@ var init_desktop_click = __esm({
8440
8749
  if (delayMs > 0) {
8441
8750
  await new Promise((r) => setTimeout(r, delayMs));
8442
8751
  }
8443
- const screenshotPath = join19(tmpdir3(), `oa-desktop-click-${Date.now()}.png`);
8752
+ const screenshotPath = join20(tmpdir4(), `oa-desktop-click-${Date.now()}.png`);
8444
8753
  captureScreenshot(screenshotPath);
8445
8754
  const dims = getImageDimensions2(screenshotPath);
8446
8755
  if (!dims) {
@@ -8615,7 +8924,7 @@ Screenshot: ${screenshotPath}`,
8615
8924
  if (delayMs > 0) {
8616
8925
  await new Promise((r) => setTimeout(r, delayMs));
8617
8926
  }
8618
- const screenshotPath = join19(tmpdir3(), `oa-desktop-describe-${Date.now()}.png`);
8927
+ const screenshotPath = join20(tmpdir4(), `oa-desktop-describe-${Date.now()}.png`);
8619
8928
  captureScreenshot(screenshotPath);
8620
8929
  const dims = getImageDimensions2(screenshotPath);
8621
8930
  const imageBuffer = readFileSync12(screenshotPath);
@@ -8853,10 +9162,10 @@ Language: ${language}
8853
9162
  });
8854
9163
 
8855
9164
  // packages/execution/dist/tools/pdf-to-text.js
8856
- import { existsSync as existsSync17, statSync as statSync7, readFileSync as readFileSync13, unlinkSync as unlinkSync2 } from "node:fs";
8857
- import { resolve as resolve18, basename as basename7, join as join20 } from "node:path";
9165
+ import { existsSync as existsSync17, statSync as statSync7, readFileSync as readFileSync13, unlinkSync as unlinkSync3 } from "node:fs";
9166
+ import { resolve as resolve18, basename as basename7, join as join21 } from "node:path";
8858
9167
  import { execSync as execSync14 } from "node:child_process";
8859
- import { tmpdir as tmpdir4 } from "node:os";
9168
+ import { tmpdir as tmpdir5 } from "node:os";
8860
9169
  var PdfToTextTool;
8861
9170
  var init_pdf_to_text = __esm({
8862
9171
  "packages/execution/dist/tools/pdf-to-text.js"() {
@@ -9008,7 +9317,7 @@ ${text}`,
9008
9317
  if (!ocrCheck.available || !tesCheck.available || !gsCheck.available) {
9009
9318
  return null;
9010
9319
  }
9011
- const tmpPdf = join20(tmpdir4(), `oa-ocr-${Date.now()}.pdf`);
9320
+ const tmpPdf = join21(tmpdir5(), `oa-ocr-${Date.now()}.pdf`);
9012
9321
  try {
9013
9322
  const ocrCmd = `ocrmypdf -l ${language} --skip-text ${JSON.stringify(inputPath)} ${JSON.stringify(tmpPdf)}`;
9014
9323
  execSync14(ocrCmd, { stdio: "pipe", timeout: 6e5 });
@@ -9028,7 +9337,7 @@ ${text}`,
9028
9337
  return null;
9029
9338
  } finally {
9030
9339
  try {
9031
- unlinkSync2(tmpPdf);
9340
+ unlinkSync3(tmpPdf);
9032
9341
  } catch {
9033
9342
  }
9034
9343
  }
@@ -9039,10 +9348,10 @@ ${text}`,
9039
9348
 
9040
9349
  // packages/execution/dist/tools/ocr-image-advanced.js
9041
9350
  import { existsSync as existsSync18, statSync as statSync8 } from "node:fs";
9042
- import { resolve as resolve19, basename as basename8, dirname as dirname8, join as join21 } from "node:path";
9351
+ import { resolve as resolve19, basename as basename8, dirname as dirname8, join as join22 } from "node:path";
9043
9352
  import { execSync as execSync15 } from "node:child_process";
9044
9353
  import { fileURLToPath as fileURLToPath4 } from "node:url";
9045
- import { homedir as homedir7, tmpdir as tmpdir5 } from "node:os";
9354
+ import { homedir as homedir7, tmpdir as tmpdir6 } from "node:os";
9046
9355
  function findOcrScript() {
9047
9356
  const thisDir = dirname8(fileURLToPath4(import.meta.url));
9048
9357
  const devPath3 = resolve19(thisDir, "../../scripts/ocr-advanced.py");
@@ -9057,7 +9366,7 @@ function findOcrScript() {
9057
9366
  return null;
9058
9367
  }
9059
9368
  function findPython() {
9060
- const venvPython = join21(homedir7(), ".open-agents", "venv", "bin", "python");
9369
+ const venvPython = join22(homedir7(), ".open-agents", "venv", "bin", "python");
9061
9370
  if (existsSync18(venvPython)) {
9062
9371
  try {
9063
9372
  execSync15(`${JSON.stringify(venvPython)} -c "import cv2, pytesseract, numpy, PIL"`, {
@@ -9203,7 +9512,7 @@ var init_ocr_image_advanced = __esm({
9203
9512
  cmdParts.push("--output-dir", JSON.stringify(resolve19(this.workingDir, outputDir)));
9204
9513
  let debugDir;
9205
9514
  if (debug) {
9206
- debugDir = join21(tmpdir5(), `oa-ocr-debug-${Date.now()}`);
9515
+ debugDir = join22(tmpdir6(), `oa-ocr-debug-${Date.now()}`);
9207
9516
  cmdParts.push("--debug-dir", debugDir);
9208
9517
  }
9209
9518
  try {
@@ -9302,7 +9611,7 @@ var init_ocr_image_advanced = __esm({
9302
9611
  if (region) {
9303
9612
  try {
9304
9613
  const [x, y, w, h] = region.split(",").map(Number);
9305
- const croppedPath = join21(tmpdir5(), `oa-ocr-crop-${Date.now()}.png`);
9614
+ const croppedPath = join22(tmpdir6(), `oa-ocr-crop-${Date.now()}.png`);
9306
9615
  execSync15(`convert ${JSON.stringify(imagePath)} -crop ${w}x${h}+${x}+${y} +repage ${JSON.stringify(croppedPath)}`, { stdio: "pipe", timeout: 1e4 });
9307
9616
  inputPath = croppedPath;
9308
9617
  } catch {
@@ -9341,20 +9650,20 @@ Note: Advanced Python pipeline not available \u2014 install pytesseract, opencv-
9341
9650
  });
9342
9651
 
9343
9652
  // packages/execution/dist/tools/browser-action.js
9344
- import { execSync as execSync16, spawn as spawn7 } from "node:child_process";
9653
+ import { execSync as execSync16, spawn as spawn8 } from "node:child_process";
9345
9654
  import { existsSync as existsSync19, readFileSync as readFileSync14 } from "node:fs";
9346
- import { join as join22, dirname as dirname9 } from "node:path";
9655
+ import { join as join23, dirname as dirname9 } from "node:path";
9347
9656
  import { fileURLToPath as fileURLToPath5 } from "node:url";
9348
9657
  function findScrapeScript() {
9349
9658
  const candidates = [
9350
9659
  // Published npm package: dist/scripts/web_scrape.py
9351
- join22(__dirname3, "scripts", "web_scrape.py"),
9660
+ join23(__dirname3, "scripts", "web_scrape.py"),
9352
9661
  // Published npm package (from node_modules): node_modules/open-agents-ai/dist/scripts/
9353
- join22(__dirname3, "..", "node_modules", "open-agents-ai", "dist", "scripts", "web_scrape.py"),
9662
+ join23(__dirname3, "..", "node_modules", "open-agents-ai", "dist", "scripts", "web_scrape.py"),
9354
9663
  // Dev monorepo: packages/execution/src/tools/../../scripts/
9355
- join22(__dirname3, "..", "..", "scripts", "web_scrape.py"),
9664
+ join23(__dirname3, "..", "..", "scripts", "web_scrape.py"),
9356
9665
  // Dev monorepo alt: packages/execution/scripts/
9357
- join22(__dirname3, "..", "scripts", "web_scrape.py")
9666
+ join23(__dirname3, "..", "scripts", "web_scrape.py")
9358
9667
  ];
9359
9668
  return candidates.find((p) => existsSync19(p)) || candidates[0];
9360
9669
  }
@@ -9389,7 +9698,7 @@ async function launchService() {
9389
9698
  if (!existsSync19(SCRAPE_SCRIPT)) {
9390
9699
  return `Scrape service script not found at ${SCRAPE_SCRIPT}`;
9391
9700
  }
9392
- serviceProcess = spawn7(python, [SCRAPE_SCRIPT], {
9701
+ serviceProcess = spawn8(python, [SCRAPE_SCRIPT], {
9393
9702
  stdio: "ignore",
9394
9703
  detached: true,
9395
9704
  env: {
@@ -9607,9 +9916,9 @@ var init_browser_action = __esm({
9607
9916
  });
9608
9917
 
9609
9918
  // packages/execution/dist/tools/autoresearch.js
9610
- import { execSync as execSync17, spawn as spawn8 } from "node:child_process";
9919
+ import { execSync as execSync17, spawn as spawn9 } from "node:child_process";
9611
9920
  import { existsSync as existsSync20, readFileSync as readFileSync15, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, appendFileSync, copyFileSync } from "node:fs";
9612
- import { join as join23, resolve as resolve20, dirname as dirname10 } from "node:path";
9921
+ import { join as join24, resolve as resolve20, dirname as dirname10 } from "node:path";
9613
9922
  import { fileURLToPath as fileURLToPath6 } from "node:url";
9614
9923
  function findAutoresearchScript(scriptName) {
9615
9924
  const thisDir = dirname10(fileURLToPath6(import.meta.url));
@@ -9711,7 +10020,7 @@ Requires: NVIDIA GPU, Python 3.10+, uv (astral.sh package manager).`;
9711
10020
  async execute(args) {
9712
10021
  const start = Date.now();
9713
10022
  const action = String(args["action"] ?? "status");
9714
- const workspacePath = String(args["workspace"] ?? join23(this.repoRoot, ".oa", "autoresearch"));
10023
+ const workspacePath = String(args["workspace"] ?? join24(this.repoRoot, ".oa", "autoresearch"));
9715
10024
  try {
9716
10025
  switch (action) {
9717
10026
  case "setup":
@@ -9752,13 +10061,13 @@ Requires: NVIDIA GPU, Python 3.10+, uv (astral.sh package manager).`;
9752
10061
  const prepareScript = findAutoresearchScript("autoresearch-prepare.py");
9753
10062
  const trainScript = findAutoresearchScript("autoresearch-train.py");
9754
10063
  if (prepareScript) {
9755
- copyFileSync(prepareScript, join23(workspace, "prepare.py"));
10064
+ copyFileSync(prepareScript, join24(workspace, "prepare.py"));
9756
10065
  output.push("Copied prepare.py template");
9757
10066
  } else {
9758
10067
  return { success: false, output: output.join("\n"), error: "autoresearch-prepare.py template not found in distribution", durationMs: Date.now() - start };
9759
10068
  }
9760
10069
  if (trainScript) {
9761
- copyFileSync(trainScript, join23(workspace, "train.py"));
10070
+ copyFileSync(trainScript, join24(workspace, "train.py"));
9762
10071
  output.push("Copied train.py template");
9763
10072
  } else {
9764
10073
  return { success: false, output: output.join("\n"), error: "autoresearch-train.py template not found in distribution", durationMs: Date.now() - start };
@@ -9790,7 +10099,7 @@ name = "pytorch-cu128"
9790
10099
  url = "https://download.pytorch.org/whl/cu128"
9791
10100
  explicit = true
9792
10101
  `;
9793
- writeFileSync6(join23(workspace, "pyproject.toml"), pyprojectContent, "utf-8");
10102
+ writeFileSync6(join24(workspace, "pyproject.toml"), pyprojectContent, "utf-8");
9794
10103
  output.push("Created pyproject.toml");
9795
10104
  try {
9796
10105
  execSync17("git rev-parse --git-dir", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
@@ -9832,7 +10141,7 @@ explicit = true
9832
10141
  const e = err;
9833
10142
  output.push(`Data prep warning: ${(e.stderr ?? e.stdout ?? "failed").slice(0, 500)}`);
9834
10143
  }
9835
- const tsvPath = join23(workspace, "results.tsv");
10144
+ const tsvPath = join24(workspace, "results.tsv");
9836
10145
  if (!existsSync20(tsvPath)) {
9837
10146
  writeFileSync6(tsvPath, "commit val_bpb memory_gb status description\n", "utf-8");
9838
10147
  output.push("Created results.tsv");
@@ -9854,10 +10163,10 @@ Next steps:
9854
10163
  }
9855
10164
  // ── Run experiment ─────────────────────────────────────────────────────
9856
10165
  async run(workspace, args, start) {
9857
- if (!existsSync20(join23(workspace, "train.py"))) {
10166
+ if (!existsSync20(join24(workspace, "train.py"))) {
9858
10167
  return { success: false, output: "", error: `No train.py found in ${workspace}. Run autoresearch(action="setup") first.`, durationMs: Date.now() - start };
9859
10168
  }
9860
- if (!existsSync20(join23(workspace, ".venv")) && existsSync20(join23(workspace, "pyproject.toml"))) {
10169
+ if (!existsSync20(join24(workspace, ".venv")) && existsSync20(join24(workspace, "pyproject.toml"))) {
9861
10170
  try {
9862
10171
  execSync17("uv sync 2>&1", { cwd: workspace, encoding: "utf-8", timeout: 3e5 });
9863
10172
  } catch {
@@ -9865,9 +10174,9 @@ Next steps:
9865
10174
  }
9866
10175
  const timeoutMin = Number(args["timeout_minutes"] ?? 10);
9867
10176
  const timeoutMs = timeoutMin * 60 * 1e3;
9868
- const logPath = join23(workspace, "run.log");
10177
+ const logPath = join24(workspace, "run.log");
9869
10178
  return new Promise((resolveResult) => {
9870
- const proc = spawn8("uv", ["run", "train.py"], {
10179
+ const proc = spawn9("uv", ["run", "train.py"], {
9871
10180
  cwd: workspace,
9872
10181
  timeout: timeoutMs,
9873
10182
  stdio: ["pipe", "pipe", "pipe"],
@@ -9936,7 +10245,7 @@ ${fullLog.slice(-2e3)}`,
9936
10245
  return;
9937
10246
  }
9938
10247
  try {
9939
- writeFileSync6(join23(workspace, ".last-result.json"), JSON.stringify(result, null, 2), "utf-8");
10248
+ writeFileSync6(join24(workspace, ".last-result.json"), JSON.stringify(result, null, 2), "utf-8");
9940
10249
  } catch {
9941
10250
  }
9942
10251
  const memGB = (result.peak_vram_mb / 1024).toFixed(1);
@@ -9972,7 +10281,7 @@ ${fullLog.slice(-2e3)}`,
9972
10281
  }
9973
10282
  // ── Results ────────────────────────────────────────────────────────────
9974
10283
  getResults(workspace, start) {
9975
- const tsvPath = join23(workspace, "results.tsv");
10284
+ const tsvPath = join24(workspace, "results.tsv");
9976
10285
  if (!existsSync20(tsvPath)) {
9977
10286
  return { success: false, output: "", error: `No results.tsv found. Run autoresearch(action="setup") first.`, durationMs: Date.now() - start };
9978
10287
  }
@@ -9999,7 +10308,7 @@ ${fullLog.slice(-2e3)}`,
9999
10308
  // ── Status ─────────────────────────────────────────────────────────────
10000
10309
  getStatus(workspace, start) {
10001
10310
  const output = [];
10002
- if (!existsSync20(join23(workspace, "train.py"))) {
10311
+ if (!existsSync20(join24(workspace, "train.py"))) {
10003
10312
  return {
10004
10313
  success: true,
10005
10314
  output: `Autoresearch workspace not initialized at ${workspace}.
@@ -10022,7 +10331,7 @@ Run autoresearch(action="setup") to begin.`,
10022
10331
  } catch {
10023
10332
  output.push("GPU: not detected");
10024
10333
  }
10025
- const lastResultPath = join23(workspace, ".last-result.json");
10334
+ const lastResultPath = join24(workspace, ".last-result.json");
10026
10335
  if (existsSync20(lastResultPath)) {
10027
10336
  try {
10028
10337
  const last = JSON.parse(readFileSync15(lastResultPath, "utf-8"));
@@ -10030,20 +10339,20 @@ Run autoresearch(action="setup") to begin.`,
10030
10339
  } catch {
10031
10340
  }
10032
10341
  }
10033
- const tsvPath = join23(workspace, "results.tsv");
10342
+ const tsvPath = join24(workspace, "results.tsv");
10034
10343
  if (existsSync20(tsvPath)) {
10035
10344
  const lines = readFileSync15(tsvPath, "utf-8").trim().split("\n");
10036
10345
  output.push(`Experiments recorded: ${lines.length - 1}`);
10037
10346
  }
10038
- const cacheDir = join23(process.env["HOME"] ?? "~", ".cache", "autoresearch");
10347
+ const cacheDir = join24(process.env["HOME"] ?? "~", ".cache", "autoresearch");
10039
10348
  output.push(`Data cache: ${existsSync20(cacheDir) ? "present" : "not found"} (${cacheDir})`);
10040
10349
  return { success: true, output: output.join("\n"), durationMs: Date.now() - start };
10041
10350
  }
10042
10351
  // ── Keep / Discard ─────────────────────────────────────────────────────
10043
10352
  keepExperiment(workspace, args, start) {
10044
10353
  const desc = String(args["description"] ?? "experiment");
10045
- const tsvPath = join23(workspace, "results.tsv");
10046
- const lastResultPath = join23(workspace, ".last-result.json");
10354
+ const tsvPath = join24(workspace, "results.tsv");
10355
+ const lastResultPath = join24(workspace, ".last-result.json");
10047
10356
  let valBpb = args["val_bpb"];
10048
10357
  let memGb = args["memory_gb"];
10049
10358
  if ((valBpb === void 0 || memGb === void 0) && existsSync20(lastResultPath)) {
@@ -10081,8 +10390,8 @@ Branch advanced. Ready for next experiment.`,
10081
10390
  }
10082
10391
  discardExperiment(workspace, args, start) {
10083
10392
  const desc = String(args["description"] ?? "experiment");
10084
- const tsvPath = join23(workspace, "results.tsv");
10085
- const lastResultPath = join23(workspace, ".last-result.json");
10393
+ const tsvPath = join24(workspace, "results.tsv");
10394
+ const lastResultPath = join24(workspace, ".last-result.json");
10086
10395
  let valBpb = args["val_bpb"];
10087
10396
  let memGb = args["memory_gb"];
10088
10397
  if ((valBpb === void 0 || memGb === void 0) && existsSync20(lastResultPath)) {
@@ -10129,8 +10438,8 @@ train.py reverted to last kept state. Ready for next experiment.`,
10129
10438
  // packages/execution/dist/tools/scheduler.js
10130
10439
  import { execSync as execSync18, exec as execCb } from "node:child_process";
10131
10440
  import { readFile as readFile9, writeFile as writeFile8, mkdir as mkdir4 } from "node:fs/promises";
10132
- import { resolve as resolve21, join as join24 } from "node:path";
10133
- import { randomBytes as randomBytes2 } from "node:crypto";
10441
+ import { resolve as resolve21, join as join25 } from "node:path";
10442
+ import { randomBytes as randomBytes3 } from "node:crypto";
10134
10443
  function isValidCron(expr) {
10135
10444
  const parts = expr.trim().split(/\s+/);
10136
10445
  if (parts.length !== 5)
@@ -10213,7 +10522,7 @@ function installCronJob(task, workingDir) {
10213
10522
  const lines = getCurrentCrontab();
10214
10523
  const oaBin = findOaBinary();
10215
10524
  const logDir = resolve21(workingDir, ".oa", "scheduled", "logs");
10216
- const logFile = join24(logDir, `${task.id}.log`);
10525
+ const logFile = join25(logDir, `${task.id}.log`);
10217
10526
  const storeFile = resolve21(workingDir, ".oa", "scheduled", "tasks.json");
10218
10527
  const taskEscaped = task.task.replace(/'/g, "'\\''");
10219
10528
  const taskId = task.id;
@@ -10255,9 +10564,9 @@ async function loadStore(workingDir) {
10255
10564
  async function saveStore(workingDir, store) {
10256
10565
  const dir = resolve21(workingDir, ".oa", "scheduled");
10257
10566
  await mkdir4(dir, { recursive: true });
10258
- await mkdir4(join24(dir, "logs"), { recursive: true });
10567
+ await mkdir4(join25(dir, "logs"), { recursive: true });
10259
10568
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
10260
- await writeFile8(join24(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
10569
+ await writeFile8(join25(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
10261
10570
  }
10262
10571
  var SCHEDULE_PRESETS, CRON_MARKER, SchedulerTool;
10263
10572
  var init_scheduler = __esm({
@@ -10368,7 +10677,7 @@ var init_scheduler = __esm({
10368
10677
  durationMs: performance.now() - start
10369
10678
  };
10370
10679
  }
10371
- const id = `sched-${randomBytes2(4).toString("hex")}`;
10680
+ const id = `sched-${randomBytes3(4).toString("hex")}`;
10372
10681
  const oneShot = Boolean(args["one_shot"]);
10373
10682
  const maxRuns = typeof args["max_runs"] === "number" ? args["max_runs"] : void 0;
10374
10683
  const newTask = {
@@ -10491,8 +10800,8 @@ ${truncated}`, durationMs: performance.now() - start };
10491
10800
 
10492
10801
  // packages/execution/dist/tools/reminder.js
10493
10802
  import { readFile as readFile10, writeFile as writeFile9, mkdir as mkdir5 } from "node:fs/promises";
10494
- import { resolve as resolve22, join as join25 } from "node:path";
10495
- import { randomBytes as randomBytes3 } from "node:crypto";
10803
+ import { resolve as resolve22, join as join26 } from "node:path";
10804
+ import { randomBytes as randomBytes4 } from "node:crypto";
10496
10805
  function parseDueTime(due) {
10497
10806
  const lower = due.toLowerCase().trim();
10498
10807
  const now = /* @__PURE__ */ new Date();
@@ -10543,7 +10852,7 @@ function parseDueTime(due) {
10543
10852
  async function getStorePath(workingDir) {
10544
10853
  const dir = resolve22(workingDir, ".oa", "scheduled");
10545
10854
  await mkdir5(dir, { recursive: true });
10546
- return join25(dir, STORE_FILE);
10855
+ return join26(dir, STORE_FILE);
10547
10856
  }
10548
10857
  async function loadReminderStore(workingDir) {
10549
10858
  const storePath = await getStorePath(workingDir);
@@ -10689,7 +10998,7 @@ var init_reminder = __esm({
10689
10998
  dueAt = parsed.isoDate;
10690
10999
  dueDescription = parsed.description;
10691
11000
  }
10692
- const id = `rem-${randomBytes3(4).toString("hex")}`;
11001
+ const id = `rem-${randomBytes4(4).toString("hex")}`;
10693
11002
  const entry = {
10694
11003
  id,
10695
11004
  message,
@@ -10804,8 +11113,8 @@ var init_reminder = __esm({
10804
11113
 
10805
11114
  // packages/execution/dist/tools/agenda.js
10806
11115
  import { readFile as readFile11, writeFile as writeFile10, mkdir as mkdir6 } from "node:fs/promises";
10807
- import { resolve as resolve23, join as join26 } from "node:path";
10808
- import { randomBytes as randomBytes4 } from "node:crypto";
11116
+ import { resolve as resolve23, join as join27 } from "node:path";
11117
+ import { randomBytes as randomBytes5 } from "node:crypto";
10809
11118
  async function loadAttentionStore(workingDir) {
10810
11119
  const storePath = resolve23(workingDir, ".oa", "scheduled", "attention.json");
10811
11120
  try {
@@ -10819,7 +11128,7 @@ async function saveAttentionStore(workingDir, store) {
10819
11128
  const dir = resolve23(workingDir, ".oa", "scheduled");
10820
11129
  await mkdir6(dir, { recursive: true });
10821
11130
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
10822
- await writeFile10(join26(dir, "attention.json"), JSON.stringify(store, null, 2), "utf-8");
11131
+ await writeFile10(join27(dir, "attention.json"), JSON.stringify(store, null, 2), "utf-8");
10823
11132
  }
10824
11133
  async function getActiveAttentionItems(workingDir) {
10825
11134
  const store = await loadAttentionStore(workingDir);
@@ -11008,7 +11317,7 @@ ${sections.join("\n")}`,
11008
11317
  expiresAt = target.toISOString();
11009
11318
  }
11010
11319
  }
11011
- const id = `attn-${randomBytes4(4).toString("hex")}`;
11320
+ const id = `attn-${randomBytes5(4).toString("hex")}`;
11012
11321
  const item = {
11013
11322
  id,
11014
11323
  title,
@@ -11127,9 +11436,9 @@ ${sections.join("\n")}`,
11127
11436
  });
11128
11437
 
11129
11438
  // packages/execution/dist/tools/opencode.js
11130
- import { execSync as execSync19, spawn as spawn9 } from "node:child_process";
11439
+ import { execSync as execSync19, spawn as spawn10 } from "node:child_process";
11131
11440
  import { existsSync as existsSync21 } from "node:fs";
11132
- import { join as join27, resolve as resolve24 } from "node:path";
11441
+ import { join as join28, resolve as resolve24 } from "node:path";
11133
11442
  function findOpencode() {
11134
11443
  for (const cmd of ["opencode"]) {
11135
11444
  try {
@@ -11141,8 +11450,8 @@ function findOpencode() {
11141
11450
  }
11142
11451
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
11143
11452
  const candidates = [
11144
- join27(homeDir, ".opencode", "bin", "opencode"),
11145
- join27(homeDir, "bin", "opencode"),
11453
+ join28(homeDir, ".opencode", "bin", "opencode"),
11454
+ join28(homeDir, "bin", "opencode"),
11146
11455
  "/usr/local/bin/opencode"
11147
11456
  ];
11148
11457
  for (const p of candidates) {
@@ -11315,7 +11624,7 @@ var init_opencode = __esm({
11315
11624
  let output = "";
11316
11625
  const maxOutput = 5e5;
11317
11626
  let timedOut = false;
11318
- const child = spawn9(binary, cmdArgs, {
11627
+ const child = spawn10(binary, cmdArgs, {
11319
11628
  cwd: dir,
11320
11629
  env: { ...process.env, CI: "true", NONINTERACTIVE: "1" },
11321
11630
  stdio: ["ignore", "pipe", "pipe"]
@@ -11401,9 +11710,9 @@ var init_opencode = __esm({
11401
11710
  });
11402
11711
 
11403
11712
  // packages/execution/dist/tools/factory.js
11404
- import { execSync as execSync20, spawn as spawn10 } from "node:child_process";
11713
+ import { execSync as execSync20, spawn as spawn11 } from "node:child_process";
11405
11714
  import { existsSync as existsSync22 } from "node:fs";
11406
- import { join as join28 } from "node:path";
11715
+ import { join as join29 } from "node:path";
11407
11716
  function findDroid() {
11408
11717
  for (const cmd of ["droid"]) {
11409
11718
  try {
@@ -11415,8 +11724,8 @@ function findDroid() {
11415
11724
  }
11416
11725
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
11417
11726
  const candidates = [
11418
- join28(homeDir, ".factory", "bin", "droid"),
11419
- join28(homeDir, "bin", "droid"),
11727
+ join29(homeDir, ".factory", "bin", "droid"),
11728
+ join29(homeDir, "bin", "droid"),
11420
11729
  "/usr/local/bin/droid"
11421
11730
  ];
11422
11731
  for (const p of candidates) {
@@ -11620,7 +11929,7 @@ var init_factory = __esm({
11620
11929
  let output = "";
11621
11930
  const maxOutput = 5e5;
11622
11931
  let timedOut = false;
11623
- const child = spawn10(binary, cmdArgs, {
11932
+ const child = spawn11(binary, cmdArgs, {
11624
11933
  cwd: dir,
11625
11934
  env: { ...process.env },
11626
11935
  stdio: ["ignore", "pipe", "pipe"]
@@ -11712,8 +12021,8 @@ var init_factory = __esm({
11712
12021
  // packages/execution/dist/tools/cron-agent.js
11713
12022
  import { execSync as execSync21 } from "node:child_process";
11714
12023
  import { readFile as readFile12, writeFile as writeFile11, mkdir as mkdir7 } from "node:fs/promises";
11715
- import { resolve as resolve25, join as join29 } from "node:path";
11716
- import { randomBytes as randomBytes5 } from "node:crypto";
12024
+ import { resolve as resolve25, join as join30 } from "node:path";
12025
+ import { randomBytes as randomBytes6 } from "node:crypto";
11717
12026
  function isValidCron2(expr) {
11718
12027
  const parts = expr.trim().split(/\s+/);
11719
12028
  if (parts.length !== 5)
@@ -11798,7 +12107,7 @@ function installCronAgentJob(job, workingDir) {
11798
12107
  const lines = getCurrentCrontab2();
11799
12108
  const oaBin = findOaBinary2();
11800
12109
  const logDir = resolve25(workingDir, ".oa", "cron-agents", "logs");
11801
- const logFile = join29(logDir, `${job.id}.log`);
12110
+ const logFile = join30(logDir, `${job.id}.log`);
11802
12111
  const storeFile = resolve25(workingDir, ".oa", "cron-agents", "store.json");
11803
12112
  const taskEscaped = job.task.replace(/'/g, "'\\''");
11804
12113
  const jobId = job.id;
@@ -11837,9 +12146,9 @@ async function loadStore2(workingDir) {
11837
12146
  async function saveStore2(workingDir, store) {
11838
12147
  const dir = resolve25(workingDir, ".oa", "cron-agents");
11839
12148
  await mkdir7(dir, { recursive: true });
11840
- await mkdir7(join29(dir, "logs"), { recursive: true });
12149
+ await mkdir7(join30(dir, "logs"), { recursive: true });
11841
12150
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
11842
- await writeFile11(join29(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
12151
+ await writeFile11(join30(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
11843
12152
  }
11844
12153
  var LONG_HORIZON_PRESETS, CRON_AGENT_MARKER, CronAgentTool;
11845
12154
  var init_cron_agent = __esm({
@@ -11973,7 +12282,7 @@ var init_cron_agent = __esm({
11973
12282
  durationMs: performance.now() - start
11974
12283
  };
11975
12284
  }
11976
- const id = `cron-${randomBytes5(4).toString("hex")}`;
12285
+ const id = `cron-${randomBytes6(4).toString("hex")}`;
11977
12286
  const verifyCommand = args["verify_command"] ? String(args["verify_command"]) : void 0;
11978
12287
  const maxRuns = typeof args["max_runs"] === "number" ? args["max_runs"] : 0;
11979
12288
  const tags = Array.isArray(args["tags"]) ? args["tags"] : [];
@@ -12177,9 +12486,9 @@ ${truncated}`, durationMs: performance.now() - start };
12177
12486
  // packages/execution/dist/tools/nexus.js
12178
12487
  import { readFile as readFile13, writeFile as writeFile12, mkdir as mkdir8, chmod, unlink, readdir as readdir3, open as fsOpen } from "node:fs/promises";
12179
12488
  import { existsSync as existsSync23, readFileSync as readFileSync16, watch as fsWatchLocal } from "node:fs";
12180
- import { resolve as resolve26, join as join30 } from "node:path";
12181
- import { randomBytes as randomBytes6, createCipheriv, createDecipheriv, scryptSync, createHash } from "node:crypto";
12182
- import { execSync as execSync22, spawn as spawn11 } from "node:child_process";
12489
+ import { resolve as resolve26, join as join31 } from "node:path";
12490
+ import { randomBytes as randomBytes7, createCipheriv, createDecipheriv, scryptSync, createHash } from "node:crypto";
12491
+ import { execSync as execSync22, spawn as spawn12 } from "node:child_process";
12183
12492
  import { hostname, userInfo } from "node:os";
12184
12493
  function containsKeyMaterial(input) {
12185
12494
  for (const pattern of KEY_PATTERNS) {
@@ -14270,7 +14579,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14270
14579
  // Daemon management
14271
14580
  // =========================================================================
14272
14581
  getDaemonPid() {
14273
- const pidFile = join30(this.nexusDir, "daemon.pid");
14582
+ const pidFile = join31(this.nexusDir, "daemon.pid");
14274
14583
  if (!existsSync23(pidFile))
14275
14584
  return null;
14276
14585
  try {
@@ -14295,9 +14604,9 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14295
14604
  if (!pid)
14296
14605
  throw new Error("Nexus daemon not running. Use action 'connect' first.");
14297
14606
  }
14298
- const cmdId = randomBytes6(8).toString("hex");
14299
- const cmdFile = join30(this.nexusDir, "cmd.json");
14300
- const respFile = join30(this.nexusDir, "resp.json");
14607
+ const cmdId = randomBytes7(8).toString("hex");
14608
+ const cmdFile = join31(this.nexusDir, "cmd.json");
14609
+ const respFile = join31(this.nexusDir, "resp.json");
14301
14610
  if (existsSync23(respFile))
14302
14611
  await unlink(respFile).catch(() => {
14303
14612
  });
@@ -14381,7 +14690,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14381
14690
  const currentScriptHash = createHash("sha256").update(DAEMON_SCRIPT).digest("hex").slice(0, 16);
14382
14691
  const existingPid = this.getDaemonPid();
14383
14692
  if (existingPid) {
14384
- const daemonPath2 = join30(this.nexusDir, "nexus-daemon.mjs");
14693
+ const daemonPath2 = join31(this.nexusDir, "nexus-daemon.mjs");
14385
14694
  let needsRestart = true;
14386
14695
  if (existsSync23(daemonPath2)) {
14387
14696
  try {
@@ -14405,13 +14714,13 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14405
14714
  } catch {
14406
14715
  }
14407
14716
  for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
14408
- const p = join30(this.nexusDir, f);
14717
+ const p = join31(this.nexusDir, f);
14409
14718
  if (existsSync23(p))
14410
14719
  await unlink(p).catch(() => {
14411
14720
  });
14412
14721
  }
14413
14722
  } else {
14414
- const statusFile2 = join30(this.nexusDir, "status.json");
14723
+ const statusFile2 = join31(this.nexusDir, "status.json");
14415
14724
  if (existsSync23(statusFile2)) {
14416
14725
  try {
14417
14726
  const status = JSON.parse(await readFile13(statusFile2, "utf8"));
@@ -14430,7 +14739,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14430
14739
  }
14431
14740
  }
14432
14741
  for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
14433
- const p = join30(this.nexusDir, f);
14742
+ const p = join31(this.nexusDir, f);
14434
14743
  if (existsSync23(p))
14435
14744
  await unlink(p).catch(() => {
14436
14745
  });
@@ -14448,7 +14757,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14448
14757
  });
14449
14758
  });
14450
14759
  try {
14451
- const nexusPkg = join30(nodeModulesDir, "open-agents-nexus", "package.json");
14760
+ const nexusPkg = join31(nodeModulesDir, "open-agents-nexus", "package.json");
14452
14761
  if (existsSync23(nexusPkg)) {
14453
14762
  nexusResolved = true;
14454
14763
  try {
@@ -14459,7 +14768,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14459
14768
  } else {
14460
14769
  try {
14461
14770
  const globalDir = await execAsync2("npm root -g", { timeout: 5e3 });
14462
- const globalPkg = join30(globalDir, "open-agents-nexus", "package.json");
14771
+ const globalPkg = join31(globalDir, "open-agents-nexus", "package.json");
14463
14772
  if (existsSync23(globalPkg)) {
14464
14773
  nexusResolved = true;
14465
14774
  try {
@@ -14504,7 +14813,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14504
14813
  }
14505
14814
  }
14506
14815
  await this.ensureWallet();
14507
- const daemonPath = join30(this.nexusDir, "nexus-daemon.mjs");
14816
+ const daemonPath = join31(this.nexusDir, "nexus-daemon.mjs");
14508
14817
  await writeFile12(daemonPath, DAEMON_SCRIPT);
14509
14818
  const agentName = args.agent_name || "open-agents-node";
14510
14819
  const agentType = args.agent_type || "general";
@@ -14515,11 +14824,11 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14515
14824
  } catch {
14516
14825
  }
14517
14826
  const { openSync: openSync2, closeSync: closeSync2 } = await import("node:fs");
14518
- const daemonLogPath = join30(this.nexusDir, "daemon.log");
14519
- const daemonErrPath = join30(this.nexusDir, "daemon.err");
14827
+ const daemonLogPath = join31(this.nexusDir, "daemon.log");
14828
+ const daemonErrPath = join31(this.nexusDir, "daemon.err");
14520
14829
  const outFd = openSync2(daemonLogPath, "w");
14521
14830
  const errFd = openSync2(daemonErrPath, "w");
14522
- const child = spawn11("node", [daemonPath, this.nexusDir, agentName, agentType], {
14831
+ const child = spawn12("node", [daemonPath, this.nexusDir, agentName, agentType], {
14523
14832
  detached: true,
14524
14833
  stdio: ["ignore", outFd, errFd],
14525
14834
  cwd: this.repoRoot,
@@ -14534,7 +14843,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14534
14843
  closeSync2(errFd);
14535
14844
  } catch {
14536
14845
  }
14537
- const statusFile = join30(this.nexusDir, "status.json");
14846
+ const statusFile = join31(this.nexusDir, "status.json");
14538
14847
  for (let i = 0; i < 40; i++) {
14539
14848
  await new Promise((r) => setTimeout(r, 500));
14540
14849
  if (existsSync23(statusFile)) {
@@ -14593,7 +14902,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14593
14902
  } catch {
14594
14903
  }
14595
14904
  for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
14596
- const p = join30(this.nexusDir, f);
14905
+ const p = join31(this.nexusDir, f);
14597
14906
  if (existsSync23(p))
14598
14907
  await unlink(p).catch(() => {
14599
14908
  });
@@ -14604,7 +14913,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14604
14913
  const pid = this.getDaemonPid();
14605
14914
  if (!pid)
14606
14915
  return "Nexus daemon not running. Use action 'connect' to start.";
14607
- const statusFile = join30(this.nexusDir, "status.json");
14916
+ const statusFile = join31(this.nexusDir, "status.json");
14608
14917
  if (!existsSync23(statusFile))
14609
14918
  return `Daemon running (pid: ${pid}) but no status yet.`;
14610
14919
  try {
@@ -14619,7 +14928,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14619
14928
  ` Capabilities: ${(status.capabilities || []).length ? (status.capabilities || []).join(", ") : "none"}`,
14620
14929
  ` Blocked peers: ${(status.blockedPeers || []).length || 0}`
14621
14930
  ];
14622
- const walletPath = join30(this.nexusDir, "wallet.enc");
14931
+ const walletPath = join31(this.nexusDir, "wallet.enc");
14623
14932
  if (existsSync23(walletPath)) {
14624
14933
  try {
14625
14934
  const w = JSON.parse(await readFile13(walletPath, "utf8"));
@@ -14630,14 +14939,14 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14630
14939
  } else {
14631
14940
  lines.push(` Wallet: not configured`);
14632
14941
  }
14633
- const inboxDir = join30(this.nexusDir, "inbox");
14942
+ const inboxDir = join31(this.nexusDir, "inbox");
14634
14943
  if (existsSync23(inboxDir)) {
14635
14944
  try {
14636
14945
  const roomDirs = await readdir3(inboxDir);
14637
14946
  let totalMsgs = 0;
14638
14947
  for (const rd of roomDirs) {
14639
14948
  try {
14640
- totalMsgs += (await readdir3(join30(inboxDir, rd))).length;
14949
+ totalMsgs += (await readdir3(join31(inboxDir, rd))).length;
14641
14950
  } catch {
14642
14951
  }
14643
14952
  }
@@ -14684,9 +14993,9 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14684
14993
  }
14685
14994
  async doReadMessages(args) {
14686
14995
  const roomId = args.room_id;
14687
- const inboxDir = join30(this.nexusDir, "inbox");
14996
+ const inboxDir = join31(this.nexusDir, "inbox");
14688
14997
  if (roomId) {
14689
- const roomInbox = join30(inboxDir, roomId);
14998
+ const roomInbox = join31(inboxDir, roomId);
14690
14999
  if (!existsSync23(roomInbox))
14691
15000
  return `No messages in room: ${roomId}`;
14692
15001
  const files = (await readdir3(roomInbox)).sort().slice(-20);
@@ -14695,7 +15004,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14695
15004
  const messages = [`Messages in ${roomId} (last ${files.length}):`];
14696
15005
  for (const f of files) {
14697
15006
  try {
14698
- const msg = JSON.parse(await readFile13(join30(roomInbox, f), "utf8"));
15007
+ const msg = JSON.parse(await readFile13(join31(roomInbox, f), "utf8"));
14699
15008
  const sender = (msg.sender || "unknown").slice(0, 12);
14700
15009
  messages.push(` [${new Date(msg.timestamp).toLocaleTimeString()}] ${sender}...: ${msg.content}`);
14701
15010
  } catch {
@@ -14711,7 +15020,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14711
15020
  const lines = ["Inbox:"];
14712
15021
  for (const rd of roomDirs) {
14713
15022
  try {
14714
- const count = (await readdir3(join30(inboxDir, rd))).length;
15023
+ const count = (await readdir3(join31(inboxDir, rd))).length;
14715
15024
  lines.push(` ${rd}: ${count} message(s)`);
14716
15025
  } catch {
14717
15026
  }
@@ -14723,7 +15032,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14723
15032
  // ---------------------------------------------------------------------------
14724
15033
  async doWalletStatus() {
14725
15034
  await this.ensureDir();
14726
- const walletPath = join30(this.nexusDir, "wallet.enc");
15035
+ const walletPath = join31(this.nexusDir, "wallet.enc");
14727
15036
  if (!existsSync23(walletPath)) {
14728
15037
  return "No wallet configured. Use wallet_create to set one up.";
14729
15038
  }
@@ -14762,7 +15071,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14762
15071
  }
14763
15072
  async doWalletCreate(args) {
14764
15073
  await this.ensureDir();
14765
- const walletPath = join30(this.nexusDir, "wallet.enc");
15074
+ const walletPath = join31(this.nexusDir, "wallet.enc");
14766
15075
  if (existsSync23(walletPath))
14767
15076
  return "Wallet already exists. Delete wallet.enc to create a new one.";
14768
15077
  const userAddress = args.wallet_address;
@@ -14791,24 +15100,24 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14791
15100
  let privKeyHex;
14792
15101
  try {
14793
15102
  const { privateKeyToAccount } = await import("viem/accounts");
14794
- const privKey = randomBytes6(32);
15103
+ const privKey = randomBytes7(32);
14795
15104
  privKeyHex = privKey.toString("hex");
14796
15105
  const account = privateKeyToAccount(`0x${privKeyHex}`);
14797
15106
  address = account.address;
14798
15107
  privKey.fill(0);
14799
15108
  } catch {
14800
- const privKey = randomBytes6(32);
15109
+ const privKey = randomBytes7(32);
14801
15110
  privKeyHex = privKey.toString("hex");
14802
15111
  address = "0x" + createHash("sha256").update(privKey).digest("hex").slice(0, 40);
14803
15112
  privKey.fill(0);
14804
15113
  }
14805
- const salt = randomBytes6(32);
15114
+ const salt = randomBytes7(32);
14806
15115
  const key = scryptSync(`${hostname()}:${userInfo().username}:nexus-wallet`, salt, 32, { N: 16384, r: 8, p: 1 });
14807
- const iv = randomBytes6(16);
15116
+ const iv = randomBytes7(16);
14808
15117
  const cipher = createCipheriv("aes-256-gcm", key, iv);
14809
15118
  let enc = cipher.update(privKeyHex, "utf8", "hex");
14810
15119
  enc += cipher.final("hex");
14811
- const x402KeyPath = join30(this.nexusDir, "x402-wallet.key");
15120
+ const x402KeyPath = join31(this.nexusDir, "x402-wallet.key");
14812
15121
  const x402Fh = await fsOpen(x402KeyPath, "w", 384);
14813
15122
  await x402Fh.writeFile("0x" + privKeyHex);
14814
15123
  await x402Fh.close();
@@ -14846,31 +15155,31 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14846
15155
  * Silent — no user output, just ensures the files exist.
14847
15156
  */
14848
15157
  async ensureWallet() {
14849
- const walletPath = join30(this.nexusDir, "wallet.enc");
15158
+ const walletPath = join31(this.nexusDir, "wallet.enc");
14850
15159
  if (existsSync23(walletPath))
14851
15160
  return;
14852
15161
  let address;
14853
15162
  let privKeyHex;
14854
15163
  try {
14855
15164
  const { privateKeyToAccount } = await import("viem/accounts");
14856
- const privKey = randomBytes6(32);
15165
+ const privKey = randomBytes7(32);
14857
15166
  privKeyHex = privKey.toString("hex");
14858
15167
  const account = privateKeyToAccount(`0x${privKeyHex}`);
14859
15168
  address = account.address;
14860
15169
  privKey.fill(0);
14861
15170
  } catch {
14862
- const privKey = randomBytes6(32);
15171
+ const privKey = randomBytes7(32);
14863
15172
  privKeyHex = privKey.toString("hex");
14864
15173
  address = "0x" + createHash("sha256").update(privKey).digest("hex").slice(0, 40);
14865
15174
  privKey.fill(0);
14866
15175
  }
14867
- const salt = randomBytes6(32);
15176
+ const salt = randomBytes7(32);
14868
15177
  const key = scryptSync(`${hostname()}:${userInfo().username}:nexus-wallet`, salt, 32, { N: 16384, r: 8, p: 1 });
14869
- const iv = randomBytes6(16);
15178
+ const iv = randomBytes7(16);
14870
15179
  const cipher = createCipheriv("aes-256-gcm", key, iv);
14871
15180
  let enc = cipher.update(privKeyHex, "utf8", "hex");
14872
15181
  enc += cipher.final("hex");
14873
- const x402KeyPath = join30(this.nexusDir, "x402-wallet.key");
15182
+ const x402KeyPath = join31(this.nexusDir, "x402-wallet.key");
14874
15183
  const x402Fh = await fsOpen(x402KeyPath, "w", 384);
14875
15184
  await x402Fh.writeFile("0x" + privKeyHex);
14876
15185
  await x402Fh.close();
@@ -14930,7 +15239,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14930
15239
  // ---------------------------------------------------------------------------
14931
15240
  async doLedgerStatus() {
14932
15241
  await this.ensureDir();
14933
- const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
15242
+ const ledgerPath = join31(this.nexusDir, "ledger.jsonl");
14934
15243
  if (!existsSync23(ledgerPath)) {
14935
15244
  return "No ledger entries. Earnings and spending will be tracked here after x402 transactions.";
14936
15245
  }
@@ -14972,7 +15281,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14972
15281
  }
14973
15282
  }
14974
15283
  async getLedgerSummary() {
14975
- const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
15284
+ const ledgerPath = join31(this.nexusDir, "ledger.jsonl");
14976
15285
  if (!existsSync23(ledgerPath))
14977
15286
  return null;
14978
15287
  try {
@@ -14997,7 +15306,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
14997
15306
  }
14998
15307
  async appendLedger(entry) {
14999
15308
  await this.ensureDir();
15000
- const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
15309
+ const ledgerPath = join31(this.nexusDir, "ledger.jsonl");
15001
15310
  const line = JSON.stringify(entry) + "\n";
15002
15311
  await writeFile12(ledgerPath, existsSync23(ledgerPath) ? await readFile13(ledgerPath, "utf8") + line : line);
15003
15312
  }
@@ -15005,7 +15314,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
15005
15314
  // Step 4: Budget Policy — Spending limits and auto-approve thresholds
15006
15315
  // ---------------------------------------------------------------------------
15007
15316
  async loadBudget() {
15008
- const budgetPath = join30(this.nexusDir, "budget.json");
15317
+ const budgetPath = join31(this.nexusDir, "budget.json");
15009
15318
  if (!existsSync23(budgetPath))
15010
15319
  return null;
15011
15320
  try {
@@ -15015,7 +15324,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
15015
15324
  }
15016
15325
  }
15017
15326
  async ensureDefaultBudget() {
15018
- const budgetPath = join30(this.nexusDir, "budget.json");
15327
+ const budgetPath = join31(this.nexusDir, "budget.json");
15019
15328
  if (existsSync23(budgetPath))
15020
15329
  return;
15021
15330
  const defaultBudget = {
@@ -15085,12 +15394,12 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
15085
15394
  if (changes.length === 0) {
15086
15395
  return "No budget parameters provided. Use daily_limit, per_invoke_max, or auto_approve_below.";
15087
15396
  }
15088
- const budgetPath = join30(this.nexusDir, "budget.json");
15397
+ const budgetPath = join31(this.nexusDir, "budget.json");
15089
15398
  await writeFile12(budgetPath, JSON.stringify(budget, null, 2));
15090
15399
  return `Budget updated: ${changes.join(", ")}`;
15091
15400
  }
15092
15401
  async getTodaySpending() {
15093
- const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
15402
+ const ledgerPath = join31(this.nexusDir, "ledger.jsonl");
15094
15403
  if (!existsSync23(ledgerPath))
15095
15404
  return 0;
15096
15405
  try {
@@ -15134,7 +15443,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
15134
15443
  if (todaySpent + amountUsdc > budget.dailyLimitUsdc) {
15135
15444
  return { allowed: false, reason: `Would exceed daily limit ($${((todaySpent + amountUsdc) / 1e6).toFixed(6)} > $${(budget.dailyLimitUsdc / 1e6).toFixed(6)})` };
15136
15445
  }
15137
- const walletPath = join30(this.nexusDir, "wallet.enc");
15446
+ const walletPath = join31(this.nexusDir, "wallet.enc");
15138
15447
  if (existsSync23(walletPath)) {
15139
15448
  try {
15140
15449
  const w = JSON.parse(await readFile13(walletPath, "utf8"));
@@ -15165,7 +15474,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
15165
15474
  const budgetResult = await this.checkBudget(amountSmallest, "transfer:direct", targetAddress);
15166
15475
  if (!budgetResult.allowed)
15167
15476
  return `BLOCKED by budget policy: ${budgetResult.reason}`;
15168
- const walletPath = join30(this.nexusDir, "wallet.enc");
15477
+ const walletPath = join31(this.nexusDir, "wallet.enc");
15169
15478
  if (!existsSync23(walletPath))
15170
15479
  throw new Error("No wallet. Use wallet_create first.");
15171
15480
  const w = JSON.parse(await readFile13(walletPath, "utf8"));
@@ -15180,7 +15489,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
15180
15489
  try {
15181
15490
  const { privateKeyToAccount } = await import("viem/accounts");
15182
15491
  const account = privateKeyToAccount(`0x${privKeyHex}`);
15183
- const nonce = "0x" + randomBytes6(32).toString("hex");
15492
+ const nonce = "0x" + randomBytes7(32).toString("hex");
15184
15493
  const now = Math.floor(Date.now() / 1e3);
15185
15494
  const validAfter = now - 60;
15186
15495
  const validBefore = now + 3600;
@@ -15226,7 +15535,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
15226
15535
  capability: "transfer:direct",
15227
15536
  note: "signed, awaiting submission"
15228
15537
  });
15229
- const proofFile = join30(this.nexusDir, "pending-transfer.json");
15538
+ const proofFile = join31(this.nexusDir, "pending-transfer.json");
15230
15539
  const proof = {
15231
15540
  from: account.address,
15232
15541
  to: targetAddress,
@@ -15268,7 +15577,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
15268
15577
  throw new Error("prompt is required");
15269
15578
  const estimatedTokens = Math.ceil(prompt.length / 4) + 1e3;
15270
15579
  let estimatedCostSmallest = 0;
15271
- const pricingPath = join30(this.nexusDir, "pricing.json");
15580
+ const pricingPath = join31(this.nexusDir, "pricing.json");
15272
15581
  if (existsSync23(pricingPath)) {
15273
15582
  try {
15274
15583
  const pricing = JSON.parse(await readFile13(pricingPath, "utf8"));
@@ -15383,12 +15692,12 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
15383
15692
  } catch {
15384
15693
  }
15385
15694
  }
15386
- const nonce = randomBytes6(16).toString("hex");
15695
+ const nonce = randomBytes7(16).toString("hex");
15387
15696
  const hash = createHash("sha256").update(`${modelName}:${nonce}:${Date.now()}`).digest("hex");
15388
15697
  const bar = (s) => "\u2588".repeat(Math.round(s / 5)) + "\u2591".repeat(20 - Math.round(s / 5));
15389
15698
  const mem = vramMb > 24e3 ? 95 : vramMb > 16e3 ? 80 : vramMb > 8e3 ? 60 : vramMb > 0 ? 40 : 20;
15390
15699
  await this.ensureDir();
15391
- await writeFile12(join30(this.nexusDir, "inference-proof.json"), JSON.stringify({
15700
+ await writeFile12(join31(this.nexusDir, "inference-proof.json"), JSON.stringify({
15392
15701
  modelName,
15393
15702
  gpuName,
15394
15703
  vramMb,
@@ -15411,14 +15720,14 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
15411
15720
  });
15412
15721
 
15413
15722
  // packages/execution/dist/shellRunner.js
15414
- import { spawn as spawn12 } from "node:child_process";
15723
+ import { spawn as spawn13 } from "node:child_process";
15415
15724
  async function runShell(options) {
15416
15725
  const { command, args = [], cwd: cwd4, env, timeoutMs = DEFAULT_TIMEOUT_MS } = options;
15417
15726
  const mergedEnv = env ? { ...process.env, ...env } : process.env;
15418
15727
  return new Promise((resolve32) => {
15419
15728
  const start = Date.now();
15420
15729
  let timedOut = false;
15421
- const child = spawn12(command, args, {
15730
+ const child = spawn13(command, args, {
15422
15731
  cwd: cwd4,
15423
15732
  env: mergedEnv
15424
15733
  // Do NOT use shell:true — we pass command + args separately
@@ -15517,7 +15826,7 @@ var init_gitWorktree = __esm({
15517
15826
  // packages/execution/dist/patchApplier.js
15518
15827
  import { readFileSync as readFileSync17, writeFileSync as writeFileSync7, existsSync as existsSync24, mkdirSync as mkdirSync7 } from "node:fs";
15519
15828
  import { dirname as dirname11 } from "node:path";
15520
- import { spawn as spawn13 } from "node:child_process";
15829
+ import { spawn as spawn14 } from "node:child_process";
15521
15830
  async function applyPatch(patch) {
15522
15831
  switch (patch.type) {
15523
15832
  case "block-replace":
@@ -15567,7 +15876,7 @@ async function applyUnifiedDiff(patch) {
15567
15876
  function runWithStdin(options) {
15568
15877
  const { command, args, cwd: cwd4, stdin } = options;
15569
15878
  return new Promise((resolve32) => {
15570
- const child = spawn13(command, args, {
15879
+ const child = spawn14(command, args, {
15571
15880
  cwd: cwd4,
15572
15881
  stdio: ["pipe", "pipe", "pipe"]
15573
15882
  });
@@ -16051,6 +16360,7 @@ __export(dist_exports, {
16051
16360
  OpenCodeTool: () => OpenCodeTool,
16052
16361
  PdfToTextTool: () => PdfToTextTool,
16053
16362
  ReminderTool: () => ReminderTool,
16363
+ ReplTool: () => ReplTool,
16054
16364
  SchedulerTool: () => SchedulerTool,
16055
16365
  ScreenshotTool: () => ScreenshotTool,
16056
16366
  ShellTool: () => ShellTool,
@@ -16135,6 +16445,7 @@ var init_dist2 = __esm({
16135
16445
  init_transcribe_tool();
16136
16446
  init_structured_file();
16137
16447
  init_code_sandbox();
16448
+ init_repl();
16138
16449
  init_structured_read();
16139
16450
  init_vision();
16140
16451
  init_desktop_click();
@@ -16835,12 +17146,12 @@ var init_dist3 = __esm({
16835
17146
 
16836
17147
  // packages/orchestrator/dist/promptLoader.js
16837
17148
  import { readFileSync as readFileSync18, existsSync as existsSync25 } from "node:fs";
16838
- import { join as join31, dirname as dirname12 } from "node:path";
17149
+ import { join as join32, dirname as dirname12 } from "node:path";
16839
17150
  import { fileURLToPath as fileURLToPath7 } from "node:url";
16840
17151
  function loadPrompt(promptPath, vars) {
16841
17152
  let content = cache.get(promptPath);
16842
17153
  if (content === void 0) {
16843
- const fullPath = join31(PROMPTS_DIR, promptPath);
17154
+ const fullPath = join32(PROMPTS_DIR, promptPath);
16844
17155
  if (!existsSync25(fullPath)) {
16845
17156
  throw new Error(`Prompt file not found: ${fullPath}`);
16846
17157
  }
@@ -16857,7 +17168,7 @@ var init_promptLoader = __esm({
16857
17168
  "use strict";
16858
17169
  __filename = fileURLToPath7(import.meta.url);
16859
17170
  __dirname4 = dirname12(__filename);
16860
- PROMPTS_DIR = join31(__dirname4, "..", "prompts");
17171
+ PROMPTS_DIR = join32(__dirname4, "..", "prompts");
16861
17172
  cache = /* @__PURE__ */ new Map();
16862
17173
  }
16863
17174
  });
@@ -17237,7 +17548,7 @@ var init_code_retriever = __esm({
17237
17548
  import { execFile as execFile5 } from "node:child_process";
17238
17549
  import { promisify as promisify4 } from "node:util";
17239
17550
  import { readFile as readFile14, readdir as readdir4, stat as stat3 } from "node:fs/promises";
17240
- import { join as join32, extname as extname7 } from "node:path";
17551
+ import { join as join33, extname as extname7 } from "node:path";
17241
17552
  async function searchByPath(pathPattern, options) {
17242
17553
  const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
17243
17554
  const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
@@ -17379,7 +17690,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
17379
17690
  continue;
17380
17691
  if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
17381
17692
  continue;
17382
- const absPath = join32(dir, entry.name);
17693
+ const absPath = join33(dir, entry.name);
17383
17694
  if (entry.isDirectory()) {
17384
17695
  await walkForFiles(rootDir, absPath, excludeGlobs, results);
17385
17696
  } else if (entry.isFile()) {
@@ -17686,7 +17997,7 @@ var init_graphExpand = __esm({
17686
17997
 
17687
17998
  // packages/retrieval/dist/snippetPacker.js
17688
17999
  import { readFile as readFile15 } from "node:fs/promises";
17689
- import { join as join33 } from "node:path";
18000
+ import { join as join34 } from "node:path";
17690
18001
  async function packSnippets(requests, opts = {}) {
17691
18002
  const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
17692
18003
  const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
@@ -17712,7 +18023,7 @@ async function packSnippets(requests, opts = {}) {
17712
18023
  return { packed, dropped, totalTokens };
17713
18024
  }
17714
18025
  async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
17715
- const absPath = req.filePath.startsWith("/") ? req.filePath : join33(repoRoot, req.filePath);
18026
+ const absPath = req.filePath.startsWith("/") ? req.filePath : join34(repoRoot, req.filePath);
17716
18027
  let content;
17717
18028
  try {
17718
18029
  content = await readFile15(absPath, "utf-8");
@@ -20253,8 +20564,8 @@ ${marker}` : marker);
20253
20564
  return;
20254
20565
  try {
20255
20566
  const { mkdirSync: mkdirSync21, writeFileSync: writeFileSync20 } = __require("node:fs");
20256
- const { join: join57 } = __require("node:path");
20257
- const sessionDir = join57(this._workingDirectory, ".oa", "session", this._sessionId);
20567
+ const { join: join58 } = __require("node:path");
20568
+ const sessionDir = join58(this._workingDirectory, ".oa", "session", this._sessionId);
20258
20569
  mkdirSync21(sessionDir, { recursive: true });
20259
20570
  const checkpoint = {
20260
20571
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -20267,7 +20578,7 @@ ${marker}` : marker);
20267
20578
  memexEntryCount: this._memexArchive.size,
20268
20579
  fileRegistrySize: this._fileRegistry.size
20269
20580
  };
20270
- writeFileSync20(join57(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
20581
+ writeFileSync20(join58(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
20271
20582
  } catch {
20272
20583
  }
20273
20584
  }
@@ -21533,11 +21844,11 @@ ${transcript}`
21533
21844
  });
21534
21845
 
21535
21846
  // packages/orchestrator/dist/nexusBackend.js
21536
- import { existsSync as existsSync26, statSync as statSync9, openSync, readSync, closeSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync8 } from "node:fs";
21847
+ import { existsSync as existsSync26, statSync as statSync9, openSync, readSync, closeSync, unlinkSync as unlinkSync4, writeFileSync as writeFileSync8 } from "node:fs";
21537
21848
  import { watch as fsWatch } from "node:fs";
21538
- import { join as join34 } from "node:path";
21539
- import { tmpdir as tmpdir6 } from "node:os";
21540
- import { randomBytes as randomBytes7 } from "node:crypto";
21849
+ import { join as join35 } from "node:path";
21850
+ import { tmpdir as tmpdir7 } from "node:os";
21851
+ import { randomBytes as randomBytes8 } from "node:crypto";
21541
21852
  var NexusAgenticBackend;
21542
21853
  var init_nexusBackend = __esm({
21543
21854
  "packages/orchestrator/dist/nexusBackend.js"() {
@@ -21685,7 +21996,7 @@ var init_nexusBackend = __esm({
21685
21996
  * Falls back to unary + word-split if streaming setup fails.
21686
21997
  */
21687
21998
  async *chatCompletionStream(request) {
21688
- const streamFile = join34(tmpdir6(), `nexus-stream-${randomBytes7(6).toString("hex")}.jsonl`);
21999
+ const streamFile = join35(tmpdir7(), `nexus-stream-${randomBytes8(6).toString("hex")}.jsonl`);
21689
22000
  writeFileSync8(streamFile, "", "utf8");
21690
22001
  const daemonArgs = {
21691
22002
  model: this.model,
@@ -21706,7 +22017,7 @@ var init_nexusBackend = __esm({
21706
22017
  } catch (sendErr) {
21707
22018
  this.consecutiveFailures++;
21708
22019
  try {
21709
- unlinkSync3(streamFile);
22020
+ unlinkSync4(streamFile);
21710
22021
  } catch {
21711
22022
  }
21712
22023
  throw sendErr;
@@ -21721,7 +22032,7 @@ var init_nexusBackend = __esm({
21721
22032
  }
21722
22033
  if (!isStreaming) {
21723
22034
  try {
21724
- unlinkSync3(streamFile);
22035
+ unlinkSync4(streamFile);
21725
22036
  } catch {
21726
22037
  }
21727
22038
  let parsed;
@@ -21877,7 +22188,7 @@ var init_nexusBackend = __esm({
21877
22188
  }
21878
22189
  } finally {
21879
22190
  try {
21880
- unlinkSync3(streamFile);
22191
+ unlinkSync4(streamFile);
21881
22192
  } catch {
21882
22193
  }
21883
22194
  }
@@ -22720,9 +23031,9 @@ __export(listen_exports, {
22720
23031
  isVideoPath: () => isVideoPath,
22721
23032
  waitForTranscribeCli: () => waitForTranscribeCli
22722
23033
  });
22723
- import { spawn as spawn14, execSync as execSync23 } from "node:child_process";
23034
+ import { spawn as spawn15, execSync as execSync23 } from "node:child_process";
22724
23035
  import { existsSync as existsSync27, mkdirSync as mkdirSync8, writeFileSync as writeFileSync9, readdirSync as readdirSync6 } from "node:fs";
22725
- import { join as join35, dirname as dirname13 } from "node:path";
23036
+ import { join as join36, dirname as dirname13 } from "node:path";
22726
23037
  import { homedir as homedir8 } from "node:os";
22727
23038
  import { fileURLToPath as fileURLToPath8 } from "node:url";
22728
23039
  import { EventEmitter } from "node:events";
@@ -22808,12 +23119,12 @@ function findMicCaptureCommand() {
22808
23119
  function findLiveWhisperScript() {
22809
23120
  const thisDir = dirname13(fileURLToPath8(import.meta.url));
22810
23121
  const candidates = [
22811
- join35(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
22812
- join35(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
22813
- join35(thisDir, "../../execution/scripts/live-whisper.py"),
23122
+ join36(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
23123
+ join36(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
23124
+ join36(thisDir, "../../execution/scripts/live-whisper.py"),
22814
23125
  // npm install layout — scripts bundled alongside dist
22815
- join35(thisDir, "../scripts/live-whisper.py"),
22816
- join35(thisDir, "../../scripts/live-whisper.py")
23126
+ join36(thisDir, "../scripts/live-whisper.py"),
23127
+ join36(thisDir, "../../scripts/live-whisper.py")
22817
23128
  ];
22818
23129
  for (const p of candidates) {
22819
23130
  if (existsSync27(p))
@@ -22826,8 +23137,8 @@ function findLiveWhisperScript() {
22826
23137
  stdio: ["pipe", "pipe", "pipe"]
22827
23138
  }).trim();
22828
23139
  const candidates2 = [
22829
- join35(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
22830
- join35(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
23140
+ join36(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
23141
+ join36(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
22831
23142
  ];
22832
23143
  for (const p of candidates2) {
22833
23144
  if (existsSync27(p))
@@ -22835,11 +23146,11 @@ function findLiveWhisperScript() {
22835
23146
  }
22836
23147
  } catch {
22837
23148
  }
22838
- const nvmBase = join35(homedir8(), ".nvm", "versions", "node");
23149
+ const nvmBase = join36(homedir8(), ".nvm", "versions", "node");
22839
23150
  if (existsSync27(nvmBase)) {
22840
23151
  try {
22841
23152
  for (const ver of readdirSync6(nvmBase)) {
22842
- const p = join35(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
23153
+ const p = join36(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
22843
23154
  if (existsSync27(p))
22844
23155
  return p;
22845
23156
  }
@@ -22858,7 +23169,7 @@ function ensureTranscribeCliBackground() {
22858
23169
  timeout: 5e3,
22859
23170
  stdio: ["pipe", "pipe", "pipe"]
22860
23171
  }).trim();
22861
- if (existsSync27(join35(globalRoot, "transcribe-cli", "dist", "index.js"))) {
23172
+ if (existsSync27(join36(globalRoot, "transcribe-cli", "dist", "index.js"))) {
22862
23173
  return true;
22863
23174
  }
22864
23175
  } catch {
@@ -22930,7 +23241,7 @@ var init_listen = __esm({
22930
23241
  const timeout = setTimeout(() => {
22931
23242
  reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
22932
23243
  }, 3e5);
22933
- this.process = spawn14("python3", [
23244
+ this.process = spawn15("python3", [
22934
23245
  this.scriptPath,
22935
23246
  "--model",
22936
23247
  this.model,
@@ -23081,24 +23392,24 @@ var init_listen = __esm({
23081
23392
  timeout: 5e3,
23082
23393
  stdio: ["pipe", "pipe", "pipe"]
23083
23394
  }).trim();
23084
- const tcPath = join35(globalRoot, "transcribe-cli");
23085
- if (existsSync27(join35(tcPath, "dist", "index.js"))) {
23395
+ const tcPath = join36(globalRoot, "transcribe-cli");
23396
+ if (existsSync27(join36(tcPath, "dist", "index.js"))) {
23086
23397
  const { createRequire: createRequire4 } = await import("node:module");
23087
23398
  const req = createRequire4(import.meta.url);
23088
- return req(join35(tcPath, "dist", "index.js"));
23399
+ return req(join36(tcPath, "dist", "index.js"));
23089
23400
  }
23090
23401
  } catch {
23091
23402
  }
23092
- const nvmBase = join35(homedir8(), ".nvm", "versions", "node");
23403
+ const nvmBase = join36(homedir8(), ".nvm", "versions", "node");
23093
23404
  if (existsSync27(nvmBase)) {
23094
23405
  try {
23095
23406
  const { readdirSync: readdirSync17 } = await import("node:fs");
23096
23407
  for (const ver of readdirSync17(nvmBase)) {
23097
- const tcPath = join35(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
23098
- if (existsSync27(join35(tcPath, "dist", "index.js"))) {
23408
+ const tcPath = join36(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
23409
+ if (existsSync27(join36(tcPath, "dist", "index.js"))) {
23099
23410
  const { createRequire: createRequire4 } = await import("node:module");
23100
23411
  const req = createRequire4(import.meta.url);
23101
- return req(join35(tcPath, "dist", "index.js"));
23412
+ return req(join36(tcPath, "dist", "index.js"));
23102
23413
  }
23103
23414
  }
23104
23415
  } catch {
@@ -23212,7 +23523,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
23212
23523
  return `Failed to start live transcription: ${msg}${tcHint}`;
23213
23524
  }
23214
23525
  }
23215
- this.micProcess = spawn14(micCmd.cmd, micCmd.args, {
23526
+ this.micProcess = spawn15(micCmd.cmd, micCmd.args, {
23216
23527
  stdio: ["pipe", "pipe", "pipe"],
23217
23528
  env: { ...process.env }
23218
23529
  });
@@ -23380,9 +23691,9 @@ transcribe-cli error: ${transcribeCliError}` : "";
23380
23691
  });
23381
23692
  if (outputDir) {
23382
23693
  const { basename: basename16 } = await import("node:path");
23383
- const transcriptDir = join35(outputDir, ".oa", "transcripts");
23694
+ const transcriptDir = join36(outputDir, ".oa", "transcripts");
23384
23695
  mkdirSync8(transcriptDir, { recursive: true });
23385
- const outFile = join35(transcriptDir, `${basename16(filePath)}.txt`);
23696
+ const outFile = join36(transcriptDir, `${basename16(filePath)}.txt`);
23386
23697
  writeFileSync9(outFile, result.text, "utf-8");
23387
23698
  }
23388
23699
  return {
@@ -25631,7 +25942,7 @@ var require_websocket = __commonJS({
25631
25942
  var http = __require("http");
25632
25943
  var net = __require("net");
25633
25944
  var tls = __require("tls");
25634
- var { randomBytes: randomBytes11, createHash: createHash5 } = __require("crypto");
25945
+ var { randomBytes: randomBytes12, createHash: createHash5 } = __require("crypto");
25635
25946
  var { Duplex, Readable } = __require("stream");
25636
25947
  var { URL: URL3 } = __require("url");
25637
25948
  var PerMessageDeflate = require_permessage_deflate();
@@ -26161,7 +26472,7 @@ var require_websocket = __commonJS({
26161
26472
  }
26162
26473
  }
26163
26474
  const defaultPort = isSecure ? 443 : 80;
26164
- const key = randomBytes11(16).toString("base64");
26475
+ const key = randomBytes12(16).toString("base64");
26165
26476
  const request = isSecure ? https.request : http.request;
26166
26477
  const protocolSet = /* @__PURE__ */ new Set();
26167
26478
  let perMessageDeflate;
@@ -28005,8 +28316,8 @@ var init_render = __esm({
28005
28316
  });
28006
28317
 
28007
28318
  // packages/cli/dist/tui/voice-session.js
28008
- import { createServer } from "node:http";
28009
- import { spawn as spawn15, execSync as execSync24 } from "node:child_process";
28319
+ import { createServer as createServer2 } from "node:http";
28320
+ import { spawn as spawn16, execSync as execSync24 } from "node:child_process";
28010
28321
  import { EventEmitter as EventEmitter2 } from "node:events";
28011
28322
  function generateFrontendHTML() {
28012
28323
  return `<!DOCTYPE html>
@@ -28432,7 +28743,7 @@ var init_voice_session = __esm({
28432
28743
  return "Voice session already active.";
28433
28744
  const port = await this.findFreePort();
28434
28745
  this.state.localPort = port;
28435
- this.server = createServer((req, res) => this.handleHTTP(req, res));
28746
+ this.server = createServer2((req, res) => this.handleHTTP(req, res));
28436
28747
  this.server.timeout = 0;
28437
28748
  this.server.keepAliveTimeout = 0;
28438
28749
  this.wss = new import_websocket_server.default({ server: this.server, path: "/ws" });
@@ -28660,7 +28971,7 @@ var init_voice_session = __esm({
28660
28971
  const timeout = setTimeout(() => {
28661
28972
  reject(new Error("Cloudflared tunnel start timeout (30s)"));
28662
28973
  }, 3e4);
28663
- this.cloudflaredProcess = spawn15("cloudflared", [
28974
+ this.cloudflaredProcess = spawn16("cloudflared", [
28664
28975
  "tunnel",
28665
28976
  "--url",
28666
28977
  `http://127.0.0.1:${port}`
@@ -28715,7 +29026,7 @@ var init_voice_session = __esm({
28715
29026
  // ── Helpers ───────────────────────────────────────────────────────────
28716
29027
  findFreePort() {
28717
29028
  return new Promise((resolve32, reject) => {
28718
- const srv = createServer();
29029
+ const srv = createServer2();
28719
29030
  srv.listen(0, "127.0.0.1", () => {
28720
29031
  const addr = srv.address();
28721
29032
  if (addr && typeof addr === "object") {
@@ -28733,14 +29044,14 @@ var init_voice_session = __esm({
28733
29044
  });
28734
29045
 
28735
29046
  // packages/cli/dist/tui/expose.js
28736
- import { createServer as createServer2, request as httpRequest } from "node:http";
28737
- import { spawn as spawn16, exec } from "node:child_process";
29047
+ import { createServer as createServer3, request as httpRequest } from "node:http";
29048
+ import { spawn as spawn17, exec } from "node:child_process";
28738
29049
  import { EventEmitter as EventEmitter3 } from "node:events";
28739
- import { randomBytes as randomBytes8 } from "node:crypto";
29050
+ import { randomBytes as randomBytes9 } from "node:crypto";
28740
29051
  import { URL as URL2 } from "node:url";
28741
29052
  import { loadavg, cpus, totalmem, freemem } from "node:os";
28742
- import { existsSync as existsSync28, readFileSync as readFileSync19, writeFileSync as writeFileSync10, unlinkSync as unlinkSync4, mkdirSync as mkdirSync9, readdirSync as readdirSync7, statSync as statSync10 } from "node:fs";
28743
- import { join as join36 } from "node:path";
29053
+ import { existsSync as existsSync28, readFileSync as readFileSync19, writeFileSync as writeFileSync10, unlinkSync as unlinkSync5, mkdirSync as mkdirSync9, readdirSync as readdirSync7, statSync as statSync10 } from "node:fs";
29054
+ import { join as join37 } from "node:path";
28744
29055
  function cleanForwardHeaders(raw, targetHost) {
28745
29056
  const out = {};
28746
29057
  for (const [key, value] of Object.entries(raw)) {
@@ -28768,7 +29079,7 @@ function fmtTokens(n) {
28768
29079
  }
28769
29080
  function readExposeState(stateDir) {
28770
29081
  try {
28771
- const path = join36(stateDir, STATE_FILE_NAME);
29082
+ const path = join37(stateDir, STATE_FILE_NAME);
28772
29083
  if (!existsSync28(path))
28773
29084
  return null;
28774
29085
  const raw = readFileSync19(path, "utf8");
@@ -28783,13 +29094,13 @@ function readExposeState(stateDir) {
28783
29094
  function writeExposeState(stateDir, state) {
28784
29095
  try {
28785
29096
  mkdirSync9(stateDir, { recursive: true });
28786
- writeFileSync10(join36(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
29097
+ writeFileSync10(join37(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
28787
29098
  } catch {
28788
29099
  }
28789
29100
  }
28790
29101
  function removeExposeState(stateDir) {
28791
29102
  try {
28792
- unlinkSync4(join36(stateDir, STATE_FILE_NAME));
29103
+ unlinkSync5(join37(stateDir, STATE_FILE_NAME));
28793
29104
  } catch {
28794
29105
  }
28795
29106
  }
@@ -28878,7 +29189,7 @@ async function collectSystemMetricsAsync() {
28878
29189
  }
28879
29190
  function readP2PExposeState(stateDir) {
28880
29191
  try {
28881
- const path = join36(stateDir, P2P_STATE_FILE_NAME);
29192
+ const path = join37(stateDir, P2P_STATE_FILE_NAME);
28882
29193
  if (!existsSync28(path))
28883
29194
  return null;
28884
29195
  const raw = readFileSync19(path, "utf8");
@@ -28893,13 +29204,13 @@ function readP2PExposeState(stateDir) {
28893
29204
  function writeP2PExposeState(stateDir, state) {
28894
29205
  try {
28895
29206
  mkdirSync9(stateDir, { recursive: true });
28896
- writeFileSync10(join36(stateDir, P2P_STATE_FILE_NAME), JSON.stringify(state, null, 2));
29207
+ writeFileSync10(join37(stateDir, P2P_STATE_FILE_NAME), JSON.stringify(state, null, 2));
28897
29208
  } catch {
28898
29209
  }
28899
29210
  }
28900
29211
  function removeP2PExposeState(stateDir) {
28901
29212
  try {
28902
- unlinkSync4(join36(stateDir, P2P_STATE_FILE_NAME));
29213
+ unlinkSync5(join37(stateDir, P2P_STATE_FILE_NAME));
28903
29214
  } catch {
28904
29215
  }
28905
29216
  }
@@ -28981,7 +29292,7 @@ var init_expose = __esm({
28981
29292
  this._stateDir = options.stateDir ?? null;
28982
29293
  this._fullAccess = options.fullAccess ?? false;
28983
29294
  if (options.authKey === void 0 || options.authKey === "") {
28984
- this._authKey = randomBytes8(24).toString("base64url");
29295
+ this._authKey = randomBytes9(24).toString("base64url");
28985
29296
  } else {
28986
29297
  this._authKey = options.authKey;
28987
29298
  }
@@ -29124,7 +29435,7 @@ var init_expose = __esm({
29124
29435
  // ── Proxy server ────────────────────────────────────────────────────────
29125
29436
  createProxyServer(localPort) {
29126
29437
  const target = new URL2(this._targetUrl);
29127
- const server = createServer2((req, res) => {
29438
+ const server = createServer3((req, res) => {
29128
29439
  res.on("error", () => {
29129
29440
  });
29130
29441
  const authHeader = req.headers.authorization;
@@ -29400,7 +29711,7 @@ var init_expose = __esm({
29400
29711
  const timeout = setTimeout(() => {
29401
29712
  reject(new Error("Cloudflared tunnel start timeout (30s)"));
29402
29713
  }, 3e4);
29403
- this.cloudflaredProcess = spawn16("cloudflared", [
29714
+ this.cloudflaredProcess = spawn17("cloudflared", [
29404
29715
  "tunnel",
29405
29716
  "--url",
29406
29717
  `http://127.0.0.1:${port}`,
@@ -29515,7 +29826,7 @@ ${this.formatConnectionInfo()}`);
29515
29826
  // ── Helpers ─────────────────────────────────────────────────────────────
29516
29827
  findFreePort() {
29517
29828
  return new Promise((resolve32, reject) => {
29518
- const srv = createServer2();
29829
+ const srv = createServer3();
29519
29830
  srv.listen(0, "127.0.0.1", () => {
29520
29831
  const addr = srv.address();
29521
29832
  if (addr && typeof addr === "object") {
@@ -29691,7 +30002,7 @@ ${this.formatConnectionInfo()}`);
29691
30002
  this._onInfo = options.onInfo;
29692
30003
  this._onError = options.onError;
29693
30004
  if (options.authKey === void 0 || options.authKey === "") {
29694
- this._authKey = randomBytes8(24).toString("base64url");
30005
+ this._authKey = randomBytes9(24).toString("base64url");
29695
30006
  } else {
29696
30007
  this._authKey = options.authKey;
29697
30008
  }
@@ -29729,7 +30040,7 @@ ${this.formatConnectionInfo()}`);
29729
30040
  throw new Error(`Expose failed: ${exposeResult.error}`);
29730
30041
  }
29731
30042
  const nexusDir = this._nexusTool.getNexusDir();
29732
- const statusPath = join36(nexusDir, "status.json");
30043
+ const statusPath = join37(nexusDir, "status.json");
29733
30044
  for (let i = 0; i < 80; i++) {
29734
30045
  try {
29735
30046
  const raw = readFileSync19(statusPath, "utf8");
@@ -29763,7 +30074,7 @@ ${this.formatConnectionInfo()}`);
29763
30074
  });
29764
30075
  }
29765
30076
  try {
29766
- const invocDir = join36(nexusDir, "invocations");
30077
+ const invocDir = join37(nexusDir, "invocations");
29767
30078
  if (existsSync28(invocDir)) {
29768
30079
  this._prevInvocCount = readdirSync7(invocDir).filter((f) => f.endsWith(".json")).length;
29769
30080
  this._stats.totalRequests = this._prevInvocCount;
@@ -29793,7 +30104,7 @@ ${this.formatConnectionInfo()}`);
29793
30104
  if (!state)
29794
30105
  return null;
29795
30106
  const nexusDir = nexusTool.getNexusDir();
29796
- const statusPath = join36(nexusDir, "status.json");
30107
+ const statusPath = join37(nexusDir, "status.json");
29797
30108
  try {
29798
30109
  if (!existsSync28(statusPath)) {
29799
30110
  removeP2PExposeState(stateDir);
@@ -29852,7 +30163,7 @@ ${this.formatConnectionInfo()}`);
29852
30163
  let lastMeteringLineCount = 0;
29853
30164
  this._activityPollTimer = setInterval(() => {
29854
30165
  try {
29855
- const invocDir = join36(nexusDir, "invocations");
30166
+ const invocDir = join37(nexusDir, "invocations");
29856
30167
  if (!existsSync28(invocDir))
29857
30168
  return;
29858
30169
  const files = readdirSync7(invocDir).filter((f) => f.endsWith(".json"));
@@ -29868,13 +30179,13 @@ ${this.formatConnectionInfo()}`);
29868
30179
  let recentActive = 0;
29869
30180
  for (const f of files.slice(-10)) {
29870
30181
  try {
29871
- const st = statSync10(join36(invocDir, f));
30182
+ const st = statSync10(join37(invocDir, f));
29872
30183
  if (now - st.mtimeMs < 1e4)
29873
30184
  recentActive++;
29874
30185
  } catch {
29875
30186
  }
29876
30187
  }
29877
- const meteringFile = join36(nexusDir, "metering.jsonl");
30188
+ const meteringFile = join37(nexusDir, "metering.jsonl");
29878
30189
  let meteringLines = lastMeteringLineCount;
29879
30190
  try {
29880
30191
  if (existsSync28(meteringFile)) {
@@ -29904,7 +30215,7 @@ ${this.formatConnectionInfo()}`);
29904
30215
  this._activityPollTimer.unref();
29905
30216
  this._pollTimer = setInterval(() => {
29906
30217
  try {
29907
- const statusPath = join36(nexusDir, "status.json");
30218
+ const statusPath = join37(nexusDir, "status.json");
29908
30219
  if (existsSync28(statusPath)) {
29909
30220
  const status = JSON.parse(readFileSync19(statusPath, "utf8"));
29910
30221
  if (status.peerId && !this._peerId) {
@@ -29915,7 +30226,7 @@ ${this.formatConnectionInfo()}`);
29915
30226
  } catch {
29916
30227
  }
29917
30228
  try {
29918
- const invocDir = join36(nexusDir, "invocations");
30229
+ const invocDir = join37(nexusDir, "invocations");
29919
30230
  if (existsSync28(invocDir)) {
29920
30231
  const files = readdirSync7(invocDir);
29921
30232
  const invocCount = files.filter((f) => f.endsWith(".json")).length;
@@ -29927,7 +30238,7 @@ ${this.formatConnectionInfo()}`);
29927
30238
  } catch {
29928
30239
  }
29929
30240
  try {
29930
- const meteringFile = join36(nexusDir, "metering.jsonl");
30241
+ const meteringFile = join37(nexusDir, "metering.jsonl");
29931
30242
  if (existsSync28(meteringFile)) {
29932
30243
  const content = readFileSync19(meteringFile, "utf8");
29933
30244
  if (content.length > lastMeteringSize) {
@@ -30137,9 +30448,9 @@ var init_types = __esm({
30137
30448
  });
30138
30449
 
30139
30450
  // packages/cli/dist/tui/p2p/secret-vault.js
30140
- import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes9, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
30451
+ import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes10, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
30141
30452
  import { readFileSync as readFileSync20, writeFileSync as writeFileSync11, existsSync as existsSync29, mkdirSync as mkdirSync10 } from "node:fs";
30142
- import { join as join37, dirname as dirname14 } from "node:path";
30453
+ import { join as join38, dirname as dirname14 } from "node:path";
30143
30454
  var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
30144
30455
  var init_secret_vault = __esm({
30145
30456
  "packages/cli/dist/tui/p2p/secret-vault.js"() {
@@ -30343,9 +30654,9 @@ var init_secret_vault = __esm({
30343
30654
  minTrust: s.minTrust,
30344
30655
  createdAt: s.createdAt
30345
30656
  })));
30346
- const salt = randomBytes9(SALT_LEN);
30657
+ const salt = randomBytes10(SALT_LEN);
30347
30658
  const key = scryptSync2(passphrase, salt, KEY_LEN);
30348
- const iv = randomBytes9(IV_LEN);
30659
+ const iv = randomBytes10(IV_LEN);
30349
30660
  const cipher = createCipheriv2(CIPHER_ALGO, key, iv);
30350
30661
  const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
30351
30662
  const tag = cipher.getAuthTag();
@@ -30402,8 +30713,8 @@ var init_secret_vault = __esm({
30402
30713
 
30403
30714
  // packages/cli/dist/tui/p2p/peer-mesh.js
30404
30715
  import { EventEmitter as EventEmitter4 } from "node:events";
30405
- import { createServer as createServer3 } from "node:http";
30406
- import { randomBytes as randomBytes10, createHash as createHash3, generateKeyPairSync } from "node:crypto";
30716
+ import { createServer as createServer4 } from "node:http";
30717
+ import { randomBytes as randomBytes11, createHash as createHash3, generateKeyPairSync } from "node:crypto";
30407
30718
  var PING_INTERVAL_MS, PEER_TIMEOUT_MS, GOSSIP_INTERVAL_MS, MAX_PEERS, PeerMesh;
30408
30719
  var init_peer_mesh = __esm({
30409
30720
  "packages/cli/dist/tui/p2p/peer-mesh.js"() {
@@ -30455,14 +30766,14 @@ var init_peer_mesh = __esm({
30455
30766
  this.peerId = createHash3("sha256").update(this.publicKey).digest("base64url").slice(0, 22);
30456
30767
  this.capabilities = options.capabilities;
30457
30768
  this.displayName = options.displayName;
30458
- this._authKey = options.authKey ?? randomBytes10(24).toString("base64url");
30769
+ this._authKey = options.authKey ?? randomBytes11(24).toString("base64url");
30459
30770
  }
30460
30771
  // ── Lifecycle ───────────────────────────────────────────────────────────
30461
30772
  /** Start the mesh node — creates WS server and connects to bootstrap peers */
30462
30773
  async start() {
30463
30774
  const port = await this.findFreePort();
30464
30775
  this._port = port;
30465
- this.server = createServer3();
30776
+ this.server = createServer4();
30466
30777
  this.wss = new import_websocket_server.default({ server: this.server });
30467
30778
  this.wss.on("connection", (ws, req) => {
30468
30779
  this.handleInboundConnection(ws, req.url ?? "");
@@ -30619,7 +30930,7 @@ var init_peer_mesh = __esm({
30619
30930
  if (!ws || ws.readyState !== import_websocket.default.OPEN) {
30620
30931
  throw new Error(`Peer ${peerId} not connected`);
30621
30932
  }
30622
- const msgId = randomBytes10(8).toString("hex");
30933
+ const msgId = randomBytes11(8).toString("hex");
30623
30934
  return new Promise((resolve32, reject) => {
30624
30935
  const timeout = setTimeout(() => {
30625
30936
  this.pendingRequests.delete(msgId);
@@ -30840,7 +31151,7 @@ var init_peer_mesh = __esm({
30840
31151
  const msg = {
30841
31152
  type,
30842
31153
  from: this.peerId,
30843
- msgId: msgId ?? randomBytes10(8).toString("hex"),
31154
+ msgId: msgId ?? randomBytes11(8).toString("hex"),
30844
31155
  ts: (/* @__PURE__ */ new Date()).toISOString(),
30845
31156
  payload
30846
31157
  };
@@ -30848,7 +31159,7 @@ var init_peer_mesh = __esm({
30848
31159
  }
30849
31160
  findFreePort() {
30850
31161
  return new Promise((resolve32, reject) => {
30851
- const srv = createServer3();
31162
+ const srv = createServer4();
30852
31163
  srv.listen(0, "127.0.0.1", () => {
30853
31164
  const addr = srv.address();
30854
31165
  if (addr && typeof addr === "object") {
@@ -31476,13 +31787,13 @@ async function fetchPeerModels(peerId, authKey) {
31476
31787
  try {
31477
31788
  const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
31478
31789
  const { existsSync: existsSync45, readFileSync: readFileSync33 } = await import("node:fs");
31479
- const { join: join57 } = await import("node:path");
31790
+ const { join: join58 } = await import("node:path");
31480
31791
  const cwd4 = process.cwd();
31481
31792
  const nexusTool = new NexusTool2(cwd4);
31482
31793
  const nexusDir = nexusTool.getNexusDir();
31483
31794
  let isLocalPeer = false;
31484
31795
  try {
31485
- const statusPath = join57(nexusDir, "status.json");
31796
+ const statusPath = join58(nexusDir, "status.json");
31486
31797
  if (existsSync45(statusPath)) {
31487
31798
  const status = JSON.parse(readFileSync33(statusPath, "utf8"));
31488
31799
  if (status.peerId === peerId)
@@ -31491,7 +31802,7 @@ async function fetchPeerModels(peerId, authKey) {
31491
31802
  } catch {
31492
31803
  }
31493
31804
  if (isLocalPeer) {
31494
- const pricingPath = join57(nexusDir, "pricing.json");
31805
+ const pricingPath = join58(nexusDir, "pricing.json");
31495
31806
  if (existsSync45(pricingPath)) {
31496
31807
  try {
31497
31808
  const pricing = JSON.parse(readFileSync33(pricingPath, "utf8"));
@@ -31508,7 +31819,7 @@ async function fetchPeerModels(peerId, authKey) {
31508
31819
  }
31509
31820
  }
31510
31821
  }
31511
- const cachePath = join57(nexusDir, "peer-models-cache.json");
31822
+ const cachePath = join58(nexusDir, "peer-models-cache.json");
31512
31823
  if (existsSync45(cachePath)) {
31513
31824
  try {
31514
31825
  const cache4 = JSON.parse(readFileSync33(cachePath, "utf8"));
@@ -31626,7 +31937,7 @@ async function fetchPeerModels(peerId, authKey) {
31626
31937
  } catch {
31627
31938
  }
31628
31939
  if (isLocalPeer) {
31629
- const pricingPath = join57(nexusDir, "pricing.json");
31940
+ const pricingPath = join58(nexusDir, "pricing.json");
31630
31941
  if (existsSync45(pricingPath)) {
31631
31942
  try {
31632
31943
  const pricing = JSON.parse(readFileSync33(pricingPath, "utf8"));
@@ -31899,12 +32210,12 @@ var init_render2 = __esm({
31899
32210
 
31900
32211
  // packages/prompts/dist/promptLoader.js
31901
32212
  import { readFileSync as readFileSync21, existsSync as existsSync30 } from "node:fs";
31902
- import { join as join38, dirname as dirname15 } from "node:path";
32213
+ import { join as join39, dirname as dirname15 } from "node:path";
31903
32214
  import { fileURLToPath as fileURLToPath9 } from "node:url";
31904
32215
  function loadPrompt2(promptPath, vars) {
31905
32216
  let content = cache2.get(promptPath);
31906
32217
  if (content === void 0) {
31907
- const fullPath = join38(PROMPTS_DIR2, promptPath);
32218
+ const fullPath = join39(PROMPTS_DIR2, promptPath);
31908
32219
  if (!existsSync30(fullPath)) {
31909
32220
  throw new Error(`Prompt file not found: ${fullPath}`);
31910
32221
  }
@@ -31921,8 +32232,8 @@ var init_promptLoader2 = __esm({
31921
32232
  "use strict";
31922
32233
  __filename2 = fileURLToPath9(import.meta.url);
31923
32234
  __dirname5 = dirname15(__filename2);
31924
- devPath = join38(__dirname5, "..", "templates");
31925
- publishedPath = join38(__dirname5, "..", "prompts", "templates");
32235
+ devPath = join39(__dirname5, "..", "templates");
32236
+ publishedPath = join39(__dirname5, "..", "prompts", "templates");
31926
32237
  PROMPTS_DIR2 = existsSync30(devPath) ? devPath : publishedPath;
31927
32238
  cache2 = /* @__PURE__ */ new Map();
31928
32239
  }
@@ -32034,7 +32345,7 @@ var init_task_templates = __esm({
32034
32345
  });
32035
32346
 
32036
32347
  // packages/prompts/dist/index.js
32037
- import { join as join39, dirname as dirname16 } from "node:path";
32348
+ import { join as join40, dirname as dirname16 } from "node:path";
32038
32349
  import { fileURLToPath as fileURLToPath10 } from "node:url";
32039
32350
  var _dir, _packageRoot;
32040
32351
  var init_dist6 = __esm({
@@ -32045,21 +32356,21 @@ var init_dist6 = __esm({
32045
32356
  init_task_templates();
32046
32357
  init_render2();
32047
32358
  _dir = dirname16(fileURLToPath10(import.meta.url));
32048
- _packageRoot = join39(_dir, "..");
32359
+ _packageRoot = join40(_dir, "..");
32049
32360
  }
32050
32361
  });
32051
32362
 
32052
32363
  // packages/cli/dist/tui/oa-directory.js
32053
- import { existsSync as existsSync31, mkdirSync as mkdirSync11, readFileSync as readFileSync22, writeFileSync as writeFileSync12, readdirSync as readdirSync8, statSync as statSync11, unlinkSync as unlinkSync5 } from "node:fs";
32054
- import { join as join40, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
32364
+ import { existsSync as existsSync31, mkdirSync as mkdirSync11, readFileSync as readFileSync22, writeFileSync as writeFileSync12, readdirSync as readdirSync8, statSync as statSync11, unlinkSync as unlinkSync6 } from "node:fs";
32365
+ import { join as join41, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
32055
32366
  import { homedir as homedir9 } from "node:os";
32056
32367
  function initOaDirectory(repoRoot) {
32057
- const oaPath = join40(repoRoot, OA_DIR);
32368
+ const oaPath = join41(repoRoot, OA_DIR);
32058
32369
  for (const sub of SUBDIRS) {
32059
- mkdirSync11(join40(oaPath, sub), { recursive: true });
32370
+ mkdirSync11(join41(oaPath, sub), { recursive: true });
32060
32371
  }
32061
32372
  try {
32062
- const gitignorePath = join40(repoRoot, ".gitignore");
32373
+ const gitignorePath = join41(repoRoot, ".gitignore");
32063
32374
  const settingsPattern = ".oa/settings.json";
32064
32375
  if (existsSync31(gitignorePath)) {
32065
32376
  const content = readFileSync22(gitignorePath, "utf-8");
@@ -32072,10 +32383,10 @@ function initOaDirectory(repoRoot) {
32072
32383
  return oaPath;
32073
32384
  }
32074
32385
  function hasOaDirectory(repoRoot) {
32075
- return existsSync31(join40(repoRoot, OA_DIR, "index"));
32386
+ return existsSync31(join41(repoRoot, OA_DIR, "index"));
32076
32387
  }
32077
32388
  function loadProjectSettings(repoRoot) {
32078
- const settingsPath = join40(repoRoot, OA_DIR, "settings.json");
32389
+ const settingsPath = join41(repoRoot, OA_DIR, "settings.json");
32079
32390
  try {
32080
32391
  if (existsSync31(settingsPath)) {
32081
32392
  return JSON.parse(readFileSync22(settingsPath, "utf-8"));
@@ -32085,14 +32396,14 @@ function loadProjectSettings(repoRoot) {
32085
32396
  return {};
32086
32397
  }
32087
32398
  function saveProjectSettings(repoRoot, settings) {
32088
- const oaPath = join40(repoRoot, OA_DIR);
32399
+ const oaPath = join41(repoRoot, OA_DIR);
32089
32400
  mkdirSync11(oaPath, { recursive: true });
32090
32401
  const existing = loadProjectSettings(repoRoot);
32091
32402
  const merged = { ...existing, ...settings };
32092
- writeFileSync12(join40(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
32403
+ writeFileSync12(join41(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
32093
32404
  }
32094
32405
  function loadGlobalSettings() {
32095
- const settingsPath = join40(homedir9(), ".open-agents", "settings.json");
32406
+ const settingsPath = join41(homedir9(), ".open-agents", "settings.json");
32096
32407
  try {
32097
32408
  if (existsSync31(settingsPath)) {
32098
32409
  return JSON.parse(readFileSync22(settingsPath, "utf-8"));
@@ -32102,11 +32413,11 @@ function loadGlobalSettings() {
32102
32413
  return {};
32103
32414
  }
32104
32415
  function saveGlobalSettings(settings) {
32105
- const dir = join40(homedir9(), ".open-agents");
32416
+ const dir = join41(homedir9(), ".open-agents");
32106
32417
  mkdirSync11(dir, { recursive: true });
32107
32418
  const existing = loadGlobalSettings();
32108
32419
  const merged = { ...existing, ...settings };
32109
- writeFileSync12(join40(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
32420
+ writeFileSync12(join41(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
32110
32421
  }
32111
32422
  function resolveSettings(repoRoot) {
32112
32423
  const global = loadGlobalSettings();
@@ -32121,7 +32432,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
32121
32432
  while (dir && !visited.has(dir)) {
32122
32433
  visited.add(dir);
32123
32434
  for (const name of CONTEXT_FILES) {
32124
- const filePath = join40(dir, name);
32435
+ const filePath = join41(dir, name);
32125
32436
  const normalizedName = name.toLowerCase();
32126
32437
  if (existsSync31(filePath) && !seen.has(filePath)) {
32127
32438
  seen.add(filePath);
@@ -32140,7 +32451,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
32140
32451
  }
32141
32452
  }
32142
32453
  }
32143
- const projectMap = join40(dir, OA_DIR, "context", "project-map.md");
32454
+ const projectMap = join41(dir, OA_DIR, "context", "project-map.md");
32144
32455
  if (existsSync31(projectMap) && !seen.has(projectMap)) {
32145
32456
  seen.add(projectMap);
32146
32457
  try {
@@ -32156,7 +32467,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
32156
32467
  } catch {
32157
32468
  }
32158
32469
  }
32159
- const parent = join40(dir, "..");
32470
+ const parent = join41(dir, "..");
32160
32471
  if (parent === dir)
32161
32472
  break;
32162
32473
  dir = parent;
@@ -32174,7 +32485,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
32174
32485
  return found;
32175
32486
  }
32176
32487
  function readIndexMeta(repoRoot) {
32177
- const metaPath = join40(repoRoot, OA_DIR, "index", "meta.json");
32488
+ const metaPath = join41(repoRoot, OA_DIR, "index", "meta.json");
32178
32489
  try {
32179
32490
  return JSON.parse(readFileSync22(metaPath, "utf-8"));
32180
32491
  } catch {
@@ -32227,28 +32538,28 @@ ${tree}\`\`\`
32227
32538
  sections.push("");
32228
32539
  }
32229
32540
  const content = sections.join("\n");
32230
- const contextDir = join40(repoRoot, OA_DIR, "context");
32541
+ const contextDir = join41(repoRoot, OA_DIR, "context");
32231
32542
  mkdirSync11(contextDir, { recursive: true });
32232
- writeFileSync12(join40(contextDir, "project-map.md"), content, "utf-8");
32543
+ writeFileSync12(join41(contextDir, "project-map.md"), content, "utf-8");
32233
32544
  return content;
32234
32545
  }
32235
32546
  function saveSession(repoRoot, session) {
32236
- const historyDir = join40(repoRoot, OA_DIR, "history");
32547
+ const historyDir = join41(repoRoot, OA_DIR, "history");
32237
32548
  mkdirSync11(historyDir, { recursive: true });
32238
- writeFileSync12(join40(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
32549
+ writeFileSync12(join41(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
32239
32550
  }
32240
32551
  function loadRecentSessions(repoRoot, limit = 5) {
32241
- const historyDir = join40(repoRoot, OA_DIR, "history");
32552
+ const historyDir = join41(repoRoot, OA_DIR, "history");
32242
32553
  if (!existsSync31(historyDir))
32243
32554
  return [];
32244
32555
  try {
32245
32556
  const files = readdirSync8(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
32246
- const stat5 = statSync11(join40(historyDir, f));
32557
+ const stat5 = statSync11(join41(historyDir, f));
32247
32558
  return { file: f, mtime: stat5.mtimeMs };
32248
32559
  }).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
32249
32560
  return files.map((f) => {
32250
32561
  try {
32251
- return JSON.parse(readFileSync22(join40(historyDir, f.file), "utf-8"));
32562
+ return JSON.parse(readFileSync22(join41(historyDir, f.file), "utf-8"));
32252
32563
  } catch {
32253
32564
  return null;
32254
32565
  }
@@ -32258,18 +32569,18 @@ function loadRecentSessions(repoRoot, limit = 5) {
32258
32569
  }
32259
32570
  }
32260
32571
  function savePendingTask(repoRoot, task) {
32261
- const historyDir = join40(repoRoot, OA_DIR, "history");
32572
+ const historyDir = join41(repoRoot, OA_DIR, "history");
32262
32573
  mkdirSync11(historyDir, { recursive: true });
32263
- writeFileSync12(join40(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
32574
+ writeFileSync12(join41(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
32264
32575
  }
32265
32576
  function loadPendingTask(repoRoot) {
32266
- const filePath = join40(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
32577
+ const filePath = join41(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
32267
32578
  try {
32268
32579
  if (!existsSync31(filePath))
32269
32580
  return null;
32270
32581
  const data = JSON.parse(readFileSync22(filePath, "utf-8"));
32271
32582
  try {
32272
- unlinkSync5(filePath);
32583
+ unlinkSync6(filePath);
32273
32584
  } catch {
32274
32585
  }
32275
32586
  return data;
@@ -32278,9 +32589,9 @@ function loadPendingTask(repoRoot) {
32278
32589
  }
32279
32590
  }
32280
32591
  function saveSessionContext(repoRoot, entry) {
32281
- const contextDir = join40(repoRoot, OA_DIR, "context");
32592
+ const contextDir = join41(repoRoot, OA_DIR, "context");
32282
32593
  mkdirSync11(contextDir, { recursive: true });
32283
- const filePath = join40(contextDir, CONTEXT_SAVE_FILE);
32594
+ const filePath = join41(contextDir, CONTEXT_SAVE_FILE);
32284
32595
  let ctx;
32285
32596
  try {
32286
32597
  if (existsSync31(filePath)) {
@@ -32299,7 +32610,7 @@ function saveSessionContext(repoRoot, entry) {
32299
32610
  writeFileSync12(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
32300
32611
  }
32301
32612
  function loadSessionContext(repoRoot) {
32302
- const filePath = join40(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
32613
+ const filePath = join41(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
32303
32614
  try {
32304
32615
  if (!existsSync31(filePath))
32305
32616
  return null;
@@ -32350,7 +32661,7 @@ function detectManifests(repoRoot) {
32350
32661
  { file: "docker-compose.yaml", type: "Docker Compose" }
32351
32662
  ];
32352
32663
  for (const check of checks) {
32353
- const filePath = join40(repoRoot, check.file);
32664
+ const filePath = join41(repoRoot, check.file);
32354
32665
  if (existsSync31(filePath)) {
32355
32666
  let name;
32356
32667
  if (check.nameField) {
@@ -32384,7 +32695,7 @@ function findKeyFiles(repoRoot) {
32384
32695
  { pattern: "CLAUDE.md", description: "Claude Code context" }
32385
32696
  ];
32386
32697
  for (const check of checks) {
32387
- if (existsSync31(join40(repoRoot, check.pattern))) {
32698
+ if (existsSync31(join41(repoRoot, check.pattern))) {
32388
32699
  keyFiles.push({ path: check.pattern, description: check.description });
32389
32700
  }
32390
32701
  }
@@ -32410,12 +32721,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
32410
32721
  if (entry.isDirectory()) {
32411
32722
  let fileCount = 0;
32412
32723
  try {
32413
- fileCount = readdirSync8(join40(root, entry.name)).filter((f) => !f.startsWith(".")).length;
32724
+ fileCount = readdirSync8(join41(root, entry.name)).filter((f) => !f.startsWith(".")).length;
32414
32725
  } catch {
32415
32726
  }
32416
32727
  result += `${prefix}${connector}${entry.name}/ (${fileCount})
32417
32728
  `;
32418
- result += buildDirTree(join40(root, entry.name), maxDepth, childPrefix, depth + 1);
32729
+ result += buildDirTree(join41(root, entry.name), maxDepth, childPrefix, depth + 1);
32419
32730
  } else if (depth < maxDepth) {
32420
32731
  result += `${prefix}${connector}${entry.name}
32421
32732
  `;
@@ -32435,7 +32746,7 @@ function loadUsageFile(filePath) {
32435
32746
  return { records: [] };
32436
32747
  }
32437
32748
  function saveUsageFile(filePath, data) {
32438
- const dir = join40(filePath, "..");
32749
+ const dir = join41(filePath, "..");
32439
32750
  mkdirSync11(dir, { recursive: true });
32440
32751
  writeFileSync12(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
32441
32752
  }
@@ -32465,15 +32776,15 @@ function recordUsage(kind, value, opts) {
32465
32776
  }
32466
32777
  saveUsageFile(filePath, data);
32467
32778
  };
32468
- update(join40(homedir9(), ".open-agents", USAGE_HISTORY_FILE));
32779
+ update(join41(homedir9(), ".open-agents", USAGE_HISTORY_FILE));
32469
32780
  if (opts?.repoRoot) {
32470
- update(join40(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
32781
+ update(join41(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
32471
32782
  }
32472
32783
  }
32473
32784
  function loadUsageHistory(kind, repoRoot) {
32474
- const globalPath = join40(homedir9(), ".open-agents", USAGE_HISTORY_FILE);
32785
+ const globalPath = join41(homedir9(), ".open-agents", USAGE_HISTORY_FILE);
32475
32786
  const globalData = loadUsageFile(globalPath);
32476
- const localData = repoRoot ? loadUsageFile(join40(repoRoot, OA_DIR, USAGE_HISTORY_FILE)) : { records: [] };
32787
+ const localData = repoRoot ? loadUsageFile(join41(repoRoot, OA_DIR, USAGE_HISTORY_FILE)) : { records: [] };
32477
32788
  const map = /* @__PURE__ */ new Map();
32478
32789
  for (const r of globalData.records) {
32479
32790
  if (r.kind !== kind)
@@ -32504,9 +32815,9 @@ function deleteUsageRecord(kind, value, repoRoot) {
32504
32815
  saveUsageFile(filePath, data);
32505
32816
  }
32506
32817
  };
32507
- remove(join40(homedir9(), ".open-agents", USAGE_HISTORY_FILE));
32818
+ remove(join41(homedir9(), ".open-agents", USAGE_HISTORY_FILE));
32508
32819
  if (repoRoot) {
32509
- remove(join40(repoRoot, OA_DIR, USAGE_HISTORY_FILE));
32820
+ remove(join41(repoRoot, OA_DIR, USAGE_HISTORY_FILE));
32510
32821
  }
32511
32822
  }
32512
32823
  var OA_DIR, SUBDIRS, CONTEXT_FILES, PENDING_TASK_FILE, CONTEXT_SAVE_FILE, MAX_CONTEXT_ENTRIES, SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
@@ -32554,10 +32865,10 @@ var init_oa_directory = __esm({
32554
32865
 
32555
32866
  // packages/cli/dist/tui/setup.js
32556
32867
  import * as readline from "node:readline";
32557
- import { execSync as execSync25, spawn as spawn17, exec as exec2 } from "node:child_process";
32868
+ import { execSync as execSync25, spawn as spawn18, exec as exec2 } from "node:child_process";
32558
32869
  import { promisify as promisify5 } from "node:util";
32559
32870
  import { existsSync as existsSync32, writeFileSync as writeFileSync13, readFileSync as readFileSync23, appendFileSync as appendFileSync2, mkdirSync as mkdirSync12 } from "node:fs";
32560
- import { join as join41 } from "node:path";
32871
+ import { join as join42 } from "node:path";
32561
32872
  import { homedir as homedir10, platform } from "node:os";
32562
32873
  function detectSystemSpecs() {
32563
32874
  let totalRamGB = 0;
@@ -32952,7 +33263,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
32952
33263
  process.stdout.write(` ${c2.cyan("\u25CF")} Starting ollama serve...
32953
33264
  `);
32954
33265
  try {
32955
- const child = spawn17("ollama", ["serve"], { stdio: "ignore", detached: true });
33266
+ const child = spawn18("ollama", ["serve"], { stdio: "ignore", detached: true });
32956
33267
  child.unref();
32957
33268
  } catch {
32958
33269
  process.stdout.write(` ${c2.yellow("\u26A0")} Could not start ollama serve.
@@ -33420,7 +33731,7 @@ async function doSetup(config, rl) {
33420
33731
  ${c2.cyan("\u25CF")} Ollama is installed but not running. Starting automatically...
33421
33732
  `);
33422
33733
  try {
33423
- const child = spawn17("ollama", ["serve"], { stdio: "ignore", detached: true });
33734
+ const child = spawn18("ollama", ["serve"], { stdio: "ignore", detached: true });
33424
33735
  child.unref();
33425
33736
  await new Promise((resolve32) => setTimeout(resolve32, 3e3));
33426
33737
  try {
@@ -33448,7 +33759,7 @@ async function doSetup(config, rl) {
33448
33759
  ${c2.cyan("\u25CF")} Starting ollama serve...
33449
33760
  `);
33450
33761
  try {
33451
- const child = spawn17("ollama", ["serve"], { stdio: "ignore", detached: true });
33762
+ const child = spawn18("ollama", ["serve"], { stdio: "ignore", detached: true });
33452
33763
  child.unref();
33453
33764
  await new Promise((resolve32) => setTimeout(resolve32, 3e3));
33454
33765
  try {
@@ -33598,9 +33909,9 @@ async function doSetup(config, rl) {
33598
33909
  `PARAMETER num_predict ${numPredict}`,
33599
33910
  `PARAMETER stop "<|endoftext|>"`
33600
33911
  ].join("\n");
33601
- const modelDir2 = join41(homedir10(), ".open-agents", "models");
33912
+ const modelDir2 = join42(homedir10(), ".open-agents", "models");
33602
33913
  mkdirSync12(modelDir2, { recursive: true });
33603
- const modelfilePath = join41(modelDir2, `Modelfile.${customName}`);
33914
+ const modelfilePath = join42(modelDir2, `Modelfile.${customName}`);
33604
33915
  writeFileSync13(modelfilePath, modelfileContent + "\n", "utf8");
33605
33916
  process.stdout.write(` ${c2.dim("Creating model...")} `);
33606
33917
  execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
@@ -33646,7 +33957,7 @@ async function isModelAvailable(config) {
33646
33957
  }
33647
33958
  function isFirstRun() {
33648
33959
  try {
33649
- return !existsSync32(join41(homedir10(), ".open-agents", "config.json"));
33960
+ return !existsSync32(join42(homedir10(), ".open-agents", "config.json"));
33650
33961
  } catch {
33651
33962
  return true;
33652
33963
  }
@@ -33683,7 +33994,7 @@ function detectPkgManager() {
33683
33994
  return null;
33684
33995
  }
33685
33996
  function getVenvDir() {
33686
- return join41(homedir10(), ".open-agents", "venv");
33997
+ return join42(homedir10(), ".open-agents", "venv");
33687
33998
  }
33688
33999
  function hasVenvModule() {
33689
34000
  try {
@@ -33695,7 +34006,7 @@ function hasVenvModule() {
33695
34006
  }
33696
34007
  function ensureVenv(log) {
33697
34008
  const venvDir = getVenvDir();
33698
- const venvPip = join41(venvDir, "bin", "pip");
34009
+ const venvPip = join42(venvDir, "bin", "pip");
33699
34010
  if (existsSync32(venvPip))
33700
34011
  return venvDir;
33701
34012
  log("Creating Python venv for vision deps...");
@@ -33708,9 +34019,9 @@ function ensureVenv(log) {
33708
34019
  return null;
33709
34020
  }
33710
34021
  try {
33711
- mkdirSync12(join41(homedir10(), ".open-agents"), { recursive: true });
34022
+ mkdirSync12(join42(homedir10(), ".open-agents"), { recursive: true });
33712
34023
  execSync25(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
33713
- execSync25(`"${join41(venvDir, "bin", "pip")}" install --upgrade pip`, {
34024
+ execSync25(`"${join42(venvDir, "bin", "pip")}" install --upgrade pip`, {
33714
34025
  stdio: "pipe",
33715
34026
  timeout: 6e4
33716
34027
  });
@@ -33901,11 +34212,11 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
33901
34212
  }
33902
34213
  }
33903
34214
  const venvDir = getVenvDir();
33904
- const venvBin = join41(venvDir, "bin");
33905
- const venvMoondream = join41(venvBin, "moondream-station");
34215
+ const venvBin = join42(venvDir, "bin");
34216
+ const venvMoondream = join42(venvBin, "moondream-station");
33906
34217
  const venv = ensureVenv(log);
33907
34218
  if (venv && !hasCmd("moondream-station") && !existsSync32(venvMoondream)) {
33908
- const venvPip = join41(venvBin, "pip");
34219
+ const venvPip = join42(venvBin, "pip");
33909
34220
  log("Installing moondream-station in ~/.open-agents/venv...");
33910
34221
  try {
33911
34222
  execSync25(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
@@ -33926,8 +34237,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
33926
34237
  }
33927
34238
  }
33928
34239
  if (venv) {
33929
- const venvPython = join41(venvBin, "python");
33930
- const venvPip2 = join41(venvBin, "pip");
34240
+ const venvPython = join42(venvBin, "python");
34241
+ const venvPip2 = join42(venvBin, "pip");
33931
34242
  let ocrStackInstalled = false;
33932
34243
  try {
33933
34244
  execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
@@ -34071,9 +34382,9 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
34071
34382
  `PARAMETER num_predict ${numPredict}`,
34072
34383
  `PARAMETER stop "<|endoftext|>"`
34073
34384
  ].join("\n");
34074
- const modelDir2 = join41(homedir10(), ".open-agents", "models");
34385
+ const modelDir2 = join42(homedir10(), ".open-agents", "models");
34075
34386
  mkdirSync12(modelDir2, { recursive: true });
34076
- const modelfilePath = join41(modelDir2, `Modelfile.${customName}`);
34387
+ const modelfilePath = join42(modelDir2, `Modelfile.${customName}`);
34077
34388
  writeFileSync13(modelfilePath, modelfileContent + "\n", "utf8");
34078
34389
  await execAsync(`ollama create ${customName} -f ${modelfilePath}`, {
34079
34390
  timeout: 12e4
@@ -34148,8 +34459,8 @@ async function ensureNeovim() {
34148
34459
  const platform5 = process.platform;
34149
34460
  const arch = process.arch;
34150
34461
  if (platform5 === "linux") {
34151
- const binDir = join41(homedir10(), ".local", "bin");
34152
- const nvimDest = join41(binDir, "nvim");
34462
+ const binDir = join42(homedir10(), ".local", "bin");
34463
+ const nvimDest = join42(binDir, "nvim");
34153
34464
  try {
34154
34465
  mkdirSync12(binDir, { recursive: true });
34155
34466
  } catch {
@@ -34220,7 +34531,7 @@ async function ensureNeovim() {
34220
34531
  }
34221
34532
  function ensurePathInShellRc(binDir) {
34222
34533
  const shell = process.env.SHELL ?? "";
34223
- const rcFile = shell.includes("zsh") ? join41(homedir10(), ".zshrc") : join41(homedir10(), ".bashrc");
34534
+ const rcFile = shell.includes("zsh") ? join42(homedir10(), ".zshrc") : join42(homedir10(), ".bashrc");
34224
34535
  try {
34225
34536
  const rcContent = existsSync32(rcFile) ? readFileSync23(rcFile, "utf8") : "";
34226
34537
  if (rcContent.includes(binDir))
@@ -34990,9 +35301,9 @@ var init_drop_panel = __esm({
34990
35301
  });
34991
35302
 
34992
35303
  // packages/cli/dist/tui/neovim-mode.js
34993
- import { existsSync as existsSync34, unlinkSync as unlinkSync6 } from "node:fs";
34994
- import { tmpdir as tmpdir7 } from "node:os";
34995
- import { join as join42 } from "node:path";
35304
+ import { existsSync as existsSync34, unlinkSync as unlinkSync7 } from "node:fs";
35305
+ import { tmpdir as tmpdir8 } from "node:os";
35306
+ import { join as join43 } from "node:path";
34996
35307
  import { execSync as execSync26 } from "node:child_process";
34997
35308
  function isNeovimActive() {
34998
35309
  return _state !== null && !_state.cleanedUp;
@@ -35040,10 +35351,10 @@ async function startNeovimMode(opts) {
35040
35351
  );
35041
35352
  } catch {
35042
35353
  }
35043
- const socketPath = join42(tmpdir7(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
35354
+ const socketPath = join43(tmpdir8(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
35044
35355
  try {
35045
35356
  if (existsSync34(socketPath))
35046
- unlinkSync6(socketPath);
35357
+ unlinkSync7(socketPath);
35047
35358
  } catch {
35048
35359
  }
35049
35360
  const ptyCols = opts.cols;
@@ -35336,7 +35647,7 @@ function doCleanup(state) {
35336
35647
  }
35337
35648
  try {
35338
35649
  if (existsSync34(state.socketPath))
35339
- unlinkSync6(state.socketPath);
35650
+ unlinkSync7(state.socketPath);
35340
35651
  } catch {
35341
35652
  }
35342
35653
  if (state.stdinHandler) {
@@ -35391,9 +35702,9 @@ __export(voice_exports, {
35391
35702
  registerCustomOnnxModel: () => registerCustomOnnxModel,
35392
35703
  resetNarrationContext: () => resetNarrationContext
35393
35704
  });
35394
- import { existsSync as existsSync35, mkdirSync as mkdirSync13, writeFileSync as writeFileSync14, readFileSync as readFileSync24, unlinkSync as unlinkSync7, readdirSync as readdirSync9, renameSync, statSync as statSync12 } from "node:fs";
35395
- import { join as join43 } from "node:path";
35396
- import { homedir as homedir11, tmpdir as tmpdir8, platform as platform2 } from "node:os";
35705
+ import { existsSync as existsSync35, mkdirSync as mkdirSync13, writeFileSync as writeFileSync14, readFileSync as readFileSync24, unlinkSync as unlinkSync8, readdirSync as readdirSync9, renameSync, statSync as statSync12 } from "node:fs";
35706
+ import { join as join44 } from "node:path";
35707
+ import { homedir as homedir11, tmpdir as tmpdir9, platform as platform2 } from "node:os";
35397
35708
  import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
35398
35709
  import { createRequire } from "node:module";
35399
35710
  function registerCustomOnnxModel(id, label) {
@@ -35414,34 +35725,34 @@ function listVoiceModels() {
35414
35725
  }));
35415
35726
  }
35416
35727
  function voiceDir() {
35417
- return join43(homedir11(), ".open-agents", "voice");
35728
+ return join44(homedir11(), ".open-agents", "voice");
35418
35729
  }
35419
35730
  function modelsDir() {
35420
- return join43(voiceDir(), "models");
35731
+ return join44(voiceDir(), "models");
35421
35732
  }
35422
35733
  function modelDir(id) {
35423
- return join43(modelsDir(), id);
35734
+ return join44(modelsDir(), id);
35424
35735
  }
35425
35736
  function modelOnnxPath(id) {
35426
- return join43(modelDir(id), "model.onnx");
35737
+ return join44(modelDir(id), "model.onnx");
35427
35738
  }
35428
35739
  function modelConfigPath(id) {
35429
- return join43(modelDir(id), "config.json");
35740
+ return join44(modelDir(id), "config.json");
35430
35741
  }
35431
35742
  function luxttsVenvDir() {
35432
- return join43(voiceDir(), "luxtts-venv");
35743
+ return join44(voiceDir(), "luxtts-venv");
35433
35744
  }
35434
35745
  function luxttsVenvPy() {
35435
- return platform2() === "win32" ? join43(luxttsVenvDir(), "Scripts", "python.exe") : join43(luxttsVenvDir(), "bin", "python3");
35746
+ return platform2() === "win32" ? join44(luxttsVenvDir(), "Scripts", "python.exe") : join44(luxttsVenvDir(), "bin", "python3");
35436
35747
  }
35437
35748
  function luxttsRepoDir() {
35438
- return join43(voiceDir(), "LuxTTS");
35749
+ return join44(voiceDir(), "LuxTTS");
35439
35750
  }
35440
35751
  function luxttsCloneRefsDir() {
35441
- return join43(voiceDir(), "clone-refs");
35752
+ return join44(voiceDir(), "clone-refs");
35442
35753
  }
35443
35754
  function luxttsInferScript() {
35444
- return join43(voiceDir(), "luxtts-infer.py");
35755
+ return join44(voiceDir(), "luxtts-infer.py");
35445
35756
  }
35446
35757
  function emotionToPitchBias(emotion, stark = false, autist = false) {
35447
35758
  if (autist)
@@ -36249,7 +36560,7 @@ var init_voice = __esm({
36249
36560
  const refsDir = luxttsCloneRefsDir();
36250
36561
  const targets = ["glados", "overwatch"];
36251
36562
  for (const modelId of targets) {
36252
- const refFile = join43(refsDir, `${modelId}-ref.wav`);
36563
+ const refFile = join44(refsDir, `${modelId}-ref.wav`);
36253
36564
  if (existsSync35(refFile))
36254
36565
  continue;
36255
36566
  try {
@@ -36329,7 +36640,7 @@ var init_voice = __esm({
36329
36640
  }
36330
36641
  p = p.replace(/\\ /g, " ");
36331
36642
  if (p.startsWith("~/") || p === "~") {
36332
- p = join43(homedir11(), p.slice(1));
36643
+ p = join44(homedir11(), p.slice(1));
36333
36644
  }
36334
36645
  if (!existsSync35(p)) {
36335
36646
  return `File not found: ${p}
@@ -36343,7 +36654,7 @@ var init_voice = __esm({
36343
36654
  const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
36344
36655
  const ts = Date.now().toString(36);
36345
36656
  const destFilename = `clone-${srcName}-${ts}.${ext}`;
36346
- const destPath = join43(refsDir, destFilename);
36657
+ const destPath = join44(refsDir, destFilename);
36347
36658
  try {
36348
36659
  const data = readFileSync24(audioPath);
36349
36660
  writeFileSync14(destPath, data);
@@ -36388,7 +36699,7 @@ var init_voice = __esm({
36388
36699
  const refsDir = luxttsCloneRefsDir();
36389
36700
  if (!existsSync35(refsDir))
36390
36701
  mkdirSync13(refsDir, { recursive: true });
36391
- const destPath = join43(refsDir, `${sourceModelId}-ref.wav`);
36702
+ const destPath = join44(refsDir, `${sourceModelId}-ref.wav`);
36392
36703
  const sampleRate = this.config?.audio?.sample_rate ?? 22050;
36393
36704
  this.writeWav(audioData, sampleRate, destPath);
36394
36705
  this.luxttsCloneRef = destPath;
@@ -36404,7 +36715,7 @@ var init_voice = __esm({
36404
36715
  // -------------------------------------------------------------------------
36405
36716
  /** Metadata file for friendly names of clone refs */
36406
36717
  static cloneMetaFile() {
36407
- return join43(luxttsCloneRefsDir(), "meta.json");
36718
+ return join44(luxttsCloneRefsDir(), "meta.json");
36408
36719
  }
36409
36720
  loadCloneMeta() {
36410
36721
  const p = _VoiceEngine.cloneMetaFile();
@@ -36438,7 +36749,7 @@ var init_voice = __esm({
36438
36749
  return _VoiceEngine.AUDIO_EXTS.has(ext);
36439
36750
  });
36440
36751
  return files.map((f) => {
36441
- const p = join43(dir, f);
36752
+ const p = join44(dir, f);
36442
36753
  let size = 0;
36443
36754
  try {
36444
36755
  size = statSync12(p).size;
@@ -36455,11 +36766,11 @@ var init_voice = __esm({
36455
36766
  }
36456
36767
  /** Delete a clone reference file by filename. Returns true if deleted. */
36457
36768
  deleteCloneRef(filename) {
36458
- const p = join43(luxttsCloneRefsDir(), filename);
36769
+ const p = join44(luxttsCloneRefsDir(), filename);
36459
36770
  if (!existsSync35(p))
36460
36771
  return false;
36461
36772
  try {
36462
- unlinkSync7(p);
36773
+ unlinkSync8(p);
36463
36774
  const meta = this.loadCloneMeta();
36464
36775
  delete meta[filename];
36465
36776
  this.saveCloneMeta(meta);
@@ -36480,7 +36791,7 @@ var init_voice = __esm({
36480
36791
  }
36481
36792
  /** Set the active clone reference by filename. */
36482
36793
  setActiveCloneRef(filename) {
36483
- const p = join43(luxttsCloneRefsDir(), filename);
36794
+ const p = join44(luxttsCloneRefsDir(), filename);
36484
36795
  if (!existsSync35(p))
36485
36796
  return `File not found: ${filename}`;
36486
36797
  this.luxttsCloneRef = p;
@@ -36766,11 +37077,11 @@ var init_voice = __esm({
36766
37077
  }
36767
37078
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
36768
37079
  }
36769
- const wavPath = join43(tmpdir8(), `oa-voice-${Date.now()}.wav`);
37080
+ const wavPath = join44(tmpdir9(), `oa-voice-${Date.now()}.wav`);
36770
37081
  this.writeWav(audioData, sampleRate, wavPath);
36771
37082
  await this.playWav(wavPath);
36772
37083
  try {
36773
- unlinkSync7(wavPath);
37084
+ unlinkSync8(wavPath);
36774
37085
  } catch {
36775
37086
  }
36776
37087
  }
@@ -37015,7 +37326,7 @@ var init_voice = __esm({
37015
37326
  return new Promise((resolve32, reject) => {
37016
37327
  const proc = nodeSpawn("sh", ["-c", command], {
37017
37328
  stdio: ["ignore", "pipe", "pipe"],
37018
- cwd: tmpdir8()
37329
+ cwd: tmpdir9()
37019
37330
  });
37020
37331
  let stdout = "";
37021
37332
  let stderr = "";
@@ -37109,7 +37420,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
37109
37420
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
37110
37421
  const mlxVoice = model.mlxVoice ?? "af_heart";
37111
37422
  const mlxLangCode = model.mlxLangCode ?? "a";
37112
- const wavPath = join43(tmpdir8(), `oa-mlx-${Date.now()}.wav`);
37423
+ const wavPath = join44(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
37113
37424
  const pyScript = [
37114
37425
  "import sys, json",
37115
37426
  "from mlx_audio.tts import generate as tts_gen",
@@ -37117,11 +37428,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
37117
37428
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
37118
37429
  ].join("; ");
37119
37430
  try {
37120
- execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir8() });
37431
+ execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
37121
37432
  } catch (err) {
37122
37433
  try {
37123
37434
  const safeText = cleaned.replace(/'/g, "'\\''");
37124
- execSync27(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir8() });
37435
+ execSync27(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
37125
37436
  } catch (err2) {
37126
37437
  return;
37127
37438
  }
@@ -37156,7 +37467,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
37156
37467
  }
37157
37468
  await this.playWav(wavPath);
37158
37469
  try {
37159
- unlinkSync7(wavPath);
37470
+ unlinkSync8(wavPath);
37160
37471
  } catch {
37161
37472
  }
37162
37473
  }
@@ -37177,7 +37488,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
37177
37488
  const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
37178
37489
  const mlxVoice = model.mlxVoice ?? "af_heart";
37179
37490
  const mlxLangCode = model.mlxLangCode ?? "a";
37180
- const wavPath = join43(tmpdir8(), `oa-mlx-buf-${Date.now()}.wav`);
37491
+ const wavPath = join44(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
37181
37492
  const pyScript = [
37182
37493
  "import sys, json",
37183
37494
  "from mlx_audio.tts import generate as tts_gen",
@@ -37185,11 +37496,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
37185
37496
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
37186
37497
  ].join("; ");
37187
37498
  try {
37188
- execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir8() });
37499
+ execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
37189
37500
  } catch {
37190
37501
  try {
37191
37502
  const safeText = cleaned.replace(/'/g, "'\\''");
37192
- execSync27(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir8() });
37503
+ execSync27(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
37193
37504
  } catch {
37194
37505
  return null;
37195
37506
  }
@@ -37198,7 +37509,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
37198
37509
  return null;
37199
37510
  try {
37200
37511
  const data = readFileSync24(wavPath);
37201
- unlinkSync7(wavPath);
37512
+ unlinkSync8(wavPath);
37202
37513
  return data;
37203
37514
  } catch {
37204
37515
  return null;
@@ -37288,7 +37599,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
37288
37599
  }
37289
37600
  }
37290
37601
  const repoDir = luxttsRepoDir();
37291
- if (!existsSync35(join43(repoDir, "zipvoice", "luxvoice.py"))) {
37602
+ if (!existsSync35(join44(repoDir, "zipvoice", "luxvoice.py"))) {
37292
37603
  renderInfo(" Cloning LuxTTS repository...");
37293
37604
  try {
37294
37605
  if (existsSync35(repoDir)) {
@@ -37337,7 +37648,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
37337
37648
  if (!existsSync35(refsDir))
37338
37649
  return;
37339
37650
  for (const name of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
37340
- const p = join43(refsDir, name);
37651
+ const p = join44(refsDir, name);
37341
37652
  if (existsSync35(p)) {
37342
37653
  this.luxttsCloneRef = p;
37343
37654
  return;
@@ -37452,7 +37763,7 @@ if __name__ == '__main__':
37452
37763
  const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
37453
37764
  const daemon = nodeSpawn(venvPy, [luxttsInferScript()], {
37454
37765
  stdio: ["pipe", "pipe", "pipe"],
37455
- cwd: tmpdir8(),
37766
+ cwd: tmpdir9(),
37456
37767
  env
37457
37768
  });
37458
37769
  this._luxttsDaemon = daemon;
@@ -37534,7 +37845,7 @@ if __name__ == '__main__':
37534
37845
  const ready = await this.ensureLuxttsDaemon();
37535
37846
  if (!ready)
37536
37847
  return;
37537
- const wavPath = join43(tmpdir8(), `oa-luxtts-${Date.now()}.wav`);
37848
+ const wavPath = join44(tmpdir9(), `oa-luxtts-${Date.now()}.wav`);
37538
37849
  try {
37539
37850
  await this.luxttsRequest({
37540
37851
  action: "synthesize",
@@ -37591,7 +37902,7 @@ if __name__ == '__main__':
37591
37902
  }
37592
37903
  await this.playWav(wavPath);
37593
37904
  try {
37594
- unlinkSync7(wavPath);
37905
+ unlinkSync8(wavPath);
37595
37906
  } catch {
37596
37907
  }
37597
37908
  }
@@ -37608,7 +37919,7 @@ if __name__ == '__main__':
37608
37919
  const ready = await this.ensureLuxttsDaemon();
37609
37920
  if (!ready)
37610
37921
  return null;
37611
- const wavPath = join43(tmpdir8(), `oa-luxtts-buf-${Date.now()}.wav`);
37922
+ const wavPath = join44(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
37612
37923
  try {
37613
37924
  await this.luxttsRequest({
37614
37925
  action: "synthesize",
@@ -37624,7 +37935,7 @@ if __name__ == '__main__':
37624
37935
  return null;
37625
37936
  try {
37626
37937
  const data = readFileSync24(wavPath);
37627
- unlinkSync7(wavPath);
37938
+ unlinkSync8(wavPath);
37628
37939
  return data;
37629
37940
  } catch {
37630
37941
  return null;
@@ -37638,7 +37949,7 @@ if __name__ == '__main__':
37638
37949
  return;
37639
37950
  const arch = process.arch;
37640
37951
  mkdirSync13(voiceDir(), { recursive: true });
37641
- const pkgPath = join43(voiceDir(), "package.json");
37952
+ const pkgPath = join44(voiceDir(), "package.json");
37642
37953
  const expectedDeps = {
37643
37954
  "onnxruntime-node": "^1.21.0",
37644
37955
  "phonemizer": "^1.2.1"
@@ -37660,17 +37971,17 @@ if __name__ == '__main__':
37660
37971
  dependencies: expectedDeps
37661
37972
  }, null, 2));
37662
37973
  }
37663
- const voiceRequire = createRequire(join43(voiceDir(), "index.js"));
37974
+ const voiceRequire = createRequire(join44(voiceDir(), "index.js"));
37664
37975
  const probeOnnx = () => {
37665
37976
  try {
37666
- const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join43(voiceDir(), "node_modules") } });
37977
+ const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join44(voiceDir(), "node_modules") } });
37667
37978
  const output = result.toString().trim();
37668
37979
  return output === "OK";
37669
37980
  } catch {
37670
37981
  return false;
37671
37982
  }
37672
37983
  };
37673
- const onnxNodeModules = join43(voiceDir(), "node_modules", "onnxruntime-node");
37984
+ const onnxNodeModules = join44(voiceDir(), "node_modules", "onnxruntime-node");
37674
37985
  const onnxInstalled = existsSync35(onnxNodeModules);
37675
37986
  if (onnxInstalled && !probeOnnx()) {
37676
37987
  throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
@@ -40014,8 +40325,8 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
40014
40325
  if (models.length > 0) {
40015
40326
  try {
40016
40327
  const { writeFileSync: writeFileSync20, mkdirSync: mkdirSync21 } = await import("node:fs");
40017
- const { join: join57, dirname: dirname20 } = await import("node:path");
40018
- const cachePath = join57(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
40328
+ const { join: join58, dirname: dirname20 } = await import("node:path");
40329
+ const cachePath = join58(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
40019
40330
  mkdirSync21(dirname20(cachePath), { recursive: true });
40020
40331
  writeFileSync20(cachePath, JSON.stringify({
40021
40332
  peerId,
@@ -40168,8 +40479,8 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
40168
40479
  }
40169
40480
  await new Promise((r) => setTimeout(r, 1e3));
40170
40481
  process.env.OLLAMA_NUM_PARALLEL = String(n);
40171
- const { spawn: spawn19 } = await import("node:child_process");
40172
- const child = spawn19("ollama", ["serve"], {
40482
+ const { spawn: spawn20 } = await import("node:child_process");
40483
+ const child = spawn20("ollama", ["serve"], {
40173
40484
  stdio: "ignore",
40174
40485
  detached: true,
40175
40486
  env: { ...process.env, OLLAMA_NUM_PARALLEL: String(n) }
@@ -40216,14 +40527,14 @@ async function handleUpdate(subcommand, ctx) {
40216
40527
  try {
40217
40528
  const { createRequire: createRequire4 } = await import("node:module");
40218
40529
  const { fileURLToPath: fileURLToPath14 } = await import("node:url");
40219
- const { dirname: dirname20, join: join57 } = await import("node:path");
40530
+ const { dirname: dirname20, join: join58 } = await import("node:path");
40220
40531
  const { existsSync: existsSync45 } = await import("node:fs");
40221
40532
  const req = createRequire4(import.meta.url);
40222
40533
  const thisDir = dirname20(fileURLToPath14(import.meta.url));
40223
40534
  const candidates = [
40224
- join57(thisDir, "..", "package.json"),
40225
- join57(thisDir, "..", "..", "package.json"),
40226
- join57(thisDir, "..", "..", "..", "package.json")
40535
+ join58(thisDir, "..", "package.json"),
40536
+ join58(thisDir, "..", "..", "package.json"),
40537
+ join58(thisDir, "..", "..", "..", "package.json")
40227
40538
  ];
40228
40539
  for (const pkgPath of candidates) {
40229
40540
  if (existsSync45(pkgPath)) {
@@ -40941,7 +41252,7 @@ var init_commands = __esm({
40941
41252
 
40942
41253
  // packages/cli/dist/tui/project-context.js
40943
41254
  import { existsSync as existsSync36, readFileSync as readFileSync25, readdirSync as readdirSync10 } from "node:fs";
40944
- import { join as join44, basename as basename10 } from "node:path";
41255
+ import { join as join45, basename as basename10 } from "node:path";
40945
41256
  import { execSync as execSync28 } from "node:child_process";
40946
41257
  import { homedir as homedir12, platform as platform3, release } from "node:os";
40947
41258
  function getModelTier(modelName) {
@@ -40976,7 +41287,7 @@ function loadProjectMap(repoRoot) {
40976
41287
  if (!hasOaDirectory(repoRoot)) {
40977
41288
  initOaDirectory(repoRoot);
40978
41289
  }
40979
- const mapPath = join44(repoRoot, OA_DIR, "context", "project-map.md");
41290
+ const mapPath = join45(repoRoot, OA_DIR, "context", "project-map.md");
40980
41291
  if (existsSync36(mapPath)) {
40981
41292
  try {
40982
41293
  const content = readFileSync25(mapPath, "utf-8");
@@ -41020,17 +41331,17 @@ ${log}`);
41020
41331
  }
41021
41332
  function loadMemoryContext(repoRoot) {
41022
41333
  const sections = [];
41023
- const oaMemDir = join44(repoRoot, OA_DIR, "memory");
41334
+ const oaMemDir = join45(repoRoot, OA_DIR, "memory");
41024
41335
  const oaEntries = loadMemoryDir(oaMemDir, "project");
41025
41336
  if (oaEntries)
41026
41337
  sections.push(oaEntries);
41027
- const legacyMemDir = join44(repoRoot, ".open-agents", "memory");
41338
+ const legacyMemDir = join45(repoRoot, ".open-agents", "memory");
41028
41339
  if (legacyMemDir !== oaMemDir && existsSync36(legacyMemDir)) {
41029
41340
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
41030
41341
  if (legacyEntries)
41031
41342
  sections.push(legacyEntries);
41032
41343
  }
41033
- const globalMemDir = join44(homedir12(), ".open-agents", "memory");
41344
+ const globalMemDir = join45(homedir12(), ".open-agents", "memory");
41034
41345
  const globalEntries = loadMemoryDir(globalMemDir, "global");
41035
41346
  if (globalEntries)
41036
41347
  sections.push(globalEntries);
@@ -41044,7 +41355,7 @@ function loadMemoryDir(memDir, scope) {
41044
41355
  const files = readdirSync10(memDir).filter((f) => f.endsWith(".json"));
41045
41356
  for (const file of files.slice(0, 10)) {
41046
41357
  try {
41047
- const raw = readFileSync25(join44(memDir, file), "utf-8");
41358
+ const raw = readFileSync25(join45(memDir, file), "utf-8");
41048
41359
  const entries = JSON.parse(raw);
41049
41360
  const topic = basename10(file, ".json");
41050
41361
  const keys = Object.keys(entries);
@@ -42068,9 +42379,9 @@ var init_carousel = __esm({
42068
42379
 
42069
42380
  // packages/cli/dist/tui/carousel-descriptors.js
42070
42381
  import { existsSync as existsSync37, readFileSync as readFileSync26, writeFileSync as writeFileSync15, mkdirSync as mkdirSync14, readdirSync as readdirSync11 } from "node:fs";
42071
- import { join as join45, basename as basename11 } from "node:path";
42382
+ import { join as join46, basename as basename11 } from "node:path";
42072
42383
  function loadToolProfile(repoRoot) {
42073
- const filePath = join45(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
42384
+ const filePath = join46(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
42074
42385
  try {
42075
42386
  if (!existsSync37(filePath))
42076
42387
  return null;
@@ -42080,9 +42391,9 @@ function loadToolProfile(repoRoot) {
42080
42391
  }
42081
42392
  }
42082
42393
  function saveToolProfile(repoRoot, profile) {
42083
- const contextDir = join45(repoRoot, OA_DIR, "context");
42394
+ const contextDir = join46(repoRoot, OA_DIR, "context");
42084
42395
  mkdirSync14(contextDir, { recursive: true });
42085
- writeFileSync15(join45(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
42396
+ writeFileSync15(join46(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
42086
42397
  }
42087
42398
  function categorizeToolCall(toolName) {
42088
42399
  for (const cat of TOOL_CATEGORIES) {
@@ -42140,7 +42451,7 @@ function weightedColor(profile) {
42140
42451
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
42141
42452
  }
42142
42453
  function loadCachedDescriptors(repoRoot) {
42143
- const filePath = join45(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
42454
+ const filePath = join46(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
42144
42455
  try {
42145
42456
  if (!existsSync37(filePath))
42146
42457
  return null;
@@ -42151,14 +42462,14 @@ function loadCachedDescriptors(repoRoot) {
42151
42462
  }
42152
42463
  }
42153
42464
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
42154
- const contextDir = join45(repoRoot, OA_DIR, "context");
42465
+ const contextDir = join46(repoRoot, OA_DIR, "context");
42155
42466
  mkdirSync14(contextDir, { recursive: true });
42156
42467
  const cached = {
42157
42468
  phrases,
42158
42469
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
42159
42470
  sourceHash
42160
42471
  };
42161
- writeFileSync15(join45(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
42472
+ writeFileSync15(join46(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
42162
42473
  }
42163
42474
  function generateDescriptors(repoRoot) {
42164
42475
  const profile = loadToolProfile(repoRoot);
@@ -42206,7 +42517,7 @@ function generateDescriptors(repoRoot) {
42206
42517
  return phrases;
42207
42518
  }
42208
42519
  function extractFromPackageJson(repoRoot, tags) {
42209
- const pkgPath = join45(repoRoot, "package.json");
42520
+ const pkgPath = join46(repoRoot, "package.json");
42210
42521
  try {
42211
42522
  if (!existsSync37(pkgPath))
42212
42523
  return;
@@ -42254,7 +42565,7 @@ function extractFromManifests(repoRoot, tags) {
42254
42565
  { file: ".github/workflows", tag: "ci/cd" }
42255
42566
  ];
42256
42567
  for (const check of manifestChecks) {
42257
- if (existsSync37(join45(repoRoot, check.file))) {
42568
+ if (existsSync37(join46(repoRoot, check.file))) {
42258
42569
  tags.push(check.tag);
42259
42570
  }
42260
42571
  }
@@ -42276,7 +42587,7 @@ function extractFromSessions(repoRoot, tags) {
42276
42587
  }
42277
42588
  }
42278
42589
  function extractFromMemory(repoRoot, tags) {
42279
- const memoryDir = join45(repoRoot, OA_DIR, "memory");
42590
+ const memoryDir = join46(repoRoot, OA_DIR, "memory");
42280
42591
  try {
42281
42592
  if (!existsSync37(memoryDir))
42282
42593
  return;
@@ -42285,7 +42596,7 @@ function extractFromMemory(repoRoot, tags) {
42285
42596
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
42286
42597
  tags.push(topic);
42287
42598
  try {
42288
- const data = JSON.parse(readFileSync26(join45(memoryDir, file), "utf-8"));
42599
+ const data = JSON.parse(readFileSync26(join46(memoryDir, file), "utf-8"));
42289
42600
  if (data && typeof data === "object") {
42290
42601
  const keys = Object.keys(data).slice(0, 3);
42291
42602
  for (const key of keys) {
@@ -42908,10 +43219,10 @@ var init_stream_renderer = __esm({
42908
43219
 
42909
43220
  // packages/cli/dist/tui/edit-history.js
42910
43221
  import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync15 } from "node:fs";
42911
- import { join as join46 } from "node:path";
43222
+ import { join as join47 } from "node:path";
42912
43223
  function createEditHistoryLogger(repoRoot, sessionId) {
42913
- const historyDir = join46(repoRoot, ".oa", "history");
42914
- const logPath = join46(historyDir, "edits.jsonl");
43224
+ const historyDir = join47(repoRoot, ".oa", "history");
43225
+ const logPath = join47(historyDir, "edits.jsonl");
42915
43226
  try {
42916
43227
  mkdirSync15(historyDir, { recursive: true });
42917
43228
  } catch {
@@ -43023,12 +43334,12 @@ var init_edit_history = __esm({
43023
43334
 
43024
43335
  // packages/cli/dist/tui/promptLoader.js
43025
43336
  import { readFileSync as readFileSync27, existsSync as existsSync38 } from "node:fs";
43026
- import { join as join47, dirname as dirname17 } from "node:path";
43337
+ import { join as join48, dirname as dirname17 } from "node:path";
43027
43338
  import { fileURLToPath as fileURLToPath11 } from "node:url";
43028
43339
  function loadPrompt3(promptPath, vars) {
43029
43340
  let content = cache3.get(promptPath);
43030
43341
  if (content === void 0) {
43031
- const fullPath = join47(PROMPTS_DIR3, promptPath);
43342
+ const fullPath = join48(PROMPTS_DIR3, promptPath);
43032
43343
  if (!existsSync38(fullPath)) {
43033
43344
  throw new Error(`Prompt file not found: ${fullPath}`);
43034
43345
  }
@@ -43045,8 +43356,8 @@ var init_promptLoader3 = __esm({
43045
43356
  "use strict";
43046
43357
  __filename3 = fileURLToPath11(import.meta.url);
43047
43358
  __dirname6 = dirname17(__filename3);
43048
- devPath2 = join47(__dirname6, "..", "..", "prompts");
43049
- publishedPath2 = join47(__dirname6, "..", "prompts");
43359
+ devPath2 = join48(__dirname6, "..", "..", "prompts");
43360
+ publishedPath2 = join48(__dirname6, "..", "prompts");
43050
43361
  PROMPTS_DIR3 = existsSync38(devPath2) ? devPath2 : publishedPath2;
43051
43362
  cache3 = /* @__PURE__ */ new Map();
43052
43363
  }
@@ -43054,10 +43365,10 @@ var init_promptLoader3 = __esm({
43054
43365
 
43055
43366
  // packages/cli/dist/tui/dream-engine.js
43056
43367
  import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync16, readFileSync as readFileSync28, existsSync as existsSync39, cpSync, rmSync, readdirSync as readdirSync12 } from "node:fs";
43057
- import { join as join48, basename as basename12 } from "node:path";
43368
+ import { join as join49, basename as basename12 } from "node:path";
43058
43369
  import { execSync as execSync29 } from "node:child_process";
43059
43370
  function loadAutoresearchMemory(repoRoot) {
43060
- const memoryPath = join48(repoRoot, ".oa", "memory", "autoresearch.json");
43371
+ const memoryPath = join49(repoRoot, ".oa", "memory", "autoresearch.json");
43061
43372
  if (!existsSync39(memoryPath))
43062
43373
  return "";
43063
43374
  try {
@@ -43251,12 +43562,12 @@ var init_dream_engine = __esm({
43251
43562
  const content = String(args["content"] ?? "");
43252
43563
  if (!rawPath)
43253
43564
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
43254
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join48(this.autoresearchDir, basename12(rawPath)) : join48(this.autoresearchDir, rawPath);
43565
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join49(this.autoresearchDir, basename12(rawPath)) : join49(this.autoresearchDir, rawPath);
43255
43566
  if (!targetPath.startsWith(this.autoresearchDir)) {
43256
43567
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
43257
43568
  }
43258
43569
  try {
43259
- const dir = join48(targetPath, "..");
43570
+ const dir = join49(targetPath, "..");
43260
43571
  mkdirSync16(dir, { recursive: true });
43261
43572
  writeFileSync16(targetPath, content, "utf-8");
43262
43573
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -43286,7 +43597,7 @@ var init_dream_engine = __esm({
43286
43597
  const rawPath = String(args["path"] ?? "");
43287
43598
  const oldStr = String(args["old_string"] ?? "");
43288
43599
  const newStr = String(args["new_string"] ?? "");
43289
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join48(this.autoresearchDir, basename12(rawPath)) : join48(this.autoresearchDir, rawPath);
43600
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join49(this.autoresearchDir, basename12(rawPath)) : join49(this.autoresearchDir, rawPath);
43290
43601
  if (!targetPath.startsWith(this.autoresearchDir)) {
43291
43602
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
43292
43603
  }
@@ -43340,12 +43651,12 @@ var init_dream_engine = __esm({
43340
43651
  const content = String(args["content"] ?? "");
43341
43652
  if (!rawPath)
43342
43653
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
43343
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join48(this.dreamsDir, basename12(rawPath)) : join48(this.dreamsDir, rawPath);
43654
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join49(this.dreamsDir, basename12(rawPath)) : join49(this.dreamsDir, rawPath);
43344
43655
  if (!targetPath.startsWith(this.dreamsDir)) {
43345
43656
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
43346
43657
  }
43347
43658
  try {
43348
- const dir = join48(targetPath, "..");
43659
+ const dir = join49(targetPath, "..");
43349
43660
  mkdirSync16(dir, { recursive: true });
43350
43661
  writeFileSync16(targetPath, content, "utf-8");
43351
43662
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -43375,7 +43686,7 @@ var init_dream_engine = __esm({
43375
43686
  const rawPath = String(args["path"] ?? "");
43376
43687
  const oldStr = String(args["old_string"] ?? "");
43377
43688
  const newStr = String(args["new_string"] ?? "");
43378
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join48(this.dreamsDir, basename12(rawPath)) : join48(this.dreamsDir, rawPath);
43689
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join49(this.dreamsDir, basename12(rawPath)) : join49(this.dreamsDir, rawPath);
43379
43690
  if (!targetPath.startsWith(this.dreamsDir)) {
43380
43691
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
43381
43692
  }
@@ -43442,7 +43753,7 @@ var init_dream_engine = __esm({
43442
43753
  constructor(config, repoRoot) {
43443
43754
  this.config = config;
43444
43755
  this.repoRoot = repoRoot;
43445
- this.dreamsDir = join48(repoRoot, ".oa", "dreams");
43756
+ this.dreamsDir = join49(repoRoot, ".oa", "dreams");
43446
43757
  this.state = {
43447
43758
  mode: "default",
43448
43759
  active: false,
@@ -43526,7 +43837,7 @@ ${result.summary}`;
43526
43837
  if (mode !== "default" || cycle === totalCycles) {
43527
43838
  renderDreamContraction(cycle);
43528
43839
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
43529
- const summaryPath = join48(this.dreamsDir, `cycle-${cycle}-summary.md`);
43840
+ const summaryPath = join49(this.dreamsDir, `cycle-${cycle}-summary.md`);
43530
43841
  writeFileSync16(summaryPath, cycleSummary, "utf-8");
43531
43842
  }
43532
43843
  if (mode === "lucid" && !this.abortController.signal.aborted) {
@@ -43739,7 +44050,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
43739
44050
  }
43740
44051
  /** Build role-specific tool sets for swarm agents */
43741
44052
  buildSwarmTools(role, _workspace) {
43742
- const autoresearchDir = join48(this.repoRoot, ".oa", "autoresearch");
44053
+ const autoresearchDir = join49(this.repoRoot, ".oa", "autoresearch");
43743
44054
  const taskComplete = this.createSwarmTaskCompleteTool(role);
43744
44055
  switch (role) {
43745
44056
  case "researcher": {
@@ -44103,7 +44414,7 @@ INSTRUCTIONS:
44103
44414
  2. Summarize the key learnings and next steps
44104
44415
 
44105
44416
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
44106
- const reportPath = join48(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
44417
+ const reportPath = join49(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
44107
44418
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
44108
44419
 
44109
44420
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -44192,7 +44503,7 @@ ${summaryResult}
44192
44503
  }
44193
44504
  /** Save workspace backup for lucid mode */
44194
44505
  saveVersionCheckpoint(cycle) {
44195
- const checkpointDir = join48(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
44506
+ const checkpointDir = join49(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
44196
44507
  try {
44197
44508
  mkdirSync16(checkpointDir, { recursive: true });
44198
44509
  try {
@@ -44211,10 +44522,10 @@ ${summaryResult}
44211
44522
  encoding: "utf-8",
44212
44523
  timeout: 5e3
44213
44524
  }).trim();
44214
- writeFileSync16(join48(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
44215
- writeFileSync16(join48(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
44216
- writeFileSync16(join48(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
44217
- writeFileSync16(join48(checkpointDir, "checkpoint.json"), JSON.stringify({
44525
+ writeFileSync16(join49(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
44526
+ writeFileSync16(join49(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
44527
+ writeFileSync16(join49(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
44528
+ writeFileSync16(join49(checkpointDir, "checkpoint.json"), JSON.stringify({
44218
44529
  cycle,
44219
44530
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
44220
44531
  gitHash,
@@ -44222,7 +44533,7 @@ ${summaryResult}
44222
44533
  }, null, 2), "utf-8");
44223
44534
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
44224
44535
  } catch {
44225
- writeFileSync16(join48(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
44536
+ writeFileSync16(join49(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
44226
44537
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
44227
44538
  }
44228
44539
  } catch (err) {
@@ -44280,14 +44591,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
44280
44591
  ---
44281
44592
  *Auto-generated by open-agents dream engine*
44282
44593
  `;
44283
- writeFileSync16(join48(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
44594
+ writeFileSync16(join49(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
44284
44595
  } catch {
44285
44596
  }
44286
44597
  }
44287
44598
  /** Save dream state for resume/inspection */
44288
44599
  saveDreamState() {
44289
44600
  try {
44290
- writeFileSync16(join48(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
44601
+ writeFileSync16(join49(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
44291
44602
  } catch {
44292
44603
  }
44293
44604
  }
@@ -44661,8 +44972,8 @@ var init_bless_engine = __esm({
44661
44972
  });
44662
44973
 
44663
44974
  // packages/cli/dist/tui/dmn-engine.js
44664
- import { existsSync as existsSync40, readFileSync as readFileSync29, writeFileSync as writeFileSync17, mkdirSync as mkdirSync17, readdirSync as readdirSync13, unlinkSync as unlinkSync8 } from "node:fs";
44665
- import { join as join49, basename as basename13 } from "node:path";
44975
+ import { existsSync as existsSync40, readFileSync as readFileSync29, writeFileSync as writeFileSync17, mkdirSync as mkdirSync17, readdirSync as readdirSync13, unlinkSync as unlinkSync9 } from "node:fs";
44976
+ import { join as join50, basename as basename13 } from "node:path";
44666
44977
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
44667
44978
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
44668
44979
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -44775,8 +45086,8 @@ var init_dmn_engine = __esm({
44775
45086
  constructor(config, repoRoot) {
44776
45087
  this.config = config;
44777
45088
  this.repoRoot = repoRoot;
44778
- this.stateDir = join49(repoRoot, ".oa", "dmn");
44779
- this.historyDir = join49(repoRoot, ".oa", "dmn", "cycles");
45089
+ this.stateDir = join50(repoRoot, ".oa", "dmn");
45090
+ this.historyDir = join50(repoRoot, ".oa", "dmn", "cycles");
44780
45091
  mkdirSync17(this.historyDir, { recursive: true });
44781
45092
  this.loadState();
44782
45093
  }
@@ -45366,8 +45677,8 @@ OUTPUT: Call task_complete with JSON:
45366
45677
  async gatherMemoryTopics() {
45367
45678
  const topics = [];
45368
45679
  const dirs = [
45369
- join49(this.repoRoot, ".oa", "memory"),
45370
- join49(this.repoRoot, ".open-agents", "memory")
45680
+ join50(this.repoRoot, ".oa", "memory"),
45681
+ join50(this.repoRoot, ".open-agents", "memory")
45371
45682
  ];
45372
45683
  for (const dir of dirs) {
45373
45684
  if (!existsSync40(dir))
@@ -45386,7 +45697,7 @@ OUTPUT: Call task_complete with JSON:
45386
45697
  }
45387
45698
  // ── State persistence ─────────────────────────────────────────────────
45388
45699
  loadState() {
45389
- const path = join49(this.stateDir, "state.json");
45700
+ const path = join50(this.stateDir, "state.json");
45390
45701
  if (existsSync40(path)) {
45391
45702
  try {
45392
45703
  this.state = JSON.parse(readFileSync29(path, "utf-8"));
@@ -45396,19 +45707,19 @@ OUTPUT: Call task_complete with JSON:
45396
45707
  }
45397
45708
  saveState() {
45398
45709
  try {
45399
- writeFileSync17(join49(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
45710
+ writeFileSync17(join50(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
45400
45711
  } catch {
45401
45712
  }
45402
45713
  }
45403
45714
  saveCycleResult(result) {
45404
45715
  try {
45405
45716
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
45406
- writeFileSync17(join49(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
45717
+ writeFileSync17(join50(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
45407
45718
  const files = readdirSync13(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
45408
45719
  if (files.length > 50) {
45409
45720
  for (const old of files.slice(0, files.length - 50)) {
45410
45721
  try {
45411
- unlinkSync8(join49(this.historyDir, old));
45722
+ unlinkSync9(join50(this.historyDir, old));
45412
45723
  } catch {
45413
45724
  }
45414
45725
  }
@@ -45422,7 +45733,7 @@ OUTPUT: Call task_complete with JSON:
45422
45733
 
45423
45734
  // packages/cli/dist/tui/snr-engine.js
45424
45735
  import { existsSync as existsSync41, readdirSync as readdirSync14, readFileSync as readFileSync30 } from "node:fs";
45425
- import { join as join50, basename as basename14 } from "node:path";
45736
+ import { join as join51, basename as basename14 } from "node:path";
45426
45737
  function computeDPrime(signalScores, noiseScores) {
45427
45738
  if (signalScores.length === 0 || noiseScores.length === 0)
45428
45739
  return 0;
@@ -45662,8 +45973,8 @@ Call task_complete with the JSON array when done.`, onEvent)
45662
45973
  loadMemoryEntries(topics) {
45663
45974
  const entries = [];
45664
45975
  const dirs = [
45665
- join50(this.repoRoot, ".oa", "memory"),
45666
- join50(this.repoRoot, ".open-agents", "memory")
45976
+ join51(this.repoRoot, ".oa", "memory"),
45977
+ join51(this.repoRoot, ".open-agents", "memory")
45667
45978
  ];
45668
45979
  for (const dir of dirs) {
45669
45980
  if (!existsSync41(dir))
@@ -45675,7 +45986,7 @@ Call task_complete with the JSON array when done.`, onEvent)
45675
45986
  if (topics.length > 0 && !topics.includes(topic))
45676
45987
  continue;
45677
45988
  try {
45678
- const data = JSON.parse(readFileSync30(join50(dir, f), "utf-8"));
45989
+ const data = JSON.parse(readFileSync30(join51(dir, f), "utf-8"));
45679
45990
  for (const [key, val] of Object.entries(data)) {
45680
45991
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
45681
45992
  entries.push({ topic, key, value });
@@ -46242,8 +46553,8 @@ var init_tool_policy = __esm({
46242
46553
  });
46243
46554
 
46244
46555
  // packages/cli/dist/tui/telegram-bridge.js
46245
- import { mkdirSync as mkdirSync18, existsSync as existsSync42, unlinkSync as unlinkSync9, readdirSync as readdirSync15, statSync as statSync13 } from "node:fs";
46246
- import { join as join51, resolve as resolve28 } from "node:path";
46556
+ import { mkdirSync as mkdirSync18, existsSync as existsSync42, unlinkSync as unlinkSync10, readdirSync as readdirSync15, statSync as statSync13 } from "node:fs";
46557
+ import { join as join52, resolve as resolve28 } from "node:path";
46247
46558
  import { writeFile as writeFileAsync } from "node:fs/promises";
46248
46559
  function convertMarkdownToTelegramHTML(md) {
46249
46560
  let html = md;
@@ -47008,7 +47319,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
47008
47319
  return null;
47009
47320
  const buffer = Buffer.from(await res.arrayBuffer());
47010
47321
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
47011
- const localPath = join51(this.mediaCacheDir, fileName);
47322
+ const localPath = join52(this.mediaCacheDir, fileName);
47012
47323
  await writeFileAsync(localPath, buffer);
47013
47324
  return localPath;
47014
47325
  } catch {
@@ -47096,7 +47407,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
47096
47407
  for (const [key, entry] of this.mediaCache) {
47097
47408
  if (now - entry.cachedAt > MEDIA_CACHE_TTL_MS) {
47098
47409
  try {
47099
- unlinkSync9(entry.localPath);
47410
+ unlinkSync10(entry.localPath);
47100
47411
  } catch {
47101
47412
  }
47102
47413
  this.mediaCache.delete(key);
@@ -47172,11 +47483,11 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
47172
47483
  let mimeType = "audio/wav";
47173
47484
  try {
47174
47485
  const { execSync: execSyncLocal } = await import("node:child_process");
47175
- const { tmpdir: tmpdir10 } = await import("node:os");
47486
+ const { tmpdir: tmpdir11 } = await import("node:os");
47176
47487
  const { join: joinPath } = await import("node:path");
47177
47488
  const { writeFileSync: writeFs, readFileSync: readFs, unlinkSync: unlinkFs } = await import("node:fs");
47178
- const tmpWav = joinPath(tmpdir10(), `oa-tg-voice-${Date.now()}.wav`);
47179
- const tmpOgg = joinPath(tmpdir10(), `oa-tg-voice-${Date.now()}.ogg`);
47489
+ const tmpWav = joinPath(tmpdir11(), `oa-tg-voice-${Date.now()}.wav`);
47490
+ const tmpOgg = joinPath(tmpdir11(), `oa-tg-voice-${Date.now()}.ogg`);
47180
47491
  writeFs(tmpWav, wavBuffer);
47181
47492
  execSyncLocal(`ffmpeg -i "${tmpWav}" -c:a libopus -b:a 48k -ar 48000 -ac 1 "${tmpOgg}" -y 2>/dev/null`, {
47182
47493
  timeout: 15e3,
@@ -49446,7 +49757,7 @@ var init_status_bar = __esm({
49446
49757
  import * as readline2 from "node:readline";
49447
49758
  import { Writable } from "node:stream";
49448
49759
  import { cwd } from "node:process";
49449
- import { resolve as resolve29, join as join52, dirname as dirname18, extname as extname10 } from "node:path";
49760
+ import { resolve as resolve29, join as join53, dirname as dirname18, extname as extname10 } from "node:path";
49450
49761
  import { createRequire as createRequire2 } from "node:module";
49451
49762
  import { fileURLToPath as fileURLToPath12 } from "node:url";
49452
49763
  import { readFileSync as readFileSync32, writeFileSync as writeFileSync18, appendFileSync as appendFileSync4, rmSync as rmSync2, readdirSync as readdirSync16, mkdirSync as mkdirSync19 } from "node:fs";
@@ -49470,9 +49781,9 @@ function getVersion3() {
49470
49781
  const require2 = createRequire2(import.meta.url);
49471
49782
  const thisDir = dirname18(fileURLToPath12(import.meta.url));
49472
49783
  const candidates = [
49473
- join52(thisDir, "..", "package.json"),
49474
- join52(thisDir, "..", "..", "package.json"),
49475
- join52(thisDir, "..", "..", "..", "package.json")
49784
+ join53(thisDir, "..", "package.json"),
49785
+ join53(thisDir, "..", "..", "package.json"),
49786
+ join53(thisDir, "..", "..", "..", "package.json")
49476
49787
  ];
49477
49788
  for (const pkgPath of candidates) {
49478
49789
  if (existsSync43(pkgPath)) {
@@ -49563,6 +49874,8 @@ function buildTools(repoRoot, config, contextWindowSize) {
49563
49874
  new StructuredFileTool(repoRoot),
49564
49875
  // Code sandbox (isolated code execution)
49565
49876
  new CodeSandboxTool(repoRoot),
49877
+ // Persistent Python REPL — RLM (arxiv:2512.24601)
49878
+ new ReplTool(repoRoot),
49566
49879
  // Structured file reading (CSV, JSON, Markdown, binary detection)
49567
49880
  new StructuredReadTool(repoRoot),
49568
49881
  // Vision tools (Moondream — desktop awareness + point-and-click)
@@ -49682,15 +49995,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
49682
49995
  function gatherMemorySnippets(root) {
49683
49996
  const snippets = [];
49684
49997
  const dirs = [
49685
- join52(root, ".oa", "memory"),
49686
- join52(root, ".open-agents", "memory")
49998
+ join53(root, ".oa", "memory"),
49999
+ join53(root, ".open-agents", "memory")
49687
50000
  ];
49688
50001
  for (const dir of dirs) {
49689
50002
  if (!existsSync43(dir))
49690
50003
  continue;
49691
50004
  try {
49692
50005
  for (const f of readdirSync16(dir).filter((f2) => f2.endsWith(".json"))) {
49693
- const data = JSON.parse(readFileSync32(join52(dir, f), "utf-8"));
50006
+ const data = JSON.parse(readFileSync32(join53(dir, f), "utf-8"));
49694
50007
  for (const val of Object.values(data)) {
49695
50008
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
49696
50009
  if (v.length > 10)
@@ -49906,6 +50219,27 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
49906
50219
  tool.setActiveModel(config.model, hasVision);
49907
50220
  }
49908
50221
  }
50222
+ for (const tool of tools) {
50223
+ if ("setLlmQueryHandler" in tool && typeof tool.setLlmQueryHandler === "function") {
50224
+ tool.setLlmQueryHandler(async (prompt, context) => {
50225
+ const subPrompt = context ? `${prompt}
50226
+
50227
+ Context:
50228
+ ${context}` : prompt;
50229
+ const response = await backend.chatCompletion({
50230
+ messages: [
50231
+ { role: "system", content: "You are a helpful assistant. Respond concisely and accurately." },
50232
+ { role: "user", content: subPrompt }
50233
+ ],
50234
+ tools: [],
50235
+ temperature: 0,
50236
+ maxTokens: 4096,
50237
+ timeoutMs: 12e4
50238
+ });
50239
+ return response.choices?.[0]?.message?.content ?? "";
50240
+ });
50241
+ }
50242
+ }
49909
50243
  runner.registerTools(tools);
49910
50244
  runner.registerTool({
49911
50245
  name: "memex_retrieve",
@@ -50654,7 +50988,7 @@ async function startInteractive(config, repoPath) {
50654
50988
  let p2pGateway = null;
50655
50989
  let peerMesh = null;
50656
50990
  let inferenceRouter = null;
50657
- const secretVault = new SecretVault(join52(repoRoot, ".oa", "vault.enc"));
50991
+ const secretVault = new SecretVault(join53(repoRoot, ".oa", "vault.enc"));
50658
50992
  let adminSessionKey = null;
50659
50993
  const callSubAgents = /* @__PURE__ */ new Map();
50660
50994
  const streamRenderer = new StreamRenderer();
@@ -50863,8 +51197,8 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
50863
51197
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
50864
51198
  return [hits, line];
50865
51199
  }
50866
- const HISTORY_DIR = join52(homedir13(), ".open-agents");
50867
- const HISTORY_FILE = join52(HISTORY_DIR, "repl-history");
51200
+ const HISTORY_DIR = join53(homedir13(), ".open-agents");
51201
+ const HISTORY_FILE = join53(HISTORY_DIR, "repl-history");
50868
51202
  const MAX_HISTORY_LINES = 500;
50869
51203
  let savedHistory = [];
50870
51204
  try {
@@ -51074,7 +51408,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
51074
51408
  } catch {
51075
51409
  }
51076
51410
  try {
51077
- const oaDir = join52(repoRoot, ".oa");
51411
+ const oaDir = join53(repoRoot, ".oa");
51078
51412
  const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
51079
51413
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
51080
51414
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -51097,7 +51431,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
51097
51431
  } catch {
51098
51432
  }
51099
51433
  try {
51100
- const oaDir = join52(repoRoot, ".oa");
51434
+ const oaDir = join53(repoRoot, ".oa");
51101
51435
  const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
51102
51436
  onInfo: (msg) => writeContent(() => renderInfo(msg)),
51103
51437
  onError: (msg) => writeContent(() => renderWarning(msg))
@@ -51916,7 +52250,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
51916
52250
  kind,
51917
52251
  targetUrl,
51918
52252
  authKey,
51919
- stateDir: join52(repoRoot, ".oa"),
52253
+ stateDir: join53(repoRoot, ".oa"),
51920
52254
  passthrough: passthrough ?? false,
51921
52255
  loadbalance: loadbalance ?? false,
51922
52256
  endpointAuth: passthrough ? currentConfig.apiKey : void 0,
@@ -51964,7 +52298,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
51964
52298
  await tunnelGateway.stop();
51965
52299
  tunnelGateway = null;
51966
52300
  }
51967
- const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join52(repoRoot, ".oa") });
52301
+ const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join53(repoRoot, ".oa") });
51968
52302
  newTunnel.on("stats", (stats) => {
51969
52303
  statusBar.setExposeStatus({
51970
52304
  status: stats.status,
@@ -52226,7 +52560,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
52226
52560
  }
52227
52561
  },
52228
52562
  destroyProject() {
52229
- const oaPath = join52(repoRoot, OA_DIR);
52563
+ const oaPath = join53(repoRoot, OA_DIR);
52230
52564
  if (existsSync43(oaPath)) {
52231
52565
  try {
52232
52566
  rmSync2(oaPath, { recursive: true, force: true });
@@ -53161,7 +53495,7 @@ import { glob } from "glob";
53161
53495
  import ignore from "ignore";
53162
53496
  import { readFile as readFile17, stat as stat4 } from "node:fs/promises";
53163
53497
  import { createHash as createHash4 } from "node:crypto";
53164
- import { join as join53, relative as relative3, extname as extname11, basename as basename15 } from "node:path";
53498
+ import { join as join54, relative as relative3, extname as extname11, basename as basename15 } from "node:path";
53165
53499
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
53166
53500
  var init_codebase_indexer = __esm({
53167
53501
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -53205,7 +53539,7 @@ var init_codebase_indexer = __esm({
53205
53539
  const ig = ignore.default();
53206
53540
  if (this.config.respectGitignore) {
53207
53541
  try {
53208
- const gitignoreContent = await readFile17(join53(this.config.rootDir, ".gitignore"), "utf-8");
53542
+ const gitignoreContent = await readFile17(join54(this.config.rootDir, ".gitignore"), "utf-8");
53209
53543
  ig.add(gitignoreContent);
53210
53544
  } catch {
53211
53545
  }
@@ -53220,7 +53554,7 @@ var init_codebase_indexer = __esm({
53220
53554
  for (const relativePath of files) {
53221
53555
  if (ig.ignores(relativePath))
53222
53556
  continue;
53223
- const fullPath = join53(this.config.rootDir, relativePath);
53557
+ const fullPath = join54(this.config.rootDir, relativePath);
53224
53558
  try {
53225
53559
  const fileStat = await stat4(fullPath);
53226
53560
  if (fileStat.size > this.config.maxFileSize)
@@ -53266,7 +53600,7 @@ var init_codebase_indexer = __esm({
53266
53600
  if (!child) {
53267
53601
  child = {
53268
53602
  name: part,
53269
- path: join53(current.path, part),
53603
+ path: join54(current.path, part),
53270
53604
  type: "directory",
53271
53605
  children: []
53272
53606
  };
@@ -53607,7 +53941,7 @@ var config_exports = {};
53607
53941
  __export(config_exports, {
53608
53942
  configCommand: () => configCommand
53609
53943
  });
53610
- import { join as join54, resolve as resolve31 } from "node:path";
53944
+ import { join as join55, resolve as resolve31 } from "node:path";
53611
53945
  import { homedir as homedir14 } from "node:os";
53612
53946
  import { cwd as cwd3 } from "node:process";
53613
53947
  function redactIfSensitive(key, value) {
@@ -53690,7 +54024,7 @@ function handleShow(opts, config) {
53690
54024
  }
53691
54025
  }
53692
54026
  printSection("Config File");
53693
- printInfo(`~/.open-agents/config.json (${join54(homedir14(), ".open-agents", "config.json")})`);
54027
+ printInfo(`~/.open-agents/config.json (${join55(homedir14(), ".open-agents", "config.json")})`);
53694
54028
  printSection("Priority Chain");
53695
54029
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
53696
54030
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -53729,7 +54063,7 @@ function handleSet(opts, _config) {
53729
54063
  const coerced = coerceForSettings(key, value);
53730
54064
  saveProjectSettings(repoRoot, { [key]: coerced });
53731
54065
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
53732
- printInfo(`Saved to ${join54(repoRoot, ".oa", "settings.json")}`);
54066
+ printInfo(`Saved to ${join55(repoRoot, ".oa", "settings.json")}`);
53733
54067
  printInfo("This override applies only when running in this workspace.");
53734
54068
  } catch (err) {
53735
54069
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -53829,7 +54163,7 @@ var serve_exports = {};
53829
54163
  __export(serve_exports, {
53830
54164
  serveCommand: () => serveCommand
53831
54165
  });
53832
- import { spawn as spawn18 } from "node:child_process";
54166
+ import { spawn as spawn19 } from "node:child_process";
53833
54167
  async function serveCommand(opts, config) {
53834
54168
  const backendType = config.backendType;
53835
54169
  if (backendType === "ollama") {
@@ -53922,7 +54256,7 @@ async function serveVllm(opts, config) {
53922
54256
  }
53923
54257
  async function runVllmServer(args, verbose) {
53924
54258
  return new Promise((resolve32, reject) => {
53925
- const child = spawn18("python", args, {
54259
+ const child = spawn19("python", args, {
53926
54260
  stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
53927
54261
  env: { ...process.env }
53928
54262
  });
@@ -53986,9 +54320,9 @@ var eval_exports = {};
53986
54320
  __export(eval_exports, {
53987
54321
  evalCommand: () => evalCommand
53988
54322
  });
53989
- import { tmpdir as tmpdir9 } from "node:os";
54323
+ import { tmpdir as tmpdir10 } from "node:os";
53990
54324
  import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync19 } from "node:fs";
53991
- import { join as join55 } from "node:path";
54325
+ import { join as join56 } from "node:path";
53992
54326
  async function evalCommand(opts, config) {
53993
54327
  const suiteName = opts.suite ?? "basic";
53994
54328
  const suite = SUITES[suiteName];
@@ -54113,9 +54447,9 @@ async function evalCommand(opts, config) {
54113
54447
  process.exit(failed > 0 ? 1 : 0);
54114
54448
  }
54115
54449
  function createTempEvalRepo() {
54116
- const dir = join55(tmpdir9(), `open-agents-eval-${Date.now()}`);
54450
+ const dir = join56(tmpdir10(), `open-agents-eval-${Date.now()}`);
54117
54451
  mkdirSync20(dir, { recursive: true });
54118
- writeFileSync19(join55(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
54452
+ writeFileSync19(join56(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
54119
54453
  return dir;
54120
54454
  }
54121
54455
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -54175,7 +54509,7 @@ init_updater();
54175
54509
  import { parseArgs as nodeParseArgs2 } from "node:util";
54176
54510
  import { createRequire as createRequire3 } from "node:module";
54177
54511
  import { fileURLToPath as fileURLToPath13 } from "node:url";
54178
- import { dirname as dirname19, join as join56 } from "node:path";
54512
+ import { dirname as dirname19, join as join57 } from "node:path";
54179
54513
 
54180
54514
  // packages/cli/dist/cli.js
54181
54515
  import { createInterface } from "node:readline";
@@ -54282,7 +54616,7 @@ init_output();
54282
54616
  function getVersion4() {
54283
54617
  try {
54284
54618
  const require2 = createRequire3(import.meta.url);
54285
- const pkgPath = join56(dirname19(fileURLToPath13(import.meta.url)), "..", "package.json");
54619
+ const pkgPath = join57(dirname19(fileURLToPath13(import.meta.url)), "..", "package.json");
54286
54620
  const pkg = require2(pkgPath);
54287
54621
  return pkg.version;
54288
54622
  } catch {