open-agents-ai 0.30.7 → 0.30.8

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 +723 -298
  2. package/package.json +5 -2
package/dist/index.js CHANGED
@@ -1284,7 +1284,7 @@ ${stdinInput ?? ""}`);
1284
1284
  }
1285
1285
  runCommand(command, timeout, stdinInput) {
1286
1286
  const start = performance.now();
1287
- return new Promise((resolve19) => {
1287
+ return new Promise((resolve21) => {
1288
1288
  const child = spawn("bash", ["-c", command], {
1289
1289
  cwd: this.workingDir,
1290
1290
  env: {
@@ -1312,7 +1312,7 @@ ${stdinInput ?? ""}`);
1312
1312
  clearTimeout(timer);
1313
1313
  if (exitFlushTimer)
1314
1314
  clearTimeout(exitFlushTimer);
1315
- resolve19(result);
1315
+ resolve21(result);
1316
1316
  };
1317
1317
  const timer = setTimeout(() => {
1318
1318
  killed = true;
@@ -3967,21 +3967,29 @@ function detectPackageManager() {
3967
3967
  _detectedPkgManager = null;
3968
3968
  return _detectedPkgManager;
3969
3969
  }
3970
+ if (plat === "win32") {
3971
+ if (hasCommand("choco"))
3972
+ _detectedPkgManager = "choco";
3973
+ else
3974
+ _detectedPkgManager = null;
3975
+ return _detectedPkgManager;
3976
+ }
3970
3977
  _detectedPkgManager = null;
3971
3978
  return null;
3972
3979
  }
3973
3980
  function hasCommand(cmd) {
3974
3981
  try {
3975
- execSync6(`which ${cmd}`, { stdio: "pipe", timeout: 3e3 });
3982
+ const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
3983
+ execSync6(whichCmd, { stdio: "pipe", timeout: 3e3 });
3976
3984
  return true;
3977
3985
  } catch {
3978
3986
  return false;
3979
3987
  }
3980
3988
  }
3981
3989
  function runInstall(installCmd) {
3982
- const needsSudo = process.platform === "linux";
3990
+ const plat = process.platform;
3983
3991
  let cmd = installCmd;
3984
- if (needsSudo) {
3992
+ if (plat === "linux") {
3985
3993
  if (_sudoPassword) {
3986
3994
  cmd = `echo ${JSON.stringify(_sudoPassword)} | sudo -S ${installCmd}`;
3987
3995
  } else {
@@ -4048,6 +4056,9 @@ function ensureCommand(command) {
4048
4056
  case "brew":
4049
4057
  installCmd = `brew install ${pkg}`;
4050
4058
  break;
4059
+ case "choco":
4060
+ installCmd = `choco install -y ${pkg}`;
4061
+ break;
4051
4062
  }
4052
4063
  try {
4053
4064
  runInstall(installCmd);
@@ -4099,9 +4110,27 @@ var init_system_deps = __esm({
4099
4110
  },
4100
4111
  {
4101
4112
  command: "identify",
4102
- packages: { apt: "imagemagick", dnf: "ImageMagick", pacman: "imagemagick", brew: "imagemagick" },
4113
+ packages: { apt: "imagemagick", dnf: "ImageMagick", pacman: "imagemagick", brew: "imagemagick", choco: "imagemagick" },
4103
4114
  description: "Image metadata and conversion (ImageMagick)",
4104
4115
  group: "image"
4116
+ },
4117
+ {
4118
+ command: "ocrmypdf",
4119
+ packages: { apt: "ocrmypdf", dnf: "ocrmypdf", pacman: "ocrmypdf", brew: "ocrmypdf", choco: "ocrmypdf" },
4120
+ description: "OCR-based PDF text layer injection",
4121
+ group: "pdf"
4122
+ },
4123
+ {
4124
+ command: "pdftotext",
4125
+ packages: { apt: "poppler-utils", dnf: "poppler-utils", pacman: "poppler", brew: "poppler", choco: "poppler" },
4126
+ description: "PDF text extraction (Poppler)",
4127
+ group: "pdf"
4128
+ },
4129
+ {
4130
+ command: "gs",
4131
+ packages: { apt: "ghostscript", dnf: "ghostscript", pacman: "ghostscript", brew: "ghostscript", choco: "ghostscript" },
4132
+ description: "PostScript/PDF rendering (Ghostscript, required by ocrmypdf)",
4133
+ group: "pdf"
4105
4134
  }
4106
4135
  ];
4107
4136
  _cache = /* @__PURE__ */ new Map();
@@ -4534,8 +4563,8 @@ function deleteCustomToolDefinition(name, scope, repoRoot) {
4534
4563
  const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
4535
4564
  const filePath = join11(dir, `${name}.json`);
4536
4565
  if (existsSync8(filePath)) {
4537
- const { unlinkSync: unlinkSync4 } = __require("node:fs");
4538
- unlinkSync4(filePath);
4566
+ const { unlinkSync: unlinkSync5 } = __require("node:fs");
4567
+ unlinkSync5(filePath);
4539
4568
  return true;
4540
4569
  }
4541
4570
  return false;
@@ -4653,7 +4682,7 @@ var init_custom_tool = __esm({
4653
4682
  }
4654
4683
  /** Execute a single shell command and return output */
4655
4684
  runCommand(command) {
4656
- return new Promise((resolve19) => {
4685
+ return new Promise((resolve21) => {
4657
4686
  const child = spawn3("bash", ["-c", command], {
4658
4687
  cwd: this.workingDir,
4659
4688
  env: { ...process.env, CI: "true", NO_COLOR: "1" },
@@ -4678,11 +4707,11 @@ var init_custom_tool = __esm({
4678
4707
  child.kill("SIGTERM");
4679
4708
  } catch {
4680
4709
  }
4681
- resolve19({ success: false, output: stdout, error: "Command timed out after 60s" });
4710
+ resolve21({ success: false, output: stdout, error: "Command timed out after 60s" });
4682
4711
  }, 6e4);
4683
4712
  child.on("close", (code) => {
4684
4713
  clearTimeout(timer);
4685
- resolve19({
4714
+ resolve21({
4686
4715
  success: code === 0,
4687
4716
  output: stdout + (stderr && code === 0 ? `
4688
4717
  STDERR:
@@ -4692,7 +4721,7 @@ ${stderr}` : ""),
4692
4721
  });
4693
4722
  child.on("error", (err) => {
4694
4723
  clearTimeout(timer);
4695
- resolve19({ success: false, output: stdout, error: err.message });
4724
+ resolve21({ success: false, output: stdout, error: err.message });
4696
4725
  });
4697
4726
  });
4698
4727
  }
@@ -5874,7 +5903,7 @@ import { writeFile as writeFile7, mkdtemp, rm, readdir, stat } from "node:fs/pro
5874
5903
  import { join as join14 } from "node:path";
5875
5904
  import { tmpdir as tmpdir2 } from "node:os";
5876
5905
  function runProcess(cmd, args, options) {
5877
- return new Promise((resolve19) => {
5906
+ return new Promise((resolve21) => {
5878
5907
  const proc = spawn5(cmd, args, {
5879
5908
  cwd: options.cwd,
5880
5909
  timeout: options.timeout,
@@ -5904,7 +5933,7 @@ function runProcess(cmd, args, options) {
5904
5933
  }
5905
5934
  });
5906
5935
  proc.on("error", (err) => {
5907
- resolve19({
5936
+ resolve21({
5908
5937
  stdout,
5909
5938
  stderr: stderr || err.message,
5910
5939
  exitCode: 1,
@@ -5916,7 +5945,7 @@ function runProcess(cmd, args, options) {
5916
5945
  if (signal === "SIGTERM" || signal === "SIGKILL") {
5917
5946
  timedOut = true;
5918
5947
  }
5919
- resolve19({
5948
+ resolve21({
5920
5949
  stdout,
5921
5950
  stderr,
5922
5951
  exitCode: code ?? (timedOut ? 124 : 1),
@@ -7333,6 +7362,314 @@ Screen: ${dims.width}x${dims.height}`);
7333
7362
  }
7334
7363
  });
7335
7364
 
7365
+ // packages/execution/dist/tools/ocr-pdf.js
7366
+ import { existsSync as existsSync13, statSync as statSync6 } from "node:fs";
7367
+ import { resolve as resolve16, basename as basename5 } from "node:path";
7368
+ import { execSync as execSync12 } from "node:child_process";
7369
+ var OcrPdfTool;
7370
+ var init_ocr_pdf = __esm({
7371
+ "packages/execution/dist/tools/ocr-pdf.js"() {
7372
+ "use strict";
7373
+ init_system_deps();
7374
+ OcrPdfTool = class {
7375
+ workingDir;
7376
+ name = "ocr_pdf";
7377
+ description = "Add a searchable text layer to a scanned or image-based PDF using OCR. The output PDF looks identical but contains selectable/searchable text. Uses ocrmypdf with Tesseract. Auto-installs dependencies if missing.";
7378
+ parameters = {
7379
+ type: "object",
7380
+ properties: {
7381
+ input: {
7382
+ type: "string",
7383
+ description: "Path to the input PDF file"
7384
+ },
7385
+ output: {
7386
+ type: "string",
7387
+ description: "Path for the output PDF (default: overwrites input with --output-type pdfa)"
7388
+ },
7389
+ language: {
7390
+ type: "string",
7391
+ description: "OCR language(s) (default: eng). Use '+' for multiple: 'eng+fra+deu'"
7392
+ },
7393
+ deskew: {
7394
+ type: "boolean",
7395
+ description: "Deskew pages before OCR (default: true)"
7396
+ },
7397
+ force_ocr: {
7398
+ type: "boolean",
7399
+ description: "Force OCR even if text layer exists (default: false)"
7400
+ }
7401
+ },
7402
+ required: ["input"]
7403
+ };
7404
+ constructor(workingDir) {
7405
+ this.workingDir = workingDir;
7406
+ }
7407
+ async execute(args) {
7408
+ const start = performance.now();
7409
+ const rawInput = args["input"];
7410
+ const rawOutput = args["output"];
7411
+ const language = args["language"] ?? "eng";
7412
+ const deskew = args["deskew"] !== false;
7413
+ const forceOcr = args["force_ocr"] === true;
7414
+ if (!rawInput) {
7415
+ return { success: false, output: "", error: "input path is required", durationMs: 0 };
7416
+ }
7417
+ const inputPath = resolve16(this.workingDir, rawInput);
7418
+ if (!existsSync13(inputPath)) {
7419
+ return { success: false, output: "", error: `File not found: ${rawInput}`, durationMs: performance.now() - start };
7420
+ }
7421
+ const stat5 = statSync6(inputPath);
7422
+ if (stat5.size > 500 * 1024 * 1024) {
7423
+ return { success: false, output: "", error: `PDF too large: ${(stat5.size / 1024 / 1024).toFixed(0)}MB (max 500MB)`, durationMs: performance.now() - start };
7424
+ }
7425
+ const deps = ["ocrmypdf", "tesseract", "gs"];
7426
+ const missing = [];
7427
+ for (const dep of deps) {
7428
+ const result = ensureCommand(dep);
7429
+ if (!result.available) {
7430
+ missing.push(`${dep}${result.error ? `: ${result.error}` : ""}`);
7431
+ }
7432
+ }
7433
+ if (missing.length > 0) {
7434
+ return {
7435
+ success: false,
7436
+ output: "",
7437
+ error: `Missing dependencies: ${missing.join("; ")}`,
7438
+ durationMs: performance.now() - start
7439
+ };
7440
+ }
7441
+ const outputPath = rawOutput ? resolve16(this.workingDir, rawOutput) : inputPath;
7442
+ const cmdParts = ["ocrmypdf"];
7443
+ cmdParts.push("-l", language);
7444
+ if (deskew)
7445
+ cmdParts.push("--deskew");
7446
+ if (forceOcr)
7447
+ cmdParts.push("--force-ocr");
7448
+ cmdParts.push("--skip-text");
7449
+ if (forceOcr) {
7450
+ cmdParts.splice(cmdParts.indexOf("--skip-text"), 1);
7451
+ }
7452
+ cmdParts.push(JSON.stringify(inputPath));
7453
+ cmdParts.push(JSON.stringify(outputPath));
7454
+ try {
7455
+ const stdout = execSync12(cmdParts.join(" "), {
7456
+ encoding: "utf8",
7457
+ stdio: ["pipe", "pipe", "pipe"],
7458
+ timeout: 6e5,
7459
+ // 10 min for large PDFs
7460
+ cwd: this.workingDir
7461
+ });
7462
+ const outputStat = statSync6(outputPath);
7463
+ const sizeMB = (outputStat.size / 1024 / 1024).toFixed(1);
7464
+ return {
7465
+ success: true,
7466
+ output: `OCR completed for ${basename5(inputPath)}
7467
+ Output: ${outputPath === inputPath ? "(in-place)" : outputPath}
7468
+ Size: ${sizeMB}MB
7469
+ Language: ${language}
7470
+ ` + (stdout.trim() ? `Details: ${stdout.trim()}` : "PDF now has a searchable text layer."),
7471
+ durationMs: performance.now() - start
7472
+ };
7473
+ } catch (err) {
7474
+ const msg = err instanceof Error ? err.message : String(err);
7475
+ const stderr = err?.stderr?.toString?.() ?? "";
7476
+ return {
7477
+ success: false,
7478
+ output: "",
7479
+ error: `ocrmypdf failed: ${stderr || msg}`.slice(0, 500),
7480
+ durationMs: performance.now() - start
7481
+ };
7482
+ }
7483
+ }
7484
+ };
7485
+ }
7486
+ });
7487
+
7488
+ // packages/execution/dist/tools/pdf-to-text.js
7489
+ import { existsSync as existsSync14, statSync as statSync7, readFileSync as readFileSync12, unlinkSync as unlinkSync2 } from "node:fs";
7490
+ import { resolve as resolve17, basename as basename6, join as join17 } from "node:path";
7491
+ import { execSync as execSync13 } from "node:child_process";
7492
+ import { tmpdir as tmpdir4 } from "node:os";
7493
+ var PdfToTextTool;
7494
+ var init_pdf_to_text = __esm({
7495
+ "packages/execution/dist/tools/pdf-to-text.js"() {
7496
+ "use strict";
7497
+ init_system_deps();
7498
+ PdfToTextTool = class {
7499
+ workingDir;
7500
+ name = "pdf_to_text";
7501
+ description = "Extract text content from a PDF file. Uses pdftotext (Poppler) for native PDFs. For scanned/image PDFs with no text layer, can optionally OCR first via ocrmypdf. Auto-installs dependencies if missing.";
7502
+ parameters = {
7503
+ type: "object",
7504
+ properties: {
7505
+ path: {
7506
+ type: "string",
7507
+ description: "Path to the PDF file"
7508
+ },
7509
+ pages: {
7510
+ type: "string",
7511
+ description: "Page range to extract: 'first' (page 1), 'N' (single page), 'N-M' (range). Default: all pages."
7512
+ },
7513
+ layout: {
7514
+ type: "boolean",
7515
+ description: "Preserve original layout/formatting (default: false \u2014 flows text naturally)"
7516
+ },
7517
+ ocr_if_empty: {
7518
+ type: "boolean",
7519
+ description: "If pdftotext returns no text, try OCR via ocrmypdf first (default: true)"
7520
+ },
7521
+ language: {
7522
+ type: "string",
7523
+ description: "OCR language if OCR fallback is used (default: eng)"
7524
+ }
7525
+ },
7526
+ required: ["path"]
7527
+ };
7528
+ constructor(workingDir) {
7529
+ this.workingDir = workingDir;
7530
+ }
7531
+ async execute(args) {
7532
+ const start = performance.now();
7533
+ const rawPath = args["path"];
7534
+ const pages = args["pages"];
7535
+ const layout = args["layout"] === true;
7536
+ const ocrIfEmpty = args["ocr_if_empty"] !== false;
7537
+ const language = args["language"] ?? "eng";
7538
+ if (!rawPath) {
7539
+ return { success: false, output: "", error: "path is required", durationMs: 0 };
7540
+ }
7541
+ const fullPath = resolve17(this.workingDir, rawPath);
7542
+ if (!existsSync14(fullPath)) {
7543
+ return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: performance.now() - start };
7544
+ }
7545
+ const fileStat = statSync7(fullPath);
7546
+ if (fileStat.size > 500 * 1024 * 1024) {
7547
+ return { success: false, output: "", error: `PDF too large: ${(fileStat.size / 1024 / 1024).toFixed(0)}MB (max 500MB)`, durationMs: performance.now() - start };
7548
+ }
7549
+ const pdftotextCheck = ensureCommand("pdftotext");
7550
+ if (!pdftotextCheck.available) {
7551
+ return {
7552
+ success: false,
7553
+ output: "",
7554
+ error: `pdftotext not available: ${pdftotextCheck.error ?? "auto-install failed"}`,
7555
+ durationMs: performance.now() - start
7556
+ };
7557
+ }
7558
+ const cmdParts = ["pdftotext"];
7559
+ if (layout)
7560
+ cmdParts.push("-layout");
7561
+ let firstPage;
7562
+ let lastPage;
7563
+ if (pages) {
7564
+ if (pages === "first") {
7565
+ firstPage = 1;
7566
+ lastPage = 1;
7567
+ } else if (pages.includes("-")) {
7568
+ const [a, b] = pages.split("-").map(Number);
7569
+ if (a && b) {
7570
+ firstPage = a;
7571
+ lastPage = b;
7572
+ }
7573
+ } else {
7574
+ const n = Number(pages);
7575
+ if (n) {
7576
+ firstPage = n;
7577
+ lastPage = n;
7578
+ }
7579
+ }
7580
+ }
7581
+ if (firstPage)
7582
+ cmdParts.push("-f", String(firstPage));
7583
+ if (lastPage)
7584
+ cmdParts.push("-l", String(lastPage));
7585
+ cmdParts.push(JSON.stringify(fullPath), "-");
7586
+ try {
7587
+ let text = execSync13(cmdParts.join(" "), {
7588
+ encoding: "utf8",
7589
+ stdio: ["pipe", "pipe", "pipe"],
7590
+ timeout: 12e4
7591
+ }).trim();
7592
+ if (!text && ocrIfEmpty) {
7593
+ const ocrText = await this.ocrFallback(fullPath, language, firstPage, lastPage);
7594
+ if (ocrText) {
7595
+ text = ocrText;
7596
+ const lineCount2 = text.split("\n").length;
7597
+ const pageInfo2 = pages ? ` (pages: ${pages})` : "";
7598
+ return {
7599
+ success: true,
7600
+ output: `Extracted ${lineCount2} lines from ${basename6(fullPath)}${pageInfo2} (via OCR):
7601
+
7602
+ ${text}`,
7603
+ durationMs: performance.now() - start
7604
+ };
7605
+ }
7606
+ return {
7607
+ success: true,
7608
+ output: `No text found in ${basename6(fullPath)} \u2014 appears to be a scanned/image PDF with no extractable text. OCR also returned no results.`,
7609
+ durationMs: performance.now() - start
7610
+ };
7611
+ }
7612
+ if (!text) {
7613
+ return {
7614
+ success: true,
7615
+ output: `No text found in ${basename6(fullPath)} \u2014 may be a scanned/image PDF. Use ocr_pdf tool to add a text layer first.`,
7616
+ durationMs: performance.now() - start
7617
+ };
7618
+ }
7619
+ const lineCount = text.split("\n").length;
7620
+ const pageInfo = pages ? ` (pages: ${pages})` : "";
7621
+ return {
7622
+ success: true,
7623
+ output: `Extracted ${lineCount} lines from ${basename6(fullPath)}${pageInfo}:
7624
+
7625
+ ${text}`,
7626
+ durationMs: performance.now() - start
7627
+ };
7628
+ } catch (err) {
7629
+ return {
7630
+ success: false,
7631
+ output: "",
7632
+ error: `pdftotext failed: ${err instanceof Error ? err.message : String(err)}`,
7633
+ durationMs: performance.now() - start
7634
+ };
7635
+ }
7636
+ }
7637
+ async ocrFallback(inputPath, language, firstPage, lastPage) {
7638
+ const ocrCheck = ensureCommand("ocrmypdf");
7639
+ const tesCheck = ensureCommand("tesseract");
7640
+ const gsCheck = ensureCommand("gs");
7641
+ if (!ocrCheck.available || !tesCheck.available || !gsCheck.available) {
7642
+ return null;
7643
+ }
7644
+ const tmpPdf = join17(tmpdir4(), `oa-ocr-${Date.now()}.pdf`);
7645
+ try {
7646
+ const ocrCmd = `ocrmypdf -l ${language} --skip-text ${JSON.stringify(inputPath)} ${JSON.stringify(tmpPdf)}`;
7647
+ execSync13(ocrCmd, { stdio: "pipe", timeout: 6e5 });
7648
+ const textCmdParts = ["pdftotext"];
7649
+ if (firstPage)
7650
+ textCmdParts.push("-f", String(firstPage));
7651
+ if (lastPage)
7652
+ textCmdParts.push("-l", String(lastPage));
7653
+ textCmdParts.push(JSON.stringify(tmpPdf), "-");
7654
+ const text = execSync13(textCmdParts.join(" "), {
7655
+ encoding: "utf8",
7656
+ stdio: ["pipe", "pipe", "pipe"],
7657
+ timeout: 12e4
7658
+ }).trim();
7659
+ return text || null;
7660
+ } catch {
7661
+ return null;
7662
+ } finally {
7663
+ try {
7664
+ unlinkSync2(tmpPdf);
7665
+ } catch {
7666
+ }
7667
+ }
7668
+ }
7669
+ };
7670
+ }
7671
+ });
7672
+
7336
7673
  // packages/execution/dist/shellRunner.js
7337
7674
  var init_shellRunner = __esm({
7338
7675
  "packages/execution/dist/shellRunner.js"() {
@@ -7442,6 +7779,8 @@ var init_dist2 = __esm({
7442
7779
  init_structured_read();
7443
7780
  init_vision();
7444
7781
  init_desktop_click();
7782
+ init_ocr_pdf();
7783
+ init_pdf_to_text();
7445
7784
  init_system_deps();
7446
7785
  init_shellRunner();
7447
7786
  init_gitWorktree();
@@ -8574,7 +8913,7 @@ var init_code_retriever = __esm({
8574
8913
  import { execFile as execFile4 } from "node:child_process";
8575
8914
  import { promisify as promisify4 } from "node:util";
8576
8915
  import { readFile as readFile8, readdir as readdir2, stat as stat3 } from "node:fs/promises";
8577
- import { join as join17, extname as extname7 } from "node:path";
8916
+ import { join as join18, extname as extname7 } from "node:path";
8578
8917
  async function searchByPath(pathPattern, options) {
8579
8918
  const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
8580
8919
  const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
@@ -8716,7 +9055,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
8716
9055
  continue;
8717
9056
  if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
8718
9057
  continue;
8719
- const absPath = join17(dir, entry.name);
9058
+ const absPath = join18(dir, entry.name);
8720
9059
  if (entry.isDirectory()) {
8721
9060
  await walkForFiles(rootDir, absPath, excludeGlobs, results);
8722
9061
  } else if (entry.isFile()) {
@@ -8891,7 +9230,7 @@ var init_graphExpand = __esm({
8891
9230
 
8892
9231
  // packages/retrieval/dist/snippetPacker.js
8893
9232
  import { readFile as readFile9 } from "node:fs/promises";
8894
- import { join as join18 } from "node:path";
9233
+ import { join as join19 } from "node:path";
8895
9234
  async function packSnippets(requests, opts = {}) {
8896
9235
  const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
8897
9236
  const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
@@ -8917,7 +9256,7 @@ async function packSnippets(requests, opts = {}) {
8917
9256
  return { packed, dropped, totalTokens };
8918
9257
  }
8919
9258
  async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
8920
- const absPath = req.filePath.startsWith("/") ? req.filePath : join18(repoRoot, req.filePath);
9259
+ const absPath = req.filePath.startsWith("/") ? req.filePath : join19(repoRoot, req.filePath);
8921
9260
  let content;
8922
9261
  try {
8923
9262
  content = await readFile9(absPath, "utf-8");
@@ -10430,8 +10769,8 @@ Rules:
10430
10769
  async waitIfPaused() {
10431
10770
  if (!this._paused)
10432
10771
  return true;
10433
- await new Promise((resolve19) => {
10434
- this._pauseResolve = resolve19;
10772
+ await new Promise((resolve21) => {
10773
+ this._pauseResolve = resolve21;
10435
10774
  });
10436
10775
  return !this.aborted;
10437
10776
  }
@@ -10941,14 +11280,14 @@ ${result.output}`;
10941
11280
  waitForSudoPassword(timeoutMs = 12e4) {
10942
11281
  if (this._sudoPassword)
10943
11282
  return Promise.resolve(this._sudoPassword);
10944
- return new Promise((resolve19) => {
11283
+ return new Promise((resolve21) => {
10945
11284
  const timer = setTimeout(() => {
10946
11285
  this._sudoResolve = null;
10947
- resolve19(null);
11286
+ resolve21(null);
10948
11287
  }, timeoutMs);
10949
11288
  this._sudoResolve = (pw) => {
10950
11289
  clearTimeout(timer);
10951
- resolve19(pw);
11290
+ resolve21(pw);
10952
11291
  };
10953
11292
  });
10954
11293
  }
@@ -12104,9 +12443,9 @@ var init_dist5 = __esm({
12104
12443
  });
12105
12444
 
12106
12445
  // packages/cli/dist/tui/listen.js
12107
- import { spawn as spawn7, execSync as execSync12 } from "node:child_process";
12108
- import { existsSync as existsSync13, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readdirSync as readdirSync6 } from "node:fs";
12109
- import { join as join19, dirname as dirname6 } from "node:path";
12446
+ import { spawn as spawn7, execSync as execSync14 } from "node:child_process";
12447
+ import { existsSync as existsSync15, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readdirSync as readdirSync6 } from "node:fs";
12448
+ import { join as join20, dirname as dirname6 } from "node:path";
12110
12449
  import { homedir as homedir6 } from "node:os";
12111
12450
  import { fileURLToPath as fileURLToPath3 } from "node:url";
12112
12451
  import { EventEmitter } from "node:events";
@@ -12126,7 +12465,7 @@ function findMicCaptureCommand() {
12126
12465
  const platform4 = process.platform;
12127
12466
  if (platform4 === "linux") {
12128
12467
  try {
12129
- execSync12("which arecord", { stdio: "pipe" });
12468
+ execSync14("which arecord", { stdio: "pipe" });
12130
12469
  return {
12131
12470
  cmd: "arecord",
12132
12471
  args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
@@ -12136,7 +12475,7 @@ function findMicCaptureCommand() {
12136
12475
  }
12137
12476
  if (platform4 === "darwin") {
12138
12477
  try {
12139
- execSync12("which sox", { stdio: "pipe" });
12478
+ execSync14("which sox", { stdio: "pipe" });
12140
12479
  return {
12141
12480
  cmd: "sox",
12142
12481
  args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
@@ -12145,7 +12484,7 @@ function findMicCaptureCommand() {
12145
12484
  }
12146
12485
  }
12147
12486
  try {
12148
- execSync12("which ffmpeg", { stdio: "pipe" });
12487
+ execSync14("which ffmpeg", { stdio: "pipe" });
12149
12488
  if (platform4 === "linux") {
12150
12489
  return {
12151
12490
  cmd: "ffmpeg",
@@ -12192,39 +12531,39 @@ function findMicCaptureCommand() {
12192
12531
  function findLiveWhisperScript() {
12193
12532
  const thisDir = dirname6(fileURLToPath3(import.meta.url));
12194
12533
  const candidates = [
12195
- join19(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
12196
- join19(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
12197
- join19(thisDir, "../../execution/scripts/live-whisper.py"),
12534
+ join20(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
12535
+ join20(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
12536
+ join20(thisDir, "../../execution/scripts/live-whisper.py"),
12198
12537
  // npm install layout — scripts bundled alongside dist
12199
- join19(thisDir, "../scripts/live-whisper.py"),
12200
- join19(thisDir, "../../scripts/live-whisper.py")
12538
+ join20(thisDir, "../scripts/live-whisper.py"),
12539
+ join20(thisDir, "../../scripts/live-whisper.py")
12201
12540
  ];
12202
12541
  for (const p of candidates) {
12203
- if (existsSync13(p))
12542
+ if (existsSync15(p))
12204
12543
  return p;
12205
12544
  }
12206
12545
  try {
12207
- const globalRoot = execSync12("npm root -g", {
12546
+ const globalRoot = execSync14("npm root -g", {
12208
12547
  encoding: "utf-8",
12209
12548
  timeout: 5e3,
12210
12549
  stdio: ["pipe", "pipe", "pipe"]
12211
12550
  }).trim();
12212
12551
  const candidates2 = [
12213
- join19(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
12214
- join19(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
12552
+ join20(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
12553
+ join20(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
12215
12554
  ];
12216
12555
  for (const p of candidates2) {
12217
- if (existsSync13(p))
12556
+ if (existsSync15(p))
12218
12557
  return p;
12219
12558
  }
12220
12559
  } catch {
12221
12560
  }
12222
- const nvmBase = join19(homedir6(), ".nvm", "versions", "node");
12223
- if (existsSync13(nvmBase)) {
12561
+ const nvmBase = join20(homedir6(), ".nvm", "versions", "node");
12562
+ if (existsSync15(nvmBase)) {
12224
12563
  try {
12225
12564
  for (const ver of readdirSync6(nvmBase)) {
12226
- const p = join19(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
12227
- if (existsSync13(p))
12565
+ const p = join20(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
12566
+ if (existsSync15(p))
12228
12567
  return p;
12229
12568
  }
12230
12569
  } catch {
@@ -12237,21 +12576,21 @@ function ensureTranscribeCliBackground() {
12237
12576
  return;
12238
12577
  _bgInstallPromise = (async () => {
12239
12578
  try {
12240
- const globalRoot = execSync12("npm root -g", {
12579
+ const globalRoot = execSync14("npm root -g", {
12241
12580
  encoding: "utf-8",
12242
12581
  timeout: 5e3,
12243
12582
  stdio: ["pipe", "pipe", "pipe"]
12244
12583
  }).trim();
12245
- if (existsSync13(join19(globalRoot, "transcribe-cli", "dist", "index.js"))) {
12584
+ if (existsSync15(join20(globalRoot, "transcribe-cli", "dist", "index.js"))) {
12246
12585
  return true;
12247
12586
  }
12248
12587
  } catch {
12249
12588
  }
12250
12589
  try {
12251
12590
  const { exec } = await import("node:child_process");
12252
- return new Promise((resolve19) => {
12591
+ return new Promise((resolve21) => {
12253
12592
  exec("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
12254
- resolve19(!err);
12593
+ resolve21(!err);
12255
12594
  });
12256
12595
  });
12257
12596
  } catch {
@@ -12304,7 +12643,7 @@ var init_listen = __esm({
12304
12643
  return this._ready;
12305
12644
  }
12306
12645
  async start() {
12307
- return new Promise((resolve19, reject) => {
12646
+ return new Promise((resolve21, reject) => {
12308
12647
  const timeout = setTimeout(() => {
12309
12648
  reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
12310
12649
  }, 3e5);
@@ -12332,7 +12671,7 @@ var init_listen = __esm({
12332
12671
  this._ready = true;
12333
12672
  clearTimeout(timeout);
12334
12673
  this.emit("ready");
12335
- resolve19();
12674
+ resolve21();
12336
12675
  break;
12337
12676
  case "transcript":
12338
12677
  this.emit("transcript", {
@@ -12437,7 +12776,7 @@ var init_listen = __esm({
12437
12776
  }
12438
12777
  if (!this.transcribeCliAvailable) {
12439
12778
  try {
12440
- execSync12("which transcribe-cli", { stdio: "pipe" });
12779
+ execSync14("which transcribe-cli", { stdio: "pipe" });
12441
12780
  this.transcribeCliAvailable = true;
12442
12781
  } catch {
12443
12782
  this.transcribeCliAvailable = false;
@@ -12454,29 +12793,29 @@ var init_listen = __esm({
12454
12793
  } catch {
12455
12794
  }
12456
12795
  try {
12457
- const globalRoot = execSync12("npm root -g", {
12796
+ const globalRoot = execSync14("npm root -g", {
12458
12797
  encoding: "utf-8",
12459
12798
  timeout: 5e3,
12460
12799
  stdio: ["pipe", "pipe", "pipe"]
12461
12800
  }).trim();
12462
- const tcPath = join19(globalRoot, "transcribe-cli");
12463
- if (existsSync13(join19(tcPath, "dist", "index.js"))) {
12801
+ const tcPath = join20(globalRoot, "transcribe-cli");
12802
+ if (existsSync15(join20(tcPath, "dist", "index.js"))) {
12464
12803
  const { createRequire: createRequire4 } = await import("node:module");
12465
12804
  const req = createRequire4(import.meta.url);
12466
- return req(join19(tcPath, "dist", "index.js"));
12805
+ return req(join20(tcPath, "dist", "index.js"));
12467
12806
  }
12468
12807
  } catch {
12469
12808
  }
12470
- const nvmBase = join19(homedir6(), ".nvm", "versions", "node");
12471
- if (existsSync13(nvmBase)) {
12809
+ const nvmBase = join20(homedir6(), ".nvm", "versions", "node");
12810
+ if (existsSync15(nvmBase)) {
12472
12811
  try {
12473
12812
  const { readdirSync: readdirSync11 } = await import("node:fs");
12474
12813
  for (const ver of readdirSync11(nvmBase)) {
12475
- const tcPath = join19(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
12476
- if (existsSync13(join19(tcPath, "dist", "index.js"))) {
12814
+ const tcPath = join20(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
12815
+ if (existsSync15(join20(tcPath, "dist", "index.js"))) {
12477
12816
  const { createRequire: createRequire4 } = await import("node:module");
12478
12817
  const req = createRequire4(import.meta.url);
12479
- return req(join19(tcPath, "dist", "index.js"));
12818
+ return req(join20(tcPath, "dist", "index.js"));
12480
12819
  }
12481
12820
  }
12482
12821
  } catch {
@@ -12504,7 +12843,7 @@ var init_listen = __esm({
12504
12843
  }
12505
12844
  if (!tc) {
12506
12845
  try {
12507
- execSync12("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
12846
+ execSync14("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
12508
12847
  this.transcribeCliAvailable = null;
12509
12848
  tc = await this.loadTranscribeCli();
12510
12849
  } catch {
@@ -12536,11 +12875,11 @@ var init_listen = __esm({
12536
12875
  this.liveTranscriber.on("error", (err) => {
12537
12876
  this.emit("error", err);
12538
12877
  });
12539
- await new Promise((resolve19, reject) => {
12878
+ await new Promise((resolve21, reject) => {
12540
12879
  const timeout = setTimeout(() => reject(new Error("Model load timeout (60s)")), 6e4);
12541
12880
  this.liveTranscriber.on("ready", () => {
12542
12881
  clearTimeout(timeout);
12543
- resolve19();
12882
+ resolve21();
12544
12883
  });
12545
12884
  this.liveTranscriber.on("error", (err) => {
12546
12885
  clearTimeout(timeout);
@@ -12685,7 +13024,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
12685
13024
  }
12686
13025
  if (!tc) {
12687
13026
  try {
12688
- execSync12("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
13027
+ execSync14("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
12689
13028
  this.transcribeCliAvailable = null;
12690
13029
  tc = await this.loadTranscribeCli();
12691
13030
  } catch {
@@ -12701,10 +13040,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
12701
13040
  wordTimestamps: false
12702
13041
  });
12703
13042
  if (outputDir) {
12704
- const { basename: basename10 } = await import("node:path");
12705
- const transcriptDir = join19(outputDir, ".oa", "transcripts");
13043
+ const { basename: basename12 } = await import("node:path");
13044
+ const transcriptDir = join20(outputDir, ".oa", "transcripts");
12706
13045
  mkdirSync5(transcriptDir, { recursive: true });
12707
- const outFile = join19(transcriptDir, `${basename10(filePath)}.txt`);
13046
+ const outFile = join20(transcriptDir, `${basename12(filePath)}.txt`);
12708
13047
  writeFileSync5(outFile, result.text, "utf-8");
12709
13048
  }
12710
13049
  return {
@@ -13968,7 +14307,7 @@ Approach this task thoughtfully:
13968
14307
  });
13969
14308
 
13970
14309
  // packages/prompts/dist/index.js
13971
- import { join as join20, dirname as dirname7 } from "node:path";
14310
+ import { join as join21, dirname as dirname7 } from "node:path";
13972
14311
  import { fileURLToPath as fileURLToPath4 } from "node:url";
13973
14312
  var _dir, _packageRoot;
13974
14313
  var init_dist6 = __esm({
@@ -13979,57 +14318,57 @@ var init_dist6 = __esm({
13979
14318
  init_task_templates();
13980
14319
  init_render2();
13981
14320
  _dir = dirname7(fileURLToPath4(import.meta.url));
13982
- _packageRoot = join20(_dir, "..");
14321
+ _packageRoot = join21(_dir, "..");
13983
14322
  }
13984
14323
  });
13985
14324
 
13986
14325
  // packages/cli/dist/tui/oa-directory.js
13987
- import { existsSync as existsSync14, mkdirSync as mkdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync6, readdirSync as readdirSync7, statSync as statSync6, unlinkSync as unlinkSync2 } from "node:fs";
13988
- import { join as join21, relative as relative2, basename as basename5, extname as extname8 } from "node:path";
14326
+ import { existsSync as existsSync16, mkdirSync as mkdirSync6, readFileSync as readFileSync13, writeFileSync as writeFileSync6, readdirSync as readdirSync7, statSync as statSync8, unlinkSync as unlinkSync3 } from "node:fs";
14327
+ import { join as join22, relative as relative2, basename as basename7, extname as extname8 } from "node:path";
13989
14328
  import { homedir as homedir7 } from "node:os";
13990
14329
  function initOaDirectory(repoRoot) {
13991
- const oaPath = join21(repoRoot, OA_DIR);
14330
+ const oaPath = join22(repoRoot, OA_DIR);
13992
14331
  for (const sub of SUBDIRS) {
13993
- mkdirSync6(join21(oaPath, sub), { recursive: true });
14332
+ mkdirSync6(join22(oaPath, sub), { recursive: true });
13994
14333
  }
13995
14334
  return oaPath;
13996
14335
  }
13997
14336
  function hasOaDirectory(repoRoot) {
13998
- return existsSync14(join21(repoRoot, OA_DIR, "index"));
14337
+ return existsSync16(join22(repoRoot, OA_DIR, "index"));
13999
14338
  }
14000
14339
  function loadProjectSettings(repoRoot) {
14001
- const settingsPath = join21(repoRoot, OA_DIR, "settings.json");
14340
+ const settingsPath = join22(repoRoot, OA_DIR, "settings.json");
14002
14341
  try {
14003
- if (existsSync14(settingsPath)) {
14004
- return JSON.parse(readFileSync12(settingsPath, "utf-8"));
14342
+ if (existsSync16(settingsPath)) {
14343
+ return JSON.parse(readFileSync13(settingsPath, "utf-8"));
14005
14344
  }
14006
14345
  } catch {
14007
14346
  }
14008
14347
  return {};
14009
14348
  }
14010
14349
  function saveProjectSettings(repoRoot, settings) {
14011
- const oaPath = join21(repoRoot, OA_DIR);
14350
+ const oaPath = join22(repoRoot, OA_DIR);
14012
14351
  mkdirSync6(oaPath, { recursive: true });
14013
14352
  const existing = loadProjectSettings(repoRoot);
14014
14353
  const merged = { ...existing, ...settings };
14015
- writeFileSync6(join21(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
14354
+ writeFileSync6(join22(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
14016
14355
  }
14017
14356
  function loadGlobalSettings() {
14018
- const settingsPath = join21(homedir7(), ".open-agents", "settings.json");
14357
+ const settingsPath = join22(homedir7(), ".open-agents", "settings.json");
14019
14358
  try {
14020
- if (existsSync14(settingsPath)) {
14021
- return JSON.parse(readFileSync12(settingsPath, "utf-8"));
14359
+ if (existsSync16(settingsPath)) {
14360
+ return JSON.parse(readFileSync13(settingsPath, "utf-8"));
14022
14361
  }
14023
14362
  } catch {
14024
14363
  }
14025
14364
  return {};
14026
14365
  }
14027
14366
  function saveGlobalSettings(settings) {
14028
- const dir = join21(homedir7(), ".open-agents");
14367
+ const dir = join22(homedir7(), ".open-agents");
14029
14368
  mkdirSync6(dir, { recursive: true });
14030
14369
  const existing = loadGlobalSettings();
14031
14370
  const merged = { ...existing, ...settings };
14032
- writeFileSync6(join21(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
14371
+ writeFileSync6(join22(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
14033
14372
  }
14034
14373
  function resolveSettings(repoRoot) {
14035
14374
  const global = loadGlobalSettings();
@@ -14044,12 +14383,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
14044
14383
  while (dir && !visited.has(dir)) {
14045
14384
  visited.add(dir);
14046
14385
  for (const name of CONTEXT_FILES) {
14047
- const filePath = join21(dir, name);
14386
+ const filePath = join22(dir, name);
14048
14387
  const normalizedName = name.toLowerCase();
14049
- if (existsSync14(filePath) && !seen.has(filePath)) {
14388
+ if (existsSync16(filePath) && !seen.has(filePath)) {
14050
14389
  seen.add(filePath);
14051
14390
  try {
14052
- let content = readFileSync12(filePath, "utf-8");
14391
+ let content = readFileSync13(filePath, "utf-8");
14053
14392
  if (content.length > maxContentLen) {
14054
14393
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
14055
14394
  }
@@ -14063,11 +14402,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
14063
14402
  }
14064
14403
  }
14065
14404
  }
14066
- const projectMap = join21(dir, OA_DIR, "context", "project-map.md");
14067
- if (existsSync14(projectMap) && !seen.has(projectMap)) {
14405
+ const projectMap = join22(dir, OA_DIR, "context", "project-map.md");
14406
+ if (existsSync16(projectMap) && !seen.has(projectMap)) {
14068
14407
  seen.add(projectMap);
14069
14408
  try {
14070
- let content = readFileSync12(projectMap, "utf-8");
14409
+ let content = readFileSync13(projectMap, "utf-8");
14071
14410
  if (content.length > maxContentLen) {
14072
14411
  content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
14073
14412
  }
@@ -14079,7 +14418,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
14079
14418
  } catch {
14080
14419
  }
14081
14420
  }
14082
- const parent = join21(dir, "..");
14421
+ const parent = join22(dir, "..");
14083
14422
  if (parent === dir)
14084
14423
  break;
14085
14424
  dir = parent;
@@ -14097,16 +14436,16 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
14097
14436
  return found;
14098
14437
  }
14099
14438
  function readIndexMeta(repoRoot) {
14100
- const metaPath = join21(repoRoot, OA_DIR, "index", "meta.json");
14439
+ const metaPath = join22(repoRoot, OA_DIR, "index", "meta.json");
14101
14440
  try {
14102
- return JSON.parse(readFileSync12(metaPath, "utf-8"));
14441
+ return JSON.parse(readFileSync13(metaPath, "utf-8"));
14103
14442
  } catch {
14104
14443
  return null;
14105
14444
  }
14106
14445
  }
14107
14446
  function generateProjectMap(repoRoot) {
14108
14447
  const sections = [];
14109
- const repoName2 = basename5(repoRoot);
14448
+ const repoName2 = basename7(repoRoot);
14110
14449
  sections.push(`# Project Map: ${repoName2}
14111
14450
  `);
14112
14451
  sections.push(`> Auto-generated by open-agents. Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -14150,28 +14489,28 @@ ${tree}\`\`\`
14150
14489
  sections.push("");
14151
14490
  }
14152
14491
  const content = sections.join("\n");
14153
- const contextDir = join21(repoRoot, OA_DIR, "context");
14492
+ const contextDir = join22(repoRoot, OA_DIR, "context");
14154
14493
  mkdirSync6(contextDir, { recursive: true });
14155
- writeFileSync6(join21(contextDir, "project-map.md"), content, "utf-8");
14494
+ writeFileSync6(join22(contextDir, "project-map.md"), content, "utf-8");
14156
14495
  return content;
14157
14496
  }
14158
14497
  function saveSession(repoRoot, session) {
14159
- const historyDir = join21(repoRoot, OA_DIR, "history");
14498
+ const historyDir = join22(repoRoot, OA_DIR, "history");
14160
14499
  mkdirSync6(historyDir, { recursive: true });
14161
- writeFileSync6(join21(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
14500
+ writeFileSync6(join22(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
14162
14501
  }
14163
14502
  function loadRecentSessions(repoRoot, limit = 5) {
14164
- const historyDir = join21(repoRoot, OA_DIR, "history");
14165
- if (!existsSync14(historyDir))
14503
+ const historyDir = join22(repoRoot, OA_DIR, "history");
14504
+ if (!existsSync16(historyDir))
14166
14505
  return [];
14167
14506
  try {
14168
14507
  const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
14169
- const stat5 = statSync6(join21(historyDir, f));
14508
+ const stat5 = statSync8(join22(historyDir, f));
14170
14509
  return { file: f, mtime: stat5.mtimeMs };
14171
14510
  }).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
14172
14511
  return files.map((f) => {
14173
14512
  try {
14174
- return JSON.parse(readFileSync12(join21(historyDir, f.file), "utf-8"));
14513
+ return JSON.parse(readFileSync13(join22(historyDir, f.file), "utf-8"));
14175
14514
  } catch {
14176
14515
  return null;
14177
14516
  }
@@ -14181,18 +14520,18 @@ function loadRecentSessions(repoRoot, limit = 5) {
14181
14520
  }
14182
14521
  }
14183
14522
  function savePendingTask(repoRoot, task) {
14184
- const historyDir = join21(repoRoot, OA_DIR, "history");
14523
+ const historyDir = join22(repoRoot, OA_DIR, "history");
14185
14524
  mkdirSync6(historyDir, { recursive: true });
14186
- writeFileSync6(join21(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
14525
+ writeFileSync6(join22(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
14187
14526
  }
14188
14527
  function loadPendingTask(repoRoot) {
14189
- const filePath = join21(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
14528
+ const filePath = join22(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
14190
14529
  try {
14191
- if (!existsSync14(filePath))
14530
+ if (!existsSync16(filePath))
14192
14531
  return null;
14193
- const data = JSON.parse(readFileSync12(filePath, "utf-8"));
14532
+ const data = JSON.parse(readFileSync13(filePath, "utf-8"));
14194
14533
  try {
14195
- unlinkSync2(filePath);
14534
+ unlinkSync3(filePath);
14196
14535
  } catch {
14197
14536
  }
14198
14537
  return data;
@@ -14218,12 +14557,12 @@ function detectManifests(repoRoot) {
14218
14557
  { file: "docker-compose.yaml", type: "Docker Compose" }
14219
14558
  ];
14220
14559
  for (const check of checks) {
14221
- const filePath = join21(repoRoot, check.file);
14222
- if (existsSync14(filePath)) {
14560
+ const filePath = join22(repoRoot, check.file);
14561
+ if (existsSync16(filePath)) {
14223
14562
  let name;
14224
14563
  if (check.nameField) {
14225
14564
  try {
14226
- const data = JSON.parse(readFileSync12(filePath, "utf-8"));
14565
+ const data = JSON.parse(readFileSync13(filePath, "utf-8"));
14227
14566
  name = data[check.nameField];
14228
14567
  } catch {
14229
14568
  }
@@ -14252,7 +14591,7 @@ function findKeyFiles(repoRoot) {
14252
14591
  { pattern: "CLAUDE.md", description: "Claude Code context" }
14253
14592
  ];
14254
14593
  for (const check of checks) {
14255
- if (existsSync14(join21(repoRoot, check.pattern))) {
14594
+ if (existsSync16(join22(repoRoot, check.pattern))) {
14256
14595
  keyFiles.push({ path: check.pattern, description: check.description });
14257
14596
  }
14258
14597
  }
@@ -14278,12 +14617,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
14278
14617
  if (entry.isDirectory()) {
14279
14618
  let fileCount = 0;
14280
14619
  try {
14281
- fileCount = readdirSync7(join21(root, entry.name)).filter((f) => !f.startsWith(".")).length;
14620
+ fileCount = readdirSync7(join22(root, entry.name)).filter((f) => !f.startsWith(".")).length;
14282
14621
  } catch {
14283
14622
  }
14284
14623
  result += `${prefix}${connector}${entry.name}/ (${fileCount})
14285
14624
  `;
14286
- result += buildDirTree(join21(root, entry.name), maxDepth, childPrefix, depth + 1);
14625
+ result += buildDirTree(join22(root, entry.name), maxDepth, childPrefix, depth + 1);
14287
14626
  } else if (depth < maxDepth) {
14288
14627
  result += `${prefix}${connector}${entry.name}
14289
14628
  `;
@@ -14334,9 +14673,9 @@ var init_oa_directory = __esm({
14334
14673
 
14335
14674
  // packages/cli/dist/tui/setup.js
14336
14675
  import * as readline from "node:readline";
14337
- import { execSync as execSync13, spawn as spawn8 } from "node:child_process";
14338
- import { existsSync as existsSync15, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
14339
- import { join as join22 } from "node:path";
14676
+ import { execSync as execSync15, spawn as spawn8 } from "node:child_process";
14677
+ import { existsSync as existsSync17, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
14678
+ import { join as join23 } from "node:path";
14340
14679
  import { homedir as homedir8, platform } from "node:os";
14341
14680
  function detectSystemSpecs() {
14342
14681
  let totalRamGB = 0;
@@ -14344,7 +14683,7 @@ function detectSystemSpecs() {
14344
14683
  let gpuVramGB = 0;
14345
14684
  let gpuName = "";
14346
14685
  try {
14347
- const memInfo = execSync13("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
14686
+ const memInfo = execSync15("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
14348
14687
  encoding: "utf8",
14349
14688
  timeout: 5e3
14350
14689
  });
@@ -14364,7 +14703,7 @@ function detectSystemSpecs() {
14364
14703
  } catch {
14365
14704
  }
14366
14705
  try {
14367
- const nvidiaSmi = execSync13("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
14706
+ const nvidiaSmi = execSync15("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
14368
14707
  const lines = nvidiaSmi.trim().split("\n");
14369
14708
  if (lines.length > 0) {
14370
14709
  for (const line of lines) {
@@ -14420,8 +14759,8 @@ function modelSupportsToolCalling(modelName) {
14420
14759
  return false;
14421
14760
  }
14422
14761
  function ask(rl, question) {
14423
- return new Promise((resolve19) => {
14424
- rl.question(question, (answer) => resolve19(answer.trim()));
14762
+ return new Promise((resolve21) => {
14763
+ rl.question(question, (answer) => resolve21(answer.trim()));
14425
14764
  });
14426
14765
  }
14427
14766
  async function autoInstallOllama(rl) {
@@ -14446,7 +14785,7 @@ function installOllamaLinux() {
14446
14785
 
14447
14786
  `);
14448
14787
  try {
14449
- execSync13("curl -fsSL https://ollama.com/install.sh | sh", {
14788
+ execSync15("curl -fsSL https://ollama.com/install.sh | sh", {
14450
14789
  stdio: "inherit",
14451
14790
  timeout: 3e5
14452
14791
  });
@@ -14485,10 +14824,10 @@ async function installOllamaMac(rl) {
14485
14824
 
14486
14825
  `);
14487
14826
  try {
14488
- execSync13('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
14827
+ execSync15('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
14489
14828
  if (!hasCmd("brew")) {
14490
14829
  try {
14491
- const brewPrefix = existsSync15("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
14830
+ const brewPrefix = existsSync17("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
14492
14831
  process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
14493
14832
  } catch {
14494
14833
  }
@@ -14518,7 +14857,7 @@ async function installOllamaMac(rl) {
14518
14857
 
14519
14858
  `);
14520
14859
  try {
14521
- execSync13("brew install ollama", {
14860
+ execSync15("brew install ollama", {
14522
14861
  stdio: "inherit",
14523
14862
  timeout: 3e5
14524
14863
  });
@@ -14545,7 +14884,7 @@ function installOllamaWindows() {
14545
14884
 
14546
14885
  `);
14547
14886
  try {
14548
- execSync13('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
14887
+ execSync15('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
14549
14888
  stdio: "inherit",
14550
14889
  timeout: 3e5
14551
14890
  });
@@ -14568,7 +14907,7 @@ function installOllamaWindows() {
14568
14907
  }
14569
14908
  function pullModelWithAutoUpdate(tag) {
14570
14909
  try {
14571
- execSync13(`ollama pull ${tag}`, {
14910
+ execSync15(`ollama pull ${tag}`, {
14572
14911
  stdio: "inherit",
14573
14912
  timeout: 36e5
14574
14913
  // 1 hour max
@@ -14585,7 +14924,7 @@ function pullModelWithAutoUpdate(tag) {
14585
14924
 
14586
14925
  `);
14587
14926
  try {
14588
- execSync13("curl -fsSL https://ollama.com/install.sh | sh", {
14927
+ execSync15("curl -fsSL https://ollama.com/install.sh | sh", {
14589
14928
  stdio: "inherit",
14590
14929
  timeout: 3e5
14591
14930
  // 5 min max for install
@@ -14596,7 +14935,7 @@ function pullModelWithAutoUpdate(tag) {
14596
14935
  process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
14597
14936
 
14598
14937
  `);
14599
- execSync13(`ollama pull ${tag}`, {
14938
+ execSync15(`ollama pull ${tag}`, {
14600
14939
  stdio: "inherit",
14601
14940
  timeout: 36e5
14602
14941
  });
@@ -14779,7 +15118,7 @@ async function doSetup(config, rl) {
14779
15118
  try {
14780
15119
  const child = spawn8("ollama", ["serve"], { stdio: "ignore", detached: true });
14781
15120
  child.unref();
14782
- await new Promise((resolve19) => setTimeout(resolve19, 3e3));
15121
+ await new Promise((resolve21) => setTimeout(resolve21, 3e3));
14783
15122
  try {
14784
15123
  models = await fetchOllamaModels(config.backendUrl);
14785
15124
  process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
@@ -14807,7 +15146,7 @@ async function doSetup(config, rl) {
14807
15146
  try {
14808
15147
  const child = spawn8("ollama", ["serve"], { stdio: "ignore", detached: true });
14809
15148
  child.unref();
14810
- await new Promise((resolve19) => setTimeout(resolve19, 3e3));
15149
+ await new Promise((resolve21) => setTimeout(resolve21, 3e3));
14811
15150
  try {
14812
15151
  models = await fetchOllamaModels(config.backendUrl);
14813
15152
  process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
@@ -14961,12 +15300,12 @@ async function doSetup(config, rl) {
14961
15300
  `PARAMETER num_predict 16384`,
14962
15301
  `PARAMETER stop "<|endoftext|>"`
14963
15302
  ].join("\n");
14964
- const modelDir2 = join22(homedir8(), ".open-agents", "models");
15303
+ const modelDir2 = join23(homedir8(), ".open-agents", "models");
14965
15304
  mkdirSync7(modelDir2, { recursive: true });
14966
- const modelfilePath = join22(modelDir2, `Modelfile.${customName}`);
15305
+ const modelfilePath = join23(modelDir2, `Modelfile.${customName}`);
14967
15306
  writeFileSync7(modelfilePath, modelfileContent + "\n", "utf8");
14968
15307
  process.stdout.write(` ${c2.dim("Creating model...")} `);
14969
- execSync13(`ollama create ${customName} -f ${modelfilePath}`, {
15308
+ execSync15(`ollama create ${customName} -f ${modelfilePath}`, {
14970
15309
  stdio: "pipe",
14971
15310
  timeout: 12e4
14972
15311
  });
@@ -15009,20 +15348,32 @@ async function isModelAvailable(config) {
15009
15348
  }
15010
15349
  function isFirstRun() {
15011
15350
  try {
15012
- return !existsSync15(join22(homedir8(), ".open-agents", "config.json"));
15351
+ return !existsSync17(join23(homedir8(), ".open-agents", "config.json"));
15013
15352
  } catch {
15014
15353
  return true;
15015
15354
  }
15016
15355
  }
15017
15356
  function hasCmd(cmd) {
15018
15357
  try {
15019
- execSync13(`which ${cmd}`, { stdio: "pipe", timeout: 3e3 });
15358
+ const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
15359
+ execSync15(whichCmd, { stdio: "pipe", timeout: 3e3 });
15020
15360
  return true;
15021
15361
  } catch {
15022
15362
  return false;
15023
15363
  }
15024
15364
  }
15025
15365
  function detectPkgManager() {
15366
+ const plat = process.platform;
15367
+ if (plat === "win32") {
15368
+ if (hasCmd("choco"))
15369
+ return "choco";
15370
+ return null;
15371
+ }
15372
+ if (plat === "darwin") {
15373
+ if (hasCmd("brew"))
15374
+ return "brew";
15375
+ return null;
15376
+ }
15026
15377
  if (hasCmd("apt-get"))
15027
15378
  return "apt";
15028
15379
  if (hasCmd("dnf"))
@@ -15034,11 +15385,11 @@ function detectPkgManager() {
15034
15385
  return null;
15035
15386
  }
15036
15387
  function getVenvDir() {
15037
- return join22(homedir8(), ".open-agents", "venv");
15388
+ return join23(homedir8(), ".open-agents", "venv");
15038
15389
  }
15039
15390
  function hasVenvModule() {
15040
15391
  try {
15041
- execSync13("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
15392
+ execSync15("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
15042
15393
  return true;
15043
15394
  } catch {
15044
15395
  return false;
@@ -15046,8 +15397,8 @@ function hasVenvModule() {
15046
15397
  }
15047
15398
  function ensureVenv(log) {
15048
15399
  const venvDir = getVenvDir();
15049
- const venvPip = join22(venvDir, "bin", "pip");
15050
- if (existsSync15(venvPip))
15400
+ const venvPip = join23(venvDir, "bin", "pip");
15401
+ if (existsSync17(venvPip))
15051
15402
  return venvDir;
15052
15403
  log("Creating Python venv for vision deps...");
15053
15404
  if (!hasCmd("python3")) {
@@ -15059,9 +15410,9 @@ function ensureVenv(log) {
15059
15410
  return null;
15060
15411
  }
15061
15412
  try {
15062
- mkdirSync7(join22(homedir8(), ".open-agents"), { recursive: true });
15063
- execSync13(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
15064
- execSync13(`"${join22(venvDir, "bin", "pip")}" install --upgrade pip`, {
15413
+ mkdirSync7(join23(homedir8(), ".open-agents"), { recursive: true });
15414
+ execSync15(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
15415
+ execSync15(`"${join23(venvDir, "bin", "pip")}" install --upgrade pip`, {
15065
15416
  stdio: "pipe",
15066
15417
  timeout: 6e4
15067
15418
  });
@@ -15074,7 +15425,7 @@ function ensureVenv(log) {
15074
15425
  }
15075
15426
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
15076
15427
  try {
15077
- execSync13(`sudo -n ${cmd}`, {
15428
+ execSync15(`sudo -n ${cmd}`, {
15078
15429
  stdio: "pipe",
15079
15430
  timeout: timeoutMs,
15080
15431
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -15086,7 +15437,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
15086
15437
  }
15087
15438
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
15088
15439
  try {
15089
- execSync13(`sudo -S ${cmd}`, {
15440
+ execSync15(`sudo -S ${cmd}`, {
15090
15441
  input: password + "\n",
15091
15442
  stdio: ["pipe", "pipe", "pipe"],
15092
15443
  timeout: timeoutMs,
@@ -15131,7 +15482,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
15131
15482
  apt: { cmd: "apt-get install -y tesseract-ocr", needsSudo: true },
15132
15483
  dnf: { cmd: "dnf install -y tesseract", needsSudo: true },
15133
15484
  pacman: { cmd: "pacman -S --noconfirm tesseract", needsSudo: true },
15134
- brew: { cmd: "brew install tesseract", needsSudo: false }
15485
+ brew: { cmd: "brew install tesseract", needsSudo: false },
15486
+ choco: { cmd: "choco install -y tesseract", needsSudo: false }
15135
15487
  };
15136
15488
  const pkg = pkgMap[pm2];
15137
15489
  if (pkg.needsSudo) {
@@ -15145,7 +15497,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
15145
15497
  } else {
15146
15498
  log("Installing tesseract-ocr...");
15147
15499
  try {
15148
- execSync13(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
15500
+ execSync15(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
15149
15501
  if (hasCmd("tesseract")) {
15150
15502
  log("tesseract-ocr installed successfully.");
15151
15503
  } else {
@@ -15159,6 +15511,76 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
15159
15511
  log("No supported package manager detected \u2014 tesseract OCR unavailable.");
15160
15512
  }
15161
15513
  }
15514
+ const pdfDeps = [
15515
+ {
15516
+ binary: "pdftotext",
15517
+ label: "poppler-utils (pdftotext)",
15518
+ pkgMap: {
15519
+ apt: { cmd: "apt-get install -y poppler-utils", needsSudo: true },
15520
+ dnf: { cmd: "dnf install -y poppler-utils", needsSudo: true },
15521
+ pacman: { cmd: "pacman -S --noconfirm poppler", needsSudo: true },
15522
+ brew: { cmd: "brew install poppler", needsSudo: false },
15523
+ choco: { cmd: "choco install -y poppler", needsSudo: false }
15524
+ }
15525
+ },
15526
+ {
15527
+ binary: "gs",
15528
+ label: "ghostscript",
15529
+ pkgMap: {
15530
+ apt: { cmd: "apt-get install -y ghostscript", needsSudo: true },
15531
+ dnf: { cmd: "dnf install -y ghostscript", needsSudo: true },
15532
+ pacman: { cmd: "pacman -S --noconfirm ghostscript", needsSudo: true },
15533
+ brew: { cmd: "brew install ghostscript", needsSudo: false },
15534
+ choco: { cmd: "choco install -y ghostscript", needsSudo: false }
15535
+ }
15536
+ },
15537
+ {
15538
+ binary: "ocrmypdf",
15539
+ label: "ocrmypdf",
15540
+ pkgMap: {
15541
+ apt: { cmd: "apt-get install -y ocrmypdf", needsSudo: true },
15542
+ dnf: { cmd: "dnf install -y ocrmypdf", needsSudo: true },
15543
+ pacman: { cmd: "pacman -S --noconfirm ocrmypdf", needsSudo: true },
15544
+ brew: { cmd: "brew install ocrmypdf", needsSudo: false },
15545
+ choco: { cmd: "choco install -y ocrmypdf", needsSudo: false }
15546
+ }
15547
+ }
15548
+ ];
15549
+ {
15550
+ const pm2 = detectPkgManager();
15551
+ for (const dep of pdfDeps) {
15552
+ if (hasCmd(dep.binary))
15553
+ continue;
15554
+ if (!pm2) {
15555
+ log(`No supported package manager detected \u2014 ${dep.label} unavailable.`);
15556
+ continue;
15557
+ }
15558
+ const pkg = dep.pkgMap[pm2];
15559
+ if (!pkg)
15560
+ continue;
15561
+ if (pkg.needsSudo) {
15562
+ log(`Installing ${dep.label}...`);
15563
+ const ok = await sudoInstall(pkg.cmd, getPassword, log, cachedPasswordRef);
15564
+ if (ok && hasCmd(dep.binary)) {
15565
+ log(`${dep.label} installed successfully.`);
15566
+ } else {
15567
+ log(`${dep.label} could not be installed \u2014 PDF OCR features will be limited.`);
15568
+ }
15569
+ } else {
15570
+ log(`Installing ${dep.label}...`);
15571
+ try {
15572
+ execSync15(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
15573
+ if (hasCmd(dep.binary)) {
15574
+ log(`${dep.label} installed successfully.`);
15575
+ } else {
15576
+ log(`${dep.label} install completed but binary not found.`);
15577
+ }
15578
+ } catch {
15579
+ log(`${dep.label} could not be installed \u2014 PDF OCR features will be limited.`);
15580
+ }
15581
+ }
15582
+ }
15583
+ }
15162
15584
  const pm = detectPkgManager();
15163
15585
  if (!hasCmd("pip3") && !hasCmd("pip") && pm) {
15164
15586
  const pipCmds = {
@@ -15178,7 +15600,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
15178
15600
  const venvCmds = {
15179
15601
  apt: () => {
15180
15602
  try {
15181
- const pyVer = execSync13(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
15603
+ const pyVer = execSync15(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
15182
15604
  return `apt-get install -y python3-venv python${pyVer}-venv`;
15183
15605
  } catch {
15184
15606
  return "apt-get install -y python3-venv";
@@ -15199,9 +15621,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
15199
15621
  }
15200
15622
  }
15201
15623
  const venvDir = getVenvDir();
15202
- const venvBin = join22(venvDir, "bin");
15203
- const venvMoondream = join22(venvBin, "moondream-station");
15204
- if (hasCmd("moondream-station") || existsSync15(venvMoondream)) {
15624
+ const venvBin = join23(venvDir, "bin");
15625
+ const venvMoondream = join23(venvBin, "moondream-station");
15626
+ if (hasCmd("moondream-station") || existsSync17(venvMoondream)) {
15205
15627
  return;
15206
15628
  }
15207
15629
  const venv = ensureVenv(log);
@@ -15209,15 +15631,15 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
15209
15631
  log("Python venv unavailable \u2014 moondream-station will not be installed.");
15210
15632
  return;
15211
15633
  }
15212
- const venvPip = join22(venvBin, "pip");
15634
+ const venvPip = join23(venvBin, "pip");
15213
15635
  log("Installing moondream-station in ~/.open-agents/venv...");
15214
15636
  try {
15215
- execSync13(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
15216
- if (existsSync15(venvMoondream)) {
15637
+ execSync15(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
15638
+ if (existsSync17(venvMoondream)) {
15217
15639
  log("moondream-station installed successfully.");
15218
15640
  } else {
15219
15641
  try {
15220
- const check = execSync13(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
15642
+ const check = execSync15(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
15221
15643
  if (check.includes("moondream")) {
15222
15644
  log("moondream-station package installed.");
15223
15645
  }
@@ -15262,11 +15684,11 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
15262
15684
  `PARAMETER num_predict 16384`,
15263
15685
  `PARAMETER stop "<|endoftext|>"`
15264
15686
  ].join("\n");
15265
- const modelDir2 = join22(homedir8(), ".open-agents", "models");
15687
+ const modelDir2 = join23(homedir8(), ".open-agents", "models");
15266
15688
  mkdirSync7(modelDir2, { recursive: true });
15267
- const modelfilePath = join22(modelDir2, `Modelfile.${customName}`);
15689
+ const modelfilePath = join23(modelDir2, `Modelfile.${customName}`);
15268
15690
  writeFileSync7(modelfilePath, modelfileContent + "\n", "utf8");
15269
- execSync13(`ollama create ${customName} -f ${modelfilePath}`, {
15691
+ execSync15(`ollama create ${customName} -f ${modelfilePath}`, {
15270
15692
  stdio: "pipe",
15271
15693
  timeout: 12e4
15272
15694
  });
@@ -15954,17 +16376,17 @@ async function handleUpdate(subcommand, ctx) {
15954
16376
  try {
15955
16377
  const { createRequire: createRequire4 } = await import("node:module");
15956
16378
  const { fileURLToPath: fileURLToPath7 } = await import("node:url");
15957
- const { dirname: dirname10, join: join33 } = await import("node:path");
15958
- const { existsSync: existsSync22 } = await import("node:fs");
16379
+ const { dirname: dirname10, join: join34 } = await import("node:path");
16380
+ const { existsSync: existsSync24 } = await import("node:fs");
15959
16381
  const req = createRequire4(import.meta.url);
15960
16382
  const thisDir = dirname10(fileURLToPath7(import.meta.url));
15961
16383
  const candidates = [
15962
- join33(thisDir, "..", "package.json"),
15963
- join33(thisDir, "..", "..", "package.json"),
15964
- join33(thisDir, "..", "..", "..", "package.json")
16384
+ join34(thisDir, "..", "package.json"),
16385
+ join34(thisDir, "..", "..", "package.json"),
16386
+ join34(thisDir, "..", "..", "..", "package.json")
15965
16387
  ];
15966
16388
  for (const pkgPath of candidates) {
15967
- if (existsSync22(pkgPath)) {
16389
+ if (existsSync24(pkgPath)) {
15968
16390
  const pkg = req(pkgPath);
15969
16391
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
15970
16392
  currentVersion = pkg.version ?? "0.0.0";
@@ -15989,9 +16411,9 @@ async function handleUpdate(subcommand, ctx) {
15989
16411
  process.stdout.write(` ${c2.cyan("\u25CF")} Installing update...
15990
16412
 
15991
16413
  `);
15992
- const { execSync: execSync17 } = await import("node:child_process");
16414
+ const { execSync: execSync19 } = await import("node:child_process");
15993
16415
  try {
15994
- execSync17(`npm cache clean --force open-agents-ai 2>/dev/null; npm install -g open-agents-ai@latest --force`, { stdio: "pipe", timeout: 18e4 });
16416
+ execSync19(`npm cache clean --force open-agents-ai 2>/dev/null; npm install -g open-agents-ai@latest --force`, { stdio: "pipe", timeout: 18e4 });
15995
16417
  } catch {
15996
16418
  renderWarning("Update install failed. Try manually: npm i -g open-agents-ai");
15997
16419
  return;
@@ -16078,9 +16500,9 @@ var init_commands = __esm({
16078
16500
  });
16079
16501
 
16080
16502
  // packages/cli/dist/tui/project-context.js
16081
- import { existsSync as existsSync16, readFileSync as readFileSync13, readdirSync as readdirSync8 } from "node:fs";
16082
- import { join as join23, basename as basename6 } from "node:path";
16083
- import { execSync as execSync14 } from "node:child_process";
16503
+ import { existsSync as existsSync18, readFileSync as readFileSync14, readdirSync as readdirSync8 } from "node:fs";
16504
+ import { join as join24, basename as basename8 } from "node:path";
16505
+ import { execSync as execSync16 } from "node:child_process";
16084
16506
  import { homedir as homedir9, platform as platform2, release } from "node:os";
16085
16507
  function getModelTier(modelName) {
16086
16508
  const m = modelName.toLowerCase();
@@ -16114,10 +16536,10 @@ function loadProjectMap(repoRoot) {
16114
16536
  if (!hasOaDirectory(repoRoot)) {
16115
16537
  initOaDirectory(repoRoot);
16116
16538
  }
16117
- const mapPath = join23(repoRoot, OA_DIR, "context", "project-map.md");
16118
- if (existsSync16(mapPath)) {
16539
+ const mapPath = join24(repoRoot, OA_DIR, "context", "project-map.md");
16540
+ if (existsSync18(mapPath)) {
16119
16541
  try {
16120
- const content = readFileSync13(mapPath, "utf-8");
16542
+ const content = readFileSync14(mapPath, "utf-8");
16121
16543
  return content;
16122
16544
  } catch {
16123
16545
  }
@@ -16126,19 +16548,19 @@ function loadProjectMap(repoRoot) {
16126
16548
  }
16127
16549
  function getGitInfo(repoRoot) {
16128
16550
  try {
16129
- execSync14("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
16551
+ execSync16("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
16130
16552
  } catch {
16131
16553
  return "";
16132
16554
  }
16133
16555
  const lines = [];
16134
16556
  try {
16135
- const branch = execSync14("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16557
+ const branch = execSync16("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16136
16558
  if (branch)
16137
16559
  lines.push(`Branch: ${branch}`);
16138
16560
  } catch {
16139
16561
  }
16140
16562
  try {
16141
- const status = execSync14("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16563
+ const status = execSync16("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16142
16564
  if (status) {
16143
16565
  const changed = status.split("\n").length;
16144
16566
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -16148,7 +16570,7 @@ function getGitInfo(repoRoot) {
16148
16570
  } catch {
16149
16571
  }
16150
16572
  try {
16151
- const log = execSync14("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16573
+ const log = execSync16("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16152
16574
  if (log)
16153
16575
  lines.push(`Recent commits:
16154
16576
  ${log}`);
@@ -16158,33 +16580,33 @@ ${log}`);
16158
16580
  }
16159
16581
  function loadMemoryContext(repoRoot) {
16160
16582
  const sections = [];
16161
- const oaMemDir = join23(repoRoot, OA_DIR, "memory");
16583
+ const oaMemDir = join24(repoRoot, OA_DIR, "memory");
16162
16584
  const oaEntries = loadMemoryDir(oaMemDir, "project");
16163
16585
  if (oaEntries)
16164
16586
  sections.push(oaEntries);
16165
- const legacyMemDir = join23(repoRoot, ".open-agents", "memory");
16166
- if (legacyMemDir !== oaMemDir && existsSync16(legacyMemDir)) {
16587
+ const legacyMemDir = join24(repoRoot, ".open-agents", "memory");
16588
+ if (legacyMemDir !== oaMemDir && existsSync18(legacyMemDir)) {
16167
16589
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
16168
16590
  if (legacyEntries)
16169
16591
  sections.push(legacyEntries);
16170
16592
  }
16171
- const globalMemDir = join23(homedir9(), ".open-agents", "memory");
16593
+ const globalMemDir = join24(homedir9(), ".open-agents", "memory");
16172
16594
  const globalEntries = loadMemoryDir(globalMemDir, "global");
16173
16595
  if (globalEntries)
16174
16596
  sections.push(globalEntries);
16175
16597
  return sections.join("\n\n");
16176
16598
  }
16177
16599
  function loadMemoryDir(memDir, scope) {
16178
- if (!existsSync16(memDir))
16600
+ if (!existsSync18(memDir))
16179
16601
  return "";
16180
16602
  const lines = [];
16181
16603
  try {
16182
16604
  const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
16183
16605
  for (const file of files.slice(0, 10)) {
16184
16606
  try {
16185
- const raw = readFileSync13(join23(memDir, file), "utf-8");
16607
+ const raw = readFileSync14(join24(memDir, file), "utf-8");
16186
16608
  const entries = JSON.parse(raw);
16187
- const topic = basename6(file, ".json");
16609
+ const topic = basename8(file, ".json");
16188
16610
  const keys = Object.keys(entries);
16189
16611
  if (keys.length === 0)
16190
16612
  continue;
@@ -17209,22 +17631,22 @@ var init_carousel = __esm({
17209
17631
  });
17210
17632
 
17211
17633
  // packages/cli/dist/tui/carousel-descriptors.js
17212
- import { existsSync as existsSync17, readFileSync as readFileSync14, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, readdirSync as readdirSync9 } from "node:fs";
17213
- import { join as join24, basename as basename7 } from "node:path";
17634
+ import { existsSync as existsSync19, readFileSync as readFileSync15, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, readdirSync as readdirSync9 } from "node:fs";
17635
+ import { join as join25, basename as basename9 } from "node:path";
17214
17636
  function loadToolProfile(repoRoot) {
17215
- const filePath = join24(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
17637
+ const filePath = join25(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
17216
17638
  try {
17217
- if (!existsSync17(filePath))
17639
+ if (!existsSync19(filePath))
17218
17640
  return null;
17219
- return JSON.parse(readFileSync14(filePath, "utf-8"));
17641
+ return JSON.parse(readFileSync15(filePath, "utf-8"));
17220
17642
  } catch {
17221
17643
  return null;
17222
17644
  }
17223
17645
  }
17224
17646
  function saveToolProfile(repoRoot, profile) {
17225
- const contextDir = join24(repoRoot, OA_DIR, "context");
17647
+ const contextDir = join25(repoRoot, OA_DIR, "context");
17226
17648
  mkdirSync8(contextDir, { recursive: true });
17227
- writeFileSync8(join24(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
17649
+ writeFileSync8(join25(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
17228
17650
  }
17229
17651
  function categorizeToolCall(toolName) {
17230
17652
  for (const cat of TOOL_CATEGORIES) {
@@ -17282,25 +17704,25 @@ function weightedColor(profile) {
17282
17704
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
17283
17705
  }
17284
17706
  function loadCachedDescriptors(repoRoot) {
17285
- const filePath = join24(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
17707
+ const filePath = join25(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
17286
17708
  try {
17287
- if (!existsSync17(filePath))
17709
+ if (!existsSync19(filePath))
17288
17710
  return null;
17289
- const cached = JSON.parse(readFileSync14(filePath, "utf-8"));
17711
+ const cached = JSON.parse(readFileSync15(filePath, "utf-8"));
17290
17712
  return cached.phrases.length > 0 ? cached.phrases : null;
17291
17713
  } catch {
17292
17714
  return null;
17293
17715
  }
17294
17716
  }
17295
17717
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
17296
- const contextDir = join24(repoRoot, OA_DIR, "context");
17718
+ const contextDir = join25(repoRoot, OA_DIR, "context");
17297
17719
  mkdirSync8(contextDir, { recursive: true });
17298
17720
  const cached = {
17299
17721
  phrases,
17300
17722
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
17301
17723
  sourceHash
17302
17724
  };
17303
- writeFileSync8(join24(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
17725
+ writeFileSync8(join25(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
17304
17726
  }
17305
17727
  function generateDescriptors(repoRoot) {
17306
17728
  const profile = loadToolProfile(repoRoot);
@@ -17311,7 +17733,7 @@ function generateDescriptors(repoRoot) {
17311
17733
  extractFromSessions(repoRoot, tags);
17312
17734
  extractFromMemory(repoRoot, tags);
17313
17735
  extractFromToolProfile(profile, tags);
17314
- const repoName2 = basename7(repoRoot);
17736
+ const repoName2 = basename9(repoRoot);
17315
17737
  if (repoName2 && !tags.includes(repoName2)) {
17316
17738
  tags.push(repoName2);
17317
17739
  }
@@ -17348,11 +17770,11 @@ function generateDescriptors(repoRoot) {
17348
17770
  return phrases;
17349
17771
  }
17350
17772
  function extractFromPackageJson(repoRoot, tags) {
17351
- const pkgPath = join24(repoRoot, "package.json");
17773
+ const pkgPath = join25(repoRoot, "package.json");
17352
17774
  try {
17353
- if (!existsSync17(pkgPath))
17775
+ if (!existsSync19(pkgPath))
17354
17776
  return;
17355
- const pkg = JSON.parse(readFileSync14(pkgPath, "utf-8"));
17777
+ const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
17356
17778
  if (pkg.name && typeof pkg.name === "string") {
17357
17779
  const parts = pkg.name.replace(/^@/, "").split("/");
17358
17780
  for (const p of parts)
@@ -17396,7 +17818,7 @@ function extractFromManifests(repoRoot, tags) {
17396
17818
  { file: ".github/workflows", tag: "ci/cd" }
17397
17819
  ];
17398
17820
  for (const check of manifestChecks) {
17399
- if (existsSync17(join24(repoRoot, check.file))) {
17821
+ if (existsSync19(join25(repoRoot, check.file))) {
17400
17822
  tags.push(check.tag);
17401
17823
  }
17402
17824
  }
@@ -17418,16 +17840,16 @@ function extractFromSessions(repoRoot, tags) {
17418
17840
  }
17419
17841
  }
17420
17842
  function extractFromMemory(repoRoot, tags) {
17421
- const memoryDir = join24(repoRoot, OA_DIR, "memory");
17843
+ const memoryDir = join25(repoRoot, OA_DIR, "memory");
17422
17844
  try {
17423
- if (!existsSync17(memoryDir))
17845
+ if (!existsSync19(memoryDir))
17424
17846
  return;
17425
17847
  const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
17426
17848
  for (const file of files) {
17427
17849
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
17428
17850
  tags.push(topic);
17429
17851
  try {
17430
- const data = JSON.parse(readFileSync14(join24(memoryDir, file), "utf-8"));
17852
+ const data = JSON.parse(readFileSync15(join25(memoryDir, file), "utf-8"));
17431
17853
  if (data && typeof data === "object") {
17432
17854
  const keys = Object.keys(data).slice(0, 3);
17433
17855
  for (const key of keys) {
@@ -17562,25 +17984,25 @@ var init_carousel_descriptors = __esm({
17562
17984
  });
17563
17985
 
17564
17986
  // packages/cli/dist/tui/voice.js
17565
- import { existsSync as existsSync18, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync15, unlinkSync as unlinkSync3 } from "node:fs";
17566
- import { join as join25 } from "node:path";
17567
- import { homedir as homedir10, tmpdir as tmpdir4, platform as platform3 } from "node:os";
17568
- import { execSync as execSync15, spawn as nodeSpawn } from "node:child_process";
17987
+ import { existsSync as existsSync20, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync16, unlinkSync as unlinkSync4 } from "node:fs";
17988
+ import { join as join26 } from "node:path";
17989
+ import { homedir as homedir10, tmpdir as tmpdir5, platform as platform3 } from "node:os";
17990
+ import { execSync as execSync17, spawn as nodeSpawn } from "node:child_process";
17569
17991
  import { createRequire } from "node:module";
17570
17992
  function voiceDir() {
17571
- return join25(homedir10(), ".open-agents", "voice");
17993
+ return join26(homedir10(), ".open-agents", "voice");
17572
17994
  }
17573
17995
  function modelsDir() {
17574
- return join25(voiceDir(), "models");
17996
+ return join26(voiceDir(), "models");
17575
17997
  }
17576
17998
  function modelDir(id) {
17577
- return join25(modelsDir(), id);
17999
+ return join26(modelsDir(), id);
17578
18000
  }
17579
18001
  function modelOnnxPath(id) {
17580
- return join25(modelDir(id), "model.onnx");
18002
+ return join26(modelDir(id), "model.onnx");
17581
18003
  }
17582
18004
  function modelConfigPath(id) {
17583
- return join25(modelDir(id), "config.json");
18005
+ return join26(modelDir(id), "config.json");
17584
18006
  }
17585
18007
  function describeToolCall(toolName, args) {
17586
18008
  const path = args["path"];
@@ -17853,11 +18275,11 @@ var init_voice = __esm({
17853
18275
  const audioData = result["output"].data;
17854
18276
  if (audioData.length === 0)
17855
18277
  return;
17856
- const wavPath = join25(tmpdir4(), `oa-voice-${Date.now()}.wav`);
18278
+ const wavPath = join26(tmpdir5(), `oa-voice-${Date.now()}.wav`);
17857
18279
  this.writeWav(audioData, this.config.audio.sample_rate, wavPath);
17858
18280
  await this.playWav(wavPath);
17859
18281
  try {
17860
- unlinkSync3(wavPath);
18282
+ unlinkSync4(wavPath);
17861
18283
  } catch {
17862
18284
  }
17863
18285
  }
@@ -17942,7 +18364,7 @@ var init_voice = __esm({
17942
18364
  const cmd = this.getPlayCommand(path);
17943
18365
  if (!cmd)
17944
18366
  return;
17945
- return new Promise((resolve19) => {
18367
+ return new Promise((resolve21) => {
17946
18368
  const child = nodeSpawn(cmd[0], cmd.slice(1), {
17947
18369
  stdio: "ignore",
17948
18370
  detached: false
@@ -17951,12 +18373,12 @@ var init_voice = __esm({
17951
18373
  child.on("close", () => {
17952
18374
  if (this.currentPlayback === child)
17953
18375
  this.currentPlayback = null;
17954
- resolve19();
18376
+ resolve21();
17955
18377
  });
17956
18378
  child.on("error", () => {
17957
18379
  if (this.currentPlayback === child)
17958
18380
  this.currentPlayback = null;
17959
- resolve19();
18381
+ resolve21();
17960
18382
  });
17961
18383
  setTimeout(() => {
17962
18384
  if (this.currentPlayback === child) {
@@ -17966,7 +18388,7 @@ var init_voice = __esm({
17966
18388
  }
17967
18389
  this.currentPlayback = null;
17968
18390
  }
17969
- resolve19();
18391
+ resolve21();
17970
18392
  }, 15e3);
17971
18393
  });
17972
18394
  }
@@ -17983,7 +18405,7 @@ var init_voice = __esm({
17983
18405
  }
17984
18406
  for (const player of ["paplay", "pw-play", "aplay"]) {
17985
18407
  try {
17986
- execSync15(`which ${player}`, { stdio: "pipe" });
18408
+ execSync17(`which ${player}`, { stdio: "pipe" });
17987
18409
  return [player, path];
17988
18410
  } catch {
17989
18411
  }
@@ -18008,14 +18430,14 @@ var init_voice = __esm({
18008
18430
  const arch = process.arch;
18009
18431
  const isArmLinux = (arch === "arm64" || arch === "arm") && process.platform === "linux";
18010
18432
  mkdirSync9(voiceDir(), { recursive: true });
18011
- const pkgPath = join25(voiceDir(), "package.json");
18433
+ const pkgPath = join26(voiceDir(), "package.json");
18012
18434
  const expectedDeps = {
18013
18435
  "onnxruntime-node": "^1.21.0",
18014
18436
  "phonemizer": "^1.2.1"
18015
18437
  };
18016
- if (existsSync18(pkgPath)) {
18438
+ if (existsSync20(pkgPath)) {
18017
18439
  try {
18018
- const existing = JSON.parse(readFileSync15(pkgPath, "utf8"));
18440
+ const existing = JSON.parse(readFileSync16(pkgPath, "utf8"));
18019
18441
  if (!existing.dependencies?.["phonemizer"]) {
18020
18442
  existing.dependencies = { ...existing.dependencies, ...expectedDeps };
18021
18443
  writeFileSync9(pkgPath, JSON.stringify(existing, null, 2));
@@ -18023,14 +18445,14 @@ var init_voice = __esm({
18023
18445
  } catch {
18024
18446
  }
18025
18447
  }
18026
- if (!existsSync18(pkgPath)) {
18448
+ if (!existsSync20(pkgPath)) {
18027
18449
  writeFileSync9(pkgPath, JSON.stringify({
18028
18450
  name: "open-agents-voice",
18029
18451
  private: true,
18030
18452
  dependencies: expectedDeps
18031
18453
  }, null, 2));
18032
18454
  }
18033
- const voiceRequire = createRequire(join25(voiceDir(), "index.js"));
18455
+ const voiceRequire = createRequire(join26(voiceDir(), "index.js"));
18034
18456
  try {
18035
18457
  this.ort = voiceRequire("onnxruntime-node");
18036
18458
  } catch {
@@ -18039,7 +18461,7 @@ var init_voice = __esm({
18039
18461
  }
18040
18462
  renderInfo("Installing ONNX runtime for voice synthesis...");
18041
18463
  try {
18042
- execSync15("npm install --no-audit --no-fund", {
18464
+ execSync17("npm install --no-audit --no-fund", {
18043
18465
  cwd: voiceDir(),
18044
18466
  stdio: "pipe",
18045
18467
  timeout: 12e4
@@ -18060,7 +18482,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
18060
18482
  }
18061
18483
  renderInfo("Installing phonemizer for voice synthesis...");
18062
18484
  try {
18063
- execSync15("npm install --no-audit --no-fund", {
18485
+ execSync17("npm install --no-audit --no-fund", {
18064
18486
  cwd: voiceDir(),
18065
18487
  stdio: "pipe",
18066
18488
  timeout: 12e4
@@ -18084,10 +18506,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
18084
18506
  const dir = modelDir(id);
18085
18507
  const onnxPath = modelOnnxPath(id);
18086
18508
  const configPath = modelConfigPath(id);
18087
- if (existsSync18(onnxPath) && existsSync18(configPath))
18509
+ if (existsSync20(onnxPath) && existsSync20(configPath))
18088
18510
  return;
18089
18511
  mkdirSync9(dir, { recursive: true });
18090
- if (!existsSync18(configPath)) {
18512
+ if (!existsSync20(configPath)) {
18091
18513
  renderInfo(`Downloading ${model.label} voice config...`);
18092
18514
  const configResp = await fetch(model.configUrl);
18093
18515
  if (!configResp.ok)
@@ -18095,7 +18517,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
18095
18517
  const configText = await configResp.text();
18096
18518
  writeFileSync9(configPath, configText);
18097
18519
  }
18098
- if (!existsSync18(onnxPath)) {
18520
+ if (!existsSync20(onnxPath)) {
18099
18521
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
18100
18522
  const onnxResp = await fetch(model.onnxUrl);
18101
18523
  if (!onnxResp.ok)
@@ -18131,10 +18553,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
18131
18553
  throw new Error("ONNX runtime not loaded");
18132
18554
  const onnxPath = modelOnnxPath(this.modelId);
18133
18555
  const configPath = modelConfigPath(this.modelId);
18134
- if (!existsSync18(onnxPath) || !existsSync18(configPath)) {
18556
+ if (!existsSync20(onnxPath) || !existsSync20(configPath)) {
18135
18557
  throw new Error(`Model files not found for ${this.modelId}`);
18136
18558
  }
18137
- this.config = JSON.parse(readFileSync15(configPath, "utf8"));
18559
+ this.config = JSON.parse(readFileSync16(configPath, "utf8"));
18138
18560
  renderInfo("Loading voice model...");
18139
18561
  this.session = await this.ort.InferenceSession.create(onnxPath, {
18140
18562
  executionProviders: ["cpu"],
@@ -18635,10 +19057,10 @@ var init_stream_renderer = __esm({
18635
19057
 
18636
19058
  // packages/cli/dist/tui/edit-history.js
18637
19059
  import { appendFileSync, mkdirSync as mkdirSync10 } from "node:fs";
18638
- import { join as join26 } from "node:path";
19060
+ import { join as join27 } from "node:path";
18639
19061
  function createEditHistoryLogger(repoRoot, sessionId) {
18640
- const historyDir = join26(repoRoot, ".oa", "history");
18641
- const logPath = join26(historyDir, "edits.jsonl");
19062
+ const historyDir = join27(repoRoot, ".oa", "history");
19063
+ const logPath = join27(historyDir, "edits.jsonl");
18642
19064
  try {
18643
19065
  mkdirSync10(historyDir, { recursive: true });
18644
19066
  } catch {
@@ -18749,9 +19171,9 @@ var init_edit_history = __esm({
18749
19171
  });
18750
19172
 
18751
19173
  // packages/cli/dist/tui/dream-engine.js
18752
- import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, readFileSync as readFileSync16, existsSync as existsSync19, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
18753
- import { join as join27, basename as basename8 } from "node:path";
18754
- import { execSync as execSync16 } from "node:child_process";
19174
+ import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, readFileSync as readFileSync17, existsSync as existsSync21, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
19175
+ import { join as join28, basename as basename10 } from "node:path";
19176
+ import { execSync as execSync18 } from "node:child_process";
18755
19177
  function adaptTool(tool) {
18756
19178
  return {
18757
19179
  name: tool.name,
@@ -18925,12 +19347,12 @@ var init_dream_engine = __esm({
18925
19347
  const content = String(args["content"] ?? "");
18926
19348
  if (!rawPath)
18927
19349
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
18928
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join27(this.dreamsDir, basename8(rawPath)) : join27(this.dreamsDir, rawPath);
19350
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join28(this.dreamsDir, basename10(rawPath)) : join28(this.dreamsDir, rawPath);
18929
19351
  if (!targetPath.startsWith(this.dreamsDir)) {
18930
19352
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
18931
19353
  }
18932
19354
  try {
18933
- const dir = join27(targetPath, "..");
19355
+ const dir = join28(targetPath, "..");
18934
19356
  mkdirSync11(dir, { recursive: true });
18935
19357
  writeFileSync10(targetPath, content, "utf-8");
18936
19358
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -18960,15 +19382,15 @@ var init_dream_engine = __esm({
18960
19382
  const rawPath = String(args["path"] ?? "");
18961
19383
  const oldStr = String(args["old_string"] ?? "");
18962
19384
  const newStr = String(args["new_string"] ?? "");
18963
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join27(this.dreamsDir, basename8(rawPath)) : join27(this.dreamsDir, rawPath);
19385
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join28(this.dreamsDir, basename10(rawPath)) : join28(this.dreamsDir, rawPath);
18964
19386
  if (!targetPath.startsWith(this.dreamsDir)) {
18965
19387
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
18966
19388
  }
18967
19389
  try {
18968
- if (!existsSync19(targetPath)) {
19390
+ if (!existsSync21(targetPath)) {
18969
19391
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
18970
19392
  }
18971
- let content = readFileSync16(targetPath, "utf-8");
19393
+ let content = readFileSync17(targetPath, "utf-8");
18972
19394
  if (!content.includes(oldStr)) {
18973
19395
  return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
18974
19396
  }
@@ -19004,7 +19426,7 @@ var init_dream_engine = __esm({
19004
19426
  }
19005
19427
  }
19006
19428
  try {
19007
- const output = execSync16(cmd, {
19429
+ const output = execSync18(cmd, {
19008
19430
  cwd: this.repoRoot,
19009
19431
  timeout: 3e4,
19010
19432
  encoding: "utf-8",
@@ -19027,7 +19449,7 @@ var init_dream_engine = __esm({
19027
19449
  constructor(config, repoRoot) {
19028
19450
  this.config = config;
19029
19451
  this.repoRoot = repoRoot;
19030
- this.dreamsDir = join27(repoRoot, ".oa", "dreams");
19452
+ this.dreamsDir = join28(repoRoot, ".oa", "dreams");
19031
19453
  this.state = {
19032
19454
  mode: "default",
19033
19455
  active: false,
@@ -19099,7 +19521,7 @@ ${result.summary}`;
19099
19521
  if (mode !== "default" || cycle === totalCycles) {
19100
19522
  renderDreamContraction(cycle);
19101
19523
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
19102
- const summaryPath = join27(this.dreamsDir, `cycle-${cycle}-summary.md`);
19524
+ const summaryPath = join28(this.dreamsDir, `cycle-${cycle}-summary.md`);
19103
19525
  writeFileSync10(summaryPath, cycleSummary, "utf-8");
19104
19526
  }
19105
19527
  if (mode === "lucid" && !this.abortController.signal.aborted) {
@@ -19222,29 +19644,29 @@ Dreams directory: ${this.dreamsDir}`);
19222
19644
  }
19223
19645
  /** Save workspace backup for lucid mode */
19224
19646
  saveVersionCheckpoint(cycle) {
19225
- const checkpointDir = join27(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
19647
+ const checkpointDir = join28(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
19226
19648
  try {
19227
19649
  mkdirSync11(checkpointDir, { recursive: true });
19228
19650
  try {
19229
- const gitStatus = execSync16("git status --porcelain", {
19651
+ const gitStatus = execSync18("git status --porcelain", {
19230
19652
  cwd: this.repoRoot,
19231
19653
  encoding: "utf-8",
19232
19654
  timeout: 1e4
19233
19655
  });
19234
- const gitDiff = execSync16("git diff", {
19656
+ const gitDiff = execSync18("git diff", {
19235
19657
  cwd: this.repoRoot,
19236
19658
  encoding: "utf-8",
19237
19659
  timeout: 1e4
19238
19660
  });
19239
- const gitHash = execSync16("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
19661
+ const gitHash = execSync18("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
19240
19662
  cwd: this.repoRoot,
19241
19663
  encoding: "utf-8",
19242
19664
  timeout: 5e3
19243
19665
  }).trim();
19244
- writeFileSync10(join27(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
19245
- writeFileSync10(join27(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
19246
- writeFileSync10(join27(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
19247
- writeFileSync10(join27(checkpointDir, "checkpoint.json"), JSON.stringify({
19666
+ writeFileSync10(join28(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
19667
+ writeFileSync10(join28(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
19668
+ writeFileSync10(join28(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
19669
+ writeFileSync10(join28(checkpointDir, "checkpoint.json"), JSON.stringify({
19248
19670
  cycle,
19249
19671
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
19250
19672
  gitHash,
@@ -19252,7 +19674,7 @@ Dreams directory: ${this.dreamsDir}`);
19252
19674
  }, null, 2), "utf-8");
19253
19675
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
19254
19676
  } catch {
19255
- writeFileSync10(join27(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
19677
+ writeFileSync10(join28(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
19256
19678
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
19257
19679
  }
19258
19680
  } catch (err) {
@@ -19310,14 +19732,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
19310
19732
  ---
19311
19733
  *Auto-generated by open-agents dream engine*
19312
19734
  `;
19313
- writeFileSync10(join27(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
19735
+ writeFileSync10(join28(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
19314
19736
  } catch {
19315
19737
  }
19316
19738
  }
19317
19739
  /** Save dream state for resume/inspection */
19318
19740
  saveDreamState() {
19319
19741
  try {
19320
- writeFileSync10(join27(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
19742
+ writeFileSync10(join28(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
19321
19743
  } catch {
19322
19744
  }
19323
19745
  }
@@ -20149,22 +20571,22 @@ var init_status_bar = __esm({
20149
20571
  import * as readline2 from "node:readline";
20150
20572
  import { Writable } from "node:stream";
20151
20573
  import { cwd } from "node:process";
20152
- import { resolve as resolve16, join as join28, dirname as dirname8, extname as extname9 } from "node:path";
20574
+ import { resolve as resolve18, join as join29, dirname as dirname8, extname as extname9 } from "node:path";
20153
20575
  import { createRequire as createRequire2 } from "node:module";
20154
20576
  import { fileURLToPath as fileURLToPath5 } from "node:url";
20155
- import { readFileSync as readFileSync17 } from "node:fs";
20156
- import { existsSync as existsSync20 } from "node:fs";
20577
+ import { readFileSync as readFileSync18 } from "node:fs";
20578
+ import { existsSync as existsSync22 } from "node:fs";
20157
20579
  function getVersion() {
20158
20580
  try {
20159
20581
  const require2 = createRequire2(import.meta.url);
20160
20582
  const thisDir = dirname8(fileURLToPath5(import.meta.url));
20161
20583
  const candidates = [
20162
- join28(thisDir, "..", "package.json"),
20163
- join28(thisDir, "..", "..", "package.json"),
20164
- join28(thisDir, "..", "..", "..", "package.json")
20584
+ join29(thisDir, "..", "package.json"),
20585
+ join29(thisDir, "..", "..", "package.json"),
20586
+ join29(thisDir, "..", "..", "..", "package.json")
20165
20587
  ];
20166
20588
  for (const pkgPath of candidates) {
20167
- if (existsSync20(pkgPath)) {
20589
+ if (existsSync22(pkgPath)) {
20168
20590
  const pkg = require2(pkgPath);
20169
20591
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
20170
20592
  return pkg.version ?? "0.0.0";
@@ -20254,7 +20676,10 @@ function buildTools(repoRoot, config) {
20254
20676
  // Vision tools (Moondream — desktop awareness + point-and-click)
20255
20677
  new VisionTool(repoRoot),
20256
20678
  new DesktopClickTool(repoRoot),
20257
- new DesktopDescribeTool(repoRoot)
20679
+ new DesktopDescribeTool(repoRoot),
20680
+ // PDF tools (OCR + text extraction)
20681
+ new OcrPdfTool(repoRoot),
20682
+ new PdfToTextTool(repoRoot)
20258
20683
  ];
20259
20684
  return [
20260
20685
  ...executionTools.map(adaptTool2),
@@ -20558,7 +20983,7 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
20558
20983
  } };
20559
20984
  }
20560
20985
  async function startInteractive(config, repoPath) {
20561
- const repoRoot = resolve16(repoPath ?? cwd());
20986
+ const repoRoot = resolve18(repoPath ?? cwd());
20562
20987
  const resumeFlag = process.env.__OA_RESUMED ?? "";
20563
20988
  const isResumed = resumeFlag !== "";
20564
20989
  const hasTaskToResume = resumeFlag === "1";
@@ -20710,14 +21135,14 @@ async function startInteractive(config, repoPath) {
20710
21135
  renderInfo(msg);
20711
21136
  statusBar.endContentWrite();
20712
21137
  }
20713
- }, () => new Promise((resolve19) => {
21138
+ }, () => new Promise((resolve21) => {
20714
21139
  depSudoPromptPending = true;
20715
21140
  depSudoResolver = (pw) => {
20716
21141
  depSudoPromptPending = false;
20717
21142
  depSudoResolver = null;
20718
21143
  if (pw)
20719
21144
  sessionSudoPassword = pw;
20720
- resolve19(pw);
21145
+ resolve21(pw);
20721
21146
  };
20722
21147
  if (statusBar?.isActive) {
20723
21148
  statusBar.beginContentWrite();
@@ -21229,13 +21654,13 @@ Execute this skill now. Follow the behavioral guidance above.`;
21229
21654
  }
21230
21655
  }
21231
21656
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
21232
- const isImage = isImagePath(cleanPath) && existsSync20(resolve16(repoRoot, cleanPath));
21233
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync20(resolve16(repoRoot, cleanPath));
21657
+ const isImage = isImagePath(cleanPath) && existsSync22(resolve18(repoRoot, cleanPath));
21658
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync22(resolve18(repoRoot, cleanPath));
21234
21659
  if (activeTask) {
21235
21660
  if (isImage) {
21236
21661
  try {
21237
- const imgPath = resolve16(repoRoot, cleanPath);
21238
- const imgBuffer = readFileSync17(imgPath);
21662
+ const imgPath = resolve18(repoRoot, cleanPath);
21663
+ const imgBuffer = readFileSync18(imgPath);
21239
21664
  const base64 = imgBuffer.toString("base64");
21240
21665
  const ext = extname9(cleanPath).toLowerCase();
21241
21666
  const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
@@ -21248,7 +21673,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
21248
21673
  } else if (isMedia) {
21249
21674
  writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
21250
21675
  const engine = getListenEngine();
21251
- const result = await engine.transcribeFile(resolve16(repoRoot, cleanPath), repoRoot);
21676
+ const result = await engine.transcribeFile(resolve18(repoRoot, cleanPath), repoRoot);
21252
21677
  if (result) {
21253
21678
  const transcript = `[Transcription of ${cleanPath}]
21254
21679
  ${result.text}`;
@@ -21281,7 +21706,7 @@ ${result.text}`;
21281
21706
  if (isMedia && fullInput === input) {
21282
21707
  writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
21283
21708
  const engine = getListenEngine();
21284
- const result = await engine.transcribeFile(resolve16(repoRoot, cleanPath), repoRoot);
21709
+ const result = await engine.transcribeFile(resolve18(repoRoot, cleanPath), repoRoot);
21285
21710
  if (result) {
21286
21711
  fullInput = `The user has provided an audio/video file: ${cleanPath}.
21287
21712
 
@@ -21401,7 +21826,7 @@ ${c2.dim("(Use /quit to exit)")}
21401
21826
  });
21402
21827
  }
21403
21828
  async function runWithTUI(task, config, repoPath) {
21404
- const repoRoot = resolve16(repoPath ?? cwd());
21829
+ const repoRoot = resolve18(repoPath ?? cwd());
21405
21830
  const needsSetup = isFirstRun() || !await isModelAvailable(config);
21406
21831
  if (needsSetup && config.backendType === "ollama") {
21407
21832
  const setupModel = await runSetupWizard(config);
@@ -21506,7 +21931,7 @@ import { glob } from "glob";
21506
21931
  import ignore from "ignore";
21507
21932
  import { readFile as readFile10, stat as stat4 } from "node:fs/promises";
21508
21933
  import { createHash } from "node:crypto";
21509
- import { join as join29, relative as relative3, extname as extname10, basename as basename9 } from "node:path";
21934
+ import { join as join30, relative as relative3, extname as extname10, basename as basename11 } from "node:path";
21510
21935
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
21511
21936
  var init_codebase_indexer = __esm({
21512
21937
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -21550,7 +21975,7 @@ var init_codebase_indexer = __esm({
21550
21975
  const ig = ignore.default();
21551
21976
  if (this.config.respectGitignore) {
21552
21977
  try {
21553
- const gitignoreContent = await readFile10(join29(this.config.rootDir, ".gitignore"), "utf-8");
21978
+ const gitignoreContent = await readFile10(join30(this.config.rootDir, ".gitignore"), "utf-8");
21554
21979
  ig.add(gitignoreContent);
21555
21980
  } catch {
21556
21981
  }
@@ -21565,7 +21990,7 @@ var init_codebase_indexer = __esm({
21565
21990
  for (const relativePath of files) {
21566
21991
  if (ig.ignores(relativePath))
21567
21992
  continue;
21568
- const fullPath = join29(this.config.rootDir, relativePath);
21993
+ const fullPath = join30(this.config.rootDir, relativePath);
21569
21994
  try {
21570
21995
  const fileStat = await stat4(fullPath);
21571
21996
  if (fileStat.size > this.config.maxFileSize)
@@ -21588,7 +22013,7 @@ var init_codebase_indexer = __esm({
21588
22013
  }
21589
22014
  buildTree(files) {
21590
22015
  const root = {
21591
- name: basename9(this.config.rootDir),
22016
+ name: basename11(this.config.rootDir),
21592
22017
  path: this.config.rootDir,
21593
22018
  type: "directory",
21594
22019
  children: []
@@ -21611,7 +22036,7 @@ var init_codebase_indexer = __esm({
21611
22036
  if (!child) {
21612
22037
  child = {
21613
22038
  name: part,
21614
- path: join29(current.path, part),
22039
+ path: join30(current.path, part),
21615
22040
  type: "directory",
21616
22041
  children: []
21617
22042
  };
@@ -21685,18 +22110,18 @@ var index_repo_exports = {};
21685
22110
  __export(index_repo_exports, {
21686
22111
  indexRepoCommand: () => indexRepoCommand
21687
22112
  });
21688
- import { resolve as resolve17 } from "node:path";
21689
- import { existsSync as existsSync21, statSync as statSync7 } from "node:fs";
22113
+ import { resolve as resolve19 } from "node:path";
22114
+ import { existsSync as existsSync23, statSync as statSync9 } from "node:fs";
21690
22115
  import { cwd as cwd2 } from "node:process";
21691
22116
  async function indexRepoCommand(opts, _config) {
21692
- const repoRoot = resolve17(opts.repoPath ?? cwd2());
22117
+ const repoRoot = resolve19(opts.repoPath ?? cwd2());
21693
22118
  printHeader("Index Repository");
21694
22119
  printInfo(`Indexing: ${repoRoot}`);
21695
- if (!existsSync21(repoRoot)) {
22120
+ if (!existsSync23(repoRoot)) {
21696
22121
  printError(`Path does not exist: ${repoRoot}`);
21697
22122
  process.exit(1);
21698
22123
  }
21699
- const stat5 = statSync7(repoRoot);
22124
+ const stat5 = statSync9(repoRoot);
21700
22125
  if (!stat5.isDirectory()) {
21701
22126
  printError(`Path is not a directory: ${repoRoot}`);
21702
22127
  process.exit(1);
@@ -21938,7 +22363,7 @@ var config_exports = {};
21938
22363
  __export(config_exports, {
21939
22364
  configCommand: () => configCommand
21940
22365
  });
21941
- import { join as join30, resolve as resolve18 } from "node:path";
22366
+ import { join as join31, resolve as resolve20 } from "node:path";
21942
22367
  import { homedir as homedir11 } from "node:os";
21943
22368
  import { cwd as cwd3 } from "node:process";
21944
22369
  function coerceForSettings(key, value) {
@@ -21959,7 +22384,7 @@ async function configCommand(opts, config) {
21959
22384
  return handleShow(opts, config);
21960
22385
  }
21961
22386
  function handleShow(opts, config) {
21962
- const repoRoot = resolve18(opts.repoPath ?? cwd3());
22387
+ const repoRoot = resolve20(opts.repoPath ?? cwd3());
21963
22388
  printHeader("Configuration");
21964
22389
  printSection("Active Settings (merged)");
21965
22390
  printKeyValue("backendUrl", config.backendUrl, 2);
@@ -21991,7 +22416,7 @@ function handleShow(opts, config) {
21991
22416
  }
21992
22417
  }
21993
22418
  printSection("Config File");
21994
- printInfo(`~/.open-agents/config.json (${join30(homedir11(), ".open-agents", "config.json")})`);
22419
+ printInfo(`~/.open-agents/config.json (${join31(homedir11(), ".open-agents", "config.json")})`);
21995
22420
  printSection("Priority Chain");
21996
22421
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
21997
22422
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -22024,13 +22449,13 @@ function handleSet(opts, _config) {
22024
22449
  process.exit(1);
22025
22450
  }
22026
22451
  if (opts.local) {
22027
- const repoRoot = resolve18(opts.repoPath ?? cwd3());
22452
+ const repoRoot = resolve20(opts.repoPath ?? cwd3());
22028
22453
  try {
22029
22454
  initOaDirectory(repoRoot);
22030
22455
  const coerced = coerceForSettings(key, value);
22031
22456
  saveProjectSettings(repoRoot, { [key]: coerced });
22032
22457
  printSuccess(`Project override set: ${key} = ${value}`);
22033
- printInfo(`Saved to ${join30(repoRoot, ".oa", "settings.json")}`);
22458
+ printInfo(`Saved to ${join31(repoRoot, ".oa", "settings.json")}`);
22034
22459
  printInfo("This override applies only when running in this workspace.");
22035
22460
  } catch (err) {
22036
22461
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -22182,7 +22607,7 @@ async function serveVllm(opts, config) {
22182
22607
  await runVllmServer(args, opts.verbose ?? false);
22183
22608
  }
22184
22609
  async function runVllmServer(args, verbose) {
22185
- return new Promise((resolve19, reject) => {
22610
+ return new Promise((resolve21, reject) => {
22186
22611
  const child = spawn9("python", args, {
22187
22612
  stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
22188
22613
  env: { ...process.env }
@@ -22217,10 +22642,10 @@ async function runVllmServer(args, verbose) {
22217
22642
  child.once("exit", (code, signal) => {
22218
22643
  if (signal) {
22219
22644
  printInfo(`vLLM server stopped by signal ${signal}`);
22220
- resolve19();
22645
+ resolve21();
22221
22646
  } else if (code === 0) {
22222
22647
  printSuccess("vLLM server exited cleanly");
22223
- resolve19();
22648
+ resolve21();
22224
22649
  } else {
22225
22650
  printError(`vLLM server exited with code ${code}`);
22226
22651
  reject(new Error(`vLLM exited with code ${code}`));
@@ -22247,9 +22672,9 @@ var eval_exports = {};
22247
22672
  __export(eval_exports, {
22248
22673
  evalCommand: () => evalCommand
22249
22674
  });
22250
- import { tmpdir as tmpdir5 } from "node:os";
22675
+ import { tmpdir as tmpdir6 } from "node:os";
22251
22676
  import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
22252
- import { join as join31 } from "node:path";
22677
+ import { join as join32 } from "node:path";
22253
22678
  async function evalCommand(opts, config) {
22254
22679
  const suiteName = opts.suite ?? "basic";
22255
22680
  const suite = SUITES[suiteName];
@@ -22370,9 +22795,9 @@ async function evalCommand(opts, config) {
22370
22795
  process.exit(failed > 0 ? 1 : 0);
22371
22796
  }
22372
22797
  function createTempEvalRepo() {
22373
- const dir = join31(tmpdir5(), `open-agents-eval-${Date.now()}`);
22798
+ const dir = join32(tmpdir6(), `open-agents-eval-${Date.now()}`);
22374
22799
  mkdirSync12(dir, { recursive: true });
22375
- writeFileSync11(join31(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
22800
+ writeFileSync11(join32(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
22376
22801
  return dir;
22377
22802
  }
22378
22803
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -22432,7 +22857,7 @@ init_updater();
22432
22857
  import { parseArgs as nodeParseArgs2 } from "node:util";
22433
22858
  import { createRequire as createRequire3 } from "node:module";
22434
22859
  import { fileURLToPath as fileURLToPath6 } from "node:url";
22435
- import { dirname as dirname9, join as join32 } from "node:path";
22860
+ import { dirname as dirname9, join as join33 } from "node:path";
22436
22861
 
22437
22862
  // packages/cli/dist/cli.js
22438
22863
  import { createInterface } from "node:readline";
@@ -22539,7 +22964,7 @@ init_output();
22539
22964
  function getVersion2() {
22540
22965
  try {
22541
22966
  const require2 = createRequire3(import.meta.url);
22542
- const pkgPath = join32(dirname9(fileURLToPath6(import.meta.url)), "..", "package.json");
22967
+ const pkgPath = join33(dirname9(fileURLToPath6(import.meta.url)), "..", "package.json");
22543
22968
  const pkg = require2(pkgPath);
22544
22969
  return pkg.version;
22545
22970
  } catch {