open-agents-ai 0.92.0 → 0.93.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.
Files changed (2) hide show
  1. package/dist/index.js +770 -424
  2. package/package.json +5 -2
package/dist/index.js CHANGED
@@ -320,23 +320,39 @@ async function checkForUpdate(currentVersion, forceCheck = false) {
320
320
  latestVersion: latest
321
321
  };
322
322
  }
323
+ function cleanStaleNpmTempDirs(sudo) {
324
+ try {
325
+ const prefix = execSync("npm prefix -g", { encoding: "utf-8", stdio: "pipe", timeout: 5e3 }).trim();
326
+ const globalModules = prefix.endsWith("/lib") ? prefix + "/node_modules" : prefix + "/lib/node_modules";
327
+ const sudoCmd = sudo ? "sudo " : "";
328
+ execSync(`${sudoCmd}find "${globalModules}" -maxdepth 1 -name ".${PACKAGE_NAME}-*" -type d -exec rm -rf {} + 2>/dev/null || true`, { stdio: "pipe", timeout: 15e3 });
329
+ execSync(`${sudoCmd}rm -rf "${globalModules}/${PACKAGE_NAME}" 2>/dev/null || true`, { stdio: "pipe", timeout: 15e3 });
330
+ } catch {
331
+ }
332
+ }
323
333
  function performSilentUpdate() {
324
334
  const installCmd = `npm install -g ${PACKAGE_NAME}@latest --prefer-online`;
325
- try {
326
- execSync(installCmd, { stdio: "pipe", timeout: 12e4 });
327
- return true;
328
- } catch (err) {
329
- const msg = err instanceof Error ? err.message : String(err);
330
- if (/EACCES|permission denied/i.test(msg)) {
331
- try {
332
- execSync(`sudo -n ${installCmd}`, { stdio: "pipe", timeout: 12e4 });
333
- return true;
334
- } catch {
335
- return false;
335
+ const trySilent = (cmd, sudo) => {
336
+ try {
337
+ execSync(cmd, { stdio: "pipe", timeout: 12e4 });
338
+ return true;
339
+ } catch (err) {
340
+ const msg = err instanceof Error ? err.message : String(err);
341
+ if (/ENOTEMPTY|errno -39/i.test(msg)) {
342
+ cleanStaleNpmTempDirs(sudo);
343
+ try {
344
+ execSync(cmd, { stdio: "pipe", timeout: 12e4 });
345
+ return true;
346
+ } catch {
347
+ return false;
348
+ }
336
349
  }
350
+ return false;
337
351
  }
338
- return false;
339
- }
352
+ };
353
+ if (trySilent(installCmd, false))
354
+ return true;
355
+ return trySilent(`sudo -n ${installCmd}`, true);
340
356
  }
341
357
  function formatUpdateBanner(info) {
342
358
  return `
@@ -10743,10 +10759,319 @@ var init_opencode = __esm({
10743
10759
  }
10744
10760
  });
10745
10761
 
10762
+ // packages/execution/dist/tools/factory.js
10763
+ import { execSync as execSync20, spawn as spawn10 } from "node:child_process";
10764
+ import { existsSync as existsSync21 } from "node:fs";
10765
+ import { join as join27 } from "node:path";
10766
+ function findDroid() {
10767
+ for (const cmd of ["droid"]) {
10768
+ try {
10769
+ const path = execSync20(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
10770
+ if (path)
10771
+ return path;
10772
+ } catch {
10773
+ }
10774
+ }
10775
+ const homeDir = process.env.HOME || process.env.USERPROFILE || "";
10776
+ const candidates = [
10777
+ join27(homeDir, ".factory", "bin", "droid"),
10778
+ join27(homeDir, "bin", "droid"),
10779
+ "/usr/local/bin/droid"
10780
+ ];
10781
+ for (const p of candidates) {
10782
+ if (existsSync21(p))
10783
+ return p;
10784
+ }
10785
+ return null;
10786
+ }
10787
+ function getVersion2(binary) {
10788
+ try {
10789
+ return execSync20(`${binary} --version 2>/dev/null`, { stdio: "pipe", timeout: 1e4 }).toString().trim();
10790
+ } catch {
10791
+ return "unknown";
10792
+ }
10793
+ }
10794
+ function installDroid() {
10795
+ const platform4 = process.platform;
10796
+ try {
10797
+ if (platform4 === "win32") {
10798
+ execSync20('powershell -Command "irm https://app.factory.ai/cli/windows | iex"', {
10799
+ stdio: "pipe",
10800
+ timeout: 12e4
10801
+ });
10802
+ } else {
10803
+ execSync20("curl -fsSL https://app.factory.ai/cli | sh", {
10804
+ stdio: "pipe",
10805
+ timeout: 12e4
10806
+ });
10807
+ }
10808
+ const binary = findDroid();
10809
+ if (binary) {
10810
+ const version = getVersion2(binary);
10811
+ return { success: true, message: `Factory CLI installed successfully (${version}) at ${binary}` };
10812
+ }
10813
+ return { success: false, message: "Install script completed but droid binary not found in PATH" };
10814
+ } catch (err) {
10815
+ return {
10816
+ success: false,
10817
+ message: `Installation failed: ${err instanceof Error ? err.message : String(err)}`
10818
+ };
10819
+ }
10820
+ }
10821
+ var FactoryTool;
10822
+ var init_factory = __esm({
10823
+ "packages/execution/dist/tools/factory.js"() {
10824
+ "use strict";
10825
+ FactoryTool = class {
10826
+ name = "factory";
10827
+ description = "Delegate coding tasks to Factory AI's Droid, a high-performance autonomous coding agent. Actions: 'install' the Factory CLI if not present, 'run' a coding task via droid exec (non-interactive, fully autonomous), 'status' check availability and API key. Factory's Droid leads the Terminal Bench for code generation. Use this to offload complex coding tasks to a separate agent that can read, write, search, test, and commit code independently. Requires FACTORY_API_KEY environment variable.";
10828
+ parameters = {
10829
+ type: "object",
10830
+ properties: {
10831
+ action: {
10832
+ type: "string",
10833
+ enum: ["install", "run", "status"],
10834
+ description: "Action: 'install' Factory CLI, 'run' a coding task, 'status' check availability"
10835
+ },
10836
+ task: {
10837
+ type: "string",
10838
+ description: "The coding task to delegate (for 'run' action). Be specific about what files to modify and what outcome to achieve."
10839
+ },
10840
+ auto: {
10841
+ type: "string",
10842
+ enum: ["low", "medium", "high"],
10843
+ description: "Autonomy level controlling what droid can do. 'low': file edits only, 'medium': + install deps/git commit/build, 'high': + git push/prod deploys. Default: read-only (no --auto flag)."
10844
+ },
10845
+ model: {
10846
+ type: "string",
10847
+ description: "Model ID to use (optional, uses Factory default if omitted)"
10848
+ },
10849
+ directory: {
10850
+ type: "string",
10851
+ description: "Working directory for the task (optional, defaults to current project root)"
10852
+ },
10853
+ timeout_seconds: {
10854
+ type: "number",
10855
+ description: "Maximum execution time in seconds (default: 600 = 10 minutes)"
10856
+ },
10857
+ reasoning_effort: {
10858
+ type: "string",
10859
+ enum: ["low", "medium", "high"],
10860
+ description: "Reasoning effort level (optional, defaults to medium)"
10861
+ },
10862
+ output_format: {
10863
+ type: "string",
10864
+ enum: ["text", "json", "stream-json"],
10865
+ description: "Output format: 'text' for human-readable, 'json' for structured, 'stream-json' for JSONL events (default: 'text')"
10866
+ },
10867
+ session_id: {
10868
+ type: "string",
10869
+ description: "Continue an existing session by ID (optional)"
10870
+ }
10871
+ },
10872
+ required: ["action"]
10873
+ };
10874
+ workingDir;
10875
+ constructor(workingDir) {
10876
+ this.workingDir = workingDir;
10877
+ }
10878
+ async execute(args) {
10879
+ const start = performance.now();
10880
+ const action = String(args["action"] ?? "status");
10881
+ try {
10882
+ switch (action) {
10883
+ case "install":
10884
+ return this.doInstall(start);
10885
+ case "run":
10886
+ return await this.doRun(args, start);
10887
+ case "status":
10888
+ return this.doStatus(start);
10889
+ default:
10890
+ return {
10891
+ success: false,
10892
+ output: "",
10893
+ error: `Unknown action '${action}'. Use: install, run, status`,
10894
+ durationMs: performance.now() - start
10895
+ };
10896
+ }
10897
+ } catch (err) {
10898
+ return {
10899
+ success: false,
10900
+ output: "",
10901
+ error: `factory error: ${err instanceof Error ? err.message : String(err)}`,
10902
+ durationMs: performance.now() - start
10903
+ };
10904
+ }
10905
+ }
10906
+ doInstall(start) {
10907
+ const existing = findDroid();
10908
+ if (existing) {
10909
+ const version = getVersion2(existing);
10910
+ return {
10911
+ success: true,
10912
+ output: `Factory CLI (droid) is already installed at ${existing} (${version}). No action needed.`,
10913
+ durationMs: performance.now() - start
10914
+ };
10915
+ }
10916
+ const result = installDroid();
10917
+ return {
10918
+ success: result.success,
10919
+ output: result.success ? result.message : "",
10920
+ error: result.success ? void 0 : result.message,
10921
+ durationMs: performance.now() - start
10922
+ };
10923
+ }
10924
+ async doRun(args, start) {
10925
+ const task = String(args["task"] ?? "");
10926
+ if (!task) {
10927
+ return { success: false, output: "", error: "task is required for run action", durationMs: performance.now() - start };
10928
+ }
10929
+ if (!process.env.FACTORY_API_KEY) {
10930
+ return {
10931
+ success: false,
10932
+ output: "",
10933
+ error: "FACTORY_API_KEY environment variable is not set. Get one from https://app.factory.ai/settings and export FACTORY_API_KEY=fk-...",
10934
+ durationMs: performance.now() - start
10935
+ };
10936
+ }
10937
+ let binary = findDroid();
10938
+ if (!binary) {
10939
+ const installResult = installDroid();
10940
+ if (!installResult.success) {
10941
+ return {
10942
+ success: false,
10943
+ output: "",
10944
+ error: `droid CLI not found and auto-install failed: ${installResult.message}`,
10945
+ durationMs: performance.now() - start
10946
+ };
10947
+ }
10948
+ binary = findDroid();
10949
+ if (!binary) {
10950
+ return {
10951
+ success: false,
10952
+ output: "",
10953
+ error: "Factory CLI installed but droid binary not found in PATH. Try adding it to your PATH.",
10954
+ durationMs: performance.now() - start
10955
+ };
10956
+ }
10957
+ }
10958
+ const dir = String(args["directory"] ?? this.workingDir);
10959
+ const model = args["model"] ? String(args["model"]) : void 0;
10960
+ const auto = args["auto"] ? String(args["auto"]) : void 0;
10961
+ const outputFormat = args["output_format"] ? String(args["output_format"]) : "text";
10962
+ const reasoningEffort = args["reasoning_effort"] ? String(args["reasoning_effort"]) : void 0;
10963
+ const sessionId = args["session_id"] ? String(args["session_id"]) : void 0;
10964
+ const timeoutSec = typeof args["timeout_seconds"] === "number" ? args["timeout_seconds"] : 600;
10965
+ const cmdArgs = ["exec"];
10966
+ if (model)
10967
+ cmdArgs.push("--model", model);
10968
+ if (auto)
10969
+ cmdArgs.push("--auto", auto);
10970
+ if (outputFormat !== "text")
10971
+ cmdArgs.push("--output-format", outputFormat);
10972
+ if (reasoningEffort)
10973
+ cmdArgs.push("--reasoning-effort", reasoningEffort);
10974
+ if (sessionId)
10975
+ cmdArgs.push("--session-id", sessionId);
10976
+ cmdArgs.push("--cwd", dir);
10977
+ cmdArgs.push(task);
10978
+ return new Promise((resolvePromise) => {
10979
+ let output = "";
10980
+ const maxOutput = 5e5;
10981
+ let timedOut = false;
10982
+ const child = spawn10(binary, cmdArgs, {
10983
+ cwd: dir,
10984
+ env: { ...process.env },
10985
+ stdio: ["ignore", "pipe", "pipe"]
10986
+ });
10987
+ child.stdout?.on("data", (chunk) => {
10988
+ if (output.length < maxOutput) {
10989
+ output += chunk.toString();
10990
+ }
10991
+ });
10992
+ child.stderr?.on("data", (chunk) => {
10993
+ if (output.length < maxOutput) {
10994
+ output += chunk.toString();
10995
+ }
10996
+ });
10997
+ const timer = setTimeout(() => {
10998
+ timedOut = true;
10999
+ try {
11000
+ child.kill("SIGTERM");
11001
+ } catch {
11002
+ }
11003
+ }, timeoutSec * 1e3);
11004
+ child.on("close", (code) => {
11005
+ clearTimeout(timer);
11006
+ if (timedOut) {
11007
+ resolvePromise({
11008
+ success: false,
11009
+ output: output.slice(-1e4),
11010
+ error: `droid exec timed out after ${timeoutSec}s. Partial output included.`,
11011
+ durationMs: performance.now() - start
11012
+ });
11013
+ return;
11014
+ }
11015
+ const truncated = output.length > 5e4 ? output.slice(0, 5e3) + "\n\n...(truncated)...\n\n" + output.slice(-1e4) : output;
11016
+ resolvePromise({
11017
+ success: code === 0,
11018
+ output: truncated || "(no output)",
11019
+ error: code !== 0 ? `droid exec exited with code ${code}` : void 0,
11020
+ durationMs: performance.now() - start
11021
+ });
11022
+ });
11023
+ child.on("error", (err) => {
11024
+ clearTimeout(timer);
11025
+ resolvePromise({
11026
+ success: false,
11027
+ output: "",
11028
+ error: `Failed to spawn droid: ${err.message}`,
11029
+ durationMs: performance.now() - start
11030
+ });
11031
+ });
11032
+ });
11033
+ }
11034
+ doStatus(start) {
11035
+ const binary = findDroid();
11036
+ const hasApiKey = !!process.env.FACTORY_API_KEY;
11037
+ if (binary) {
11038
+ const version = getVersion2(binary);
11039
+ const lines = [
11040
+ `Factory CLI (droid) is installed`,
11041
+ ` Binary: ${binary}`,
11042
+ ` Version: ${version}`,
11043
+ ` API Key: ${hasApiKey ? "set" : "NOT SET \u2014 export FACTORY_API_KEY=fk-..."}`,
11044
+ ``,
11045
+ `Usage: factory(action='run', task='your coding task', auto='low')`,
11046
+ ` Autonomy levels: omit for read-only, 'low' for edits, 'medium' for builds/deps, 'high' for git push`,
11047
+ ` The task runs fully autonomously via droid exec.`
11048
+ ];
11049
+ return {
11050
+ success: true,
11051
+ output: lines.join("\n"),
11052
+ durationMs: performance.now() - start
11053
+ };
11054
+ }
11055
+ return {
11056
+ success: true,
11057
+ output: [
11058
+ `Factory CLI (droid) is NOT installed.`,
11059
+ ` API Key: ${hasApiKey ? "set" : "NOT SET \u2014 export FACTORY_API_KEY=fk-..."}`,
11060
+ ``,
11061
+ `Use factory(action='install') to install it.`,
11062
+ `Manual install: curl -fsSL https://app.factory.ai/cli | sh`
11063
+ ].join("\n"),
11064
+ durationMs: performance.now() - start
11065
+ };
11066
+ }
11067
+ };
11068
+ }
11069
+ });
11070
+
10746
11071
  // packages/execution/dist/tools/cron-agent.js
10747
- import { execSync as execSync20 } from "node:child_process";
11072
+ import { execSync as execSync21 } from "node:child_process";
10748
11073
  import { readFile as readFile12, writeFile as writeFile11, mkdir as mkdir7 } from "node:fs/promises";
10749
- import { resolve as resolve25, join as join27 } from "node:path";
11074
+ import { resolve as resolve25, join as join28 } from "node:path";
10750
11075
  import { randomBytes as randomBytes5 } from "node:crypto";
10751
11076
  function isValidCron2(expr) {
10752
11077
  const parts = expr.trim().split(/\s+/);
@@ -10808,19 +11133,19 @@ function resolveSchedule2(schedule) {
10808
11133
  }
10809
11134
  function getCurrentCrontab2() {
10810
11135
  try {
10811
- return execSync20("crontab -l 2>/dev/null", { stdio: "pipe" }).toString().split("\n");
11136
+ return execSync21("crontab -l 2>/dev/null", { stdio: "pipe" }).toString().split("\n");
10812
11137
  } catch {
10813
11138
  return [];
10814
11139
  }
10815
11140
  }
10816
11141
  function writeCrontab2(lines) {
10817
11142
  const content = lines.join("\n") + "\n";
10818
- execSync20(`echo ${JSON.stringify(content)} | crontab -`, { stdio: "pipe" });
11143
+ execSync21(`echo ${JSON.stringify(content)} | crontab -`, { stdio: "pipe" });
10819
11144
  }
10820
11145
  function findOaBinary2() {
10821
11146
  for (const cmd of ["oa", "open-agents"]) {
10822
11147
  try {
10823
- const path = execSync20(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
11148
+ const path = execSync21(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
10824
11149
  if (path)
10825
11150
  return path;
10826
11151
  } catch {
@@ -10832,7 +11157,7 @@ function installCronAgentJob(job, workingDir) {
10832
11157
  const lines = getCurrentCrontab2();
10833
11158
  const oaBin = findOaBinary2();
10834
11159
  const logDir = resolve25(workingDir, ".oa", "cron-agents", "logs");
10835
- const logFile = join27(logDir, `${job.id}.log`);
11160
+ const logFile = join28(logDir, `${job.id}.log`);
10836
11161
  const storeFile = resolve25(workingDir, ".oa", "cron-agents", "store.json");
10837
11162
  const taskEscaped = job.task.replace(/'/g, "'\\''");
10838
11163
  const jobId = job.id;
@@ -10871,9 +11196,9 @@ async function loadStore2(workingDir) {
10871
11196
  async function saveStore2(workingDir, store) {
10872
11197
  const dir = resolve25(workingDir, ".oa", "cron-agents");
10873
11198
  await mkdir7(dir, { recursive: true });
10874
- await mkdir7(join27(dir, "logs"), { recursive: true });
11199
+ await mkdir7(join28(dir, "logs"), { recursive: true });
10875
11200
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
10876
- await writeFile11(join27(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
11201
+ await writeFile11(join28(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
10877
11202
  }
10878
11203
  var LONG_HORIZON_PRESETS, CRON_AGENT_MARKER, CronAgentTool;
10879
11204
  var init_cron_agent = __esm({
@@ -11163,7 +11488,7 @@ ${truncated}`, durationMs: performance.now() - start };
11163
11488
  ];
11164
11489
  if (job.verifyCommand) {
11165
11490
  try {
11166
- const result = execSync20(job.verifyCommand, {
11491
+ const result = execSync21(job.verifyCommand, {
11167
11492
  cwd: this.workingDir,
11168
11493
  stdio: "pipe",
11169
11494
  timeout: 3e4
@@ -11210,10 +11535,10 @@ ${truncated}`, durationMs: performance.now() - start };
11210
11535
 
11211
11536
  // packages/execution/dist/tools/nexus.js
11212
11537
  import { readFile as readFile13, writeFile as writeFile12, mkdir as mkdir8, chmod, unlink, readdir as readdir3, open as fsOpen } from "node:fs/promises";
11213
- import { existsSync as existsSync21, readFileSync as readFileSync15 } from "node:fs";
11214
- import { resolve as resolve26, join as join28 } from "node:path";
11538
+ import { existsSync as existsSync22, readFileSync as readFileSync15 } from "node:fs";
11539
+ import { resolve as resolve26, join as join29 } from "node:path";
11215
11540
  import { randomBytes as randomBytes6, createCipheriv, createDecipheriv, scryptSync, createHash } from "node:crypto";
11216
- import { execSync as execSync21, spawn as spawn10 } from "node:child_process";
11541
+ import { execSync as execSync22, spawn as spawn11 } from "node:child_process";
11217
11542
  import { hostname, userInfo } from "node:os";
11218
11543
  function containsKeyMaterial(input) {
11219
11544
  for (const pattern of KEY_PATTERNS) {
@@ -12247,7 +12572,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12247
12572
  this.nexusDir = resolve26(repoRoot, ".oa", "nexus");
12248
12573
  }
12249
12574
  async ensureDir() {
12250
- if (!existsSync21(this.nexusDir)) {
12575
+ if (!existsSync22(this.nexusDir)) {
12251
12576
  await mkdir8(this.nexusDir, { recursive: true });
12252
12577
  }
12253
12578
  }
@@ -12362,8 +12687,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12362
12687
  // Daemon management
12363
12688
  // =========================================================================
12364
12689
  getDaemonPid() {
12365
- const pidFile = join28(this.nexusDir, "daemon.pid");
12366
- if (!existsSync21(pidFile))
12690
+ const pidFile = join29(this.nexusDir, "daemon.pid");
12691
+ if (!existsSync22(pidFile))
12367
12692
  return null;
12368
12693
  try {
12369
12694
  const pid = parseInt(readFileSync15(pidFile, "utf8").trim(), 10);
@@ -12378,16 +12703,16 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12378
12703
  if (!pid)
12379
12704
  throw new Error("Nexus daemon not running. Use action 'connect' first.");
12380
12705
  const cmdId = randomBytes6(8).toString("hex");
12381
- const cmdFile = join28(this.nexusDir, "cmd.json");
12382
- const respFile = join28(this.nexusDir, "resp.json");
12383
- if (existsSync21(respFile))
12706
+ const cmdFile = join29(this.nexusDir, "cmd.json");
12707
+ const respFile = join29(this.nexusDir, "resp.json");
12708
+ if (existsSync22(respFile))
12384
12709
  await unlink(respFile).catch(() => {
12385
12710
  });
12386
12711
  await writeFile12(cmdFile, JSON.stringify({ id: cmdId, action, args }, null, 2));
12387
12712
  const polls = Math.ceil(timeoutMs / 500);
12388
12713
  for (let i = 0; i < polls; i++) {
12389
12714
  await new Promise((r) => setTimeout(r, 500));
12390
- if (!existsSync21(respFile))
12715
+ if (!existsSync22(respFile))
12391
12716
  continue;
12392
12717
  try {
12393
12718
  const resp = JSON.parse(await readFile13(respFile, "utf8"));
@@ -12414,8 +12739,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12414
12739
  await this.ensureDir();
12415
12740
  const existingPid = this.getDaemonPid();
12416
12741
  if (existingPid) {
12417
- const statusFile2 = join28(this.nexusDir, "status.json");
12418
- if (existsSync21(statusFile2)) {
12742
+ const statusFile2 = join29(this.nexusDir, "status.json");
12743
+ if (existsSync22(statusFile2)) {
12419
12744
  try {
12420
12745
  const status = JSON.parse(await readFile13(statusFile2, "utf8"));
12421
12746
  if (status.connected && status.peerId) {
@@ -12431,8 +12756,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12431
12756
  await new Promise((r) => setTimeout(r, 500));
12432
12757
  }
12433
12758
  for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
12434
- const p = join28(this.nexusDir, f);
12435
- if (existsSync21(p))
12759
+ const p = join29(this.nexusDir, f);
12760
+ if (existsSync22(p))
12436
12761
  await unlink(p).catch(() => {
12437
12762
  });
12438
12763
  }
@@ -12440,8 +12765,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12440
12765
  let nexusResolved = false;
12441
12766
  let installedVersion = "";
12442
12767
  try {
12443
- const nexusPkg = join28(nodeModulesDir, "open-agents-nexus", "package.json");
12444
- if (existsSync21(nexusPkg)) {
12768
+ const nexusPkg = join29(nodeModulesDir, "open-agents-nexus", "package.json");
12769
+ if (existsSync22(nexusPkg)) {
12445
12770
  nexusResolved = true;
12446
12771
  try {
12447
12772
  const pkg = JSON.parse(readFileSync15(nexusPkg, "utf8"));
@@ -12449,9 +12774,9 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12449
12774
  } catch {
12450
12775
  }
12451
12776
  } else {
12452
- const globalDir = execSync21("npm root -g", { encoding: "utf8", timeout: 5e3 }).trim();
12453
- const globalPkg = join28(globalDir, "open-agents-nexus", "package.json");
12454
- if (existsSync21(globalPkg)) {
12777
+ const globalDir = execSync22("npm root -g", { encoding: "utf8", timeout: 5e3 }).trim();
12778
+ const globalPkg = join29(globalDir, "open-agents-nexus", "package.json");
12779
+ if (existsSync22(globalPkg)) {
12455
12780
  nexusResolved = true;
12456
12781
  try {
12457
12782
  const pkg = JSON.parse(readFileSync15(globalPkg, "utf8"));
@@ -12464,13 +12789,13 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12464
12789
  }
12465
12790
  if (nexusResolved && installedVersion) {
12466
12791
  try {
12467
- const latestRaw = execSync21("npm view open-agents-nexus version 2>/dev/null", {
12792
+ const latestRaw = execSync22("npm view open-agents-nexus version 2>/dev/null", {
12468
12793
  encoding: "utf8",
12469
12794
  timeout: 8e3
12470
12795
  }).trim();
12471
12796
  if (latestRaw && latestRaw !== installedVersion) {
12472
12797
  try {
12473
- execSync21(`npm install open-agents-nexus@${latestRaw} --save 2>&1`, {
12798
+ execSync22(`npm install open-agents-nexus@${latestRaw} --save 2>&1`, {
12474
12799
  cwd: this.repoRoot,
12475
12800
  stdio: "pipe",
12476
12801
  timeout: 6e4
@@ -12484,30 +12809,30 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12484
12809
  }
12485
12810
  if (!nexusResolved) {
12486
12811
  try {
12487
- execSync21("npm install open-agents-nexus@latest 2>&1", {
12812
+ execSync22("npm install open-agents-nexus@latest 2>&1", {
12488
12813
  cwd: this.repoRoot,
12489
12814
  stdio: "pipe",
12490
12815
  timeout: 12e4
12491
12816
  });
12492
12817
  } catch {
12493
12818
  try {
12494
- execSync21("npm install -g open-agents-nexus@latest 2>&1", { stdio: "pipe", timeout: 12e4 });
12819
+ execSync22("npm install -g open-agents-nexus@latest 2>&1", { stdio: "pipe", timeout: 12e4 });
12495
12820
  } catch {
12496
12821
  throw new Error("Failed to install open-agents-nexus. Run: npm install open-agents-nexus");
12497
12822
  }
12498
12823
  }
12499
12824
  }
12500
- const daemonPath = join28(this.nexusDir, "nexus-daemon.mjs");
12825
+ const daemonPath = join29(this.nexusDir, "nexus-daemon.mjs");
12501
12826
  await writeFile12(daemonPath, DAEMON_SCRIPT);
12502
12827
  const agentName = args.agent_name || "open-agents-node";
12503
12828
  const agentType = args.agent_type || "general";
12504
12829
  const nodePaths = [nodeModulesDir];
12505
12830
  try {
12506
- const globalDir = execSync21("npm root -g", { encoding: "utf8", timeout: 5e3 }).trim();
12831
+ const globalDir = execSync22("npm root -g", { encoding: "utf8", timeout: 5e3 }).trim();
12507
12832
  nodePaths.push(globalDir);
12508
12833
  } catch {
12509
12834
  }
12510
- const child = spawn10("node", [daemonPath, this.nexusDir, agentName, agentType], {
12835
+ const child = spawn11("node", [daemonPath, this.nexusDir, agentName, agentType], {
12511
12836
  detached: true,
12512
12837
  stdio: ["ignore", "pipe", "pipe"],
12513
12838
  cwd: this.repoRoot,
@@ -12522,10 +12847,10 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12522
12847
  child.stderr?.on("data", (d) => {
12523
12848
  earlyError += d.toString();
12524
12849
  });
12525
- const statusFile = join28(this.nexusDir, "status.json");
12850
+ const statusFile = join29(this.nexusDir, "status.json");
12526
12851
  for (let i = 0; i < 40; i++) {
12527
12852
  await new Promise((r) => setTimeout(r, 500));
12528
- if (existsSync21(statusFile)) {
12853
+ if (existsSync22(statusFile)) {
12529
12854
  try {
12530
12855
  const status = JSON.parse(await readFile13(statusFile, "utf8"));
12531
12856
  if (status.error) {
@@ -12566,8 +12891,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12566
12891
  } catch {
12567
12892
  }
12568
12893
  for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
12569
- const p = join28(this.nexusDir, f);
12570
- if (existsSync21(p))
12894
+ const p = join29(this.nexusDir, f);
12895
+ if (existsSync22(p))
12571
12896
  await unlink(p).catch(() => {
12572
12897
  });
12573
12898
  }
@@ -12577,8 +12902,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12577
12902
  const pid = this.getDaemonPid();
12578
12903
  if (!pid)
12579
12904
  return "Nexus daemon not running. Use action 'connect' to start.";
12580
- const statusFile = join28(this.nexusDir, "status.json");
12581
- if (!existsSync21(statusFile))
12905
+ const statusFile = join29(this.nexusDir, "status.json");
12906
+ if (!existsSync22(statusFile))
12582
12907
  return `Daemon running (pid: ${pid}) but no status yet.`;
12583
12908
  try {
12584
12909
  const status = JSON.parse(await readFile13(statusFile, "utf8"));
@@ -12592,8 +12917,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12592
12917
  ` Capabilities: ${(status.capabilities || []).length ? (status.capabilities || []).join(", ") : "none"}`,
12593
12918
  ` Blocked peers: ${(status.blockedPeers || []).length || 0}`
12594
12919
  ];
12595
- const walletPath = join28(this.nexusDir, "wallet.enc");
12596
- if (existsSync21(walletPath)) {
12920
+ const walletPath = join29(this.nexusDir, "wallet.enc");
12921
+ if (existsSync22(walletPath)) {
12597
12922
  try {
12598
12923
  const w = JSON.parse(await readFile13(walletPath, "utf8"));
12599
12924
  lines.push(` Wallet: ${w.address}`);
@@ -12603,14 +12928,14 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12603
12928
  } else {
12604
12929
  lines.push(` Wallet: not configured`);
12605
12930
  }
12606
- const inboxDir = join28(this.nexusDir, "inbox");
12607
- if (existsSync21(inboxDir)) {
12931
+ const inboxDir = join29(this.nexusDir, "inbox");
12932
+ if (existsSync22(inboxDir)) {
12608
12933
  try {
12609
12934
  const roomDirs = await readdir3(inboxDir);
12610
12935
  let totalMsgs = 0;
12611
12936
  for (const rd of roomDirs) {
12612
12937
  try {
12613
- totalMsgs += (await readdir3(join28(inboxDir, rd))).length;
12938
+ totalMsgs += (await readdir3(join29(inboxDir, rd))).length;
12614
12939
  } catch {
12615
12940
  }
12616
12941
  }
@@ -12657,10 +12982,10 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12657
12982
  }
12658
12983
  async doReadMessages(args) {
12659
12984
  const roomId = args.room_id;
12660
- const inboxDir = join28(this.nexusDir, "inbox");
12985
+ const inboxDir = join29(this.nexusDir, "inbox");
12661
12986
  if (roomId) {
12662
- const roomInbox = join28(inboxDir, roomId);
12663
- if (!existsSync21(roomInbox))
12987
+ const roomInbox = join29(inboxDir, roomId);
12988
+ if (!existsSync22(roomInbox))
12664
12989
  return `No messages in room: ${roomId}`;
12665
12990
  const files = (await readdir3(roomInbox)).sort().slice(-20);
12666
12991
  if (files.length === 0)
@@ -12668,7 +12993,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12668
12993
  const messages = [`Messages in ${roomId} (last ${files.length}):`];
12669
12994
  for (const f of files) {
12670
12995
  try {
12671
- const msg = JSON.parse(await readFile13(join28(roomInbox, f), "utf8"));
12996
+ const msg = JSON.parse(await readFile13(join29(roomInbox, f), "utf8"));
12672
12997
  const sender = (msg.sender || "unknown").slice(0, 12);
12673
12998
  messages.push(` [${new Date(msg.timestamp).toLocaleTimeString()}] ${sender}...: ${msg.content}`);
12674
12999
  } catch {
@@ -12676,7 +13001,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12676
13001
  }
12677
13002
  return messages.join("\n");
12678
13003
  }
12679
- if (!existsSync21(inboxDir))
13004
+ if (!existsSync22(inboxDir))
12680
13005
  return "No messages received yet.";
12681
13006
  const roomDirs = await readdir3(inboxDir);
12682
13007
  if (roomDirs.length === 0)
@@ -12684,7 +13009,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12684
13009
  const lines = ["Inbox:"];
12685
13010
  for (const rd of roomDirs) {
12686
13011
  try {
12687
- const count = (await readdir3(join28(inboxDir, rd))).length;
13012
+ const count = (await readdir3(join29(inboxDir, rd))).length;
12688
13013
  lines.push(` ${rd}: ${count} message(s)`);
12689
13014
  } catch {
12690
13015
  }
@@ -12696,8 +13021,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12696
13021
  // ---------------------------------------------------------------------------
12697
13022
  async doWalletStatus() {
12698
13023
  await this.ensureDir();
12699
- const walletPath = join28(this.nexusDir, "wallet.enc");
12700
- if (!existsSync21(walletPath)) {
13024
+ const walletPath = join29(this.nexusDir, "wallet.enc");
13025
+ if (!existsSync22(walletPath)) {
12701
13026
  return "No wallet configured. Use wallet_create to set one up.";
12702
13027
  }
12703
13028
  try {
@@ -12735,8 +13060,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12735
13060
  }
12736
13061
  async doWalletCreate(args) {
12737
13062
  await this.ensureDir();
12738
- const walletPath = join28(this.nexusDir, "wallet.enc");
12739
- if (existsSync21(walletPath))
13063
+ const walletPath = join29(this.nexusDir, "wallet.enc");
13064
+ if (existsSync22(walletPath))
12740
13065
  return "Wallet already exists. Delete wallet.enc to create a new one.";
12741
13066
  const userAddress = args.wallet_address;
12742
13067
  if (userAddress) {
@@ -12781,7 +13106,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12781
13106
  const cipher = createCipheriv("aes-256-gcm", key, iv);
12782
13107
  let enc = cipher.update(privKeyHex, "utf8", "hex");
12783
13108
  enc += cipher.final("hex");
12784
- const x402KeyPath = join28(this.nexusDir, "x402-wallet.key");
13109
+ const x402KeyPath = join29(this.nexusDir, "x402-wallet.key");
12785
13110
  const x402Fh = await fsOpen(x402KeyPath, "w", 384);
12786
13111
  await x402Fh.writeFile("0x" + privKeyHex);
12787
13112
  await x402Fh.close();
@@ -12852,8 +13177,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12852
13177
  // ---------------------------------------------------------------------------
12853
13178
  async doLedgerStatus() {
12854
13179
  await this.ensureDir();
12855
- const ledgerPath = join28(this.nexusDir, "ledger.jsonl");
12856
- if (!existsSync21(ledgerPath)) {
13180
+ const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
13181
+ if (!existsSync22(ledgerPath)) {
12857
13182
  return "No ledger entries. Earnings and spending will be tracked here after x402 transactions.";
12858
13183
  }
12859
13184
  try {
@@ -12894,8 +13219,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12894
13219
  }
12895
13220
  }
12896
13221
  async getLedgerSummary() {
12897
- const ledgerPath = join28(this.nexusDir, "ledger.jsonl");
12898
- if (!existsSync21(ledgerPath))
13222
+ const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
13223
+ if (!existsSync22(ledgerPath))
12899
13224
  return null;
12900
13225
  try {
12901
13226
  const raw = await readFile13(ledgerPath, "utf8");
@@ -12919,16 +13244,16 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12919
13244
  }
12920
13245
  async appendLedger(entry) {
12921
13246
  await this.ensureDir();
12922
- const ledgerPath = join28(this.nexusDir, "ledger.jsonl");
13247
+ const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
12923
13248
  const line = JSON.stringify(entry) + "\n";
12924
- await writeFile12(ledgerPath, existsSync21(ledgerPath) ? await readFile13(ledgerPath, "utf8") + line : line);
13249
+ await writeFile12(ledgerPath, existsSync22(ledgerPath) ? await readFile13(ledgerPath, "utf8") + line : line);
12925
13250
  }
12926
13251
  // ---------------------------------------------------------------------------
12927
13252
  // Step 4: Budget Policy — Spending limits and auto-approve thresholds
12928
13253
  // ---------------------------------------------------------------------------
12929
13254
  async loadBudget() {
12930
- const budgetPath = join28(this.nexusDir, "budget.json");
12931
- if (!existsSync21(budgetPath))
13255
+ const budgetPath = join29(this.nexusDir, "budget.json");
13256
+ if (!existsSync22(budgetPath))
12932
13257
  return null;
12933
13258
  try {
12934
13259
  return JSON.parse(await readFile13(budgetPath, "utf8"));
@@ -12937,8 +13262,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
12937
13262
  }
12938
13263
  }
12939
13264
  async ensureDefaultBudget() {
12940
- const budgetPath = join28(this.nexusDir, "budget.json");
12941
- if (existsSync21(budgetPath))
13265
+ const budgetPath = join29(this.nexusDir, "budget.json");
13266
+ if (existsSync22(budgetPath))
12942
13267
  return;
12943
13268
  const defaultBudget = {
12944
13269
  version: 1,
@@ -13007,13 +13332,13 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13007
13332
  if (changes.length === 0) {
13008
13333
  return "No budget parameters provided. Use daily_limit, per_invoke_max, or auto_approve_below.";
13009
13334
  }
13010
- const budgetPath = join28(this.nexusDir, "budget.json");
13335
+ const budgetPath = join29(this.nexusDir, "budget.json");
13011
13336
  await writeFile12(budgetPath, JSON.stringify(budget, null, 2));
13012
13337
  return `Budget updated: ${changes.join(", ")}`;
13013
13338
  }
13014
13339
  async getTodaySpending() {
13015
- const ledgerPath = join28(this.nexusDir, "ledger.jsonl");
13016
- if (!existsSync21(ledgerPath))
13340
+ const ledgerPath = join29(this.nexusDir, "ledger.jsonl");
13341
+ if (!existsSync22(ledgerPath))
13017
13342
  return 0;
13018
13343
  try {
13019
13344
  const todayPrefix = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -13056,8 +13381,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13056
13381
  if (todaySpent + amountUsdc > budget.dailyLimitUsdc) {
13057
13382
  return { allowed: false, reason: `Would exceed daily limit ($${((todaySpent + amountUsdc) / 1e6).toFixed(6)} > $${(budget.dailyLimitUsdc / 1e6).toFixed(6)})` };
13058
13383
  }
13059
- const walletPath = join28(this.nexusDir, "wallet.enc");
13060
- if (existsSync21(walletPath)) {
13384
+ const walletPath = join29(this.nexusDir, "wallet.enc");
13385
+ if (existsSync22(walletPath)) {
13061
13386
  try {
13062
13387
  const w = JSON.parse(await readFile13(walletPath, "utf8"));
13063
13388
  if (w.version === 2 && w.address) {
@@ -13087,8 +13412,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13087
13412
  const budgetResult = await this.checkBudget(amountSmallest, "transfer:direct", targetAddress);
13088
13413
  if (!budgetResult.allowed)
13089
13414
  return `BLOCKED by budget policy: ${budgetResult.reason}`;
13090
- const walletPath = join28(this.nexusDir, "wallet.enc");
13091
- if (!existsSync21(walletPath))
13415
+ const walletPath = join29(this.nexusDir, "wallet.enc");
13416
+ if (!existsSync22(walletPath))
13092
13417
  throw new Error("No wallet. Use wallet_create first.");
13093
13418
  const w = JSON.parse(await readFile13(walletPath, "utf8"));
13094
13419
  if (!w.encryptedKey)
@@ -13148,7 +13473,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13148
13473
  capability: "transfer:direct",
13149
13474
  note: "signed, awaiting submission"
13150
13475
  });
13151
- const proofFile = join28(this.nexusDir, "pending-transfer.json");
13476
+ const proofFile = join29(this.nexusDir, "pending-transfer.json");
13152
13477
  const proof = {
13153
13478
  from: account.address,
13154
13479
  to: targetAddress,
@@ -13190,8 +13515,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13190
13515
  throw new Error("prompt is required");
13191
13516
  const estimatedTokens = Math.ceil(prompt.length / 4) + 1e3;
13192
13517
  let estimatedCostSmallest = 0;
13193
- const pricingPath = join28(this.nexusDir, "pricing.json");
13194
- if (existsSync21(pricingPath)) {
13518
+ const pricingPath = join29(this.nexusDir, "pricing.json");
13519
+ if (existsSync22(pricingPath)) {
13195
13520
  try {
13196
13521
  const pricing = JSON.parse(await readFile13(pricingPath, "utf8"));
13197
13522
  const modelPricing = (pricing.models || []).find((m) => m.model === model || m.model.startsWith(model.split(":")[0]));
@@ -13283,7 +13608,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13283
13608
  }
13284
13609
  async doInferenceProof() {
13285
13610
  try {
13286
- const psRaw = execSync21("ollama ps 2>/dev/null", { timeout: 1e4, encoding: "utf8" });
13611
+ const psRaw = execSync22("ollama ps 2>/dev/null", { timeout: 1e4, encoding: "utf8" });
13287
13612
  const lines = psRaw.trim().split("\n").filter((l) => l.trim());
13288
13613
  if (lines.length < 2)
13289
13614
  return "No model loaded. Run 'ollama ps' to check.";
@@ -13291,7 +13616,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13291
13616
  const modelName = parts[0] || "unknown";
13292
13617
  let gpuName = "none", vramMb = 0;
13293
13618
  try {
13294
- const smi = execSync21("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null", {
13619
+ const smi = execSync22("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null", {
13295
13620
  timeout: 5e3,
13296
13621
  encoding: "utf8"
13297
13622
  });
@@ -13300,7 +13625,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13300
13625
  vramMb = parseInt(gp[1]?.trim() || "0", 10);
13301
13626
  } catch {
13302
13627
  try {
13303
- execSync21("rocm-smi 2>/dev/null", { timeout: 5e3 });
13628
+ execSync22("rocm-smi 2>/dev/null", { timeout: 5e3 });
13304
13629
  gpuName = "AMD GPU";
13305
13630
  } catch {
13306
13631
  }
@@ -13310,7 +13635,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
13310
13635
  const bar = (s) => "\u2588".repeat(Math.round(s / 5)) + "\u2591".repeat(20 - Math.round(s / 5));
13311
13636
  const mem = vramMb > 24e3 ? 95 : vramMb > 16e3 ? 80 : vramMb > 8e3 ? 60 : vramMb > 0 ? 40 : 20;
13312
13637
  await this.ensureDir();
13313
- await writeFile12(join28(this.nexusDir, "inference-proof.json"), JSON.stringify({
13638
+ await writeFile12(join29(this.nexusDir, "inference-proof.json"), JSON.stringify({
13314
13639
  modelName,
13315
13640
  gpuName,
13316
13641
  vramMb,
@@ -13453,6 +13778,7 @@ var init_dist2 = __esm({
13453
13778
  init_reminder();
13454
13779
  init_agenda();
13455
13780
  init_opencode();
13781
+ init_factory();
13456
13782
  init_cron_agent();
13457
13783
  init_nexus();
13458
13784
  init_system_deps();
@@ -14139,14 +14465,14 @@ var init_dist3 = __esm({
14139
14465
  });
14140
14466
 
14141
14467
  // packages/orchestrator/dist/promptLoader.js
14142
- import { readFileSync as readFileSync16, existsSync as existsSync22 } from "node:fs";
14143
- import { join as join29, dirname as dirname10 } from "node:path";
14468
+ import { readFileSync as readFileSync16, existsSync as existsSync23 } from "node:fs";
14469
+ import { join as join30, dirname as dirname10 } from "node:path";
14144
14470
  import { fileURLToPath as fileURLToPath7 } from "node:url";
14145
14471
  function loadPrompt(promptPath, vars) {
14146
14472
  let content = cache.get(promptPath);
14147
14473
  if (content === void 0) {
14148
- const fullPath = join29(PROMPTS_DIR, promptPath);
14149
- if (!existsSync22(fullPath)) {
14474
+ const fullPath = join30(PROMPTS_DIR, promptPath);
14475
+ if (!existsSync23(fullPath)) {
14150
14476
  throw new Error(`Prompt file not found: ${fullPath}`);
14151
14477
  }
14152
14478
  content = readFileSync16(fullPath, "utf-8");
@@ -14162,7 +14488,7 @@ var init_promptLoader = __esm({
14162
14488
  "use strict";
14163
14489
  __filename = fileURLToPath7(import.meta.url);
14164
14490
  __dirname3 = dirname10(__filename);
14165
- PROMPTS_DIR = join29(__dirname3, "..", "prompts");
14491
+ PROMPTS_DIR = join30(__dirname3, "..", "prompts");
14166
14492
  cache = /* @__PURE__ */ new Map();
14167
14493
  }
14168
14494
  });
@@ -14542,7 +14868,7 @@ var init_code_retriever = __esm({
14542
14868
  import { execFile as execFile5 } from "node:child_process";
14543
14869
  import { promisify as promisify4 } from "node:util";
14544
14870
  import { readFile as readFile14, readdir as readdir4, stat as stat3 } from "node:fs/promises";
14545
- import { join as join30, extname as extname7 } from "node:path";
14871
+ import { join as join31, extname as extname7 } from "node:path";
14546
14872
  async function searchByPath(pathPattern, options) {
14547
14873
  const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
14548
14874
  const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
@@ -14684,7 +15010,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
14684
15010
  continue;
14685
15011
  if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
14686
15012
  continue;
14687
- const absPath = join30(dir, entry.name);
15013
+ const absPath = join31(dir, entry.name);
14688
15014
  if (entry.isDirectory()) {
14689
15015
  await walkForFiles(rootDir, absPath, excludeGlobs, results);
14690
15016
  } else if (entry.isFile()) {
@@ -14991,7 +15317,7 @@ var init_graphExpand = __esm({
14991
15317
 
14992
15318
  // packages/retrieval/dist/snippetPacker.js
14993
15319
  import { readFile as readFile15 } from "node:fs/promises";
14994
- import { join as join31 } from "node:path";
15320
+ import { join as join32 } from "node:path";
14995
15321
  async function packSnippets(requests, opts = {}) {
14996
15322
  const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
14997
15323
  const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
@@ -15017,7 +15343,7 @@ async function packSnippets(requests, opts = {}) {
15017
15343
  return { packed, dropped, totalTokens };
15018
15344
  }
15019
15345
  async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
15020
- const absPath = req.filePath.startsWith("/") ? req.filePath : join31(repoRoot, req.filePath);
15346
+ const absPath = req.filePath.startsWith("/") ? req.filePath : join32(repoRoot, req.filePath);
15021
15347
  let content;
15022
15348
  try {
15023
15349
  content = await readFile15(absPath, "utf-8");
@@ -17187,8 +17513,8 @@ ${marker}` : marker);
17187
17513
  return;
17188
17514
  try {
17189
17515
  const { mkdirSync: mkdirSync18, writeFileSync: writeFileSync16 } = __require("node:fs");
17190
- const { join: join52 } = __require("node:path");
17191
- const sessionDir = join52(this._workingDirectory, ".oa", "session", this._sessionId);
17516
+ const { join: join53 } = __require("node:path");
17517
+ const sessionDir = join53(this._workingDirectory, ".oa", "session", this._sessionId);
17192
17518
  mkdirSync18(sessionDir, { recursive: true });
17193
17519
  const checkpoint = {
17194
17520
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -17201,7 +17527,7 @@ ${marker}` : marker);
17201
17527
  memexEntryCount: this._memexArchive.size,
17202
17528
  fileRegistrySize: this._fileRegistry.size
17203
17529
  };
17204
- writeFileSync16(join52(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
17530
+ writeFileSync16(join53(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
17205
17531
  } catch {
17206
17532
  }
17207
17533
  }
@@ -18978,9 +19304,9 @@ __export(listen_exports, {
18978
19304
  isVideoPath: () => isVideoPath,
18979
19305
  waitForTranscribeCli: () => waitForTranscribeCli
18980
19306
  });
18981
- import { spawn as spawn11, execSync as execSync22 } from "node:child_process";
18982
- import { existsSync as existsSync23, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, readdirSync as readdirSync6 } from "node:fs";
18983
- import { join as join32, dirname as dirname11 } from "node:path";
19307
+ import { spawn as spawn12, execSync as execSync23 } from "node:child_process";
19308
+ import { existsSync as existsSync24, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, readdirSync as readdirSync6 } from "node:fs";
19309
+ import { join as join33, dirname as dirname11 } from "node:path";
18984
19310
  import { homedir as homedir8 } from "node:os";
18985
19311
  import { fileURLToPath as fileURLToPath8 } from "node:url";
18986
19312
  import { EventEmitter } from "node:events";
@@ -19000,7 +19326,7 @@ function findMicCaptureCommand() {
19000
19326
  const platform4 = process.platform;
19001
19327
  if (platform4 === "linux") {
19002
19328
  try {
19003
- execSync22("which arecord", { stdio: "pipe" });
19329
+ execSync23("which arecord", { stdio: "pipe" });
19004
19330
  return {
19005
19331
  cmd: "arecord",
19006
19332
  args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
@@ -19010,7 +19336,7 @@ function findMicCaptureCommand() {
19010
19336
  }
19011
19337
  if (platform4 === "darwin") {
19012
19338
  try {
19013
- execSync22("which sox", { stdio: "pipe" });
19339
+ execSync23("which sox", { stdio: "pipe" });
19014
19340
  return {
19015
19341
  cmd: "sox",
19016
19342
  args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
@@ -19019,7 +19345,7 @@ function findMicCaptureCommand() {
19019
19345
  }
19020
19346
  }
19021
19347
  try {
19022
- execSync22("which ffmpeg", { stdio: "pipe" });
19348
+ execSync23("which ffmpeg", { stdio: "pipe" });
19023
19349
  if (platform4 === "linux") {
19024
19350
  return {
19025
19351
  cmd: "ffmpeg",
@@ -19066,39 +19392,39 @@ function findMicCaptureCommand() {
19066
19392
  function findLiveWhisperScript() {
19067
19393
  const thisDir = dirname11(fileURLToPath8(import.meta.url));
19068
19394
  const candidates = [
19069
- join32(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
19070
- join32(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
19071
- join32(thisDir, "../../execution/scripts/live-whisper.py"),
19395
+ join33(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
19396
+ join33(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
19397
+ join33(thisDir, "../../execution/scripts/live-whisper.py"),
19072
19398
  // npm install layout — scripts bundled alongside dist
19073
- join32(thisDir, "../scripts/live-whisper.py"),
19074
- join32(thisDir, "../../scripts/live-whisper.py")
19399
+ join33(thisDir, "../scripts/live-whisper.py"),
19400
+ join33(thisDir, "../../scripts/live-whisper.py")
19075
19401
  ];
19076
19402
  for (const p of candidates) {
19077
- if (existsSync23(p))
19403
+ if (existsSync24(p))
19078
19404
  return p;
19079
19405
  }
19080
19406
  try {
19081
- const globalRoot = execSync22("npm root -g", {
19407
+ const globalRoot = execSync23("npm root -g", {
19082
19408
  encoding: "utf-8",
19083
19409
  timeout: 5e3,
19084
19410
  stdio: ["pipe", "pipe", "pipe"]
19085
19411
  }).trim();
19086
19412
  const candidates2 = [
19087
- join32(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
19088
- join32(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
19413
+ join33(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
19414
+ join33(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
19089
19415
  ];
19090
19416
  for (const p of candidates2) {
19091
- if (existsSync23(p))
19417
+ if (existsSync24(p))
19092
19418
  return p;
19093
19419
  }
19094
19420
  } catch {
19095
19421
  }
19096
- const nvmBase = join32(homedir8(), ".nvm", "versions", "node");
19097
- if (existsSync23(nvmBase)) {
19422
+ const nvmBase = join33(homedir8(), ".nvm", "versions", "node");
19423
+ if (existsSync24(nvmBase)) {
19098
19424
  try {
19099
19425
  for (const ver of readdirSync6(nvmBase)) {
19100
- const p = join32(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
19101
- if (existsSync23(p))
19426
+ const p = join33(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
19427
+ if (existsSync24(p))
19102
19428
  return p;
19103
19429
  }
19104
19430
  } catch {
@@ -19111,12 +19437,12 @@ function ensureTranscribeCliBackground() {
19111
19437
  return;
19112
19438
  _bgInstallPromise = (async () => {
19113
19439
  try {
19114
- const globalRoot = execSync22("npm root -g", {
19440
+ const globalRoot = execSync23("npm root -g", {
19115
19441
  encoding: "utf-8",
19116
19442
  timeout: 5e3,
19117
19443
  stdio: ["pipe", "pipe", "pipe"]
19118
19444
  }).trim();
19119
- if (existsSync23(join32(globalRoot, "transcribe-cli", "dist", "index.js"))) {
19445
+ if (existsSync24(join33(globalRoot, "transcribe-cli", "dist", "index.js"))) {
19120
19446
  return true;
19121
19447
  }
19122
19448
  } catch {
@@ -19188,7 +19514,7 @@ var init_listen = __esm({
19188
19514
  const timeout = setTimeout(() => {
19189
19515
  reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
19190
19516
  }, 3e5);
19191
- this.process = spawn11("python3", [
19517
+ this.process = spawn12("python3", [
19192
19518
  this.scriptPath,
19193
19519
  "--model",
19194
19520
  this.model,
@@ -19317,7 +19643,7 @@ var init_listen = __esm({
19317
19643
  }
19318
19644
  if (!this.transcribeCliAvailable) {
19319
19645
  try {
19320
- execSync22("which transcribe-cli", { stdio: "pipe" });
19646
+ execSync23("which transcribe-cli", { stdio: "pipe" });
19321
19647
  this.transcribeCliAvailable = true;
19322
19648
  } catch {
19323
19649
  this.transcribeCliAvailable = false;
@@ -19334,29 +19660,29 @@ var init_listen = __esm({
19334
19660
  } catch {
19335
19661
  }
19336
19662
  try {
19337
- const globalRoot = execSync22("npm root -g", {
19663
+ const globalRoot = execSync23("npm root -g", {
19338
19664
  encoding: "utf-8",
19339
19665
  timeout: 5e3,
19340
19666
  stdio: ["pipe", "pipe", "pipe"]
19341
19667
  }).trim();
19342
- const tcPath = join32(globalRoot, "transcribe-cli");
19343
- if (existsSync23(join32(tcPath, "dist", "index.js"))) {
19668
+ const tcPath = join33(globalRoot, "transcribe-cli");
19669
+ if (existsSync24(join33(tcPath, "dist", "index.js"))) {
19344
19670
  const { createRequire: createRequire4 } = await import("node:module");
19345
19671
  const req = createRequire4(import.meta.url);
19346
- return req(join32(tcPath, "dist", "index.js"));
19672
+ return req(join33(tcPath, "dist", "index.js"));
19347
19673
  }
19348
19674
  } catch {
19349
19675
  }
19350
- const nvmBase = join32(homedir8(), ".nvm", "versions", "node");
19351
- if (existsSync23(nvmBase)) {
19676
+ const nvmBase = join33(homedir8(), ".nvm", "versions", "node");
19677
+ if (existsSync24(nvmBase)) {
19352
19678
  try {
19353
19679
  const { readdirSync: readdirSync15 } = await import("node:fs");
19354
19680
  for (const ver of readdirSync15(nvmBase)) {
19355
- const tcPath = join32(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
19356
- if (existsSync23(join32(tcPath, "dist", "index.js"))) {
19681
+ const tcPath = join33(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
19682
+ if (existsSync24(join33(tcPath, "dist", "index.js"))) {
19357
19683
  const { createRequire: createRequire4 } = await import("node:module");
19358
19684
  const req = createRequire4(import.meta.url);
19359
- return req(join32(tcPath, "dist", "index.js"));
19685
+ return req(join33(tcPath, "dist", "index.js"));
19360
19686
  }
19361
19687
  }
19362
19688
  } catch {
@@ -19384,7 +19710,7 @@ var init_listen = __esm({
19384
19710
  }
19385
19711
  if (!tc) {
19386
19712
  try {
19387
- execSync22("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
19713
+ execSync23("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
19388
19714
  this.transcribeCliAvailable = null;
19389
19715
  tc = await this.loadTranscribeCli();
19390
19716
  } catch {
@@ -19470,7 +19796,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
19470
19796
  return `Failed to start live transcription: ${msg}${tcHint}`;
19471
19797
  }
19472
19798
  }
19473
- this.micProcess = spawn11(micCmd.cmd, micCmd.args, {
19799
+ this.micProcess = spawn12(micCmd.cmd, micCmd.args, {
19474
19800
  stdio: ["pipe", "pipe", "pipe"],
19475
19801
  env: { ...process.env }
19476
19802
  });
@@ -19567,7 +19893,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
19567
19893
  }
19568
19894
  if (!tc) {
19569
19895
  try {
19570
- execSync22("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
19896
+ execSync23("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
19571
19897
  this.transcribeCliAvailable = null;
19572
19898
  tc = await this.loadTranscribeCli();
19573
19899
  } catch {
@@ -19621,7 +19947,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
19621
19947
  }
19622
19948
  if (!tc) {
19623
19949
  try {
19624
- execSync22("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
19950
+ execSync23("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
19625
19951
  this.transcribeCliAvailable = null;
19626
19952
  tc = await this.loadTranscribeCli();
19627
19953
  } catch {
@@ -19638,9 +19964,9 @@ transcribe-cli error: ${transcribeCliError}` : "";
19638
19964
  });
19639
19965
  if (outputDir) {
19640
19966
  const { basename: basename16 } = await import("node:path");
19641
- const transcriptDir = join32(outputDir, ".oa", "transcripts");
19967
+ const transcriptDir = join33(outputDir, ".oa", "transcripts");
19642
19968
  mkdirSync6(transcriptDir, { recursive: true });
19643
- const outFile = join32(transcriptDir, `${basename16(filePath)}.txt`);
19969
+ const outFile = join33(transcriptDir, `${basename16(filePath)}.txt`);
19644
19970
  writeFileSync6(outFile, result.text, "utf-8");
19645
19971
  }
19646
19972
  return {
@@ -24209,7 +24535,7 @@ var init_render = __esm({
24209
24535
 
24210
24536
  // packages/cli/dist/tui/voice-session.js
24211
24537
  import { createServer } from "node:http";
24212
- import { spawn as spawn12, execSync as execSync23 } from "node:child_process";
24538
+ import { spawn as spawn13, execSync as execSync24 } from "node:child_process";
24213
24539
  import { EventEmitter as EventEmitter2 } from "node:events";
24214
24540
  function generateFrontendHTML() {
24215
24541
  return `<!DOCTYPE html>
@@ -24863,7 +25189,7 @@ var init_voice_session = __esm({
24863
25189
  const timeout = setTimeout(() => {
24864
25190
  reject(new Error("Cloudflared tunnel start timeout (30s)"));
24865
25191
  }, 3e4);
24866
- this.cloudflaredProcess = spawn12("cloudflared", [
25192
+ this.cloudflaredProcess = spawn13("cloudflared", [
24867
25193
  "tunnel",
24868
25194
  "--url",
24869
25195
  `http://127.0.0.1:${port}`
@@ -24937,7 +25263,7 @@ var init_voice_session = __esm({
24937
25263
 
24938
25264
  // packages/cli/dist/tui/expose.js
24939
25265
  import { createServer as createServer2, request as httpRequest } from "node:http";
24940
- import { spawn as spawn13 } from "node:child_process";
25266
+ import { spawn as spawn14 } from "node:child_process";
24941
25267
  import { EventEmitter as EventEmitter3 } from "node:events";
24942
25268
  import { randomBytes as randomBytes7 } from "node:crypto";
24943
25269
  import { URL as URL2 } from "node:url";
@@ -25113,7 +25439,7 @@ var init_expose = __esm({
25113
25439
  const timeout = setTimeout(() => {
25114
25440
  reject(new Error("Cloudflared tunnel start timeout (30s)"));
25115
25441
  }, 3e4);
25116
- this.cloudflaredProcess = spawn13("cloudflared", [
25442
+ this.cloudflaredProcess = spawn14("cloudflared", [
25117
25443
  "tunnel",
25118
25444
  "--url",
25119
25445
  `http://127.0.0.1:${port}`
@@ -25216,8 +25542,8 @@ var init_types = __esm({
25216
25542
 
25217
25543
  // packages/cli/dist/tui/p2p/secret-vault.js
25218
25544
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes8, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
25219
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync7, existsSync as existsSync24, mkdirSync as mkdirSync7 } from "node:fs";
25220
- import { join as join33, dirname as dirname12 } from "node:path";
25545
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync7, existsSync as existsSync25, mkdirSync as mkdirSync7 } from "node:fs";
25546
+ import { join as join34, dirname as dirname12 } from "node:path";
25221
25547
  var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
25222
25548
  var init_secret_vault = __esm({
25223
25549
  "packages/cli/dist/tui/p2p/secret-vault.js"() {
@@ -25429,7 +25755,7 @@ var init_secret_vault = __esm({
25429
25755
  const tag = cipher.getAuthTag();
25430
25756
  const blob = Buffer.concat([salt, iv, tag, encrypted]);
25431
25757
  const dir = dirname12(this.storePath);
25432
- if (!existsSync24(dir))
25758
+ if (!existsSync25(dir))
25433
25759
  mkdirSync7(dir, { recursive: true });
25434
25760
  writeFileSync7(this.storePath, blob, { mode: 384 });
25435
25761
  }
@@ -25438,7 +25764,7 @@ var init_secret_vault = __esm({
25438
25764
  * Returns the number of secrets loaded.
25439
25765
  */
25440
25766
  load(passphrase) {
25441
- if (!this.storePath || !existsSync24(this.storePath))
25767
+ if (!this.storePath || !existsSync25(this.storePath))
25442
25768
  return 0;
25443
25769
  const blob = readFileSync17(this.storePath);
25444
25770
  if (blob.length < SALT_LEN + IV_LEN + 16) {
@@ -26660,14 +26986,14 @@ var init_render2 = __esm({
26660
26986
  });
26661
26987
 
26662
26988
  // packages/prompts/dist/promptLoader.js
26663
- import { readFileSync as readFileSync18, existsSync as existsSync25 } from "node:fs";
26664
- import { join as join34, dirname as dirname13 } from "node:path";
26989
+ import { readFileSync as readFileSync18, existsSync as existsSync26 } from "node:fs";
26990
+ import { join as join35, dirname as dirname13 } from "node:path";
26665
26991
  import { fileURLToPath as fileURLToPath9 } from "node:url";
26666
26992
  function loadPrompt2(promptPath, vars) {
26667
26993
  let content = cache2.get(promptPath);
26668
26994
  if (content === void 0) {
26669
- const fullPath = join34(PROMPTS_DIR2, promptPath);
26670
- if (!existsSync25(fullPath)) {
26995
+ const fullPath = join35(PROMPTS_DIR2, promptPath);
26996
+ if (!existsSync26(fullPath)) {
26671
26997
  throw new Error(`Prompt file not found: ${fullPath}`);
26672
26998
  }
26673
26999
  content = readFileSync18(fullPath, "utf-8");
@@ -26683,9 +27009,9 @@ var init_promptLoader2 = __esm({
26683
27009
  "use strict";
26684
27010
  __filename2 = fileURLToPath9(import.meta.url);
26685
27011
  __dirname4 = dirname13(__filename2);
26686
- devPath = join34(__dirname4, "..", "templates");
26687
- publishedPath = join34(__dirname4, "..", "prompts", "templates");
26688
- PROMPTS_DIR2 = existsSync25(devPath) ? devPath : publishedPath;
27012
+ devPath = join35(__dirname4, "..", "templates");
27013
+ publishedPath = join35(__dirname4, "..", "prompts", "templates");
27014
+ PROMPTS_DIR2 = existsSync26(devPath) ? devPath : publishedPath;
26689
27015
  cache2 = /* @__PURE__ */ new Map();
26690
27016
  }
26691
27017
  });
@@ -26796,7 +27122,7 @@ var init_task_templates = __esm({
26796
27122
  });
26797
27123
 
26798
27124
  // packages/prompts/dist/index.js
26799
- import { join as join35, dirname as dirname14 } from "node:path";
27125
+ import { join as join36, dirname as dirname14 } from "node:path";
26800
27126
  import { fileURLToPath as fileURLToPath10 } from "node:url";
26801
27127
  var _dir, _packageRoot;
26802
27128
  var init_dist6 = __esm({
@@ -26807,23 +27133,23 @@ var init_dist6 = __esm({
26807
27133
  init_task_templates();
26808
27134
  init_render2();
26809
27135
  _dir = dirname14(fileURLToPath10(import.meta.url));
26810
- _packageRoot = join35(_dir, "..");
27136
+ _packageRoot = join36(_dir, "..");
26811
27137
  }
26812
27138
  });
26813
27139
 
26814
27140
  // packages/cli/dist/tui/oa-directory.js
26815
- import { existsSync as existsSync26, mkdirSync as mkdirSync8, readFileSync as readFileSync19, writeFileSync as writeFileSync8, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
26816
- import { join as join36, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
27141
+ import { existsSync as existsSync27, mkdirSync as mkdirSync8, readFileSync as readFileSync19, writeFileSync as writeFileSync8, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
27142
+ import { join as join37, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
26817
27143
  import { homedir as homedir9 } from "node:os";
26818
27144
  function initOaDirectory(repoRoot) {
26819
- const oaPath = join36(repoRoot, OA_DIR);
27145
+ const oaPath = join37(repoRoot, OA_DIR);
26820
27146
  for (const sub of SUBDIRS) {
26821
- mkdirSync8(join36(oaPath, sub), { recursive: true });
27147
+ mkdirSync8(join37(oaPath, sub), { recursive: true });
26822
27148
  }
26823
27149
  try {
26824
- const gitignorePath = join36(repoRoot, ".gitignore");
27150
+ const gitignorePath = join37(repoRoot, ".gitignore");
26825
27151
  const settingsPattern = ".oa/settings.json";
26826
- if (existsSync26(gitignorePath)) {
27152
+ if (existsSync27(gitignorePath)) {
26827
27153
  const content = readFileSync19(gitignorePath, "utf-8");
26828
27154
  if (!content.includes(settingsPattern)) {
26829
27155
  writeFileSync8(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
@@ -26834,12 +27160,12 @@ function initOaDirectory(repoRoot) {
26834
27160
  return oaPath;
26835
27161
  }
26836
27162
  function hasOaDirectory(repoRoot) {
26837
- return existsSync26(join36(repoRoot, OA_DIR, "index"));
27163
+ return existsSync27(join37(repoRoot, OA_DIR, "index"));
26838
27164
  }
26839
27165
  function loadProjectSettings(repoRoot) {
26840
- const settingsPath = join36(repoRoot, OA_DIR, "settings.json");
27166
+ const settingsPath = join37(repoRoot, OA_DIR, "settings.json");
26841
27167
  try {
26842
- if (existsSync26(settingsPath)) {
27168
+ if (existsSync27(settingsPath)) {
26843
27169
  return JSON.parse(readFileSync19(settingsPath, "utf-8"));
26844
27170
  }
26845
27171
  } catch {
@@ -26847,16 +27173,16 @@ function loadProjectSettings(repoRoot) {
26847
27173
  return {};
26848
27174
  }
26849
27175
  function saveProjectSettings(repoRoot, settings) {
26850
- const oaPath = join36(repoRoot, OA_DIR);
27176
+ const oaPath = join37(repoRoot, OA_DIR);
26851
27177
  mkdirSync8(oaPath, { recursive: true });
26852
27178
  const existing = loadProjectSettings(repoRoot);
26853
27179
  const merged = { ...existing, ...settings };
26854
- writeFileSync8(join36(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
27180
+ writeFileSync8(join37(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
26855
27181
  }
26856
27182
  function loadGlobalSettings() {
26857
- const settingsPath = join36(homedir9(), ".open-agents", "settings.json");
27183
+ const settingsPath = join37(homedir9(), ".open-agents", "settings.json");
26858
27184
  try {
26859
- if (existsSync26(settingsPath)) {
27185
+ if (existsSync27(settingsPath)) {
26860
27186
  return JSON.parse(readFileSync19(settingsPath, "utf-8"));
26861
27187
  }
26862
27188
  } catch {
@@ -26864,11 +27190,11 @@ function loadGlobalSettings() {
26864
27190
  return {};
26865
27191
  }
26866
27192
  function saveGlobalSettings(settings) {
26867
- const dir = join36(homedir9(), ".open-agents");
27193
+ const dir = join37(homedir9(), ".open-agents");
26868
27194
  mkdirSync8(dir, { recursive: true });
26869
27195
  const existing = loadGlobalSettings();
26870
27196
  const merged = { ...existing, ...settings };
26871
- writeFileSync8(join36(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
27197
+ writeFileSync8(join37(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
26872
27198
  }
26873
27199
  function resolveSettings(repoRoot) {
26874
27200
  const global = loadGlobalSettings();
@@ -26883,9 +27209,9 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
26883
27209
  while (dir && !visited.has(dir)) {
26884
27210
  visited.add(dir);
26885
27211
  for (const name of CONTEXT_FILES) {
26886
- const filePath = join36(dir, name);
27212
+ const filePath = join37(dir, name);
26887
27213
  const normalizedName = name.toLowerCase();
26888
- if (existsSync26(filePath) && !seen.has(filePath)) {
27214
+ if (existsSync27(filePath) && !seen.has(filePath)) {
26889
27215
  seen.add(filePath);
26890
27216
  try {
26891
27217
  let content = readFileSync19(filePath, "utf-8");
@@ -26902,8 +27228,8 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
26902
27228
  }
26903
27229
  }
26904
27230
  }
26905
- const projectMap = join36(dir, OA_DIR, "context", "project-map.md");
26906
- if (existsSync26(projectMap) && !seen.has(projectMap)) {
27231
+ const projectMap = join37(dir, OA_DIR, "context", "project-map.md");
27232
+ if (existsSync27(projectMap) && !seen.has(projectMap)) {
26907
27233
  seen.add(projectMap);
26908
27234
  try {
26909
27235
  let content = readFileSync19(projectMap, "utf-8");
@@ -26918,7 +27244,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
26918
27244
  } catch {
26919
27245
  }
26920
27246
  }
26921
- const parent = join36(dir, "..");
27247
+ const parent = join37(dir, "..");
26922
27248
  if (parent === dir)
26923
27249
  break;
26924
27250
  dir = parent;
@@ -26936,7 +27262,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
26936
27262
  return found;
26937
27263
  }
26938
27264
  function readIndexMeta(repoRoot) {
26939
- const metaPath = join36(repoRoot, OA_DIR, "index", "meta.json");
27265
+ const metaPath = join37(repoRoot, OA_DIR, "index", "meta.json");
26940
27266
  try {
26941
27267
  return JSON.parse(readFileSync19(metaPath, "utf-8"));
26942
27268
  } catch {
@@ -26989,28 +27315,28 @@ ${tree}\`\`\`
26989
27315
  sections.push("");
26990
27316
  }
26991
27317
  const content = sections.join("\n");
26992
- const contextDir = join36(repoRoot, OA_DIR, "context");
27318
+ const contextDir = join37(repoRoot, OA_DIR, "context");
26993
27319
  mkdirSync8(contextDir, { recursive: true });
26994
- writeFileSync8(join36(contextDir, "project-map.md"), content, "utf-8");
27320
+ writeFileSync8(join37(contextDir, "project-map.md"), content, "utf-8");
26995
27321
  return content;
26996
27322
  }
26997
27323
  function saveSession(repoRoot, session) {
26998
- const historyDir = join36(repoRoot, OA_DIR, "history");
27324
+ const historyDir = join37(repoRoot, OA_DIR, "history");
26999
27325
  mkdirSync8(historyDir, { recursive: true });
27000
- writeFileSync8(join36(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
27326
+ writeFileSync8(join37(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
27001
27327
  }
27002
27328
  function loadRecentSessions(repoRoot, limit = 5) {
27003
- const historyDir = join36(repoRoot, OA_DIR, "history");
27004
- if (!existsSync26(historyDir))
27329
+ const historyDir = join37(repoRoot, OA_DIR, "history");
27330
+ if (!existsSync27(historyDir))
27005
27331
  return [];
27006
27332
  try {
27007
27333
  const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
27008
- const stat5 = statSync9(join36(historyDir, f));
27334
+ const stat5 = statSync9(join37(historyDir, f));
27009
27335
  return { file: f, mtime: stat5.mtimeMs };
27010
27336
  }).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
27011
27337
  return files.map((f) => {
27012
27338
  try {
27013
- return JSON.parse(readFileSync19(join36(historyDir, f.file), "utf-8"));
27339
+ return JSON.parse(readFileSync19(join37(historyDir, f.file), "utf-8"));
27014
27340
  } catch {
27015
27341
  return null;
27016
27342
  }
@@ -27020,14 +27346,14 @@ function loadRecentSessions(repoRoot, limit = 5) {
27020
27346
  }
27021
27347
  }
27022
27348
  function savePendingTask(repoRoot, task) {
27023
- const historyDir = join36(repoRoot, OA_DIR, "history");
27349
+ const historyDir = join37(repoRoot, OA_DIR, "history");
27024
27350
  mkdirSync8(historyDir, { recursive: true });
27025
- writeFileSync8(join36(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
27351
+ writeFileSync8(join37(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
27026
27352
  }
27027
27353
  function loadPendingTask(repoRoot) {
27028
- const filePath = join36(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
27354
+ const filePath = join37(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
27029
27355
  try {
27030
- if (!existsSync26(filePath))
27356
+ if (!existsSync27(filePath))
27031
27357
  return null;
27032
27358
  const data = JSON.parse(readFileSync19(filePath, "utf-8"));
27033
27359
  try {
@@ -27040,12 +27366,12 @@ function loadPendingTask(repoRoot) {
27040
27366
  }
27041
27367
  }
27042
27368
  function saveSessionContext(repoRoot, entry) {
27043
- const contextDir = join36(repoRoot, OA_DIR, "context");
27369
+ const contextDir = join37(repoRoot, OA_DIR, "context");
27044
27370
  mkdirSync8(contextDir, { recursive: true });
27045
- const filePath = join36(contextDir, CONTEXT_SAVE_FILE);
27371
+ const filePath = join37(contextDir, CONTEXT_SAVE_FILE);
27046
27372
  let ctx;
27047
27373
  try {
27048
- if (existsSync26(filePath)) {
27374
+ if (existsSync27(filePath)) {
27049
27375
  ctx = JSON.parse(readFileSync19(filePath, "utf-8"));
27050
27376
  } else {
27051
27377
  ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
@@ -27061,9 +27387,9 @@ function saveSessionContext(repoRoot, entry) {
27061
27387
  writeFileSync8(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
27062
27388
  }
27063
27389
  function loadSessionContext(repoRoot) {
27064
- const filePath = join36(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
27390
+ const filePath = join37(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
27065
27391
  try {
27066
- if (!existsSync26(filePath))
27392
+ if (!existsSync27(filePath))
27067
27393
  return null;
27068
27394
  return JSON.parse(readFileSync19(filePath, "utf-8"));
27069
27395
  } catch {
@@ -27112,8 +27438,8 @@ function detectManifests(repoRoot) {
27112
27438
  { file: "docker-compose.yaml", type: "Docker Compose" }
27113
27439
  ];
27114
27440
  for (const check of checks) {
27115
- const filePath = join36(repoRoot, check.file);
27116
- if (existsSync26(filePath)) {
27441
+ const filePath = join37(repoRoot, check.file);
27442
+ if (existsSync27(filePath)) {
27117
27443
  let name;
27118
27444
  if (check.nameField) {
27119
27445
  try {
@@ -27146,7 +27472,7 @@ function findKeyFiles(repoRoot) {
27146
27472
  { pattern: "CLAUDE.md", description: "Claude Code context" }
27147
27473
  ];
27148
27474
  for (const check of checks) {
27149
- if (existsSync26(join36(repoRoot, check.pattern))) {
27475
+ if (existsSync27(join37(repoRoot, check.pattern))) {
27150
27476
  keyFiles.push({ path: check.pattern, description: check.description });
27151
27477
  }
27152
27478
  }
@@ -27172,12 +27498,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
27172
27498
  if (entry.isDirectory()) {
27173
27499
  let fileCount = 0;
27174
27500
  try {
27175
- fileCount = readdirSync7(join36(root, entry.name)).filter((f) => !f.startsWith(".")).length;
27501
+ fileCount = readdirSync7(join37(root, entry.name)).filter((f) => !f.startsWith(".")).length;
27176
27502
  } catch {
27177
27503
  }
27178
27504
  result += `${prefix}${connector}${entry.name}/ (${fileCount})
27179
27505
  `;
27180
- result += buildDirTree(join36(root, entry.name), maxDepth, childPrefix, depth + 1);
27506
+ result += buildDirTree(join37(root, entry.name), maxDepth, childPrefix, depth + 1);
27181
27507
  } else if (depth < maxDepth) {
27182
27508
  result += `${prefix}${connector}${entry.name}
27183
27509
  `;
@@ -27230,9 +27556,9 @@ var init_oa_directory = __esm({
27230
27556
 
27231
27557
  // packages/cli/dist/tui/setup.js
27232
27558
  import * as readline from "node:readline";
27233
- import { execSync as execSync24, spawn as spawn14 } from "node:child_process";
27234
- import { existsSync as existsSync27, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "node:fs";
27235
- import { join as join37 } from "node:path";
27559
+ import { execSync as execSync25, spawn as spawn15 } from "node:child_process";
27560
+ import { existsSync as existsSync28, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "node:fs";
27561
+ import { join as join38 } from "node:path";
27236
27562
  import { homedir as homedir10, platform } from "node:os";
27237
27563
  function detectSystemSpecs() {
27238
27564
  let totalRamGB = 0;
@@ -27240,7 +27566,7 @@ function detectSystemSpecs() {
27240
27566
  let gpuVramGB = 0;
27241
27567
  let gpuName = "";
27242
27568
  try {
27243
- const memInfo = execSync24("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
27569
+ const memInfo = execSync25("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
27244
27570
  encoding: "utf8",
27245
27571
  timeout: 5e3
27246
27572
  });
@@ -27260,7 +27586,7 @@ function detectSystemSpecs() {
27260
27586
  } catch {
27261
27587
  }
27262
27588
  try {
27263
- const nvidiaSmi = execSync24("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
27589
+ const nvidiaSmi = execSync25("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
27264
27590
  const lines = nvidiaSmi.trim().split("\n");
27265
27591
  if (lines.length > 0) {
27266
27592
  for (const line of lines) {
@@ -27385,7 +27711,7 @@ function ensureCurl() {
27385
27711
  for (const s of strategies) {
27386
27712
  if (hasCmd(s.check)) {
27387
27713
  try {
27388
- execSync24(s.install, { stdio: "inherit", timeout: 12e4 });
27714
+ execSync25(s.install, { stdio: "inherit", timeout: 12e4 });
27389
27715
  if (hasCmd("curl")) {
27390
27716
  process.stdout.write(` ${c2.green("\u2714")} curl installed via ${s.label}.
27391
27717
  `);
@@ -27399,7 +27725,7 @@ function ensureCurl() {
27399
27725
  }
27400
27726
  if (plat === "darwin") {
27401
27727
  try {
27402
- execSync24("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
27728
+ execSync25("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
27403
27729
  if (hasCmd("curl"))
27404
27730
  return true;
27405
27731
  } catch {
@@ -27434,7 +27760,7 @@ function installOllamaLinux() {
27434
27760
 
27435
27761
  `);
27436
27762
  try {
27437
- execSync24("curl -fsSL https://ollama.com/install.sh | sh", {
27763
+ execSync25("curl -fsSL https://ollama.com/install.sh | sh", {
27438
27764
  stdio: "inherit",
27439
27765
  timeout: 3e5
27440
27766
  });
@@ -27462,10 +27788,10 @@ async function installOllamaMac(_rl) {
27462
27788
 
27463
27789
  `);
27464
27790
  try {
27465
- execSync24('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
27791
+ execSync25('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
27466
27792
  if (!hasCmd("brew")) {
27467
27793
  try {
27468
- const brewPrefix = existsSync27("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
27794
+ const brewPrefix = existsSync28("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
27469
27795
  process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
27470
27796
  } catch {
27471
27797
  }
@@ -27495,7 +27821,7 @@ async function installOllamaMac(_rl) {
27495
27821
 
27496
27822
  `);
27497
27823
  try {
27498
- execSync24("brew install ollama", {
27824
+ execSync25("brew install ollama", {
27499
27825
  stdio: "inherit",
27500
27826
  timeout: 3e5
27501
27827
  });
@@ -27522,7 +27848,7 @@ function installOllamaWindows() {
27522
27848
 
27523
27849
  `);
27524
27850
  try {
27525
- execSync24('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
27851
+ execSync25('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
27526
27852
  stdio: "inherit",
27527
27853
  timeout: 3e5
27528
27854
  });
@@ -27573,7 +27899,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
27573
27899
  process.stdout.write(` ${c2.cyan("\u25CF")} Starting ollama serve...
27574
27900
  `);
27575
27901
  try {
27576
- const child = spawn14("ollama", ["serve"], { stdio: "ignore", detached: true });
27902
+ const child = spawn15("ollama", ["serve"], { stdio: "ignore", detached: true });
27577
27903
  child.unref();
27578
27904
  } catch {
27579
27905
  process.stdout.write(` ${c2.yellow("\u26A0")} Could not start ollama serve.
@@ -27603,7 +27929,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
27603
27929
  }
27604
27930
  function pullModelWithAutoUpdate(tag) {
27605
27931
  try {
27606
- execSync24(`ollama pull ${tag}`, {
27932
+ execSync25(`ollama pull ${tag}`, {
27607
27933
  stdio: "inherit",
27608
27934
  timeout: 36e5
27609
27935
  // 1 hour max
@@ -27623,7 +27949,7 @@ function pullModelWithAutoUpdate(tag) {
27623
27949
 
27624
27950
  `);
27625
27951
  try {
27626
- execSync24("curl -fsSL https://ollama.com/install.sh | sh", {
27952
+ execSync25("curl -fsSL https://ollama.com/install.sh | sh", {
27627
27953
  stdio: "inherit",
27628
27954
  timeout: 3e5
27629
27955
  // 5 min max for install
@@ -27634,7 +27960,7 @@ function pullModelWithAutoUpdate(tag) {
27634
27960
  process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
27635
27961
 
27636
27962
  `);
27637
- execSync24(`ollama pull ${tag}`, {
27963
+ execSync25(`ollama pull ${tag}`, {
27638
27964
  stdio: "inherit",
27639
27965
  timeout: 36e5
27640
27966
  });
@@ -27736,7 +28062,7 @@ function ensurePython3() {
27736
28062
  if (plat === "darwin") {
27737
28063
  if (hasCmd("brew")) {
27738
28064
  try {
27739
- execSync24("brew install python3", { stdio: "inherit", timeout: 3e5 });
28065
+ execSync25("brew install python3", { stdio: "inherit", timeout: 3e5 });
27740
28066
  if (hasCmd("python3")) {
27741
28067
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via Homebrew.
27742
28068
  `);
@@ -27749,7 +28075,7 @@ function ensurePython3() {
27749
28075
  for (const s of strategies) {
27750
28076
  if (hasCmd(s.check)) {
27751
28077
  try {
27752
- execSync24(s.install, { stdio: "inherit", timeout: 12e4 });
28078
+ execSync25(s.install, { stdio: "inherit", timeout: 12e4 });
27753
28079
  if (hasCmd("python3") || hasCmd("python")) {
27754
28080
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via ${s.label}.
27755
28081
  `);
@@ -27765,11 +28091,11 @@ function ensurePython3() {
27765
28091
  }
27766
28092
  function checkPythonVenv() {
27767
28093
  try {
27768
- execSync24("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
28094
+ execSync25("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
27769
28095
  return true;
27770
28096
  } catch {
27771
28097
  try {
27772
- execSync24("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
28098
+ execSync25("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
27773
28099
  return true;
27774
28100
  } catch {
27775
28101
  return false;
@@ -27788,7 +28114,7 @@ function ensurePythonVenv() {
27788
28114
  for (const s of strategies) {
27789
28115
  if (hasCmd(s.check)) {
27790
28116
  try {
27791
- execSync24(s.install, { stdio: "inherit", timeout: 12e4 });
28117
+ execSync25(s.install, { stdio: "inherit", timeout: 12e4 });
27792
28118
  if (checkPythonVenv()) {
27793
28119
  process.stdout.write(` ${c2.green("\u2714")} python3-venv installed via ${s.label}.
27794
28120
  `);
@@ -28041,7 +28367,7 @@ async function doSetup(config, rl) {
28041
28367
  ${c2.cyan("\u25CF")} Ollama is installed but not running. Starting automatically...
28042
28368
  `);
28043
28369
  try {
28044
- const child = spawn14("ollama", ["serve"], { stdio: "ignore", detached: true });
28370
+ const child = spawn15("ollama", ["serve"], { stdio: "ignore", detached: true });
28045
28371
  child.unref();
28046
28372
  await new Promise((resolve31) => setTimeout(resolve31, 3e3));
28047
28373
  try {
@@ -28069,7 +28395,7 @@ async function doSetup(config, rl) {
28069
28395
  ${c2.cyan("\u25CF")} Starting ollama serve...
28070
28396
  `);
28071
28397
  try {
28072
- const child = spawn14("ollama", ["serve"], { stdio: "ignore", detached: true });
28398
+ const child = spawn15("ollama", ["serve"], { stdio: "ignore", detached: true });
28073
28399
  child.unref();
28074
28400
  await new Promise((resolve31) => setTimeout(resolve31, 3e3));
28075
28401
  try {
@@ -28219,12 +28545,12 @@ async function doSetup(config, rl) {
28219
28545
  `PARAMETER num_predict ${numPredict}`,
28220
28546
  `PARAMETER stop "<|endoftext|>"`
28221
28547
  ].join("\n");
28222
- const modelDir2 = join37(homedir10(), ".open-agents", "models");
28548
+ const modelDir2 = join38(homedir10(), ".open-agents", "models");
28223
28549
  mkdirSync9(modelDir2, { recursive: true });
28224
- const modelfilePath = join37(modelDir2, `Modelfile.${customName}`);
28550
+ const modelfilePath = join38(modelDir2, `Modelfile.${customName}`);
28225
28551
  writeFileSync9(modelfilePath, modelfileContent + "\n", "utf8");
28226
28552
  process.stdout.write(` ${c2.dim("Creating model...")} `);
28227
- execSync24(`ollama create ${customName} -f ${modelfilePath}`, {
28553
+ execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
28228
28554
  stdio: "pipe",
28229
28555
  timeout: 12e4
28230
28556
  });
@@ -28267,7 +28593,7 @@ async function isModelAvailable(config) {
28267
28593
  }
28268
28594
  function isFirstRun() {
28269
28595
  try {
28270
- return !existsSync27(join37(homedir10(), ".open-agents", "config.json"));
28596
+ return !existsSync28(join38(homedir10(), ".open-agents", "config.json"));
28271
28597
  } catch {
28272
28598
  return true;
28273
28599
  }
@@ -28275,7 +28601,7 @@ function isFirstRun() {
28275
28601
  function hasCmd(cmd) {
28276
28602
  try {
28277
28603
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
28278
- execSync24(whichCmd, { stdio: "pipe", timeout: 3e3 });
28604
+ execSync25(whichCmd, { stdio: "pipe", timeout: 3e3 });
28279
28605
  return true;
28280
28606
  } catch {
28281
28607
  return false;
@@ -28304,11 +28630,11 @@ function detectPkgManager() {
28304
28630
  return null;
28305
28631
  }
28306
28632
  function getVenvDir() {
28307
- return join37(homedir10(), ".open-agents", "venv");
28633
+ return join38(homedir10(), ".open-agents", "venv");
28308
28634
  }
28309
28635
  function hasVenvModule() {
28310
28636
  try {
28311
- execSync24("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
28637
+ execSync25("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
28312
28638
  return true;
28313
28639
  } catch {
28314
28640
  return false;
@@ -28316,8 +28642,8 @@ function hasVenvModule() {
28316
28642
  }
28317
28643
  function ensureVenv(log) {
28318
28644
  const venvDir = getVenvDir();
28319
- const venvPip = join37(venvDir, "bin", "pip");
28320
- if (existsSync27(venvPip))
28645
+ const venvPip = join38(venvDir, "bin", "pip");
28646
+ if (existsSync28(venvPip))
28321
28647
  return venvDir;
28322
28648
  log("Creating Python venv for vision deps...");
28323
28649
  if (!hasCmd("python3")) {
@@ -28329,9 +28655,9 @@ function ensureVenv(log) {
28329
28655
  return null;
28330
28656
  }
28331
28657
  try {
28332
- mkdirSync9(join37(homedir10(), ".open-agents"), { recursive: true });
28333
- execSync24(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
28334
- execSync24(`"${join37(venvDir, "bin", "pip")}" install --upgrade pip`, {
28658
+ mkdirSync9(join38(homedir10(), ".open-agents"), { recursive: true });
28659
+ execSync25(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
28660
+ execSync25(`"${join38(venvDir, "bin", "pip")}" install --upgrade pip`, {
28335
28661
  stdio: "pipe",
28336
28662
  timeout: 6e4
28337
28663
  });
@@ -28344,7 +28670,7 @@ function ensureVenv(log) {
28344
28670
  }
28345
28671
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
28346
28672
  try {
28347
- execSync24(`sudo -n ${cmd}`, {
28673
+ execSync25(`sudo -n ${cmd}`, {
28348
28674
  stdio: "pipe",
28349
28675
  timeout: timeoutMs,
28350
28676
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -28356,7 +28682,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
28356
28682
  }
28357
28683
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
28358
28684
  try {
28359
- execSync24(`sudo -S ${cmd}`, {
28685
+ execSync25(`sudo -S ${cmd}`, {
28360
28686
  input: password + "\n",
28361
28687
  stdio: ["pipe", "pipe", "pipe"],
28362
28688
  timeout: timeoutMs,
@@ -28416,7 +28742,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
28416
28742
  } else {
28417
28743
  log("Installing tesseract-ocr...");
28418
28744
  try {
28419
- execSync24(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
28745
+ execSync25(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
28420
28746
  if (hasCmd("tesseract")) {
28421
28747
  log("tesseract-ocr installed successfully.");
28422
28748
  } else {
@@ -28488,7 +28814,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
28488
28814
  } else {
28489
28815
  log(`Installing ${dep.label}...`);
28490
28816
  try {
28491
- execSync24(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
28817
+ execSync25(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
28492
28818
  if (hasCmd(dep.binary)) {
28493
28819
  log(`${dep.label} installed successfully.`);
28494
28820
  } else {
@@ -28519,7 +28845,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
28519
28845
  const venvCmds = {
28520
28846
  apt: () => {
28521
28847
  try {
28522
- const pyVer = execSync24(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
28848
+ const pyVer = execSync25(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
28523
28849
  return `apt-get install -y python3-venv python${pyVer}-venv`;
28524
28850
  } catch {
28525
28851
  return "apt-get install -y python3-venv";
@@ -28540,19 +28866,19 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
28540
28866
  }
28541
28867
  }
28542
28868
  const venvDir = getVenvDir();
28543
- const venvBin = join37(venvDir, "bin");
28544
- const venvMoondream = join37(venvBin, "moondream-station");
28869
+ const venvBin = join38(venvDir, "bin");
28870
+ const venvMoondream = join38(venvBin, "moondream-station");
28545
28871
  const venv = ensureVenv(log);
28546
- if (venv && !hasCmd("moondream-station") && !existsSync27(venvMoondream)) {
28547
- const venvPip = join37(venvBin, "pip");
28872
+ if (venv && !hasCmd("moondream-station") && !existsSync28(venvMoondream)) {
28873
+ const venvPip = join38(venvBin, "pip");
28548
28874
  log("Installing moondream-station in ~/.open-agents/venv...");
28549
28875
  try {
28550
- execSync24(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
28551
- if (existsSync27(venvMoondream)) {
28876
+ execSync25(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
28877
+ if (existsSync28(venvMoondream)) {
28552
28878
  log("moondream-station installed successfully.");
28553
28879
  } else {
28554
28880
  try {
28555
- const check = execSync24(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
28881
+ const check = execSync25(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
28556
28882
  if (check.includes("moondream")) {
28557
28883
  log("moondream-station package installed.");
28558
28884
  }
@@ -28565,11 +28891,11 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
28565
28891
  }
28566
28892
  }
28567
28893
  if (venv) {
28568
- const venvPython = join37(venvBin, "python");
28569
- const venvPip2 = join37(venvBin, "pip");
28894
+ const venvPython = join38(venvBin, "python");
28895
+ const venvPip2 = join38(venvBin, "pip");
28570
28896
  let ocrStackInstalled = false;
28571
28897
  try {
28572
- execSync24(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
28898
+ execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
28573
28899
  ocrStackInstalled = true;
28574
28900
  } catch {
28575
28901
  }
@@ -28577,9 +28903,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
28577
28903
  const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
28578
28904
  log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
28579
28905
  try {
28580
- execSync24(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
28906
+ execSync25(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
28581
28907
  try {
28582
- execSync24(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
28908
+ execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
28583
28909
  log("OCR Python stack installed successfully.");
28584
28910
  } catch {
28585
28911
  log("OCR Python stack install completed but import verification failed.");
@@ -28613,7 +28939,7 @@ function ensureCloudflaredBackground(onInfo) {
28613
28939
  const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
28614
28940
  const cfArch = archMap[arch] ?? "amd64";
28615
28941
  try {
28616
- execSync24(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir10()}/.local/bin" && mv /tmp/cloudflared "${homedir10()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
28942
+ execSync25(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir10()}/.local/bin" && mv /tmp/cloudflared "${homedir10()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
28617
28943
  if (!process.env.PATH?.includes(`${homedir10()}/.local/bin`)) {
28618
28944
  process.env.PATH = `${homedir10()}/.local/bin:${process.env.PATH}`;
28619
28945
  }
@@ -28624,7 +28950,7 @@ function ensureCloudflaredBackground(onInfo) {
28624
28950
  } catch {
28625
28951
  }
28626
28952
  try {
28627
- execSync24(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
28953
+ execSync25(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
28628
28954
  if (hasCmd("cloudflared")) {
28629
28955
  log("cloudflared installed.");
28630
28956
  return true;
@@ -28633,7 +28959,7 @@ function ensureCloudflaredBackground(onInfo) {
28633
28959
  }
28634
28960
  } else if (os === "darwin") {
28635
28961
  try {
28636
- execSync24("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
28962
+ execSync25("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
28637
28963
  if (hasCmd("cloudflared")) {
28638
28964
  log("cloudflared installed via Homebrew.");
28639
28965
  return true;
@@ -28679,11 +29005,11 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
28679
29005
  `PARAMETER num_predict ${numPredict}`,
28680
29006
  `PARAMETER stop "<|endoftext|>"`
28681
29007
  ].join("\n");
28682
- const modelDir2 = join37(homedir10(), ".open-agents", "models");
29008
+ const modelDir2 = join38(homedir10(), ".open-agents", "models");
28683
29009
  mkdirSync9(modelDir2, { recursive: true });
28684
- const modelfilePath = join37(modelDir2, `Modelfile.${customName}`);
29010
+ const modelfilePath = join38(modelDir2, `Modelfile.${customName}`);
28685
29011
  writeFileSync9(modelfilePath, modelfileContent + "\n", "utf8");
28686
- execSync24(`ollama create ${customName} -f ${modelfilePath}`, {
29012
+ execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
28687
29013
  stdio: "pipe",
28688
29014
  timeout: 12e4
28689
29015
  });
@@ -29986,17 +30312,17 @@ async function handleUpdate(subcommand, ctx) {
29986
30312
  try {
29987
30313
  const { createRequire: createRequire4 } = await import("node:module");
29988
30314
  const { fileURLToPath: fileURLToPath14 } = await import("node:url");
29989
- const { dirname: dirname18, join: join52 } = await import("node:path");
29990
- const { existsSync: existsSync38 } = await import("node:fs");
30315
+ const { dirname: dirname18, join: join53 } = await import("node:path");
30316
+ const { existsSync: existsSync39 } = await import("node:fs");
29991
30317
  const req = createRequire4(import.meta.url);
29992
30318
  const thisDir = dirname18(fileURLToPath14(import.meta.url));
29993
30319
  const candidates = [
29994
- join52(thisDir, "..", "package.json"),
29995
- join52(thisDir, "..", "..", "package.json"),
29996
- join52(thisDir, "..", "..", "..", "package.json")
30320
+ join53(thisDir, "..", "package.json"),
30321
+ join53(thisDir, "..", "..", "package.json"),
30322
+ join53(thisDir, "..", "..", "..", "package.json")
29997
30323
  ];
29998
30324
  for (const pkgPath of candidates) {
29999
- if (existsSync38(pkgPath)) {
30325
+ if (existsSync39(pkgPath)) {
30000
30326
  const pkg = req(pkgPath);
30001
30327
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
30002
30328
  currentVersion = pkg.version ?? "0.0.0";
@@ -30060,14 +30386,33 @@ async function handleUpdate(subcommand, ctx) {
30060
30386
  const installCmd = `${sudoPrefix}npm install -g open-agents-ai@latest --prefer-online`;
30061
30387
  let installOk = false;
30062
30388
  let installError = "";
30063
- installOk = await new Promise((resolve31) => {
30064
- const child = exec(installCmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
30389
+ const runInstall2 = (cmd) => new Promise((resolve31) => {
30390
+ const child = exec(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
30065
30391
  if (err)
30066
30392
  installError = (stderr || err.message || "").trim();
30067
30393
  resolve31(!err);
30068
30394
  });
30069
30395
  child.stdout?.resume();
30070
30396
  });
30397
+ installOk = await runInstall2(installCmd);
30398
+ if (!installOk && /ENOTEMPTY|errno -39/i.test(installError)) {
30399
+ installSpinner.stop("Cleaning stale npm temp files...");
30400
+ try {
30401
+ const prefix = es2("npm prefix -g", { encoding: "utf8", timeout: 5e3 }).trim();
30402
+ const globalModules = prefix.endsWith("/lib") ? prefix + "/node_modules" : prefix + "/lib/node_modules";
30403
+ es2(`${sudoPrefix}find "${globalModules}" -maxdepth 1 -name ".open-agents-ai-*" -type d -exec rm -rf {} + 2>/dev/null || true`, { timeout: 15e3 });
30404
+ es2(`${sudoPrefix}rm -rf "${globalModules}/open-agents-ai" 2>/dev/null || true`, { timeout: 15e3 });
30405
+ } catch {
30406
+ }
30407
+ const retrySpinner = startInlineSpinner("Retrying install");
30408
+ installError = "";
30409
+ installOk = await runInstall2(installCmd);
30410
+ if (!installOk) {
30411
+ retrySpinner.stop("Retry failed.");
30412
+ } else {
30413
+ retrySpinner.stop(`Update installed (v${info.latestVersion}).`);
30414
+ }
30415
+ }
30071
30416
  if (!installOk) {
30072
30417
  installSpinner.stop("Update install failed.");
30073
30418
  const errPreview = installError.split("\n").filter((l) => l.trim()).slice(-3).join("\n ");
@@ -30252,9 +30597,9 @@ var init_commands = __esm({
30252
30597
  });
30253
30598
 
30254
30599
  // packages/cli/dist/tui/project-context.js
30255
- import { existsSync as existsSync28, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "node:fs";
30256
- import { join as join38, basename as basename10 } from "node:path";
30257
- import { execSync as execSync25 } from "node:child_process";
30600
+ import { existsSync as existsSync29, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "node:fs";
30601
+ import { join as join39, basename as basename10 } from "node:path";
30602
+ import { execSync as execSync26 } from "node:child_process";
30258
30603
  import { homedir as homedir11, platform as platform2, release } from "node:os";
30259
30604
  function getModelTier(modelName) {
30260
30605
  const m = modelName.toLowerCase();
@@ -30288,8 +30633,8 @@ function loadProjectMap(repoRoot) {
30288
30633
  if (!hasOaDirectory(repoRoot)) {
30289
30634
  initOaDirectory(repoRoot);
30290
30635
  }
30291
- const mapPath = join38(repoRoot, OA_DIR, "context", "project-map.md");
30292
- if (existsSync28(mapPath)) {
30636
+ const mapPath = join39(repoRoot, OA_DIR, "context", "project-map.md");
30637
+ if (existsSync29(mapPath)) {
30293
30638
  try {
30294
30639
  const content = readFileSync20(mapPath, "utf-8");
30295
30640
  return content;
@@ -30300,19 +30645,19 @@ function loadProjectMap(repoRoot) {
30300
30645
  }
30301
30646
  function getGitInfo(repoRoot) {
30302
30647
  try {
30303
- execSync25("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
30648
+ execSync26("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
30304
30649
  } catch {
30305
30650
  return "";
30306
30651
  }
30307
30652
  const lines = [];
30308
30653
  try {
30309
- const branch = execSync25("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
30654
+ const branch = execSync26("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
30310
30655
  if (branch)
30311
30656
  lines.push(`Branch: ${branch}`);
30312
30657
  } catch {
30313
30658
  }
30314
30659
  try {
30315
- const status = execSync25("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
30660
+ const status = execSync26("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
30316
30661
  if (status) {
30317
30662
  const changed = status.split("\n").length;
30318
30663
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -30322,7 +30667,7 @@ function getGitInfo(repoRoot) {
30322
30667
  } catch {
30323
30668
  }
30324
30669
  try {
30325
- const log = execSync25("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
30670
+ const log = execSync26("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
30326
30671
  if (log)
30327
30672
  lines.push(`Recent commits:
30328
30673
  ${log}`);
@@ -30332,31 +30677,31 @@ ${log}`);
30332
30677
  }
30333
30678
  function loadMemoryContext(repoRoot) {
30334
30679
  const sections = [];
30335
- const oaMemDir = join38(repoRoot, OA_DIR, "memory");
30680
+ const oaMemDir = join39(repoRoot, OA_DIR, "memory");
30336
30681
  const oaEntries = loadMemoryDir(oaMemDir, "project");
30337
30682
  if (oaEntries)
30338
30683
  sections.push(oaEntries);
30339
- const legacyMemDir = join38(repoRoot, ".open-agents", "memory");
30340
- if (legacyMemDir !== oaMemDir && existsSync28(legacyMemDir)) {
30684
+ const legacyMemDir = join39(repoRoot, ".open-agents", "memory");
30685
+ if (legacyMemDir !== oaMemDir && existsSync29(legacyMemDir)) {
30341
30686
  const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
30342
30687
  if (legacyEntries)
30343
30688
  sections.push(legacyEntries);
30344
30689
  }
30345
- const globalMemDir = join38(homedir11(), ".open-agents", "memory");
30690
+ const globalMemDir = join39(homedir11(), ".open-agents", "memory");
30346
30691
  const globalEntries = loadMemoryDir(globalMemDir, "global");
30347
30692
  if (globalEntries)
30348
30693
  sections.push(globalEntries);
30349
30694
  return sections.join("\n\n");
30350
30695
  }
30351
30696
  function loadMemoryDir(memDir, scope) {
30352
- if (!existsSync28(memDir))
30697
+ if (!existsSync29(memDir))
30353
30698
  return "";
30354
30699
  const lines = [];
30355
30700
  try {
30356
30701
  const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
30357
30702
  for (const file of files.slice(0, 10)) {
30358
30703
  try {
30359
- const raw = readFileSync20(join38(memDir, file), "utf-8");
30704
+ const raw = readFileSync20(join39(memDir, file), "utf-8");
30360
30705
  const entries = JSON.parse(raw);
30361
30706
  const topic = basename10(file, ".json");
30362
30707
  const keys = Object.keys(entries);
@@ -31383,12 +31728,12 @@ var init_carousel = __esm({
31383
31728
  });
31384
31729
 
31385
31730
  // packages/cli/dist/tui/carousel-descriptors.js
31386
- import { existsSync as existsSync29, readFileSync as readFileSync21, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync9 } from "node:fs";
31387
- import { join as join39, basename as basename11 } from "node:path";
31731
+ import { existsSync as existsSync30, readFileSync as readFileSync21, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync9 } from "node:fs";
31732
+ import { join as join40, basename as basename11 } from "node:path";
31388
31733
  function loadToolProfile(repoRoot) {
31389
- const filePath = join39(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
31734
+ const filePath = join40(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
31390
31735
  try {
31391
- if (!existsSync29(filePath))
31736
+ if (!existsSync30(filePath))
31392
31737
  return null;
31393
31738
  return JSON.parse(readFileSync21(filePath, "utf-8"));
31394
31739
  } catch {
@@ -31396,9 +31741,9 @@ function loadToolProfile(repoRoot) {
31396
31741
  }
31397
31742
  }
31398
31743
  function saveToolProfile(repoRoot, profile) {
31399
- const contextDir = join39(repoRoot, OA_DIR, "context");
31744
+ const contextDir = join40(repoRoot, OA_DIR, "context");
31400
31745
  mkdirSync10(contextDir, { recursive: true });
31401
- writeFileSync10(join39(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
31746
+ writeFileSync10(join40(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
31402
31747
  }
31403
31748
  function categorizeToolCall(toolName) {
31404
31749
  for (const cat of TOOL_CATEGORIES) {
@@ -31456,9 +31801,9 @@ function weightedColor(profile) {
31456
31801
  return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
31457
31802
  }
31458
31803
  function loadCachedDescriptors(repoRoot) {
31459
- const filePath = join39(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
31804
+ const filePath = join40(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
31460
31805
  try {
31461
- if (!existsSync29(filePath))
31806
+ if (!existsSync30(filePath))
31462
31807
  return null;
31463
31808
  const cached = JSON.parse(readFileSync21(filePath, "utf-8"));
31464
31809
  return cached.phrases.length > 0 ? cached.phrases : null;
@@ -31467,14 +31812,14 @@ function loadCachedDescriptors(repoRoot) {
31467
31812
  }
31468
31813
  }
31469
31814
  function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
31470
- const contextDir = join39(repoRoot, OA_DIR, "context");
31815
+ const contextDir = join40(repoRoot, OA_DIR, "context");
31471
31816
  mkdirSync10(contextDir, { recursive: true });
31472
31817
  const cached = {
31473
31818
  phrases,
31474
31819
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
31475
31820
  sourceHash
31476
31821
  };
31477
- writeFileSync10(join39(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
31822
+ writeFileSync10(join40(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
31478
31823
  }
31479
31824
  function generateDescriptors(repoRoot) {
31480
31825
  const profile = loadToolProfile(repoRoot);
@@ -31522,9 +31867,9 @@ function generateDescriptors(repoRoot) {
31522
31867
  return phrases;
31523
31868
  }
31524
31869
  function extractFromPackageJson(repoRoot, tags) {
31525
- const pkgPath = join39(repoRoot, "package.json");
31870
+ const pkgPath = join40(repoRoot, "package.json");
31526
31871
  try {
31527
- if (!existsSync29(pkgPath))
31872
+ if (!existsSync30(pkgPath))
31528
31873
  return;
31529
31874
  const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
31530
31875
  if (pkg.name && typeof pkg.name === "string") {
@@ -31570,7 +31915,7 @@ function extractFromManifests(repoRoot, tags) {
31570
31915
  { file: ".github/workflows", tag: "ci/cd" }
31571
31916
  ];
31572
31917
  for (const check of manifestChecks) {
31573
- if (existsSync29(join39(repoRoot, check.file))) {
31918
+ if (existsSync30(join40(repoRoot, check.file))) {
31574
31919
  tags.push(check.tag);
31575
31920
  }
31576
31921
  }
@@ -31592,16 +31937,16 @@ function extractFromSessions(repoRoot, tags) {
31592
31937
  }
31593
31938
  }
31594
31939
  function extractFromMemory(repoRoot, tags) {
31595
- const memoryDir = join39(repoRoot, OA_DIR, "memory");
31940
+ const memoryDir = join40(repoRoot, OA_DIR, "memory");
31596
31941
  try {
31597
- if (!existsSync29(memoryDir))
31942
+ if (!existsSync30(memoryDir))
31598
31943
  return;
31599
31944
  const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
31600
31945
  for (const file of files) {
31601
31946
  const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
31602
31947
  tags.push(topic);
31603
31948
  try {
31604
- const data = JSON.parse(readFileSync21(join39(memoryDir, file), "utf-8"));
31949
+ const data = JSON.parse(readFileSync21(join40(memoryDir, file), "utf-8"));
31605
31950
  if (data && typeof data === "object") {
31606
31951
  const keys = Object.keys(data).slice(0, 3);
31607
31952
  for (const key of keys) {
@@ -31736,25 +32081,25 @@ var init_carousel_descriptors = __esm({
31736
32081
  });
31737
32082
 
31738
32083
  // packages/cli/dist/tui/voice.js
31739
- import { existsSync as existsSync30, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11, readFileSync as readFileSync22, unlinkSync as unlinkSync4 } from "node:fs";
31740
- import { join as join40 } from "node:path";
32084
+ import { existsSync as existsSync31, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11, readFileSync as readFileSync22, unlinkSync as unlinkSync4 } from "node:fs";
32085
+ import { join as join41 } from "node:path";
31741
32086
  import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
31742
- import { execSync as execSync26, spawn as nodeSpawn } from "node:child_process";
32087
+ import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
31743
32088
  import { createRequire } from "node:module";
31744
32089
  function voiceDir() {
31745
- return join40(homedir12(), ".open-agents", "voice");
32090
+ return join41(homedir12(), ".open-agents", "voice");
31746
32091
  }
31747
32092
  function modelsDir() {
31748
- return join40(voiceDir(), "models");
32093
+ return join41(voiceDir(), "models");
31749
32094
  }
31750
32095
  function modelDir(id) {
31751
- return join40(modelsDir(), id);
32096
+ return join41(modelsDir(), id);
31752
32097
  }
31753
32098
  function modelOnnxPath(id) {
31754
- return join40(modelDir(id), "model.onnx");
32099
+ return join41(modelDir(id), "model.onnx");
31755
32100
  }
31756
32101
  function modelConfigPath(id) {
31757
- return join40(modelDir(id), "config.json");
32102
+ return join41(modelDir(id), "config.json");
31758
32103
  }
31759
32104
  function emotionToPitchBias(emotion) {
31760
32105
  const raw = emotion.valence * 0.6 + (emotion.arousal - 0.5) * 0.4;
@@ -32477,7 +32822,7 @@ var init_voice = __esm({
32477
32822
  }
32478
32823
  this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
32479
32824
  }
32480
- const wavPath = join40(tmpdir6(), `oa-voice-${Date.now()}.wav`);
32825
+ const wavPath = join41(tmpdir6(), `oa-voice-${Date.now()}.wav`);
32481
32826
  this.writeWav(audioData, sampleRate, wavPath);
32482
32827
  await this.playWav(wavPath);
32483
32828
  try {
@@ -32659,7 +33004,7 @@ var init_voice = __esm({
32659
33004
  }
32660
33005
  for (const player of ["paplay", "pw-play", "aplay"]) {
32661
33006
  try {
32662
- execSync26(`which ${player}`, { stdio: "pipe" });
33007
+ execSync27(`which ${player}`, { stdio: "pipe" });
32663
33008
  return [player, path];
32664
33009
  } catch {
32665
33010
  }
@@ -32683,12 +33028,12 @@ var init_voice = __esm({
32683
33028
  return;
32684
33029
  const arch = process.arch;
32685
33030
  mkdirSync11(voiceDir(), { recursive: true });
32686
- const pkgPath = join40(voiceDir(), "package.json");
33031
+ const pkgPath = join41(voiceDir(), "package.json");
32687
33032
  const expectedDeps = {
32688
33033
  "onnxruntime-node": "^1.21.0",
32689
33034
  "phonemizer": "^1.2.1"
32690
33035
  };
32691
- if (existsSync30(pkgPath)) {
33036
+ if (existsSync31(pkgPath)) {
32692
33037
  try {
32693
33038
  const existing = JSON.parse(readFileSync22(pkgPath, "utf8"));
32694
33039
  if (!existing.dependencies?.["phonemizer"]) {
@@ -32698,17 +33043,17 @@ var init_voice = __esm({
32698
33043
  } catch {
32699
33044
  }
32700
33045
  }
32701
- if (!existsSync30(pkgPath)) {
33046
+ if (!existsSync31(pkgPath)) {
32702
33047
  writeFileSync11(pkgPath, JSON.stringify({
32703
33048
  name: "open-agents-voice",
32704
33049
  private: true,
32705
33050
  dependencies: expectedDeps
32706
33051
  }, null, 2));
32707
33052
  }
32708
- const voiceRequire = createRequire(join40(voiceDir(), "index.js"));
33053
+ const voiceRequire = createRequire(join41(voiceDir(), "index.js"));
32709
33054
  const probeOnnx = () => {
32710
33055
  try {
32711
- const result = execSync26(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join40(voiceDir(), "node_modules") } });
33056
+ const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join41(voiceDir(), "node_modules") } });
32712
33057
  const output = result.toString().trim();
32713
33058
  if (output === "OK")
32714
33059
  return true;
@@ -32725,8 +33070,8 @@ var init_voice = __esm({
32725
33070
  return false;
32726
33071
  }
32727
33072
  };
32728
- const onnxNodeModules = join40(voiceDir(), "node_modules", "onnxruntime-node");
32729
- const onnxInstalled = existsSync30(onnxNodeModules);
33073
+ const onnxNodeModules = join41(voiceDir(), "node_modules", "onnxruntime-node");
33074
+ const onnxInstalled = existsSync31(onnxNodeModules);
32730
33075
  if (onnxInstalled && !probeOnnx()) {
32731
33076
  throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
32732
33077
  }
@@ -32735,7 +33080,7 @@ var init_voice = __esm({
32735
33080
  } catch {
32736
33081
  renderInfo("Installing ONNX runtime for voice synthesis...");
32737
33082
  try {
32738
- execSync26("npm install --no-audit --no-fund", {
33083
+ execSync27("npm install --no-audit --no-fund", {
32739
33084
  cwd: voiceDir(),
32740
33085
  stdio: "pipe",
32741
33086
  timeout: 12e4
@@ -32760,7 +33105,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
32760
33105
  } catch {
32761
33106
  renderInfo("Installing phonemizer for voice synthesis...");
32762
33107
  try {
32763
- execSync26("npm install --no-audit --no-fund", {
33108
+ execSync27("npm install --no-audit --no-fund", {
32764
33109
  cwd: voiceDir(),
32765
33110
  stdio: "pipe",
32766
33111
  timeout: 12e4
@@ -32784,10 +33129,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
32784
33129
  const dir = modelDir(id);
32785
33130
  const onnxPath = modelOnnxPath(id);
32786
33131
  const configPath = modelConfigPath(id);
32787
- if (existsSync30(onnxPath) && existsSync30(configPath))
33132
+ if (existsSync31(onnxPath) && existsSync31(configPath))
32788
33133
  return;
32789
33134
  mkdirSync11(dir, { recursive: true });
32790
- if (!existsSync30(configPath)) {
33135
+ if (!existsSync31(configPath)) {
32791
33136
  renderInfo(`Downloading ${model.label} voice config...`);
32792
33137
  const configResp = await fetch(model.configUrl);
32793
33138
  if (!configResp.ok)
@@ -32795,7 +33140,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
32795
33140
  const configText = await configResp.text();
32796
33141
  writeFileSync11(configPath, configText);
32797
33142
  }
32798
- if (!existsSync30(onnxPath)) {
33143
+ if (!existsSync31(onnxPath)) {
32799
33144
  renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
32800
33145
  const onnxResp = await fetch(model.onnxUrl);
32801
33146
  if (!onnxResp.ok)
@@ -32831,7 +33176,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
32831
33176
  throw new Error("ONNX runtime not loaded");
32832
33177
  const onnxPath = modelOnnxPath(this.modelId);
32833
33178
  const configPath = modelConfigPath(this.modelId);
32834
- if (!existsSync30(onnxPath) || !existsSync30(configPath)) {
33179
+ if (!existsSync31(onnxPath) || !existsSync31(configPath)) {
32835
33180
  throw new Error(`Model files not found for ${this.modelId}`);
32836
33181
  }
32837
33182
  this.config = JSON.parse(readFileSync22(configPath, "utf8"));
@@ -33698,10 +34043,10 @@ var init_stream_renderer = __esm({
33698
34043
 
33699
34044
  // packages/cli/dist/tui/edit-history.js
33700
34045
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync12 } from "node:fs";
33701
- import { join as join41 } from "node:path";
34046
+ import { join as join42 } from "node:path";
33702
34047
  function createEditHistoryLogger(repoRoot, sessionId) {
33703
- const historyDir = join41(repoRoot, ".oa", "history");
33704
- const logPath = join41(historyDir, "edits.jsonl");
34048
+ const historyDir = join42(repoRoot, ".oa", "history");
34049
+ const logPath = join42(historyDir, "edits.jsonl");
33705
34050
  try {
33706
34051
  mkdirSync12(historyDir, { recursive: true });
33707
34052
  } catch {
@@ -33812,14 +34157,14 @@ var init_edit_history = __esm({
33812
34157
  });
33813
34158
 
33814
34159
  // packages/cli/dist/tui/promptLoader.js
33815
- import { readFileSync as readFileSync23, existsSync as existsSync31 } from "node:fs";
33816
- import { join as join42, dirname as dirname15 } from "node:path";
34160
+ import { readFileSync as readFileSync23, existsSync as existsSync32 } from "node:fs";
34161
+ import { join as join43, dirname as dirname15 } from "node:path";
33817
34162
  import { fileURLToPath as fileURLToPath11 } from "node:url";
33818
34163
  function loadPrompt3(promptPath, vars) {
33819
34164
  let content = cache3.get(promptPath);
33820
34165
  if (content === void 0) {
33821
- const fullPath = join42(PROMPTS_DIR3, promptPath);
33822
- if (!existsSync31(fullPath)) {
34166
+ const fullPath = join43(PROMPTS_DIR3, promptPath);
34167
+ if (!existsSync32(fullPath)) {
33823
34168
  throw new Error(`Prompt file not found: ${fullPath}`);
33824
34169
  }
33825
34170
  content = readFileSync23(fullPath, "utf-8");
@@ -33835,20 +34180,20 @@ var init_promptLoader3 = __esm({
33835
34180
  "use strict";
33836
34181
  __filename3 = fileURLToPath11(import.meta.url);
33837
34182
  __dirname5 = dirname15(__filename3);
33838
- devPath2 = join42(__dirname5, "..", "..", "prompts");
33839
- publishedPath2 = join42(__dirname5, "..", "prompts");
33840
- PROMPTS_DIR3 = existsSync31(devPath2) ? devPath2 : publishedPath2;
34183
+ devPath2 = join43(__dirname5, "..", "..", "prompts");
34184
+ publishedPath2 = join43(__dirname5, "..", "prompts");
34185
+ PROMPTS_DIR3 = existsSync32(devPath2) ? devPath2 : publishedPath2;
33841
34186
  cache3 = /* @__PURE__ */ new Map();
33842
34187
  }
33843
34188
  });
33844
34189
 
33845
34190
  // packages/cli/dist/tui/dream-engine.js
33846
- import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12, readFileSync as readFileSync24, existsSync as existsSync32, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
33847
- import { join as join43, basename as basename12 } from "node:path";
33848
- import { execSync as execSync27 } from "node:child_process";
34191
+ import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12, readFileSync as readFileSync24, existsSync as existsSync33, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
34192
+ import { join as join44, basename as basename12 } from "node:path";
34193
+ import { execSync as execSync28 } from "node:child_process";
33849
34194
  function loadAutoresearchMemory(repoRoot) {
33850
- const memoryPath = join43(repoRoot, ".oa", "memory", "autoresearch.json");
33851
- if (!existsSync32(memoryPath))
34195
+ const memoryPath = join44(repoRoot, ".oa", "memory", "autoresearch.json");
34196
+ if (!existsSync33(memoryPath))
33852
34197
  return "";
33853
34198
  try {
33854
34199
  const raw = readFileSync24(memoryPath, "utf-8");
@@ -34041,12 +34386,12 @@ var init_dream_engine = __esm({
34041
34386
  const content = String(args["content"] ?? "");
34042
34387
  if (!rawPath)
34043
34388
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
34044
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join43(this.autoresearchDir, basename12(rawPath)) : join43(this.autoresearchDir, rawPath);
34389
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join44(this.autoresearchDir, basename12(rawPath)) : join44(this.autoresearchDir, rawPath);
34045
34390
  if (!targetPath.startsWith(this.autoresearchDir)) {
34046
34391
  return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
34047
34392
  }
34048
34393
  try {
34049
- const dir = join43(targetPath, "..");
34394
+ const dir = join44(targetPath, "..");
34050
34395
  mkdirSync13(dir, { recursive: true });
34051
34396
  writeFileSync12(targetPath, content, "utf-8");
34052
34397
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -34076,12 +34421,12 @@ var init_dream_engine = __esm({
34076
34421
  const rawPath = String(args["path"] ?? "");
34077
34422
  const oldStr = String(args["old_string"] ?? "");
34078
34423
  const newStr = String(args["new_string"] ?? "");
34079
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join43(this.autoresearchDir, basename12(rawPath)) : join43(this.autoresearchDir, rawPath);
34424
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join44(this.autoresearchDir, basename12(rawPath)) : join44(this.autoresearchDir, rawPath);
34080
34425
  if (!targetPath.startsWith(this.autoresearchDir)) {
34081
34426
  return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
34082
34427
  }
34083
34428
  try {
34084
- if (!existsSync32(targetPath)) {
34429
+ if (!existsSync33(targetPath)) {
34085
34430
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
34086
34431
  }
34087
34432
  let content = readFileSync24(targetPath, "utf-8");
@@ -34130,12 +34475,12 @@ var init_dream_engine = __esm({
34130
34475
  const content = String(args["content"] ?? "");
34131
34476
  if (!rawPath)
34132
34477
  return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
34133
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join43(this.dreamsDir, basename12(rawPath)) : join43(this.dreamsDir, rawPath);
34478
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join44(this.dreamsDir, basename12(rawPath)) : join44(this.dreamsDir, rawPath);
34134
34479
  if (!targetPath.startsWith(this.dreamsDir)) {
34135
34480
  return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
34136
34481
  }
34137
34482
  try {
34138
- const dir = join43(targetPath, "..");
34483
+ const dir = join44(targetPath, "..");
34139
34484
  mkdirSync13(dir, { recursive: true });
34140
34485
  writeFileSync12(targetPath, content, "utf-8");
34141
34486
  return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
@@ -34165,12 +34510,12 @@ var init_dream_engine = __esm({
34165
34510
  const rawPath = String(args["path"] ?? "");
34166
34511
  const oldStr = String(args["old_string"] ?? "");
34167
34512
  const newStr = String(args["new_string"] ?? "");
34168
- const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join43(this.dreamsDir, basename12(rawPath)) : join43(this.dreamsDir, rawPath);
34513
+ const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join44(this.dreamsDir, basename12(rawPath)) : join44(this.dreamsDir, rawPath);
34169
34514
  if (!targetPath.startsWith(this.dreamsDir)) {
34170
34515
  return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
34171
34516
  }
34172
34517
  try {
34173
- if (!existsSync32(targetPath)) {
34518
+ if (!existsSync33(targetPath)) {
34174
34519
  return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
34175
34520
  }
34176
34521
  let content = readFileSync24(targetPath, "utf-8");
@@ -34209,7 +34554,7 @@ var init_dream_engine = __esm({
34209
34554
  }
34210
34555
  }
34211
34556
  try {
34212
- const output = execSync27(cmd, {
34557
+ const output = execSync28(cmd, {
34213
34558
  cwd: this.repoRoot,
34214
34559
  timeout: 3e4,
34215
34560
  encoding: "utf-8",
@@ -34232,7 +34577,7 @@ var init_dream_engine = __esm({
34232
34577
  constructor(config, repoRoot) {
34233
34578
  this.config = config;
34234
34579
  this.repoRoot = repoRoot;
34235
- this.dreamsDir = join43(repoRoot, ".oa", "dreams");
34580
+ this.dreamsDir = join44(repoRoot, ".oa", "dreams");
34236
34581
  this.state = {
34237
34582
  mode: "default",
34238
34583
  active: false,
@@ -34316,7 +34661,7 @@ ${result.summary}`;
34316
34661
  if (mode !== "default" || cycle === totalCycles) {
34317
34662
  renderDreamContraction(cycle);
34318
34663
  const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
34319
- const summaryPath = join43(this.dreamsDir, `cycle-${cycle}-summary.md`);
34664
+ const summaryPath = join44(this.dreamsDir, `cycle-${cycle}-summary.md`);
34320
34665
  writeFileSync12(summaryPath, cycleSummary, "utf-8");
34321
34666
  }
34322
34667
  if (mode === "lucid" && !this.abortController.signal.aborted) {
@@ -34529,7 +34874,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
34529
34874
  }
34530
34875
  /** Build role-specific tool sets for swarm agents */
34531
34876
  buildSwarmTools(role, _workspace) {
34532
- const autoresearchDir = join43(this.repoRoot, ".oa", "autoresearch");
34877
+ const autoresearchDir = join44(this.repoRoot, ".oa", "autoresearch");
34533
34878
  const taskComplete = this.createSwarmTaskCompleteTool(role);
34534
34879
  switch (role) {
34535
34880
  case "researcher": {
@@ -34893,7 +35238,7 @@ INSTRUCTIONS:
34893
35238
  2. Summarize the key learnings and next steps
34894
35239
 
34895
35240
  Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
34896
- const reportPath = join43(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
35241
+ const reportPath = join44(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
34897
35242
  const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
34898
35243
 
34899
35244
  **Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
@@ -34982,29 +35327,29 @@ ${summaryResult}
34982
35327
  }
34983
35328
  /** Save workspace backup for lucid mode */
34984
35329
  saveVersionCheckpoint(cycle) {
34985
- const checkpointDir = join43(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
35330
+ const checkpointDir = join44(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
34986
35331
  try {
34987
35332
  mkdirSync13(checkpointDir, { recursive: true });
34988
35333
  try {
34989
- const gitStatus = execSync27("git status --porcelain", {
35334
+ const gitStatus = execSync28("git status --porcelain", {
34990
35335
  cwd: this.repoRoot,
34991
35336
  encoding: "utf-8",
34992
35337
  timeout: 1e4
34993
35338
  });
34994
- const gitDiff = execSync27("git diff", {
35339
+ const gitDiff = execSync28("git diff", {
34995
35340
  cwd: this.repoRoot,
34996
35341
  encoding: "utf-8",
34997
35342
  timeout: 1e4
34998
35343
  });
34999
- const gitHash = execSync27("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
35344
+ const gitHash = execSync28("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
35000
35345
  cwd: this.repoRoot,
35001
35346
  encoding: "utf-8",
35002
35347
  timeout: 5e3
35003
35348
  }).trim();
35004
- writeFileSync12(join43(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
35005
- writeFileSync12(join43(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
35006
- writeFileSync12(join43(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
35007
- writeFileSync12(join43(checkpointDir, "checkpoint.json"), JSON.stringify({
35349
+ writeFileSync12(join44(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
35350
+ writeFileSync12(join44(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
35351
+ writeFileSync12(join44(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
35352
+ writeFileSync12(join44(checkpointDir, "checkpoint.json"), JSON.stringify({
35008
35353
  cycle,
35009
35354
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
35010
35355
  gitHash,
@@ -35012,7 +35357,7 @@ ${summaryResult}
35012
35357
  }, null, 2), "utf-8");
35013
35358
  renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
35014
35359
  } catch {
35015
- writeFileSync12(join43(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
35360
+ writeFileSync12(join44(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
35016
35361
  renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
35017
35362
  }
35018
35363
  } catch (err) {
@@ -35070,14 +35415,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
35070
35415
  ---
35071
35416
  *Auto-generated by open-agents dream engine*
35072
35417
  `;
35073
- writeFileSync12(join43(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
35418
+ writeFileSync12(join44(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
35074
35419
  } catch {
35075
35420
  }
35076
35421
  }
35077
35422
  /** Save dream state for resume/inspection */
35078
35423
  saveDreamState() {
35079
35424
  try {
35080
- writeFileSync12(join43(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
35425
+ writeFileSync12(join44(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
35081
35426
  } catch {
35082
35427
  }
35083
35428
  }
@@ -35451,8 +35796,8 @@ var init_bless_engine = __esm({
35451
35796
  });
35452
35797
 
35453
35798
  // packages/cli/dist/tui/dmn-engine.js
35454
- import { existsSync as existsSync33, readFileSync as readFileSync25, writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
35455
- import { join as join44, basename as basename13 } from "node:path";
35799
+ import { existsSync as existsSync34, readFileSync as readFileSync25, writeFileSync as writeFileSync13, mkdirSync as mkdirSync14, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
35800
+ import { join as join45, basename as basename13 } from "node:path";
35456
35801
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
35457
35802
  const competenceReport = competence.length > 0 ? competence.map((c3) => {
35458
35803
  const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
@@ -35565,8 +35910,8 @@ var init_dmn_engine = __esm({
35565
35910
  constructor(config, repoRoot) {
35566
35911
  this.config = config;
35567
35912
  this.repoRoot = repoRoot;
35568
- this.stateDir = join44(repoRoot, ".oa", "dmn");
35569
- this.historyDir = join44(repoRoot, ".oa", "dmn", "cycles");
35913
+ this.stateDir = join45(repoRoot, ".oa", "dmn");
35914
+ this.historyDir = join45(repoRoot, ".oa", "dmn", "cycles");
35570
35915
  mkdirSync14(this.historyDir, { recursive: true });
35571
35916
  this.loadState();
35572
35917
  }
@@ -36156,11 +36501,11 @@ OUTPUT: Call task_complete with JSON:
36156
36501
  async gatherMemoryTopics() {
36157
36502
  const topics = [];
36158
36503
  const dirs = [
36159
- join44(this.repoRoot, ".oa", "memory"),
36160
- join44(this.repoRoot, ".open-agents", "memory")
36504
+ join45(this.repoRoot, ".oa", "memory"),
36505
+ join45(this.repoRoot, ".open-agents", "memory")
36161
36506
  ];
36162
36507
  for (const dir of dirs) {
36163
- if (!existsSync33(dir))
36508
+ if (!existsSync34(dir))
36164
36509
  continue;
36165
36510
  try {
36166
36511
  const files = readdirSync11(dir).filter((f) => f.endsWith(".json"));
@@ -36176,8 +36521,8 @@ OUTPUT: Call task_complete with JSON:
36176
36521
  }
36177
36522
  // ── State persistence ─────────────────────────────────────────────────
36178
36523
  loadState() {
36179
- const path = join44(this.stateDir, "state.json");
36180
- if (existsSync33(path)) {
36524
+ const path = join45(this.stateDir, "state.json");
36525
+ if (existsSync34(path)) {
36181
36526
  try {
36182
36527
  this.state = JSON.parse(readFileSync25(path, "utf-8"));
36183
36528
  } catch {
@@ -36186,19 +36531,19 @@ OUTPUT: Call task_complete with JSON:
36186
36531
  }
36187
36532
  saveState() {
36188
36533
  try {
36189
- writeFileSync13(join44(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
36534
+ writeFileSync13(join45(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
36190
36535
  } catch {
36191
36536
  }
36192
36537
  }
36193
36538
  saveCycleResult(result) {
36194
36539
  try {
36195
36540
  const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
36196
- writeFileSync13(join44(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
36541
+ writeFileSync13(join45(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
36197
36542
  const files = readdirSync11(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
36198
36543
  if (files.length > 50) {
36199
36544
  for (const old of files.slice(0, files.length - 50)) {
36200
36545
  try {
36201
- unlinkSync5(join44(this.historyDir, old));
36546
+ unlinkSync5(join45(this.historyDir, old));
36202
36547
  } catch {
36203
36548
  }
36204
36549
  }
@@ -36211,8 +36556,8 @@ OUTPUT: Call task_complete with JSON:
36211
36556
  });
36212
36557
 
36213
36558
  // packages/cli/dist/tui/snr-engine.js
36214
- import { existsSync as existsSync34, readdirSync as readdirSync12, readFileSync as readFileSync26 } from "node:fs";
36215
- import { join as join45, basename as basename14 } from "node:path";
36559
+ import { existsSync as existsSync35, readdirSync as readdirSync12, readFileSync as readFileSync26 } from "node:fs";
36560
+ import { join as join46, basename as basename14 } from "node:path";
36216
36561
  function computeDPrime(signalScores, noiseScores) {
36217
36562
  if (signalScores.length === 0 || noiseScores.length === 0)
36218
36563
  return 0;
@@ -36452,11 +36797,11 @@ Call task_complete with the JSON array when done.`, onEvent)
36452
36797
  loadMemoryEntries(topics) {
36453
36798
  const entries = [];
36454
36799
  const dirs = [
36455
- join45(this.repoRoot, ".oa", "memory"),
36456
- join45(this.repoRoot, ".open-agents", "memory")
36800
+ join46(this.repoRoot, ".oa", "memory"),
36801
+ join46(this.repoRoot, ".open-agents", "memory")
36457
36802
  ];
36458
36803
  for (const dir of dirs) {
36459
- if (!existsSync34(dir))
36804
+ if (!existsSync35(dir))
36460
36805
  continue;
36461
36806
  try {
36462
36807
  const files = readdirSync12(dir).filter((f) => f.endsWith(".json"));
@@ -36465,7 +36810,7 @@ Call task_complete with the JSON array when done.`, onEvent)
36465
36810
  if (topics.length > 0 && !topics.includes(topic))
36466
36811
  continue;
36467
36812
  try {
36468
- const data = JSON.parse(readFileSync26(join45(dir, f), "utf-8"));
36813
+ const data = JSON.parse(readFileSync26(join46(dir, f), "utf-8"));
36469
36814
  for (const [key, val] of Object.entries(data)) {
36470
36815
  const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
36471
36816
  entries.push({ topic, key, value });
@@ -37016,8 +37361,8 @@ var init_tool_policy = __esm({
37016
37361
  });
37017
37362
 
37018
37363
  // packages/cli/dist/tui/telegram-bridge.js
37019
- import { mkdirSync as mkdirSync15, existsSync as existsSync35, unlinkSync as unlinkSync6, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
37020
- import { join as join46, resolve as resolve27 } from "node:path";
37364
+ import { mkdirSync as mkdirSync15, existsSync as existsSync36, unlinkSync as unlinkSync6, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
37365
+ import { join as join47, resolve as resolve27 } from "node:path";
37021
37366
  import { writeFile as writeFileAsync } from "node:fs/promises";
37022
37367
  function convertMarkdownToTelegramHTML(md) {
37023
37368
  let html = md;
@@ -37782,7 +38127,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
37782
38127
  return null;
37783
38128
  const buffer = Buffer.from(await res.arrayBuffer());
37784
38129
  const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
37785
- const localPath = join46(this.mediaCacheDir, fileName);
38130
+ const localPath = join47(this.mediaCacheDir, fileName);
37786
38131
  await writeFileAsync(localPath, buffer);
37787
38132
  return localPath;
37788
38133
  } catch {
@@ -39505,11 +39850,11 @@ var init_status_bar = __esm({
39505
39850
  import * as readline2 from "node:readline";
39506
39851
  import { Writable } from "node:stream";
39507
39852
  import { cwd } from "node:process";
39508
- import { resolve as resolve28, join as join47, dirname as dirname16, extname as extname9 } from "node:path";
39853
+ import { resolve as resolve28, join as join48, dirname as dirname16, extname as extname9 } from "node:path";
39509
39854
  import { createRequire as createRequire2 } from "node:module";
39510
39855
  import { fileURLToPath as fileURLToPath12 } from "node:url";
39511
39856
  import { readFileSync as readFileSync27, writeFileSync as writeFileSync14, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync16 } from "node:fs";
39512
- import { existsSync as existsSync36 } from "node:fs";
39857
+ import { existsSync as existsSync37 } from "node:fs";
39513
39858
  import { homedir as homedir13 } from "node:os";
39514
39859
  function formatTimeAgo(date) {
39515
39860
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -39524,17 +39869,17 @@ function formatTimeAgo(date) {
39524
39869
  const days = Math.floor(hours / 24);
39525
39870
  return `${days}d ago`;
39526
39871
  }
39527
- function getVersion2() {
39872
+ function getVersion3() {
39528
39873
  try {
39529
39874
  const require2 = createRequire2(import.meta.url);
39530
39875
  const thisDir = dirname16(fileURLToPath12(import.meta.url));
39531
39876
  const candidates = [
39532
- join47(thisDir, "..", "package.json"),
39533
- join47(thisDir, "..", "..", "package.json"),
39534
- join47(thisDir, "..", "..", "..", "package.json")
39877
+ join48(thisDir, "..", "package.json"),
39878
+ join48(thisDir, "..", "..", "package.json"),
39879
+ join48(thisDir, "..", "..", "..", "package.json")
39535
39880
  ];
39536
39881
  for (const pkgPath of candidates) {
39537
- if (existsSync36(pkgPath)) {
39882
+ if (existsSync37(pkgPath)) {
39538
39883
  const pkg = require2(pkgPath);
39539
39884
  if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
39540
39885
  return pkg.version ?? "0.0.0";
@@ -39641,8 +39986,9 @@ function buildTools(repoRoot, config, contextWindowSize) {
39641
39986
  new SchedulerTool(repoRoot),
39642
39987
  new ReminderTool(repoRoot),
39643
39988
  new AgendaTool(repoRoot),
39644
- // OpenCode delegation + long-horizon cron agent
39989
+ // OpenCode + Factory AI delegation + long-horizon cron agent
39645
39990
  new OpenCodeTool(repoRoot),
39991
+ new FactoryTool(repoRoot),
39646
39992
  new CronAgentTool(repoRoot),
39647
39993
  // Nexus P2P networking + x402 micropayments
39648
39994
  new NexusTool(repoRoot)
@@ -39739,15 +40085,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
39739
40085
  function gatherMemorySnippets(root) {
39740
40086
  const snippets = [];
39741
40087
  const dirs = [
39742
- join47(root, ".oa", "memory"),
39743
- join47(root, ".open-agents", "memory")
40088
+ join48(root, ".oa", "memory"),
40089
+ join48(root, ".open-agents", "memory")
39744
40090
  ];
39745
40091
  for (const dir of dirs) {
39746
- if (!existsSync36(dir))
40092
+ if (!existsSync37(dir))
39747
40093
  continue;
39748
40094
  try {
39749
40095
  for (const f of readdirSync14(dir).filter((f2) => f2.endsWith(".json"))) {
39750
- const data = JSON.parse(readFileSync27(join47(dir, f), "utf-8"));
40096
+ const data = JSON.parse(readFileSync27(join48(dir, f), "utf-8"));
39751
40097
  for (const val of Object.values(data)) {
39752
40098
  const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
39753
40099
  if (v.length > 10)
@@ -40285,7 +40631,7 @@ async function startInteractive(config, repoPath) {
40285
40631
  }
40286
40632
  const carousel = new Carousel(carouselPhrases ?? void 0);
40287
40633
  let carouselLines = 0;
40288
- const version = getVersion2();
40634
+ const version = getVersion3();
40289
40635
  if (isResumed) {
40290
40636
  const resumeMsg = hasTaskToResume ? `Updated to v${version} \u2014 picking up where you left off.
40291
40637
  ` : `Updated to v${version}.
@@ -40397,7 +40743,7 @@ async function startInteractive(config, repoPath) {
40397
40743
  let exposeGateway = null;
40398
40744
  let peerMesh = null;
40399
40745
  let inferenceRouter = null;
40400
- const secretVault = new SecretVault(join47(repoRoot, ".oa", "vault.enc"));
40746
+ const secretVault = new SecretVault(join48(repoRoot, ".oa", "vault.enc"));
40401
40747
  let adminSessionKey = null;
40402
40748
  const callSubAgents = /* @__PURE__ */ new Map();
40403
40749
  const streamRenderer = new StreamRenderer();
@@ -40602,12 +40948,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
40602
40948
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
40603
40949
  return [hits, line];
40604
40950
  }
40605
- const HISTORY_DIR = join47(homedir13(), ".open-agents");
40606
- const HISTORY_FILE = join47(HISTORY_DIR, "repl-history");
40951
+ const HISTORY_DIR = join48(homedir13(), ".open-agents");
40952
+ const HISTORY_FILE = join48(HISTORY_DIR, "repl-history");
40607
40953
  const MAX_HISTORY_LINES = 500;
40608
40954
  let savedHistory = [];
40609
40955
  try {
40610
- if (existsSync36(HISTORY_FILE)) {
40956
+ if (existsSync37(HISTORY_FILE)) {
40611
40957
  const raw = readFileSync27(HISTORY_FILE, "utf8").trim();
40612
40958
  if (raw)
40613
40959
  savedHistory = raw.split("\n").reverse();
@@ -41486,8 +41832,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
41486
41832
  return true;
41487
41833
  },
41488
41834
  destroyProject() {
41489
- const oaPath = join47(repoRoot, OA_DIR);
41490
- if (existsSync36(oaPath)) {
41835
+ const oaPath = join48(repoRoot, OA_DIR);
41836
+ if (existsSync37(oaPath)) {
41491
41837
  try {
41492
41838
  rmSync2(oaPath, { recursive: true, force: true });
41493
41839
  writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
@@ -41788,8 +42134,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
41788
42134
  }
41789
42135
  }
41790
42136
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
41791
- const isImage = isImagePath(cleanPath) && existsSync36(resolve28(repoRoot, cleanPath));
41792
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync36(resolve28(repoRoot, cleanPath));
42137
+ const isImage = isImagePath(cleanPath) && existsSync37(resolve28(repoRoot, cleanPath));
42138
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync37(resolve28(repoRoot, cleanPath));
41793
42139
  if (activeTask) {
41794
42140
  if (isImage) {
41795
42141
  try {
@@ -42308,7 +42654,7 @@ import { glob } from "glob";
42308
42654
  import ignore from "ignore";
42309
42655
  import { readFile as readFile16, stat as stat4 } from "node:fs/promises";
42310
42656
  import { createHash as createHash4 } from "node:crypto";
42311
- import { join as join48, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
42657
+ import { join as join49, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
42312
42658
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
42313
42659
  var init_codebase_indexer = __esm({
42314
42660
  "packages/indexer/dist/codebase-indexer.js"() {
@@ -42352,7 +42698,7 @@ var init_codebase_indexer = __esm({
42352
42698
  const ig = ignore.default();
42353
42699
  if (this.config.respectGitignore) {
42354
42700
  try {
42355
- const gitignoreContent = await readFile16(join48(this.config.rootDir, ".gitignore"), "utf-8");
42701
+ const gitignoreContent = await readFile16(join49(this.config.rootDir, ".gitignore"), "utf-8");
42356
42702
  ig.add(gitignoreContent);
42357
42703
  } catch {
42358
42704
  }
@@ -42367,7 +42713,7 @@ var init_codebase_indexer = __esm({
42367
42713
  for (const relativePath of files) {
42368
42714
  if (ig.ignores(relativePath))
42369
42715
  continue;
42370
- const fullPath = join48(this.config.rootDir, relativePath);
42716
+ const fullPath = join49(this.config.rootDir, relativePath);
42371
42717
  try {
42372
42718
  const fileStat = await stat4(fullPath);
42373
42719
  if (fileStat.size > this.config.maxFileSize)
@@ -42413,7 +42759,7 @@ var init_codebase_indexer = __esm({
42413
42759
  if (!child) {
42414
42760
  child = {
42415
42761
  name: part,
42416
- path: join48(current.path, part),
42762
+ path: join49(current.path, part),
42417
42763
  type: "directory",
42418
42764
  children: []
42419
42765
  };
@@ -42496,13 +42842,13 @@ __export(index_repo_exports, {
42496
42842
  indexRepoCommand: () => indexRepoCommand
42497
42843
  });
42498
42844
  import { resolve as resolve29 } from "node:path";
42499
- import { existsSync as existsSync37, statSync as statSync11 } from "node:fs";
42845
+ import { existsSync as existsSync38, statSync as statSync11 } from "node:fs";
42500
42846
  import { cwd as cwd2 } from "node:process";
42501
42847
  async function indexRepoCommand(opts, _config) {
42502
42848
  const repoRoot = resolve29(opts.repoPath ?? cwd2());
42503
42849
  printHeader("Index Repository");
42504
42850
  printInfo(`Indexing: ${repoRoot}`);
42505
- if (!existsSync37(repoRoot)) {
42851
+ if (!existsSync38(repoRoot)) {
42506
42852
  printError(`Path does not exist: ${repoRoot}`);
42507
42853
  process.exit(1);
42508
42854
  }
@@ -42754,7 +43100,7 @@ var config_exports = {};
42754
43100
  __export(config_exports, {
42755
43101
  configCommand: () => configCommand
42756
43102
  });
42757
- import { join as join49, resolve as resolve30 } from "node:path";
43103
+ import { join as join50, resolve as resolve30 } from "node:path";
42758
43104
  import { homedir as homedir14 } from "node:os";
42759
43105
  import { cwd as cwd3 } from "node:process";
42760
43106
  function redactIfSensitive(key, value) {
@@ -42813,7 +43159,7 @@ function handleShow(opts, config) {
42813
43159
  }
42814
43160
  }
42815
43161
  printSection("Config File");
42816
- printInfo(`~/.open-agents/config.json (${join49(homedir14(), ".open-agents", "config.json")})`);
43162
+ printInfo(`~/.open-agents/config.json (${join50(homedir14(), ".open-agents", "config.json")})`);
42817
43163
  printSection("Priority Chain");
42818
43164
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
42819
43165
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -42852,7 +43198,7 @@ function handleSet(opts, _config) {
42852
43198
  const coerced = coerceForSettings(key, value);
42853
43199
  saveProjectSettings(repoRoot, { [key]: coerced });
42854
43200
  printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
42855
- printInfo(`Saved to ${join49(repoRoot, ".oa", "settings.json")}`);
43201
+ printInfo(`Saved to ${join50(repoRoot, ".oa", "settings.json")}`);
42856
43202
  printInfo("This override applies only when running in this workspace.");
42857
43203
  } catch (err) {
42858
43204
  printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
@@ -42913,7 +43259,7 @@ var serve_exports = {};
42913
43259
  __export(serve_exports, {
42914
43260
  serveCommand: () => serveCommand
42915
43261
  });
42916
- import { spawn as spawn15 } from "node:child_process";
43262
+ import { spawn as spawn16 } from "node:child_process";
42917
43263
  async function serveCommand(opts, config) {
42918
43264
  const backendType = config.backendType;
42919
43265
  if (backendType === "ollama") {
@@ -43006,7 +43352,7 @@ async function serveVllm(opts, config) {
43006
43352
  }
43007
43353
  async function runVllmServer(args, verbose) {
43008
43354
  return new Promise((resolve31, reject) => {
43009
- const child = spawn15("python", args, {
43355
+ const child = spawn16("python", args, {
43010
43356
  stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
43011
43357
  env: { ...process.env }
43012
43358
  });
@@ -43072,7 +43418,7 @@ __export(eval_exports, {
43072
43418
  });
43073
43419
  import { tmpdir as tmpdir7 } from "node:os";
43074
43420
  import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "node:fs";
43075
- import { join as join50 } from "node:path";
43421
+ import { join as join51 } from "node:path";
43076
43422
  async function evalCommand(opts, config) {
43077
43423
  const suiteName = opts.suite ?? "basic";
43078
43424
  const suite = SUITES[suiteName];
@@ -43197,9 +43543,9 @@ async function evalCommand(opts, config) {
43197
43543
  process.exit(failed > 0 ? 1 : 0);
43198
43544
  }
43199
43545
  function createTempEvalRepo() {
43200
- const dir = join50(tmpdir7(), `open-agents-eval-${Date.now()}`);
43546
+ const dir = join51(tmpdir7(), `open-agents-eval-${Date.now()}`);
43201
43547
  mkdirSync17(dir, { recursive: true });
43202
- writeFileSync15(join50(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
43548
+ writeFileSync15(join51(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
43203
43549
  return dir;
43204
43550
  }
43205
43551
  var BASIC_SUITE, FULL_SUITE, SUITES;
@@ -43259,7 +43605,7 @@ init_updater();
43259
43605
  import { parseArgs as nodeParseArgs2 } from "node:util";
43260
43606
  import { createRequire as createRequire3 } from "node:module";
43261
43607
  import { fileURLToPath as fileURLToPath13 } from "node:url";
43262
- import { dirname as dirname17, join as join51 } from "node:path";
43608
+ import { dirname as dirname17, join as join52 } from "node:path";
43263
43609
 
43264
43610
  // packages/cli/dist/cli.js
43265
43611
  import { createInterface } from "node:readline";
@@ -43363,10 +43709,10 @@ Options:
43363
43709
  init_config();
43364
43710
  init_spinner();
43365
43711
  init_output();
43366
- function getVersion3() {
43712
+ function getVersion4() {
43367
43713
  try {
43368
43714
  const require2 = createRequire3(import.meta.url);
43369
- const pkgPath = join51(dirname17(fileURLToPath13(import.meta.url)), "..", "package.json");
43715
+ const pkgPath = join52(dirname17(fileURLToPath13(import.meta.url)), "..", "package.json");
43370
43716
  const pkg = require2(pkgPath);
43371
43717
  return pkg.version;
43372
43718
  } catch {
@@ -43513,7 +43859,7 @@ Examples:
43513
43859
  process.stdout.write(text + "\n");
43514
43860
  }
43515
43861
  async function main() {
43516
- const version = getVersion3();
43862
+ const version = getVersion4();
43517
43863
  const parsed = parseCliArgs(process.argv);
43518
43864
  if (parsed.version) {
43519
43865
  process.stdout.write(`open-agents v${version}