open-agents-ai 0.30.9 → 0.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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((resolve21) => {
1287
+ return new Promise((resolve22) => {
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
- resolve21(result);
1315
+ resolve22(result);
1316
1316
  };
1317
1317
  const timer = setTimeout(() => {
1318
1318
  killed = true;
@@ -4682,7 +4682,7 @@ var init_custom_tool = __esm({
4682
4682
  }
4683
4683
  /** Execute a single shell command and return output */
4684
4684
  runCommand(command) {
4685
- return new Promise((resolve21) => {
4685
+ return new Promise((resolve22) => {
4686
4686
  const child = spawn3("bash", ["-c", command], {
4687
4687
  cwd: this.workingDir,
4688
4688
  env: { ...process.env, CI: "true", NO_COLOR: "1" },
@@ -4707,11 +4707,11 @@ var init_custom_tool = __esm({
4707
4707
  child.kill("SIGTERM");
4708
4708
  } catch {
4709
4709
  }
4710
- resolve21({ success: false, output: stdout, error: "Command timed out after 60s" });
4710
+ resolve22({ success: false, output: stdout, error: "Command timed out after 60s" });
4711
4711
  }, 6e4);
4712
4712
  child.on("close", (code) => {
4713
4713
  clearTimeout(timer);
4714
- resolve21({
4714
+ resolve22({
4715
4715
  success: code === 0,
4716
4716
  output: stdout + (stderr && code === 0 ? `
4717
4717
  STDERR:
@@ -4721,7 +4721,7 @@ ${stderr}` : ""),
4721
4721
  });
4722
4722
  child.on("error", (err) => {
4723
4723
  clearTimeout(timer);
4724
- resolve21({ success: false, output: stdout, error: err.message });
4724
+ resolve22({ success: false, output: stdout, error: err.message });
4725
4725
  });
4726
4726
  });
4727
4727
  }
@@ -5903,7 +5903,7 @@ import { writeFile as writeFile7, mkdtemp, rm, readdir, stat } from "node:fs/pro
5903
5903
  import { join as join14 } from "node:path";
5904
5904
  import { tmpdir as tmpdir2 } from "node:os";
5905
5905
  function runProcess(cmd, args, options) {
5906
- return new Promise((resolve21) => {
5906
+ return new Promise((resolve22) => {
5907
5907
  const proc = spawn5(cmd, args, {
5908
5908
  cwd: options.cwd,
5909
5909
  timeout: options.timeout,
@@ -5933,7 +5933,7 @@ function runProcess(cmd, args, options) {
5933
5933
  }
5934
5934
  });
5935
5935
  proc.on("error", (err) => {
5936
- resolve21({
5936
+ resolve22({
5937
5937
  stdout,
5938
5938
  stderr: stderr || err.message,
5939
5939
  exitCode: 1,
@@ -5945,7 +5945,7 @@ function runProcess(cmd, args, options) {
5945
5945
  if (signal === "SIGTERM" || signal === "SIGKILL") {
5946
5946
  timedOut = true;
5947
5947
  }
5948
- resolve21({
5948
+ resolve22({
5949
5949
  stdout,
5950
5950
  stderr,
5951
5951
  exitCode: code ?? (timedOut ? 124 : 1),
@@ -7670,6 +7670,309 @@ ${text}`,
7670
7670
  }
7671
7671
  });
7672
7672
 
7673
+ // packages/execution/dist/tools/ocr-image-advanced.js
7674
+ import { existsSync as existsSync15, statSync as statSync8 } from "node:fs";
7675
+ import { resolve as resolve18, basename as basename7, dirname as dirname6, join as join18 } from "node:path";
7676
+ import { execSync as execSync14 } from "node:child_process";
7677
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
7678
+ import { homedir as homedir6, tmpdir as tmpdir5 } from "node:os";
7679
+ function findOcrScript() {
7680
+ const thisDir = dirname6(fileURLToPath3(import.meta.url));
7681
+ const devPath = resolve18(thisDir, "../../scripts/ocr-advanced.py");
7682
+ if (existsSync15(devPath))
7683
+ return devPath;
7684
+ const bundledPath = resolve18(thisDir, "../scripts/ocr-advanced.py");
7685
+ if (existsSync15(bundledPath))
7686
+ return bundledPath;
7687
+ const sameDirPath = resolve18(thisDir, "ocr-advanced.py");
7688
+ if (existsSync15(sameDirPath))
7689
+ return sameDirPath;
7690
+ return null;
7691
+ }
7692
+ function findPython() {
7693
+ const venvPython = join18(homedir6(), ".open-agents", "venv", "bin", "python");
7694
+ if (existsSync15(venvPython)) {
7695
+ try {
7696
+ execSync14(`${JSON.stringify(venvPython)} -c "import cv2, pytesseract, numpy, PIL"`, {
7697
+ stdio: "pipe",
7698
+ timeout: 5e3
7699
+ });
7700
+ return venvPython;
7701
+ } catch {
7702
+ }
7703
+ }
7704
+ try {
7705
+ execSync14(`python3 -c "import cv2, pytesseract, numpy, PIL"`, {
7706
+ stdio: "pipe",
7707
+ timeout: 5e3
7708
+ });
7709
+ return "python3";
7710
+ } catch {
7711
+ }
7712
+ return null;
7713
+ }
7714
+ var OcrImageAdvancedTool;
7715
+ var init_ocr_image_advanced = __esm({
7716
+ "packages/execution/dist/tools/ocr-image-advanced.js"() {
7717
+ "use strict";
7718
+ init_system_deps();
7719
+ OcrImageAdvancedTool = class {
7720
+ workingDir;
7721
+ name = "ocr_image_advanced";
7722
+ description = "Advanced OCR for images using multi-variant preprocessing and multi-PSM Tesseract pipeline. Generates 8 image preprocessing variants (2 adaptive windows, OTSU, 2 fixed thresholds, Laplacian sharpen, unsharp mask sharpen, denoise) and runs Tesseract with 3 PSM modes on each (up to 24 passes), picking the best by combined confidence + line-count score. Much more accurate than basic OCR for photos, scans, invoices, and documents with uneven lighting. Supports region extraction (header/body/footer), batch directory processing, and multi-format output (TXT + CSV + PDF).";
7723
+ parameters = {
7724
+ type: "object",
7725
+ properties: {
7726
+ image: {
7727
+ type: "string",
7728
+ description: "Path to image file or directory (for batch mode). Supports JPEG, PNG, TIFF, BMP, WebP."
7729
+ },
7730
+ language: {
7731
+ type: "string",
7732
+ description: "OCR language (default: eng). Use '+' for multiple: 'eng+fra+deu'"
7733
+ },
7734
+ regions: {
7735
+ type: "boolean",
7736
+ description: "Also extract text from header/body/footer regions separately (good for invoices, forms)"
7737
+ },
7738
+ region: {
7739
+ type: "string",
7740
+ description: "Crop to a specific region before OCR: 'x,y,w,h' in pixels"
7741
+ },
7742
+ psm: {
7743
+ type: "number",
7744
+ description: "Use a single PSM mode instead of testing all 3. Options: 4 (single block), 6 (default), 11 (sparse)"
7745
+ },
7746
+ output_dir: {
7747
+ type: "string",
7748
+ description: "Write TXT + CSV + PDF outputs to this directory (in addition to returning text)"
7749
+ },
7750
+ batch: {
7751
+ type: "boolean",
7752
+ description: "Process all images in the directory specified by 'image'. Writes results + summary to output_dir."
7753
+ },
7754
+ debug: {
7755
+ type: "boolean",
7756
+ description: "Save preprocessed variants to a debug directory (default: false)"
7757
+ }
7758
+ },
7759
+ required: ["image"]
7760
+ };
7761
+ constructor(workingDir) {
7762
+ this.workingDir = workingDir;
7763
+ }
7764
+ async execute(args) {
7765
+ const start = performance.now();
7766
+ const rawPath = args["image"];
7767
+ const language = args["language"] ?? "eng";
7768
+ const doRegions = args["regions"] === true;
7769
+ const region = args["region"];
7770
+ const psm = args["psm"];
7771
+ const debug = args["debug"] === true;
7772
+ const outputDir = args["output_dir"];
7773
+ const batch = args["batch"] === true;
7774
+ if (!rawPath) {
7775
+ return { success: false, output: "", error: "image path is required", durationMs: 0 };
7776
+ }
7777
+ const fullPath = resolve18(this.workingDir, rawPath);
7778
+ if (!existsSync15(fullPath)) {
7779
+ return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: performance.now() - start };
7780
+ }
7781
+ if (!batch) {
7782
+ const stat5 = statSync8(fullPath);
7783
+ if (stat5.isDirectory()) {
7784
+ return this.executeBatchOrSingle(fullPath, language, doRegions, region, psm, debug, outputDir, true, start);
7785
+ }
7786
+ if (stat5.size > 50 * 1024 * 1024) {
7787
+ return { success: false, output: "", error: `Image too large: ${(stat5.size / 1024 / 1024).toFixed(0)}MB (max 50MB)`, durationMs: performance.now() - start };
7788
+ }
7789
+ }
7790
+ return this.executeBatchOrSingle(fullPath, language, doRegions, region, psm, debug, outputDir, batch, start);
7791
+ }
7792
+ executeBatchOrSingle(fullPath, language, doRegions, region, psm, debug, outputDir, batch, start) {
7793
+ const tesCheck = ensureCommand("tesseract");
7794
+ if (!tesCheck.available) {
7795
+ return {
7796
+ success: false,
7797
+ output: "",
7798
+ error: `Tesseract not available: ${tesCheck.error ?? "auto-install failed"}`,
7799
+ durationMs: performance.now() - start
7800
+ };
7801
+ }
7802
+ const python = findPython();
7803
+ const script = findOcrScript();
7804
+ if (python && script) {
7805
+ return this.runPythonPipeline(python, script, fullPath, language, doRegions, region, psm, debug, outputDir, batch, start);
7806
+ }
7807
+ if (batch) {
7808
+ return {
7809
+ success: false,
7810
+ output: "",
7811
+ error: "Batch mode requires the Python OCR pipeline (pytesseract, opencv-python-headless, Pillow, numpy). Install them in ~/.open-agents/venv.",
7812
+ durationMs: performance.now() - start
7813
+ };
7814
+ }
7815
+ return this.runBasicTesseract(fullPath, language, region, psm, start);
7816
+ }
7817
+ runPythonPipeline(python, script, imagePath, language, regions, region, psm, debug, outputDir, batch, start) {
7818
+ const cmdParts = [
7819
+ JSON.stringify(python),
7820
+ JSON.stringify(script),
7821
+ JSON.stringify(imagePath),
7822
+ "-l",
7823
+ language,
7824
+ "--output",
7825
+ "json"
7826
+ ];
7827
+ if (regions)
7828
+ cmdParts.push("--regions");
7829
+ if (region)
7830
+ cmdParts.push("--region", region);
7831
+ if (psm)
7832
+ cmdParts.push("--psm", String(psm));
7833
+ if (batch)
7834
+ cmdParts.push("--batch");
7835
+ if (outputDir)
7836
+ cmdParts.push("--output-dir", JSON.stringify(resolve18(this.workingDir, outputDir)));
7837
+ let debugDir;
7838
+ if (debug) {
7839
+ debugDir = join18(tmpdir5(), `oa-ocr-debug-${Date.now()}`);
7840
+ cmdParts.push("--debug-dir", debugDir);
7841
+ }
7842
+ try {
7843
+ const stdout = execSync14(cmdParts.join(" "), {
7844
+ encoding: "utf8",
7845
+ stdio: ["pipe", "pipe", "pipe"],
7846
+ timeout: 3e5,
7847
+ // 5 min for large images
7848
+ cwd: this.workingDir
7849
+ });
7850
+ const result = JSON.parse(stdout);
7851
+ if (result.error) {
7852
+ return {
7853
+ success: false,
7854
+ output: "",
7855
+ error: result.error,
7856
+ durationMs: performance.now() - start
7857
+ };
7858
+ }
7859
+ if (result.batch && result.results) {
7860
+ const parts2 = [];
7861
+ parts2.push(`Batch OCR: processed ${result.images_processed} images`);
7862
+ parts2.push(`Output directory: ${result.output_dir}`);
7863
+ parts2.push(`Summary: ${result.summary}`);
7864
+ parts2.push("");
7865
+ for (const [imgName, imgResult] of Object.entries(result.results)) {
7866
+ if (imgResult.error) {
7867
+ parts2.push(` ${imgName}: ERROR \u2014 ${imgResult.error}`);
7868
+ } else {
7869
+ parts2.push(` ${imgName}: ${imgResult.lines} lines, ${imgResult.chars} chars, ${imgResult.confidence}% confidence (${imgResult.variant})`);
7870
+ }
7871
+ }
7872
+ return {
7873
+ success: true,
7874
+ output: parts2.join("\n"),
7875
+ durationMs: performance.now() - start
7876
+ };
7877
+ }
7878
+ const parts = [];
7879
+ parts.push(`OCR extracted from ${basename7(imagePath)} (${result.image_size})`);
7880
+ parts.push(`Best variant: ${result.variant} (confidence: ${result.confidence}%, ${result.chars} chars, ${result.lines} lines, score: ${result.score})`);
7881
+ parts.push(`Variants tested: ${result.variants_tested}`);
7882
+ if (result.output_files) {
7883
+ const files = result.output_files;
7884
+ const saved = [files.txt, files.csv, files.pdf].filter(Boolean);
7885
+ parts.push(`Output files: ${saved.join(", ")}`);
7886
+ }
7887
+ parts.push("");
7888
+ parts.push("--- Extracted Text ---");
7889
+ parts.push(result.text);
7890
+ if (result.regions) {
7891
+ parts.push("");
7892
+ parts.push("--- Region Extraction ---");
7893
+ for (const [rname, rtext] of Object.entries(result.regions)) {
7894
+ if (rtext) {
7895
+ parts.push(`
7896
+ [${rname.toUpperCase()}]`);
7897
+ parts.push(rtext);
7898
+ }
7899
+ }
7900
+ }
7901
+ if (result.all_variants) {
7902
+ const sorted = Object.entries(result.all_variants).filter(([_, v]) => v.chars > 0).sort((a, b) => b[1].score - a[1].score).slice(0, 5);
7903
+ if (sorted.length > 1) {
7904
+ parts.push("");
7905
+ parts.push("--- Top Variants ---");
7906
+ for (const [key, v] of sorted) {
7907
+ parts.push(` ${key}: ${v.confidence}% confidence, ${v.chars} chars, ${v.lines} lines (score: ${v.score})`);
7908
+ }
7909
+ }
7910
+ }
7911
+ if (debugDir) {
7912
+ parts.push("");
7913
+ parts.push(`Debug images saved: ${debugDir}`);
7914
+ }
7915
+ return {
7916
+ success: true,
7917
+ output: parts.join("\n"),
7918
+ durationMs: performance.now() - start
7919
+ };
7920
+ } catch (err) {
7921
+ const stderr = err?.stderr?.toString?.() ?? "";
7922
+ if (stderr.includes("ModuleNotFoundError") || stderr.includes("ImportError")) {
7923
+ return this.runBasicTesseract(imagePath, language, region, void 0, start);
7924
+ }
7925
+ return {
7926
+ success: false,
7927
+ output: "",
7928
+ error: `Advanced OCR failed: ${(stderr || (err instanceof Error ? err.message : String(err))).slice(0, 500)}`,
7929
+ durationMs: performance.now() - start
7930
+ };
7931
+ }
7932
+ }
7933
+ runBasicTesseract(imagePath, language, region, psm, start) {
7934
+ let inputPath = imagePath;
7935
+ if (region) {
7936
+ try {
7937
+ const [x, y, w, h] = region.split(",").map(Number);
7938
+ const croppedPath = join18(tmpdir5(), `oa-ocr-crop-${Date.now()}.png`);
7939
+ execSync14(`convert ${JSON.stringify(imagePath)} -crop ${w}x${h}+${x}+${y} +repage ${JSON.stringify(croppedPath)}`, { stdio: "pipe", timeout: 1e4 });
7940
+ inputPath = croppedPath;
7941
+ } catch {
7942
+ }
7943
+ }
7944
+ const psmArg = psm ?? 6;
7945
+ try {
7946
+ const text = execSync14(`tesseract ${JSON.stringify(inputPath)} stdout -l ${language} --psm ${psmArg} 2>/dev/null`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 6e4 }).trim();
7947
+ if (!text) {
7948
+ return {
7949
+ success: true,
7950
+ output: `(no text detected in ${basename7(imagePath)} \u2014 try the advanced Python OCR pipeline for better results)`,
7951
+ durationMs: performance.now() - start
7952
+ };
7953
+ }
7954
+ const lineCount = text.split("\n").length;
7955
+ return {
7956
+ success: true,
7957
+ output: `OCR extracted ${lineCount} lines from ${basename7(imagePath)} (basic tesseract, PSM ${psmArg}):
7958
+ Note: Advanced Python pipeline not available \u2014 install pytesseract, opencv-python-headless, Pillow, numpy for better results.
7959
+
7960
+ ` + text,
7961
+ durationMs: performance.now() - start
7962
+ };
7963
+ } catch (err) {
7964
+ return {
7965
+ success: false,
7966
+ output: "",
7967
+ error: `Tesseract OCR failed: ${err instanceof Error ? err.message : String(err)}`,
7968
+ durationMs: performance.now() - start
7969
+ };
7970
+ }
7971
+ }
7972
+ };
7973
+ }
7974
+ });
7975
+
7673
7976
  // packages/execution/dist/shellRunner.js
7674
7977
  var init_shellRunner = __esm({
7675
7978
  "packages/execution/dist/shellRunner.js"() {
@@ -7781,6 +8084,7 @@ var init_dist2 = __esm({
7781
8084
  init_desktop_click();
7782
8085
  init_ocr_pdf();
7783
8086
  init_pdf_to_text();
8087
+ init_ocr_image_advanced();
7784
8088
  init_system_deps();
7785
8089
  init_shellRunner();
7786
8090
  init_gitWorktree();
@@ -8913,7 +9217,7 @@ var init_code_retriever = __esm({
8913
9217
  import { execFile as execFile4 } from "node:child_process";
8914
9218
  import { promisify as promisify4 } from "node:util";
8915
9219
  import { readFile as readFile8, readdir as readdir2, stat as stat3 } from "node:fs/promises";
8916
- import { join as join18, extname as extname7 } from "node:path";
9220
+ import { join as join19, extname as extname7 } from "node:path";
8917
9221
  async function searchByPath(pathPattern, options) {
8918
9222
  const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
8919
9223
  const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
@@ -9055,7 +9359,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
9055
9359
  continue;
9056
9360
  if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
9057
9361
  continue;
9058
- const absPath = join18(dir, entry.name);
9362
+ const absPath = join19(dir, entry.name);
9059
9363
  if (entry.isDirectory()) {
9060
9364
  await walkForFiles(rootDir, absPath, excludeGlobs, results);
9061
9365
  } else if (entry.isFile()) {
@@ -9230,7 +9534,7 @@ var init_graphExpand = __esm({
9230
9534
 
9231
9535
  // packages/retrieval/dist/snippetPacker.js
9232
9536
  import { readFile as readFile9 } from "node:fs/promises";
9233
- import { join as join19 } from "node:path";
9537
+ import { join as join20 } from "node:path";
9234
9538
  async function packSnippets(requests, opts = {}) {
9235
9539
  const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
9236
9540
  const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
@@ -9256,7 +9560,7 @@ async function packSnippets(requests, opts = {}) {
9256
9560
  return { packed, dropped, totalTokens };
9257
9561
  }
9258
9562
  async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
9259
- const absPath = req.filePath.startsWith("/") ? req.filePath : join19(repoRoot, req.filePath);
9563
+ const absPath = req.filePath.startsWith("/") ? req.filePath : join20(repoRoot, req.filePath);
9260
9564
  let content;
9261
9565
  try {
9262
9566
  content = await readFile9(absPath, "utf-8");
@@ -10769,8 +11073,8 @@ Rules:
10769
11073
  async waitIfPaused() {
10770
11074
  if (!this._paused)
10771
11075
  return true;
10772
- await new Promise((resolve21) => {
10773
- this._pauseResolve = resolve21;
11076
+ await new Promise((resolve22) => {
11077
+ this._pauseResolve = resolve22;
10774
11078
  });
10775
11079
  return !this.aborted;
10776
11080
  }
@@ -11280,14 +11584,14 @@ ${result.output}`;
11280
11584
  waitForSudoPassword(timeoutMs = 12e4) {
11281
11585
  if (this._sudoPassword)
11282
11586
  return Promise.resolve(this._sudoPassword);
11283
- return new Promise((resolve21) => {
11587
+ return new Promise((resolve22) => {
11284
11588
  const timer = setTimeout(() => {
11285
11589
  this._sudoResolve = null;
11286
- resolve21(null);
11590
+ resolve22(null);
11287
11591
  }, timeoutMs);
11288
11592
  this._sudoResolve = (pw) => {
11289
11593
  clearTimeout(timer);
11290
- resolve21(pw);
11594
+ resolve22(pw);
11291
11595
  };
11292
11596
  });
11293
11597
  }
@@ -12443,11 +12747,11 @@ var init_dist5 = __esm({
12443
12747
  });
12444
12748
 
12445
12749
  // packages/cli/dist/tui/listen.js
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";
12449
- import { homedir as homedir6 } from "node:os";
12450
- import { fileURLToPath as fileURLToPath3 } from "node:url";
12750
+ import { spawn as spawn7, execSync as execSync15 } from "node:child_process";
12751
+ import { existsSync as existsSync16, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readdirSync as readdirSync6 } from "node:fs";
12752
+ import { join as join21, dirname as dirname7 } from "node:path";
12753
+ import { homedir as homedir7 } from "node:os";
12754
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
12451
12755
  import { EventEmitter } from "node:events";
12452
12756
  import { createInterface as createInterface2 } from "node:readline";
12453
12757
  function isAudioPath(path) {
@@ -12465,7 +12769,7 @@ function findMicCaptureCommand() {
12465
12769
  const platform4 = process.platform;
12466
12770
  if (platform4 === "linux") {
12467
12771
  try {
12468
- execSync14("which arecord", { stdio: "pipe" });
12772
+ execSync15("which arecord", { stdio: "pipe" });
12469
12773
  return {
12470
12774
  cmd: "arecord",
12471
12775
  args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
@@ -12475,7 +12779,7 @@ function findMicCaptureCommand() {
12475
12779
  }
12476
12780
  if (platform4 === "darwin") {
12477
12781
  try {
12478
- execSync14("which sox", { stdio: "pipe" });
12782
+ execSync15("which sox", { stdio: "pipe" });
12479
12783
  return {
12480
12784
  cmd: "sox",
12481
12785
  args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
@@ -12484,7 +12788,7 @@ function findMicCaptureCommand() {
12484
12788
  }
12485
12789
  }
12486
12790
  try {
12487
- execSync14("which ffmpeg", { stdio: "pipe" });
12791
+ execSync15("which ffmpeg", { stdio: "pipe" });
12488
12792
  if (platform4 === "linux") {
12489
12793
  return {
12490
12794
  cmd: "ffmpeg",
@@ -12529,41 +12833,41 @@ function findMicCaptureCommand() {
12529
12833
  return null;
12530
12834
  }
12531
12835
  function findLiveWhisperScript() {
12532
- const thisDir = dirname6(fileURLToPath3(import.meta.url));
12836
+ const thisDir = dirname7(fileURLToPath4(import.meta.url));
12533
12837
  const candidates = [
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"),
12838
+ join21(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
12839
+ join21(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
12840
+ join21(thisDir, "../../execution/scripts/live-whisper.py"),
12537
12841
  // npm install layout — scripts bundled alongside dist
12538
- join20(thisDir, "../scripts/live-whisper.py"),
12539
- join20(thisDir, "../../scripts/live-whisper.py")
12842
+ join21(thisDir, "../scripts/live-whisper.py"),
12843
+ join21(thisDir, "../../scripts/live-whisper.py")
12540
12844
  ];
12541
12845
  for (const p of candidates) {
12542
- if (existsSync15(p))
12846
+ if (existsSync16(p))
12543
12847
  return p;
12544
12848
  }
12545
12849
  try {
12546
- const globalRoot = execSync14("npm root -g", {
12850
+ const globalRoot = execSync15("npm root -g", {
12547
12851
  encoding: "utf-8",
12548
12852
  timeout: 5e3,
12549
12853
  stdio: ["pipe", "pipe", "pipe"]
12550
12854
  }).trim();
12551
12855
  const candidates2 = [
12552
- join20(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
12553
- join20(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
12856
+ join21(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
12857
+ join21(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
12554
12858
  ];
12555
12859
  for (const p of candidates2) {
12556
- if (existsSync15(p))
12860
+ if (existsSync16(p))
12557
12861
  return p;
12558
12862
  }
12559
12863
  } catch {
12560
12864
  }
12561
- const nvmBase = join20(homedir6(), ".nvm", "versions", "node");
12562
- if (existsSync15(nvmBase)) {
12865
+ const nvmBase = join21(homedir7(), ".nvm", "versions", "node");
12866
+ if (existsSync16(nvmBase)) {
12563
12867
  try {
12564
12868
  for (const ver of readdirSync6(nvmBase)) {
12565
- const p = join20(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
12566
- if (existsSync15(p))
12869
+ const p = join21(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
12870
+ if (existsSync16(p))
12567
12871
  return p;
12568
12872
  }
12569
12873
  } catch {
@@ -12576,21 +12880,21 @@ function ensureTranscribeCliBackground() {
12576
12880
  return;
12577
12881
  _bgInstallPromise = (async () => {
12578
12882
  try {
12579
- const globalRoot = execSync14("npm root -g", {
12883
+ const globalRoot = execSync15("npm root -g", {
12580
12884
  encoding: "utf-8",
12581
12885
  timeout: 5e3,
12582
12886
  stdio: ["pipe", "pipe", "pipe"]
12583
12887
  }).trim();
12584
- if (existsSync15(join20(globalRoot, "transcribe-cli", "dist", "index.js"))) {
12888
+ if (existsSync16(join21(globalRoot, "transcribe-cli", "dist", "index.js"))) {
12585
12889
  return true;
12586
12890
  }
12587
12891
  } catch {
12588
12892
  }
12589
12893
  try {
12590
12894
  const { exec } = await import("node:child_process");
12591
- return new Promise((resolve21) => {
12895
+ return new Promise((resolve22) => {
12592
12896
  exec("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
12593
- resolve21(!err);
12897
+ resolve22(!err);
12594
12898
  });
12595
12899
  });
12596
12900
  } catch {
@@ -12643,7 +12947,7 @@ var init_listen = __esm({
12643
12947
  return this._ready;
12644
12948
  }
12645
12949
  async start() {
12646
- return new Promise((resolve21, reject) => {
12950
+ return new Promise((resolve22, reject) => {
12647
12951
  const timeout = setTimeout(() => {
12648
12952
  reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
12649
12953
  }, 3e5);
@@ -12671,7 +12975,7 @@ var init_listen = __esm({
12671
12975
  this._ready = true;
12672
12976
  clearTimeout(timeout);
12673
12977
  this.emit("ready");
12674
- resolve21();
12978
+ resolve22();
12675
12979
  break;
12676
12980
  case "transcript":
12677
12981
  this.emit("transcript", {
@@ -12776,7 +13080,7 @@ var init_listen = __esm({
12776
13080
  }
12777
13081
  if (!this.transcribeCliAvailable) {
12778
13082
  try {
12779
- execSync14("which transcribe-cli", { stdio: "pipe" });
13083
+ execSync15("which transcribe-cli", { stdio: "pipe" });
12780
13084
  this.transcribeCliAvailable = true;
12781
13085
  } catch {
12782
13086
  this.transcribeCliAvailable = false;
@@ -12793,29 +13097,29 @@ var init_listen = __esm({
12793
13097
  } catch {
12794
13098
  }
12795
13099
  try {
12796
- const globalRoot = execSync14("npm root -g", {
13100
+ const globalRoot = execSync15("npm root -g", {
12797
13101
  encoding: "utf-8",
12798
13102
  timeout: 5e3,
12799
13103
  stdio: ["pipe", "pipe", "pipe"]
12800
13104
  }).trim();
12801
- const tcPath = join20(globalRoot, "transcribe-cli");
12802
- if (existsSync15(join20(tcPath, "dist", "index.js"))) {
13105
+ const tcPath = join21(globalRoot, "transcribe-cli");
13106
+ if (existsSync16(join21(tcPath, "dist", "index.js"))) {
12803
13107
  const { createRequire: createRequire4 } = await import("node:module");
12804
13108
  const req = createRequire4(import.meta.url);
12805
- return req(join20(tcPath, "dist", "index.js"));
13109
+ return req(join21(tcPath, "dist", "index.js"));
12806
13110
  }
12807
13111
  } catch {
12808
13112
  }
12809
- const nvmBase = join20(homedir6(), ".nvm", "versions", "node");
12810
- if (existsSync15(nvmBase)) {
13113
+ const nvmBase = join21(homedir7(), ".nvm", "versions", "node");
13114
+ if (existsSync16(nvmBase)) {
12811
13115
  try {
12812
13116
  const { readdirSync: readdirSync11 } = await import("node:fs");
12813
13117
  for (const ver of readdirSync11(nvmBase)) {
12814
- const tcPath = join20(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
12815
- if (existsSync15(join20(tcPath, "dist", "index.js"))) {
13118
+ const tcPath = join21(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
13119
+ if (existsSync16(join21(tcPath, "dist", "index.js"))) {
12816
13120
  const { createRequire: createRequire4 } = await import("node:module");
12817
13121
  const req = createRequire4(import.meta.url);
12818
- return req(join20(tcPath, "dist", "index.js"));
13122
+ return req(join21(tcPath, "dist", "index.js"));
12819
13123
  }
12820
13124
  }
12821
13125
  } catch {
@@ -12843,7 +13147,7 @@ var init_listen = __esm({
12843
13147
  }
12844
13148
  if (!tc) {
12845
13149
  try {
12846
- execSync14("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
13150
+ execSync15("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
12847
13151
  this.transcribeCliAvailable = null;
12848
13152
  tc = await this.loadTranscribeCli();
12849
13153
  } catch {
@@ -12875,11 +13179,11 @@ var init_listen = __esm({
12875
13179
  this.liveTranscriber.on("error", (err) => {
12876
13180
  this.emit("error", err);
12877
13181
  });
12878
- await new Promise((resolve21, reject) => {
13182
+ await new Promise((resolve22, reject) => {
12879
13183
  const timeout = setTimeout(() => reject(new Error("Model load timeout (60s)")), 6e4);
12880
13184
  this.liveTranscriber.on("ready", () => {
12881
13185
  clearTimeout(timeout);
12882
- resolve21();
13186
+ resolve22();
12883
13187
  });
12884
13188
  this.liveTranscriber.on("error", (err) => {
12885
13189
  clearTimeout(timeout);
@@ -13024,7 +13328,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
13024
13328
  }
13025
13329
  if (!tc) {
13026
13330
  try {
13027
- execSync14("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
13331
+ execSync15("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
13028
13332
  this.transcribeCliAvailable = null;
13029
13333
  tc = await this.loadTranscribeCli();
13030
13334
  } catch {
@@ -13040,10 +13344,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
13040
13344
  wordTimestamps: false
13041
13345
  });
13042
13346
  if (outputDir) {
13043
- const { basename: basename12 } = await import("node:path");
13044
- const transcriptDir = join20(outputDir, ".oa", "transcripts");
13347
+ const { basename: basename13 } = await import("node:path");
13348
+ const transcriptDir = join21(outputDir, ".oa", "transcripts");
13045
13349
  mkdirSync5(transcriptDir, { recursive: true });
13046
- const outFile = join20(transcriptDir, `${basename12(filePath)}.txt`);
13350
+ const outFile = join21(transcriptDir, `${basename13(filePath)}.txt`);
13047
13351
  writeFileSync5(outFile, result.text, "utf-8");
13048
13352
  }
13049
13353
  return {
@@ -14307,8 +14611,8 @@ Approach this task thoughtfully:
14307
14611
  });
14308
14612
 
14309
14613
  // packages/prompts/dist/index.js
14310
- import { join as join21, dirname as dirname7 } from "node:path";
14311
- import { fileURLToPath as fileURLToPath4 } from "node:url";
14614
+ import { join as join22, dirname as dirname8 } from "node:path";
14615
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
14312
14616
  var _dir, _packageRoot;
14313
14617
  var init_dist6 = __esm({
14314
14618
  "packages/prompts/dist/index.js"() {
@@ -14317,29 +14621,29 @@ var init_dist6 = __esm({
14317
14621
  init_render2();
14318
14622
  init_task_templates();
14319
14623
  init_render2();
14320
- _dir = dirname7(fileURLToPath4(import.meta.url));
14321
- _packageRoot = join21(_dir, "..");
14624
+ _dir = dirname8(fileURLToPath5(import.meta.url));
14625
+ _packageRoot = join22(_dir, "..");
14322
14626
  }
14323
14627
  });
14324
14628
 
14325
14629
  // packages/cli/dist/tui/oa-directory.js
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";
14328
- import { homedir as homedir7 } from "node:os";
14630
+ import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync13, writeFileSync as writeFileSync6, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
14631
+ import { join as join23, relative as relative2, basename as basename8, extname as extname8 } from "node:path";
14632
+ import { homedir as homedir8 } from "node:os";
14329
14633
  function initOaDirectory(repoRoot) {
14330
- const oaPath = join22(repoRoot, OA_DIR);
14634
+ const oaPath = join23(repoRoot, OA_DIR);
14331
14635
  for (const sub of SUBDIRS) {
14332
- mkdirSync6(join22(oaPath, sub), { recursive: true });
14636
+ mkdirSync6(join23(oaPath, sub), { recursive: true });
14333
14637
  }
14334
14638
  return oaPath;
14335
14639
  }
14336
14640
  function hasOaDirectory(repoRoot) {
14337
- return existsSync16(join22(repoRoot, OA_DIR, "index"));
14641
+ return existsSync17(join23(repoRoot, OA_DIR, "index"));
14338
14642
  }
14339
14643
  function loadProjectSettings(repoRoot) {
14340
- const settingsPath = join22(repoRoot, OA_DIR, "settings.json");
14644
+ const settingsPath = join23(repoRoot, OA_DIR, "settings.json");
14341
14645
  try {
14342
- if (existsSync16(settingsPath)) {
14646
+ if (existsSync17(settingsPath)) {
14343
14647
  return JSON.parse(readFileSync13(settingsPath, "utf-8"));
14344
14648
  }
14345
14649
  } catch {
@@ -14347,16 +14651,16 @@ function loadProjectSettings(repoRoot) {
14347
14651
  return {};
14348
14652
  }
14349
14653
  function saveProjectSettings(repoRoot, settings) {
14350
- const oaPath = join22(repoRoot, OA_DIR);
14654
+ const oaPath = join23(repoRoot, OA_DIR);
14351
14655
  mkdirSync6(oaPath, { recursive: true });
14352
14656
  const existing = loadProjectSettings(repoRoot);
14353
14657
  const merged = { ...existing, ...settings };
14354
- writeFileSync6(join22(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
14658
+ writeFileSync6(join23(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
14355
14659
  }
14356
14660
  function loadGlobalSettings() {
14357
- const settingsPath = join22(homedir7(), ".open-agents", "settings.json");
14661
+ const settingsPath = join23(homedir8(), ".open-agents", "settings.json");
14358
14662
  try {
14359
- if (existsSync16(settingsPath)) {
14663
+ if (existsSync17(settingsPath)) {
14360
14664
  return JSON.parse(readFileSync13(settingsPath, "utf-8"));
14361
14665
  }
14362
14666
  } catch {
@@ -14364,11 +14668,11 @@ function loadGlobalSettings() {
14364
14668
  return {};
14365
14669
  }
14366
14670
  function saveGlobalSettings(settings) {
14367
- const dir = join22(homedir7(), ".open-agents");
14671
+ const dir = join23(homedir8(), ".open-agents");
14368
14672
  mkdirSync6(dir, { recursive: true });
14369
14673
  const existing = loadGlobalSettings();
14370
14674
  const merged = { ...existing, ...settings };
14371
- writeFileSync6(join22(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
14675
+ writeFileSync6(join23(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
14372
14676
  }
14373
14677
  function resolveSettings(repoRoot) {
14374
14678
  const global = loadGlobalSettings();
@@ -14383,9 +14687,9 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
14383
14687
  while (dir && !visited.has(dir)) {
14384
14688
  visited.add(dir);
14385
14689
  for (const name of CONTEXT_FILES) {
14386
- const filePath = join22(dir, name);
14690
+ const filePath = join23(dir, name);
14387
14691
  const normalizedName = name.toLowerCase();
14388
- if (existsSync16(filePath) && !seen.has(filePath)) {
14692
+ if (existsSync17(filePath) && !seen.has(filePath)) {
14389
14693
  seen.add(filePath);
14390
14694
  try {
14391
14695
  let content = readFileSync13(filePath, "utf-8");
@@ -14402,8 +14706,8 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
14402
14706
  }
14403
14707
  }
14404
14708
  }
14405
- const projectMap = join22(dir, OA_DIR, "context", "project-map.md");
14406
- if (existsSync16(projectMap) && !seen.has(projectMap)) {
14709
+ const projectMap = join23(dir, OA_DIR, "context", "project-map.md");
14710
+ if (existsSync17(projectMap) && !seen.has(projectMap)) {
14407
14711
  seen.add(projectMap);
14408
14712
  try {
14409
14713
  let content = readFileSync13(projectMap, "utf-8");
@@ -14418,7 +14722,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
14418
14722
  } catch {
14419
14723
  }
14420
14724
  }
14421
- const parent = join22(dir, "..");
14725
+ const parent = join23(dir, "..");
14422
14726
  if (parent === dir)
14423
14727
  break;
14424
14728
  dir = parent;
@@ -14436,7 +14740,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
14436
14740
  return found;
14437
14741
  }
14438
14742
  function readIndexMeta(repoRoot) {
14439
- const metaPath = join22(repoRoot, OA_DIR, "index", "meta.json");
14743
+ const metaPath = join23(repoRoot, OA_DIR, "index", "meta.json");
14440
14744
  try {
14441
14745
  return JSON.parse(readFileSync13(metaPath, "utf-8"));
14442
14746
  } catch {
@@ -14445,7 +14749,7 @@ function readIndexMeta(repoRoot) {
14445
14749
  }
14446
14750
  function generateProjectMap(repoRoot) {
14447
14751
  const sections = [];
14448
- const repoName2 = basename7(repoRoot);
14752
+ const repoName2 = basename8(repoRoot);
14449
14753
  sections.push(`# Project Map: ${repoName2}
14450
14754
  `);
14451
14755
  sections.push(`> Auto-generated by open-agents. Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -14489,28 +14793,28 @@ ${tree}\`\`\`
14489
14793
  sections.push("");
14490
14794
  }
14491
14795
  const content = sections.join("\n");
14492
- const contextDir = join22(repoRoot, OA_DIR, "context");
14796
+ const contextDir = join23(repoRoot, OA_DIR, "context");
14493
14797
  mkdirSync6(contextDir, { recursive: true });
14494
- writeFileSync6(join22(contextDir, "project-map.md"), content, "utf-8");
14798
+ writeFileSync6(join23(contextDir, "project-map.md"), content, "utf-8");
14495
14799
  return content;
14496
14800
  }
14497
14801
  function saveSession(repoRoot, session) {
14498
- const historyDir = join22(repoRoot, OA_DIR, "history");
14802
+ const historyDir = join23(repoRoot, OA_DIR, "history");
14499
14803
  mkdirSync6(historyDir, { recursive: true });
14500
- writeFileSync6(join22(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
14804
+ writeFileSync6(join23(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
14501
14805
  }
14502
14806
  function loadRecentSessions(repoRoot, limit = 5) {
14503
- const historyDir = join22(repoRoot, OA_DIR, "history");
14504
- if (!existsSync16(historyDir))
14807
+ const historyDir = join23(repoRoot, OA_DIR, "history");
14808
+ if (!existsSync17(historyDir))
14505
14809
  return [];
14506
14810
  try {
14507
14811
  const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
14508
- const stat5 = statSync8(join22(historyDir, f));
14812
+ const stat5 = statSync9(join23(historyDir, f));
14509
14813
  return { file: f, mtime: stat5.mtimeMs };
14510
14814
  }).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
14511
14815
  return files.map((f) => {
14512
14816
  try {
14513
- return JSON.parse(readFileSync13(join22(historyDir, f.file), "utf-8"));
14817
+ return JSON.parse(readFileSync13(join23(historyDir, f.file), "utf-8"));
14514
14818
  } catch {
14515
14819
  return null;
14516
14820
  }
@@ -14520,14 +14824,14 @@ function loadRecentSessions(repoRoot, limit = 5) {
14520
14824
  }
14521
14825
  }
14522
14826
  function savePendingTask(repoRoot, task) {
14523
- const historyDir = join22(repoRoot, OA_DIR, "history");
14827
+ const historyDir = join23(repoRoot, OA_DIR, "history");
14524
14828
  mkdirSync6(historyDir, { recursive: true });
14525
- writeFileSync6(join22(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
14829
+ writeFileSync6(join23(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
14526
14830
  }
14527
14831
  function loadPendingTask(repoRoot) {
14528
- const filePath = join22(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
14832
+ const filePath = join23(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
14529
14833
  try {
14530
- if (!existsSync16(filePath))
14834
+ if (!existsSync17(filePath))
14531
14835
  return null;
14532
14836
  const data = JSON.parse(readFileSync13(filePath, "utf-8"));
14533
14837
  try {
@@ -14557,8 +14861,8 @@ function detectManifests(repoRoot) {
14557
14861
  { file: "docker-compose.yaml", type: "Docker Compose" }
14558
14862
  ];
14559
14863
  for (const check of checks) {
14560
- const filePath = join22(repoRoot, check.file);
14561
- if (existsSync16(filePath)) {
14864
+ const filePath = join23(repoRoot, check.file);
14865
+ if (existsSync17(filePath)) {
14562
14866
  let name;
14563
14867
  if (check.nameField) {
14564
14868
  try {
@@ -14591,7 +14895,7 @@ function findKeyFiles(repoRoot) {
14591
14895
  { pattern: "CLAUDE.md", description: "Claude Code context" }
14592
14896
  ];
14593
14897
  for (const check of checks) {
14594
- if (existsSync16(join22(repoRoot, check.pattern))) {
14898
+ if (existsSync17(join23(repoRoot, check.pattern))) {
14595
14899
  keyFiles.push({ path: check.pattern, description: check.description });
14596
14900
  }
14597
14901
  }
@@ -14617,12 +14921,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
14617
14921
  if (entry.isDirectory()) {
14618
14922
  let fileCount = 0;
14619
14923
  try {
14620
- fileCount = readdirSync7(join22(root, entry.name)).filter((f) => !f.startsWith(".")).length;
14924
+ fileCount = readdirSync7(join23(root, entry.name)).filter((f) => !f.startsWith(".")).length;
14621
14925
  } catch {
14622
14926
  }
14623
14927
  result += `${prefix}${connector}${entry.name}/ (${fileCount})
14624
14928
  `;
14625
- result += buildDirTree(join22(root, entry.name), maxDepth, childPrefix, depth + 1);
14929
+ result += buildDirTree(join23(root, entry.name), maxDepth, childPrefix, depth + 1);
14626
14930
  } else if (depth < maxDepth) {
14627
14931
  result += `${prefix}${connector}${entry.name}
14628
14932
  `;
@@ -14673,17 +14977,17 @@ var init_oa_directory = __esm({
14673
14977
 
14674
14978
  // packages/cli/dist/tui/setup.js
14675
14979
  import * as readline from "node:readline";
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";
14679
- import { homedir as homedir8, platform } from "node:os";
14980
+ import { execSync as execSync16, spawn as spawn8 } from "node:child_process";
14981
+ import { existsSync as existsSync18, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
14982
+ import { join as join24 } from "node:path";
14983
+ import { homedir as homedir9, platform } from "node:os";
14680
14984
  function detectSystemSpecs() {
14681
14985
  let totalRamGB = 0;
14682
14986
  let availableRamGB = 0;
14683
14987
  let gpuVramGB = 0;
14684
14988
  let gpuName = "";
14685
14989
  try {
14686
- const memInfo = execSync15("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
14990
+ const memInfo = execSync16("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
14687
14991
  encoding: "utf8",
14688
14992
  timeout: 5e3
14689
14993
  });
@@ -14703,7 +15007,7 @@ function detectSystemSpecs() {
14703
15007
  } catch {
14704
15008
  }
14705
15009
  try {
14706
- const nvidiaSmi = execSync15("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
15010
+ const nvidiaSmi = execSync16("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
14707
15011
  const lines = nvidiaSmi.trim().split("\n");
14708
15012
  if (lines.length > 0) {
14709
15013
  for (const line of lines) {
@@ -14759,8 +15063,8 @@ function modelSupportsToolCalling(modelName) {
14759
15063
  return false;
14760
15064
  }
14761
15065
  function ask(rl, question) {
14762
- return new Promise((resolve21) => {
14763
- rl.question(question, (answer) => resolve21(answer.trim()));
15066
+ return new Promise((resolve22) => {
15067
+ rl.question(question, (answer) => resolve22(answer.trim()));
14764
15068
  });
14765
15069
  }
14766
15070
  async function autoInstallOllama(rl) {
@@ -14785,7 +15089,7 @@ function installOllamaLinux() {
14785
15089
 
14786
15090
  `);
14787
15091
  try {
14788
- execSync15("curl -fsSL https://ollama.com/install.sh | sh", {
15092
+ execSync16("curl -fsSL https://ollama.com/install.sh | sh", {
14789
15093
  stdio: "inherit",
14790
15094
  timeout: 3e5
14791
15095
  });
@@ -14824,10 +15128,10 @@ async function installOllamaMac(rl) {
14824
15128
 
14825
15129
  `);
14826
15130
  try {
14827
- execSync15('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
15131
+ execSync16('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
14828
15132
  if (!hasCmd("brew")) {
14829
15133
  try {
14830
- const brewPrefix = existsSync17("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
15134
+ const brewPrefix = existsSync18("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
14831
15135
  process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
14832
15136
  } catch {
14833
15137
  }
@@ -14857,7 +15161,7 @@ async function installOllamaMac(rl) {
14857
15161
 
14858
15162
  `);
14859
15163
  try {
14860
- execSync15("brew install ollama", {
15164
+ execSync16("brew install ollama", {
14861
15165
  stdio: "inherit",
14862
15166
  timeout: 3e5
14863
15167
  });
@@ -14884,7 +15188,7 @@ function installOllamaWindows() {
14884
15188
 
14885
15189
  `);
14886
15190
  try {
14887
- execSync15('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
15191
+ execSync16('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
14888
15192
  stdio: "inherit",
14889
15193
  timeout: 3e5
14890
15194
  });
@@ -14907,7 +15211,7 @@ function installOllamaWindows() {
14907
15211
  }
14908
15212
  function pullModelWithAutoUpdate(tag) {
14909
15213
  try {
14910
- execSync15(`ollama pull ${tag}`, {
15214
+ execSync16(`ollama pull ${tag}`, {
14911
15215
  stdio: "inherit",
14912
15216
  timeout: 36e5
14913
15217
  // 1 hour max
@@ -14924,7 +15228,7 @@ function pullModelWithAutoUpdate(tag) {
14924
15228
 
14925
15229
  `);
14926
15230
  try {
14927
- execSync15("curl -fsSL https://ollama.com/install.sh | sh", {
15231
+ execSync16("curl -fsSL https://ollama.com/install.sh | sh", {
14928
15232
  stdio: "inherit",
14929
15233
  timeout: 3e5
14930
15234
  // 5 min max for install
@@ -14935,7 +15239,7 @@ function pullModelWithAutoUpdate(tag) {
14935
15239
  process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
14936
15240
 
14937
15241
  `);
14938
- execSync15(`ollama pull ${tag}`, {
15242
+ execSync16(`ollama pull ${tag}`, {
14939
15243
  stdio: "inherit",
14940
15244
  timeout: 36e5
14941
15245
  });
@@ -15118,7 +15422,7 @@ async function doSetup(config, rl) {
15118
15422
  try {
15119
15423
  const child = spawn8("ollama", ["serve"], { stdio: "ignore", detached: true });
15120
15424
  child.unref();
15121
- await new Promise((resolve21) => setTimeout(resolve21, 3e3));
15425
+ await new Promise((resolve22) => setTimeout(resolve22, 3e3));
15122
15426
  try {
15123
15427
  models = await fetchOllamaModels(config.backendUrl);
15124
15428
  process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
@@ -15146,7 +15450,7 @@ async function doSetup(config, rl) {
15146
15450
  try {
15147
15451
  const child = spawn8("ollama", ["serve"], { stdio: "ignore", detached: true });
15148
15452
  child.unref();
15149
- await new Promise((resolve21) => setTimeout(resolve21, 3e3));
15453
+ await new Promise((resolve22) => setTimeout(resolve22, 3e3));
15150
15454
  try {
15151
15455
  models = await fetchOllamaModels(config.backendUrl);
15152
15456
  process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
@@ -15300,12 +15604,12 @@ async function doSetup(config, rl) {
15300
15604
  `PARAMETER num_predict 16384`,
15301
15605
  `PARAMETER stop "<|endoftext|>"`
15302
15606
  ].join("\n");
15303
- const modelDir2 = join23(homedir8(), ".open-agents", "models");
15607
+ const modelDir2 = join24(homedir9(), ".open-agents", "models");
15304
15608
  mkdirSync7(modelDir2, { recursive: true });
15305
- const modelfilePath = join23(modelDir2, `Modelfile.${customName}`);
15609
+ const modelfilePath = join24(modelDir2, `Modelfile.${customName}`);
15306
15610
  writeFileSync7(modelfilePath, modelfileContent + "\n", "utf8");
15307
15611
  process.stdout.write(` ${c2.dim("Creating model...")} `);
15308
- execSync15(`ollama create ${customName} -f ${modelfilePath}`, {
15612
+ execSync16(`ollama create ${customName} -f ${modelfilePath}`, {
15309
15613
  stdio: "pipe",
15310
15614
  timeout: 12e4
15311
15615
  });
@@ -15348,7 +15652,7 @@ async function isModelAvailable(config) {
15348
15652
  }
15349
15653
  function isFirstRun() {
15350
15654
  try {
15351
- return !existsSync17(join23(homedir8(), ".open-agents", "config.json"));
15655
+ return !existsSync18(join24(homedir9(), ".open-agents", "config.json"));
15352
15656
  } catch {
15353
15657
  return true;
15354
15658
  }
@@ -15356,7 +15660,7 @@ function isFirstRun() {
15356
15660
  function hasCmd(cmd) {
15357
15661
  try {
15358
15662
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
15359
- execSync15(whichCmd, { stdio: "pipe", timeout: 3e3 });
15663
+ execSync16(whichCmd, { stdio: "pipe", timeout: 3e3 });
15360
15664
  return true;
15361
15665
  } catch {
15362
15666
  return false;
@@ -15385,11 +15689,11 @@ function detectPkgManager() {
15385
15689
  return null;
15386
15690
  }
15387
15691
  function getVenvDir() {
15388
- return join23(homedir8(), ".open-agents", "venv");
15692
+ return join24(homedir9(), ".open-agents", "venv");
15389
15693
  }
15390
15694
  function hasVenvModule() {
15391
15695
  try {
15392
- execSync15("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
15696
+ execSync16("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
15393
15697
  return true;
15394
15698
  } catch {
15395
15699
  return false;
@@ -15397,8 +15701,8 @@ function hasVenvModule() {
15397
15701
  }
15398
15702
  function ensureVenv(log) {
15399
15703
  const venvDir = getVenvDir();
15400
- const venvPip = join23(venvDir, "bin", "pip");
15401
- if (existsSync17(venvPip))
15704
+ const venvPip = join24(venvDir, "bin", "pip");
15705
+ if (existsSync18(venvPip))
15402
15706
  return venvDir;
15403
15707
  log("Creating Python venv for vision deps...");
15404
15708
  if (!hasCmd("python3")) {
@@ -15410,9 +15714,9 @@ function ensureVenv(log) {
15410
15714
  return null;
15411
15715
  }
15412
15716
  try {
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`, {
15717
+ mkdirSync7(join24(homedir9(), ".open-agents"), { recursive: true });
15718
+ execSync16(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
15719
+ execSync16(`"${join24(venvDir, "bin", "pip")}" install --upgrade pip`, {
15416
15720
  stdio: "pipe",
15417
15721
  timeout: 6e4
15418
15722
  });
@@ -15425,7 +15729,7 @@ function ensureVenv(log) {
15425
15729
  }
15426
15730
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
15427
15731
  try {
15428
- execSync15(`sudo -n ${cmd}`, {
15732
+ execSync16(`sudo -n ${cmd}`, {
15429
15733
  stdio: "pipe",
15430
15734
  timeout: timeoutMs,
15431
15735
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -15437,7 +15741,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
15437
15741
  }
15438
15742
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
15439
15743
  try {
15440
- execSync15(`sudo -S ${cmd}`, {
15744
+ execSync16(`sudo -S ${cmd}`, {
15441
15745
  input: password + "\n",
15442
15746
  stdio: ["pipe", "pipe", "pipe"],
15443
15747
  timeout: timeoutMs,
@@ -15497,7 +15801,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
15497
15801
  } else {
15498
15802
  log("Installing tesseract-ocr...");
15499
15803
  try {
15500
- execSync15(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
15804
+ execSync16(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
15501
15805
  if (hasCmd("tesseract")) {
15502
15806
  log("tesseract-ocr installed successfully.");
15503
15807
  } else {
@@ -15569,7 +15873,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
15569
15873
  } else {
15570
15874
  log(`Installing ${dep.label}...`);
15571
15875
  try {
15572
- execSync15(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
15876
+ execSync16(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
15573
15877
  if (hasCmd(dep.binary)) {
15574
15878
  log(`${dep.label} installed successfully.`);
15575
15879
  } else {
@@ -15600,7 +15904,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
15600
15904
  const venvCmds = {
15601
15905
  apt: () => {
15602
15906
  try {
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();
15907
+ const pyVer = execSync16(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
15604
15908
  return `apt-get install -y python3-venv python${pyVer}-venv`;
15605
15909
  } catch {
15606
15910
  return "apt-get install -y python3-venv";
@@ -15621,34 +15925,56 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
15621
15925
  }
15622
15926
  }
15623
15927
  const venvDir = getVenvDir();
15624
- const venvBin = join23(venvDir, "bin");
15625
- const venvMoondream = join23(venvBin, "moondream-station");
15626
- if (hasCmd("moondream-station") || existsSync17(venvMoondream)) {
15627
- return;
15628
- }
15928
+ const venvBin = join24(venvDir, "bin");
15929
+ const venvMoondream = join24(venvBin, "moondream-station");
15629
15930
  const venv = ensureVenv(log);
15630
- if (!venv) {
15631
- log("Python venv unavailable \u2014 moondream-station will not be installed.");
15632
- return;
15931
+ if (venv && !hasCmd("moondream-station") && !existsSync18(venvMoondream)) {
15932
+ const venvPip = join24(venvBin, "pip");
15933
+ log("Installing moondream-station in ~/.open-agents/venv...");
15934
+ try {
15935
+ execSync16(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
15936
+ if (existsSync18(venvMoondream)) {
15937
+ log("moondream-station installed successfully.");
15938
+ } else {
15939
+ try {
15940
+ const check = execSync16(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
15941
+ if (check.includes("moondream")) {
15942
+ log("moondream-station package installed.");
15943
+ }
15944
+ } catch {
15945
+ log("moondream-station install completed.");
15946
+ }
15947
+ }
15948
+ } catch (err) {
15949
+ log(`moondream-station install failed: ${err instanceof Error ? err.message : String(err)}`);
15950
+ }
15633
15951
  }
15634
- const venvPip = join23(venvBin, "pip");
15635
- log("Installing moondream-station in ~/.open-agents/venv...");
15636
- try {
15637
- execSync15(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
15638
- if (existsSync17(venvMoondream)) {
15639
- log("moondream-station installed successfully.");
15640
- } else {
15952
+ if (venv) {
15953
+ const venvPython = join24(venvBin, "python");
15954
+ const venvPip2 = join24(venvBin, "pip");
15955
+ let ocrStackInstalled = false;
15956
+ try {
15957
+ execSync16(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
15958
+ ocrStackInstalled = true;
15959
+ } catch {
15960
+ }
15961
+ if (!ocrStackInstalled) {
15962
+ const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
15963
+ log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
15641
15964
  try {
15642
- const check = execSync15(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
15643
- if (check.includes("moondream")) {
15644
- log("moondream-station package installed.");
15965
+ execSync16(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
15966
+ try {
15967
+ execSync16(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
15968
+ log("OCR Python stack installed successfully.");
15969
+ } catch {
15970
+ log("OCR Python stack install completed but import verification failed.");
15645
15971
  }
15646
- } catch {
15647
- log("moondream-station install completed.");
15972
+ } catch (err) {
15973
+ log(`OCR Python stack install failed: ${err instanceof Error ? err.message : String(err)}`);
15648
15974
  }
15649
15975
  }
15650
- } catch (err) {
15651
- log(`moondream-station install failed: ${err instanceof Error ? err.message : String(err)}`);
15976
+ } else {
15977
+ log("Python venv unavailable \u2014 advanced OCR pipeline will fall back to basic tesseract.");
15652
15978
  }
15653
15979
  }
15654
15980
  function expandedModelName(baseModel) {
@@ -15684,11 +16010,11 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
15684
16010
  `PARAMETER num_predict 16384`,
15685
16011
  `PARAMETER stop "<|endoftext|>"`
15686
16012
  ].join("\n");
15687
- const modelDir2 = join23(homedir8(), ".open-agents", "models");
16013
+ const modelDir2 = join24(homedir9(), ".open-agents", "models");
15688
16014
  mkdirSync7(modelDir2, { recursive: true });
15689
- const modelfilePath = join23(modelDir2, `Modelfile.${customName}`);
16015
+ const modelfilePath = join24(modelDir2, `Modelfile.${customName}`);
15690
16016
  writeFileSync7(modelfilePath, modelfileContent + "\n", "utf8");
15691
- execSync15(`ollama create ${customName} -f ${modelfilePath}`, {
16017
+ execSync16(`ollama create ${customName} -f ${modelfilePath}`, {
15692
16018
  stdio: "pipe",
15693
16019
  timeout: 12e4
15694
16020
  });
@@ -16375,18 +16701,18 @@ async function handleUpdate(subcommand, ctx) {
16375
16701
  let currentVersion = "0.0.0";
16376
16702
  try {
16377
16703
  const { createRequire: createRequire4 } = await import("node:module");
16378
- const { fileURLToPath: fileURLToPath7 } = await import("node:url");
16379
- const { dirname: dirname10, join: join34 } = await import("node:path");
16380
- const { existsSync: existsSync24 } = await import("node:fs");
16704
+ const { fileURLToPath: fileURLToPath8 } = await import("node:url");
16705
+ const { dirname: dirname11, join: join35 } = await import("node:path");
16706
+ const { existsSync: existsSync25 } = await import("node:fs");
16381
16707
  const req = createRequire4(import.meta.url);
16382
- const thisDir = dirname10(fileURLToPath7(import.meta.url));
16708
+ const thisDir = dirname11(fileURLToPath8(import.meta.url));
16383
16709
  const candidates = [
16384
- join34(thisDir, "..", "package.json"),
16385
- join34(thisDir, "..", "..", "package.json"),
16386
- join34(thisDir, "..", "..", "..", "package.json")
16710
+ join35(thisDir, "..", "package.json"),
16711
+ join35(thisDir, "..", "..", "package.json"),
16712
+ join35(thisDir, "..", "..", "..", "package.json")
16387
16713
  ];
16388
16714
  for (const pkgPath of candidates) {
16389
- if (existsSync24(pkgPath)) {
16715
+ if (existsSync25(pkgPath)) {
16390
16716
  const pkg = req(pkgPath);
16391
16717
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
16392
16718
  currentVersion = pkg.version ?? "0.0.0";
@@ -16411,9 +16737,9 @@ async function handleUpdate(subcommand, ctx) {
16411
16737
  process.stdout.write(` ${c2.cyan("\u25CF")} Installing update...
16412
16738
 
16413
16739
  `);
16414
- const { execSync: execSync19 } = await import("node:child_process");
16740
+ const { execSync: execSync20 } = await import("node:child_process");
16415
16741
  try {
16416
- execSync19(`npm cache clean --force open-agents-ai 2>/dev/null; npm install -g open-agents-ai@latest --force`, { stdio: "pipe", timeout: 18e4 });
16742
+ execSync20(`npm cache clean --force open-agents-ai 2>/dev/null; npm install -g open-agents-ai@latest --force`, { stdio: "pipe", timeout: 18e4 });
16417
16743
  } catch {
16418
16744
  renderWarning("Update install failed. Try manually: npm i -g open-agents-ai");
16419
16745
  return;
@@ -16500,10 +16826,10 @@ var init_commands = __esm({
16500
16826
  });
16501
16827
 
16502
16828
  // packages/cli/dist/tui/project-context.js
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";
16506
- import { homedir as homedir9, platform as platform2, release } from "node:os";
16829
+ import { existsSync as existsSync19, readFileSync as readFileSync14, readdirSync as readdirSync8 } from "node:fs";
16830
+ import { join as join25, basename as basename9 } from "node:path";
16831
+ import { execSync as execSync17 } from "node:child_process";
16832
+ import { homedir as homedir10, platform as platform2, release } from "node:os";
16507
16833
  function getModelTier(modelName) {
16508
16834
  const m = modelName.toLowerCase();
16509
16835
  const sizeMatch = m.match(/\b(\d+)b\b/);
@@ -16536,8 +16862,8 @@ function loadProjectMap(repoRoot) {
16536
16862
  if (!hasOaDirectory(repoRoot)) {
16537
16863
  initOaDirectory(repoRoot);
16538
16864
  }
16539
- const mapPath = join24(repoRoot, OA_DIR, "context", "project-map.md");
16540
- if (existsSync18(mapPath)) {
16865
+ const mapPath = join25(repoRoot, OA_DIR, "context", "project-map.md");
16866
+ if (existsSync19(mapPath)) {
16541
16867
  try {
16542
16868
  const content = readFileSync14(mapPath, "utf-8");
16543
16869
  return content;
@@ -16548,19 +16874,19 @@ function loadProjectMap(repoRoot) {
16548
16874
  }
16549
16875
  function getGitInfo(repoRoot) {
16550
16876
  try {
16551
- execSync16("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
16877
+ execSync17("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
16552
16878
  } catch {
16553
16879
  return "";
16554
16880
  }
16555
16881
  const lines = [];
16556
16882
  try {
16557
- const branch = execSync16("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16883
+ const branch = execSync17("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16558
16884
  if (branch)
16559
16885
  lines.push(`Branch: ${branch}`);
16560
16886
  } catch {
16561
16887
  }
16562
16888
  try {
16563
- const status = execSync16("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16889
+ const status = execSync17("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16564
16890
  if (status) {
16565
16891
  const changed = status.split("\n").length;
16566
16892
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -16570,7 +16896,7 @@ function getGitInfo(repoRoot) {
16570
16896
  } catch {
16571
16897
  }
16572
16898
  try {
16573
- const log = execSync16("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16899
+ const log = execSync17("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
16574
16900
  if (log)
16575
16901
  lines.push(`Recent commits:
16576
16902
  ${log}`);
@@ -16580,33 +16906,33 @@ ${log}`);
16580
16906
  }
16581
16907
  function loadMemoryContext(repoRoot) {
16582
16908
  const sections = [];
16583
- const oaMemDir = join24(repoRoot, OA_DIR, "memory");
16909
+ const oaMemDir = join25(repoRoot, OA_DIR, "memory");
16584
16910
  const oaEntries = loadMemoryDir(oaMemDir, "project");
16585
16911
  if (oaEntries)
16586
16912
  sections.push(oaEntries);
16587
- const legacyMemDir = join24(repoRoot, ".open-agents", "memory");
16588
- if (legacyMemDir !== oaMemDir && existsSync18(legacyMemDir)) {
16913
+ const legacyMemDir = join25(repoRoot, ".open-agents", "memory");
16914
+ if (legacyMemDir !== oaMemDir && existsSync19(legacyMemDir)) {
16589
16915
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
16590
16916
  if (legacyEntries)
16591
16917
  sections.push(legacyEntries);
16592
16918
  }
16593
- const globalMemDir = join24(homedir9(), ".open-agents", "memory");
16919
+ const globalMemDir = join25(homedir10(), ".open-agents", "memory");
16594
16920
  const globalEntries = loadMemoryDir(globalMemDir, "global");
16595
16921
  if (globalEntries)
16596
16922
  sections.push(globalEntries);
16597
16923
  return sections.join("\n\n");
16598
16924
  }
16599
16925
  function loadMemoryDir(memDir, scope) {
16600
- if (!existsSync18(memDir))
16926
+ if (!existsSync19(memDir))
16601
16927
  return "";
16602
16928
  const lines = [];
16603
16929
  try {
16604
16930
  const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
16605
16931
  for (const file of files.slice(0, 10)) {
16606
16932
  try {
16607
- const raw = readFileSync14(join24(memDir, file), "utf-8");
16933
+ const raw = readFileSync14(join25(memDir, file), "utf-8");
16608
16934
  const entries = JSON.parse(raw);
16609
- const topic = basename8(file, ".json");
16935
+ const topic = basename9(file, ".json");
16610
16936
  const keys = Object.keys(entries);
16611
16937
  if (keys.length === 0)
16612
16938
  continue;
@@ -17631,12 +17957,12 @@ var init_carousel = __esm({
17631
17957
  });
17632
17958
 
17633
17959
  // packages/cli/dist/tui/carousel-descriptors.js
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";
17960
+ import { existsSync as existsSync20, readFileSync as readFileSync15, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, readdirSync as readdirSync9 } from "node:fs";
17961
+ import { join as join26, basename as basename10 } from "node:path";
17636
17962
  function loadToolProfile(repoRoot) {
17637
- const filePath = join25(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
17963
+ const filePath = join26(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
17638
17964
  try {
17639
- if (!existsSync19(filePath))
17965
+ if (!existsSync20(filePath))
17640
17966
  return null;
17641
17967
  return JSON.parse(readFileSync15(filePath, "utf-8"));
17642
17968
  } catch {
@@ -17644,9 +17970,9 @@ function loadToolProfile(repoRoot) {
17644
17970
  }
17645
17971
  }
17646
17972
  function saveToolProfile(repoRoot, profile) {
17647
- const contextDir = join25(repoRoot, OA_DIR, "context");
17973
+ const contextDir = join26(repoRoot, OA_DIR, "context");
17648
17974
  mkdirSync8(contextDir, { recursive: true });
17649
- writeFileSync8(join25(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
17975
+ writeFileSync8(join26(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
17650
17976
  }
17651
17977
  function categorizeToolCall(toolName) {
17652
17978
  for (const cat of TOOL_CATEGORIES) {
@@ -17704,9 +18030,9 @@ function weightedColor(profile) {
17704
18030
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
17705
18031
  }
17706
18032
  function loadCachedDescriptors(repoRoot) {
17707
- const filePath = join25(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
18033
+ const filePath = join26(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
17708
18034
  try {
17709
- if (!existsSync19(filePath))
18035
+ if (!existsSync20(filePath))
17710
18036
  return null;
17711
18037
  const cached = JSON.parse(readFileSync15(filePath, "utf-8"));
17712
18038
  return cached.phrases.length > 0 ? cached.phrases : null;
@@ -17715,14 +18041,14 @@ function loadCachedDescriptors(repoRoot) {
17715
18041
  }
17716
18042
  }
17717
18043
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
17718
- const contextDir = join25(repoRoot, OA_DIR, "context");
18044
+ const contextDir = join26(repoRoot, OA_DIR, "context");
17719
18045
  mkdirSync8(contextDir, { recursive: true });
17720
18046
  const cached = {
17721
18047
  phrases,
17722
18048
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
17723
18049
  sourceHash
17724
18050
  };
17725
- writeFileSync8(join25(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
18051
+ writeFileSync8(join26(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
17726
18052
  }
17727
18053
  function generateDescriptors(repoRoot) {
17728
18054
  const profile = loadToolProfile(repoRoot);
@@ -17733,7 +18059,7 @@ function generateDescriptors(repoRoot) {
17733
18059
  extractFromSessions(repoRoot, tags);
17734
18060
  extractFromMemory(repoRoot, tags);
17735
18061
  extractFromToolProfile(profile, tags);
17736
- const repoName2 = basename9(repoRoot);
18062
+ const repoName2 = basename10(repoRoot);
17737
18063
  if (repoName2 && !tags.includes(repoName2)) {
17738
18064
  tags.push(repoName2);
17739
18065
  }
@@ -17770,9 +18096,9 @@ function generateDescriptors(repoRoot) {
17770
18096
  return phrases;
17771
18097
  }
17772
18098
  function extractFromPackageJson(repoRoot, tags) {
17773
- const pkgPath = join25(repoRoot, "package.json");
18099
+ const pkgPath = join26(repoRoot, "package.json");
17774
18100
  try {
17775
- if (!existsSync19(pkgPath))
18101
+ if (!existsSync20(pkgPath))
17776
18102
  return;
17777
18103
  const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
17778
18104
  if (pkg.name && typeof pkg.name === "string") {
@@ -17818,7 +18144,7 @@ function extractFromManifests(repoRoot, tags) {
17818
18144
  { file: ".github/workflows", tag: "ci/cd" }
17819
18145
  ];
17820
18146
  for (const check of manifestChecks) {
17821
- if (existsSync19(join25(repoRoot, check.file))) {
18147
+ if (existsSync20(join26(repoRoot, check.file))) {
17822
18148
  tags.push(check.tag);
17823
18149
  }
17824
18150
  }
@@ -17840,16 +18166,16 @@ function extractFromSessions(repoRoot, tags) {
17840
18166
  }
17841
18167
  }
17842
18168
  function extractFromMemory(repoRoot, tags) {
17843
- const memoryDir = join25(repoRoot, OA_DIR, "memory");
18169
+ const memoryDir = join26(repoRoot, OA_DIR, "memory");
17844
18170
  try {
17845
- if (!existsSync19(memoryDir))
18171
+ if (!existsSync20(memoryDir))
17846
18172
  return;
17847
18173
  const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
17848
18174
  for (const file of files) {
17849
18175
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
17850
18176
  tags.push(topic);
17851
18177
  try {
17852
- const data = JSON.parse(readFileSync15(join25(memoryDir, file), "utf-8"));
18178
+ const data = JSON.parse(readFileSync15(join26(memoryDir, file), "utf-8"));
17853
18179
  if (data && typeof data === "object") {
17854
18180
  const keys = Object.keys(data).slice(0, 3);
17855
18181
  for (const key of keys) {
@@ -17984,25 +18310,25 @@ var init_carousel_descriptors = __esm({
17984
18310
  });
17985
18311
 
17986
18312
  // packages/cli/dist/tui/voice.js
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";
18313
+ import { existsSync as existsSync21, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync16, unlinkSync as unlinkSync4 } from "node:fs";
18314
+ import { join as join27 } from "node:path";
18315
+ import { homedir as homedir11, tmpdir as tmpdir6, platform as platform3 } from "node:os";
18316
+ import { execSync as execSync18, spawn as nodeSpawn } from "node:child_process";
17991
18317
  import { createRequire } from "node:module";
17992
18318
  function voiceDir() {
17993
- return join26(homedir10(), ".open-agents", "voice");
18319
+ return join27(homedir11(), ".open-agents", "voice");
17994
18320
  }
17995
18321
  function modelsDir() {
17996
- return join26(voiceDir(), "models");
18322
+ return join27(voiceDir(), "models");
17997
18323
  }
17998
18324
  function modelDir(id) {
17999
- return join26(modelsDir(), id);
18325
+ return join27(modelsDir(), id);
18000
18326
  }
18001
18327
  function modelOnnxPath(id) {
18002
- return join26(modelDir(id), "model.onnx");
18328
+ return join27(modelDir(id), "model.onnx");
18003
18329
  }
18004
18330
  function modelConfigPath(id) {
18005
- return join26(modelDir(id), "config.json");
18331
+ return join27(modelDir(id), "config.json");
18006
18332
  }
18007
18333
  function describeToolCall(toolName, args) {
18008
18334
  const path = args["path"];
@@ -18275,7 +18601,7 @@ var init_voice = __esm({
18275
18601
  const audioData = result["output"].data;
18276
18602
  if (audioData.length === 0)
18277
18603
  return;
18278
- const wavPath = join26(tmpdir5(), `oa-voice-${Date.now()}.wav`);
18604
+ const wavPath = join27(tmpdir6(), `oa-voice-${Date.now()}.wav`);
18279
18605
  this.writeWav(audioData, this.config.audio.sample_rate, wavPath);
18280
18606
  await this.playWav(wavPath);
18281
18607
  try {
@@ -18364,7 +18690,7 @@ var init_voice = __esm({
18364
18690
  const cmd = this.getPlayCommand(path);
18365
18691
  if (!cmd)
18366
18692
  return;
18367
- return new Promise((resolve21) => {
18693
+ return new Promise((resolve22) => {
18368
18694
  const child = nodeSpawn(cmd[0], cmd.slice(1), {
18369
18695
  stdio: "ignore",
18370
18696
  detached: false
@@ -18373,12 +18699,12 @@ var init_voice = __esm({
18373
18699
  child.on("close", () => {
18374
18700
  if (this.currentPlayback === child)
18375
18701
  this.currentPlayback = null;
18376
- resolve21();
18702
+ resolve22();
18377
18703
  });
18378
18704
  child.on("error", () => {
18379
18705
  if (this.currentPlayback === child)
18380
18706
  this.currentPlayback = null;
18381
- resolve21();
18707
+ resolve22();
18382
18708
  });
18383
18709
  setTimeout(() => {
18384
18710
  if (this.currentPlayback === child) {
@@ -18388,7 +18714,7 @@ var init_voice = __esm({
18388
18714
  }
18389
18715
  this.currentPlayback = null;
18390
18716
  }
18391
- resolve21();
18717
+ resolve22();
18392
18718
  }, 15e3);
18393
18719
  });
18394
18720
  }
@@ -18405,7 +18731,7 @@ var init_voice = __esm({
18405
18731
  }
18406
18732
  for (const player of ["paplay", "pw-play", "aplay"]) {
18407
18733
  try {
18408
- execSync17(`which ${player}`, { stdio: "pipe" });
18734
+ execSync18(`which ${player}`, { stdio: "pipe" });
18409
18735
  return [player, path];
18410
18736
  } catch {
18411
18737
  }
@@ -18430,12 +18756,12 @@ var init_voice = __esm({
18430
18756
  const arch = process.arch;
18431
18757
  const isArmLinux = (arch === "arm64" || arch === "arm") && process.platform === "linux";
18432
18758
  mkdirSync9(voiceDir(), { recursive: true });
18433
- const pkgPath = join26(voiceDir(), "package.json");
18759
+ const pkgPath = join27(voiceDir(), "package.json");
18434
18760
  const expectedDeps = {
18435
18761
  "onnxruntime-node": "^1.21.0",
18436
18762
  "phonemizer": "^1.2.1"
18437
18763
  };
18438
- if (existsSync20(pkgPath)) {
18764
+ if (existsSync21(pkgPath)) {
18439
18765
  try {
18440
18766
  const existing = JSON.parse(readFileSync16(pkgPath, "utf8"));
18441
18767
  if (!existing.dependencies?.["phonemizer"]) {
@@ -18445,14 +18771,14 @@ var init_voice = __esm({
18445
18771
  } catch {
18446
18772
  }
18447
18773
  }
18448
- if (!existsSync20(pkgPath)) {
18774
+ if (!existsSync21(pkgPath)) {
18449
18775
  writeFileSync9(pkgPath, JSON.stringify({
18450
18776
  name: "open-agents-voice",
18451
18777
  private: true,
18452
18778
  dependencies: expectedDeps
18453
18779
  }, null, 2));
18454
18780
  }
18455
- const voiceRequire = createRequire(join26(voiceDir(), "index.js"));
18781
+ const voiceRequire = createRequire(join27(voiceDir(), "index.js"));
18456
18782
  try {
18457
18783
  this.ort = voiceRequire("onnxruntime-node");
18458
18784
  } catch {
@@ -18461,7 +18787,7 @@ var init_voice = __esm({
18461
18787
  }
18462
18788
  renderInfo("Installing ONNX runtime for voice synthesis...");
18463
18789
  try {
18464
- execSync17("npm install --no-audit --no-fund", {
18790
+ execSync18("npm install --no-audit --no-fund", {
18465
18791
  cwd: voiceDir(),
18466
18792
  stdio: "pipe",
18467
18793
  timeout: 12e4
@@ -18482,7 +18808,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
18482
18808
  }
18483
18809
  renderInfo("Installing phonemizer for voice synthesis...");
18484
18810
  try {
18485
- execSync17("npm install --no-audit --no-fund", {
18811
+ execSync18("npm install --no-audit --no-fund", {
18486
18812
  cwd: voiceDir(),
18487
18813
  stdio: "pipe",
18488
18814
  timeout: 12e4
@@ -18506,10 +18832,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
18506
18832
  const dir = modelDir(id);
18507
18833
  const onnxPath = modelOnnxPath(id);
18508
18834
  const configPath = modelConfigPath(id);
18509
- if (existsSync20(onnxPath) && existsSync20(configPath))
18835
+ if (existsSync21(onnxPath) && existsSync21(configPath))
18510
18836
  return;
18511
18837
  mkdirSync9(dir, { recursive: true });
18512
- if (!existsSync20(configPath)) {
18838
+ if (!existsSync21(configPath)) {
18513
18839
  renderInfo(`Downloading ${model.label} voice config...`);
18514
18840
  const configResp = await fetch(model.configUrl);
18515
18841
  if (!configResp.ok)
@@ -18517,7 +18843,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
18517
18843
  const configText = await configResp.text();
18518
18844
  writeFileSync9(configPath, configText);
18519
18845
  }
18520
- if (!existsSync20(onnxPath)) {
18846
+ if (!existsSync21(onnxPath)) {
18521
18847
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
18522
18848
  const onnxResp = await fetch(model.onnxUrl);
18523
18849
  if (!onnxResp.ok)
@@ -18553,7 +18879,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
18553
18879
  throw new Error("ONNX runtime not loaded");
18554
18880
  const onnxPath = modelOnnxPath(this.modelId);
18555
18881
  const configPath = modelConfigPath(this.modelId);
18556
- if (!existsSync20(onnxPath) || !existsSync20(configPath)) {
18882
+ if (!existsSync21(onnxPath) || !existsSync21(configPath)) {
18557
18883
  throw new Error(`Model files not found for ${this.modelId}`);
18558
18884
  }
18559
18885
  this.config = JSON.parse(readFileSync16(configPath, "utf8"));
@@ -19057,10 +19383,10 @@ var init_stream_renderer = __esm({
19057
19383
 
19058
19384
  // packages/cli/dist/tui/edit-history.js
19059
19385
  import { appendFileSync, mkdirSync as mkdirSync10 } from "node:fs";
19060
- import { join as join27 } from "node:path";
19386
+ import { join as join28 } from "node:path";
19061
19387
  function createEditHistoryLogger(repoRoot, sessionId) {
19062
- const historyDir = join27(repoRoot, ".oa", "history");
19063
- const logPath = join27(historyDir, "edits.jsonl");
19388
+ const historyDir = join28(repoRoot, ".oa", "history");
19389
+ const logPath = join28(historyDir, "edits.jsonl");
19064
19390
  try {
19065
19391
  mkdirSync10(historyDir, { recursive: true });
19066
19392
  } catch {
@@ -19171,9 +19497,9 @@ var init_edit_history = __esm({
19171
19497
  });
19172
19498
 
19173
19499
  // packages/cli/dist/tui/dream-engine.js
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";
19500
+ import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, readFileSync as readFileSync17, existsSync as existsSync22, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
19501
+ import { join as join29, basename as basename11 } from "node:path";
19502
+ import { execSync as execSync19 } from "node:child_process";
19177
19503
  function adaptTool(tool) {
19178
19504
  return {
19179
19505
  name: tool.name,
@@ -19347,12 +19673,12 @@ var init_dream_engine = __esm({
19347
19673
  const content = String(args["content"] ?? "");
19348
19674
  if (!rawPath)
19349
19675
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
19350
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join28(this.dreamsDir, basename10(rawPath)) : join28(this.dreamsDir, rawPath);
19676
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join29(this.dreamsDir, basename11(rawPath)) : join29(this.dreamsDir, rawPath);
19351
19677
  if (!targetPath.startsWith(this.dreamsDir)) {
19352
19678
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
19353
19679
  }
19354
19680
  try {
19355
- const dir = join28(targetPath, "..");
19681
+ const dir = join29(targetPath, "..");
19356
19682
  mkdirSync11(dir, { recursive: true });
19357
19683
  writeFileSync10(targetPath, content, "utf-8");
19358
19684
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -19382,12 +19708,12 @@ var init_dream_engine = __esm({
19382
19708
  const rawPath = String(args["path"] ?? "");
19383
19709
  const oldStr = String(args["old_string"] ?? "");
19384
19710
  const newStr = String(args["new_string"] ?? "");
19385
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join28(this.dreamsDir, basename10(rawPath)) : join28(this.dreamsDir, rawPath);
19711
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join29(this.dreamsDir, basename11(rawPath)) : join29(this.dreamsDir, rawPath);
19386
19712
  if (!targetPath.startsWith(this.dreamsDir)) {
19387
19713
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
19388
19714
  }
19389
19715
  try {
19390
- if (!existsSync21(targetPath)) {
19716
+ if (!existsSync22(targetPath)) {
19391
19717
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
19392
19718
  }
19393
19719
  let content = readFileSync17(targetPath, "utf-8");
@@ -19426,7 +19752,7 @@ var init_dream_engine = __esm({
19426
19752
  }
19427
19753
  }
19428
19754
  try {
19429
- const output = execSync18(cmd, {
19755
+ const output = execSync19(cmd, {
19430
19756
  cwd: this.repoRoot,
19431
19757
  timeout: 3e4,
19432
19758
  encoding: "utf-8",
@@ -19449,7 +19775,7 @@ var init_dream_engine = __esm({
19449
19775
  constructor(config, repoRoot) {
19450
19776
  this.config = config;
19451
19777
  this.repoRoot = repoRoot;
19452
- this.dreamsDir = join28(repoRoot, ".oa", "dreams");
19778
+ this.dreamsDir = join29(repoRoot, ".oa", "dreams");
19453
19779
  this.state = {
19454
19780
  mode: "default",
19455
19781
  active: false,
@@ -19521,7 +19847,7 @@ ${result.summary}`;
19521
19847
  if (mode !== "default" || cycle === totalCycles) {
19522
19848
  renderDreamContraction(cycle);
19523
19849
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
19524
- const summaryPath = join28(this.dreamsDir, `cycle-${cycle}-summary.md`);
19850
+ const summaryPath = join29(this.dreamsDir, `cycle-${cycle}-summary.md`);
19525
19851
  writeFileSync10(summaryPath, cycleSummary, "utf-8");
19526
19852
  }
19527
19853
  if (mode === "lucid" && !this.abortController.signal.aborted) {
@@ -19644,29 +19970,29 @@ Dreams directory: ${this.dreamsDir}`);
19644
19970
  }
19645
19971
  /** Save workspace backup for lucid mode */
19646
19972
  saveVersionCheckpoint(cycle) {
19647
- const checkpointDir = join28(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
19973
+ const checkpointDir = join29(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
19648
19974
  try {
19649
19975
  mkdirSync11(checkpointDir, { recursive: true });
19650
19976
  try {
19651
- const gitStatus = execSync18("git status --porcelain", {
19977
+ const gitStatus = execSync19("git status --porcelain", {
19652
19978
  cwd: this.repoRoot,
19653
19979
  encoding: "utf-8",
19654
19980
  timeout: 1e4
19655
19981
  });
19656
- const gitDiff = execSync18("git diff", {
19982
+ const gitDiff = execSync19("git diff", {
19657
19983
  cwd: this.repoRoot,
19658
19984
  encoding: "utf-8",
19659
19985
  timeout: 1e4
19660
19986
  });
19661
- const gitHash = execSync18("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
19987
+ const gitHash = execSync19("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
19662
19988
  cwd: this.repoRoot,
19663
19989
  encoding: "utf-8",
19664
19990
  timeout: 5e3
19665
19991
  }).trim();
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({
19992
+ writeFileSync10(join29(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
19993
+ writeFileSync10(join29(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
19994
+ writeFileSync10(join29(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
19995
+ writeFileSync10(join29(checkpointDir, "checkpoint.json"), JSON.stringify({
19670
19996
  cycle,
19671
19997
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
19672
19998
  gitHash,
@@ -19674,7 +20000,7 @@ Dreams directory: ${this.dreamsDir}`);
19674
20000
  }, null, 2), "utf-8");
19675
20001
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
19676
20002
  } catch {
19677
- writeFileSync10(join28(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
20003
+ writeFileSync10(join29(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
19678
20004
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
19679
20005
  }
19680
20006
  } catch (err) {
@@ -19732,14 +20058,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
19732
20058
  ---
19733
20059
  *Auto-generated by open-agents dream engine*
19734
20060
  `;
19735
- writeFileSync10(join28(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
20061
+ writeFileSync10(join29(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
19736
20062
  } catch {
19737
20063
  }
19738
20064
  }
19739
20065
  /** Save dream state for resume/inspection */
19740
20066
  saveDreamState() {
19741
20067
  try {
19742
- writeFileSync10(join28(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
20068
+ writeFileSync10(join29(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
19743
20069
  } catch {
19744
20070
  }
19745
20071
  }
@@ -20571,22 +20897,22 @@ var init_status_bar = __esm({
20571
20897
  import * as readline2 from "node:readline";
20572
20898
  import { Writable } from "node:stream";
20573
20899
  import { cwd } from "node:process";
20574
- import { resolve as resolve18, join as join29, dirname as dirname8, extname as extname9 } from "node:path";
20900
+ import { resolve as resolve19, join as join30, dirname as dirname9, extname as extname9 } from "node:path";
20575
20901
  import { createRequire as createRequire2 } from "node:module";
20576
- import { fileURLToPath as fileURLToPath5 } from "node:url";
20902
+ import { fileURLToPath as fileURLToPath6 } from "node:url";
20577
20903
  import { readFileSync as readFileSync18 } from "node:fs";
20578
- import { existsSync as existsSync22 } from "node:fs";
20904
+ import { existsSync as existsSync23 } from "node:fs";
20579
20905
  function getVersion() {
20580
20906
  try {
20581
20907
  const require2 = createRequire2(import.meta.url);
20582
- const thisDir = dirname8(fileURLToPath5(import.meta.url));
20908
+ const thisDir = dirname9(fileURLToPath6(import.meta.url));
20583
20909
  const candidates = [
20584
- join29(thisDir, "..", "package.json"),
20585
- join29(thisDir, "..", "..", "package.json"),
20586
- join29(thisDir, "..", "..", "..", "package.json")
20910
+ join30(thisDir, "..", "package.json"),
20911
+ join30(thisDir, "..", "..", "package.json"),
20912
+ join30(thisDir, "..", "..", "..", "package.json")
20587
20913
  ];
20588
20914
  for (const pkgPath of candidates) {
20589
- if (existsSync22(pkgPath)) {
20915
+ if (existsSync23(pkgPath)) {
20590
20916
  const pkg = require2(pkgPath);
20591
20917
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
20592
20918
  return pkg.version ?? "0.0.0";
@@ -20679,7 +21005,9 @@ function buildTools(repoRoot, config) {
20679
21005
  new DesktopDescribeTool(repoRoot),
20680
21006
  // PDF tools (OCR + text extraction)
20681
21007
  new OcrPdfTool(repoRoot),
20682
- new PdfToTextTool(repoRoot)
21008
+ new PdfToTextTool(repoRoot),
21009
+ // Advanced image OCR (multi-variant preprocessing pipeline)
21010
+ new OcrImageAdvancedTool(repoRoot)
20683
21011
  ];
20684
21012
  return [
20685
21013
  ...executionTools.map(adaptTool2),
@@ -20983,7 +21311,7 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
20983
21311
  } };
20984
21312
  }
20985
21313
  async function startInteractive(config, repoPath) {
20986
- const repoRoot = resolve18(repoPath ?? cwd());
21314
+ const repoRoot = resolve19(repoPath ?? cwd());
20987
21315
  const resumeFlag = process.env.__OA_RESUMED ?? "";
20988
21316
  const isResumed = resumeFlag !== "";
20989
21317
  const hasTaskToResume = resumeFlag === "1";
@@ -21135,14 +21463,14 @@ async function startInteractive(config, repoPath) {
21135
21463
  renderInfo(msg);
21136
21464
  statusBar.endContentWrite();
21137
21465
  }
21138
- }, () => new Promise((resolve21) => {
21466
+ }, () => new Promise((resolve22) => {
21139
21467
  depSudoPromptPending = true;
21140
21468
  depSudoResolver = (pw) => {
21141
21469
  depSudoPromptPending = false;
21142
21470
  depSudoResolver = null;
21143
21471
  if (pw)
21144
21472
  sessionSudoPassword = pw;
21145
- resolve21(pw);
21473
+ resolve22(pw);
21146
21474
  };
21147
21475
  if (statusBar?.isActive) {
21148
21476
  statusBar.beginContentWrite();
@@ -21654,12 +21982,12 @@ Execute this skill now. Follow the behavioral guidance above.`;
21654
21982
  }
21655
21983
  }
21656
21984
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
21657
- const isImage = isImagePath(cleanPath) && existsSync22(resolve18(repoRoot, cleanPath));
21658
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync22(resolve18(repoRoot, cleanPath));
21985
+ const isImage = isImagePath(cleanPath) && existsSync23(resolve19(repoRoot, cleanPath));
21986
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync23(resolve19(repoRoot, cleanPath));
21659
21987
  if (activeTask) {
21660
21988
  if (isImage) {
21661
21989
  try {
21662
- const imgPath = resolve18(repoRoot, cleanPath);
21990
+ const imgPath = resolve19(repoRoot, cleanPath);
21663
21991
  const imgBuffer = readFileSync18(imgPath);
21664
21992
  const base64 = imgBuffer.toString("base64");
21665
21993
  const ext = extname9(cleanPath).toLowerCase();
@@ -21673,7 +22001,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
21673
22001
  } else if (isMedia) {
21674
22002
  writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
21675
22003
  const engine = getListenEngine();
21676
- const result = await engine.transcribeFile(resolve18(repoRoot, cleanPath), repoRoot);
22004
+ const result = await engine.transcribeFile(resolve19(repoRoot, cleanPath), repoRoot);
21677
22005
  if (result) {
21678
22006
  const transcript = `[Transcription of ${cleanPath}]
21679
22007
  ${result.text}`;
@@ -21706,7 +22034,7 @@ ${result.text}`;
21706
22034
  if (isMedia && fullInput === input) {
21707
22035
  writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
21708
22036
  const engine = getListenEngine();
21709
- const result = await engine.transcribeFile(resolve18(repoRoot, cleanPath), repoRoot);
22037
+ const result = await engine.transcribeFile(resolve19(repoRoot, cleanPath), repoRoot);
21710
22038
  if (result) {
21711
22039
  fullInput = `The user has provided an audio/video file: ${cleanPath}.
21712
22040
 
@@ -21826,7 +22154,7 @@ ${c2.dim("(Use /quit to exit)")}
21826
22154
  });
21827
22155
  }
21828
22156
  async function runWithTUI(task, config, repoPath) {
21829
- const repoRoot = resolve18(repoPath ?? cwd());
22157
+ const repoRoot = resolve19(repoPath ?? cwd());
21830
22158
  const needsSetup = isFirstRun() || !await isModelAvailable(config);
21831
22159
  if (needsSetup && config.backendType === "ollama") {
21832
22160
  const setupModel = await runSetupWizard(config);
@@ -21931,7 +22259,7 @@ import { glob } from "glob";
21931
22259
  import ignore from "ignore";
21932
22260
  import { readFile as readFile10, stat as stat4 } from "node:fs/promises";
21933
22261
  import { createHash } from "node:crypto";
21934
- import { join as join30, relative as relative3, extname as extname10, basename as basename11 } from "node:path";
22262
+ import { join as join31, relative as relative3, extname as extname10, basename as basename12 } from "node:path";
21935
22263
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
21936
22264
  var init_codebase_indexer = __esm({
21937
22265
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -21975,7 +22303,7 @@ var init_codebase_indexer = __esm({
21975
22303
  const ig = ignore.default();
21976
22304
  if (this.config.respectGitignore) {
21977
22305
  try {
21978
- const gitignoreContent = await readFile10(join30(this.config.rootDir, ".gitignore"), "utf-8");
22306
+ const gitignoreContent = await readFile10(join31(this.config.rootDir, ".gitignore"), "utf-8");
21979
22307
  ig.add(gitignoreContent);
21980
22308
  } catch {
21981
22309
  }
@@ -21990,7 +22318,7 @@ var init_codebase_indexer = __esm({
21990
22318
  for (const relativePath of files) {
21991
22319
  if (ig.ignores(relativePath))
21992
22320
  continue;
21993
- const fullPath = join30(this.config.rootDir, relativePath);
22321
+ const fullPath = join31(this.config.rootDir, relativePath);
21994
22322
  try {
21995
22323
  const fileStat = await stat4(fullPath);
21996
22324
  if (fileStat.size > this.config.maxFileSize)
@@ -22013,7 +22341,7 @@ var init_codebase_indexer = __esm({
22013
22341
  }
22014
22342
  buildTree(files) {
22015
22343
  const root = {
22016
- name: basename11(this.config.rootDir),
22344
+ name: basename12(this.config.rootDir),
22017
22345
  path: this.config.rootDir,
22018
22346
  type: "directory",
22019
22347
  children: []
@@ -22036,7 +22364,7 @@ var init_codebase_indexer = __esm({
22036
22364
  if (!child) {
22037
22365
  child = {
22038
22366
  name: part,
22039
- path: join30(current.path, part),
22367
+ path: join31(current.path, part),
22040
22368
  type: "directory",
22041
22369
  children: []
22042
22370
  };
@@ -22110,18 +22438,18 @@ var index_repo_exports = {};
22110
22438
  __export(index_repo_exports, {
22111
22439
  indexRepoCommand: () => indexRepoCommand
22112
22440
  });
22113
- import { resolve as resolve19 } from "node:path";
22114
- import { existsSync as existsSync23, statSync as statSync9 } from "node:fs";
22441
+ import { resolve as resolve20 } from "node:path";
22442
+ import { existsSync as existsSync24, statSync as statSync10 } from "node:fs";
22115
22443
  import { cwd as cwd2 } from "node:process";
22116
22444
  async function indexRepoCommand(opts, _config) {
22117
- const repoRoot = resolve19(opts.repoPath ?? cwd2());
22445
+ const repoRoot = resolve20(opts.repoPath ?? cwd2());
22118
22446
  printHeader("Index Repository");
22119
22447
  printInfo(`Indexing: ${repoRoot}`);
22120
- if (!existsSync23(repoRoot)) {
22448
+ if (!existsSync24(repoRoot)) {
22121
22449
  printError(`Path does not exist: ${repoRoot}`);
22122
22450
  process.exit(1);
22123
22451
  }
22124
- const stat5 = statSync9(repoRoot);
22452
+ const stat5 = statSync10(repoRoot);
22125
22453
  if (!stat5.isDirectory()) {
22126
22454
  printError(`Path is not a directory: ${repoRoot}`);
22127
22455
  process.exit(1);
@@ -22363,8 +22691,8 @@ var config_exports = {};
22363
22691
  __export(config_exports, {
22364
22692
  configCommand: () => configCommand
22365
22693
  });
22366
- import { join as join31, resolve as resolve20 } from "node:path";
22367
- import { homedir as homedir11 } from "node:os";
22694
+ import { join as join32, resolve as resolve21 } from "node:path";
22695
+ import { homedir as homedir12 } from "node:os";
22368
22696
  import { cwd as cwd3 } from "node:process";
22369
22697
  function coerceForSettings(key, value) {
22370
22698
  if (INT_KEYS.has(key))
@@ -22384,7 +22712,7 @@ async function configCommand(opts, config) {
22384
22712
  return handleShow(opts, config);
22385
22713
  }
22386
22714
  function handleShow(opts, config) {
22387
- const repoRoot = resolve20(opts.repoPath ?? cwd3());
22715
+ const repoRoot = resolve21(opts.repoPath ?? cwd3());
22388
22716
  printHeader("Configuration");
22389
22717
  printSection("Active Settings (merged)");
22390
22718
  printKeyValue("backendUrl", config.backendUrl, 2);
@@ -22416,7 +22744,7 @@ function handleShow(opts, config) {
22416
22744
  }
22417
22745
  }
22418
22746
  printSection("Config File");
22419
- printInfo(`~/.open-agents/config.json (${join31(homedir11(), ".open-agents", "config.json")})`);
22747
+ printInfo(`~/.open-agents/config.json (${join32(homedir12(), ".open-agents", "config.json")})`);
22420
22748
  printSection("Priority Chain");
22421
22749
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
22422
22750
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -22449,13 +22777,13 @@ function handleSet(opts, _config) {
22449
22777
  process.exit(1);
22450
22778
  }
22451
22779
  if (opts.local) {
22452
- const repoRoot = resolve20(opts.repoPath ?? cwd3());
22780
+ const repoRoot = resolve21(opts.repoPath ?? cwd3());
22453
22781
  try {
22454
22782
  initOaDirectory(repoRoot);
22455
22783
  const coerced = coerceForSettings(key, value);
22456
22784
  saveProjectSettings(repoRoot, { [key]: coerced });
22457
22785
  printSuccess(`Project override set: ${key} = ${value}`);
22458
- printInfo(`Saved to ${join31(repoRoot, ".oa", "settings.json")}`);
22786
+ printInfo(`Saved to ${join32(repoRoot, ".oa", "settings.json")}`);
22459
22787
  printInfo("This override applies only when running in this workspace.");
22460
22788
  } catch (err) {
22461
22789
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -22607,7 +22935,7 @@ async function serveVllm(opts, config) {
22607
22935
  await runVllmServer(args, opts.verbose ?? false);
22608
22936
  }
22609
22937
  async function runVllmServer(args, verbose) {
22610
- return new Promise((resolve21, reject) => {
22938
+ return new Promise((resolve22, reject) => {
22611
22939
  const child = spawn9("python", args, {
22612
22940
  stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
22613
22941
  env: { ...process.env }
@@ -22642,10 +22970,10 @@ async function runVllmServer(args, verbose) {
22642
22970
  child.once("exit", (code, signal) => {
22643
22971
  if (signal) {
22644
22972
  printInfo(`vLLM server stopped by signal ${signal}`);
22645
- resolve21();
22973
+ resolve22();
22646
22974
  } else if (code === 0) {
22647
22975
  printSuccess("vLLM server exited cleanly");
22648
- resolve21();
22976
+ resolve22();
22649
22977
  } else {
22650
22978
  printError(`vLLM server exited with code ${code}`);
22651
22979
  reject(new Error(`vLLM exited with code ${code}`));
@@ -22672,9 +23000,9 @@ var eval_exports = {};
22672
23000
  __export(eval_exports, {
22673
23001
  evalCommand: () => evalCommand
22674
23002
  });
22675
- import { tmpdir as tmpdir6 } from "node:os";
23003
+ import { tmpdir as tmpdir7 } from "node:os";
22676
23004
  import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
22677
- import { join as join32 } from "node:path";
23005
+ import { join as join33 } from "node:path";
22678
23006
  async function evalCommand(opts, config) {
22679
23007
  const suiteName = opts.suite ?? "basic";
22680
23008
  const suite = SUITES[suiteName];
@@ -22795,9 +23123,9 @@ async function evalCommand(opts, config) {
22795
23123
  process.exit(failed > 0 ? 1 : 0);
22796
23124
  }
22797
23125
  function createTempEvalRepo() {
22798
- const dir = join32(tmpdir6(), `open-agents-eval-${Date.now()}`);
23126
+ const dir = join33(tmpdir7(), `open-agents-eval-${Date.now()}`);
22799
23127
  mkdirSync12(dir, { recursive: true });
22800
- writeFileSync11(join32(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
23128
+ writeFileSync11(join33(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
22801
23129
  return dir;
22802
23130
  }
22803
23131
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -22856,8 +23184,8 @@ init_output();
22856
23184
  init_updater();
22857
23185
  import { parseArgs as nodeParseArgs2 } from "node:util";
22858
23186
  import { createRequire as createRequire3 } from "node:module";
22859
- import { fileURLToPath as fileURLToPath6 } from "node:url";
22860
- import { dirname as dirname9, join as join33 } from "node:path";
23187
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
23188
+ import { dirname as dirname10, join as join34 } from "node:path";
22861
23189
 
22862
23190
  // packages/cli/dist/cli.js
22863
23191
  import { createInterface } from "node:readline";
@@ -22964,7 +23292,7 @@ init_output();
22964
23292
  function getVersion2() {
22965
23293
  try {
22966
23294
  const require2 = createRequire3(import.meta.url);
22967
- const pkgPath = join33(dirname9(fileURLToPath6(import.meta.url)), "..", "package.json");
23295
+ const pkgPath = join34(dirname10(fileURLToPath7(import.meta.url)), "..", "package.json");
22968
23296
  const pkg = require2(pkgPath);
22969
23297
  return pkg.version;
22970
23298
  } catch {