open-agents-ai 0.142.2 → 0.143.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1370,7 +1370,7 @@ ${stdinInput ?? ""}`);
1370
1370
  }
1371
1371
  runCommand(command, timeout, stdinInput) {
1372
1372
  const start = performance.now();
1373
- return new Promise((resolve32) => {
1373
+ return new Promise((resolve33) => {
1374
1374
  const child = spawn("bash", ["-c", command], {
1375
1375
  cwd: this.workingDir,
1376
1376
  env: {
@@ -1395,7 +1395,7 @@ ${stdinInput ?? ""}`);
1395
1395
  clearTimeout(timer);
1396
1396
  if (exitFlushTimer)
1397
1397
  clearTimeout(exitFlushTimer);
1398
- resolve32(result);
1398
+ resolve33(result);
1399
1399
  };
1400
1400
  const timer = setTimeout(() => {
1401
1401
  killed = true;
@@ -2556,7 +2556,7 @@ ${JSON.stringify(extracted, null, 2)}`);
2556
2556
  return null;
2557
2557
  }
2558
2558
  runProcess(cmd, args, timeoutMs) {
2559
- return new Promise((resolve32, reject) => {
2559
+ return new Promise((resolve33, reject) => {
2560
2560
  const proc = execFile3(cmd, args, {
2561
2561
  timeout: timeoutMs,
2562
2562
  maxBuffer: 10 * 1024 * 1024,
@@ -2566,7 +2566,7 @@ ${JSON.stringify(extracted, null, 2)}`);
2566
2566
  reject(new Error(`Process timeout after ${timeoutMs}ms`));
2567
2567
  return;
2568
2568
  }
2569
- resolve32({
2569
+ resolve33({
2570
2570
  stdout: String(stdout),
2571
2571
  stderr: String(stderr),
2572
2572
  exitCode: error ? error.code ?? 1 : 0
@@ -9975,7 +9975,7 @@ var init_custom_tool = __esm({
9975
9975
  }
9976
9976
  /** Execute a single shell command and return output */
9977
9977
  runCommand(command) {
9978
- return new Promise((resolve32) => {
9978
+ return new Promise((resolve33) => {
9979
9979
  const child = spawn4("bash", ["-c", command], {
9980
9980
  cwd: this.workingDir,
9981
9981
  env: { ...process.env, CI: "true", NO_COLOR: "1" },
@@ -10000,11 +10000,11 @@ var init_custom_tool = __esm({
10000
10000
  child.kill("SIGTERM");
10001
10001
  } catch {
10002
10002
  }
10003
- resolve32({ success: false, output: stdout, error: "Command timed out after 60s" });
10003
+ resolve33({ success: false, output: stdout, error: "Command timed out after 60s" });
10004
10004
  }, 6e4);
10005
10005
  child.on("close", (code) => {
10006
10006
  clearTimeout(timer);
10007
- resolve32({
10007
+ resolve33({
10008
10008
  success: code === 0,
10009
10009
  output: stdout + (stderr && code === 0 ? `
10010
10010
  STDERR:
@@ -10014,7 +10014,7 @@ ${stderr}` : ""),
10014
10014
  });
10015
10015
  child.on("error", (err) => {
10016
10016
  clearTimeout(timer);
10017
- resolve32({ success: false, output: stdout, error: err.message });
10017
+ resolve33({ success: false, output: stdout, error: err.message });
10018
10018
  });
10019
10019
  });
10020
10020
  }
@@ -11481,7 +11481,7 @@ import { writeFile as writeFile8, mkdtemp, rm, readdir as readdir3, stat } from
11481
11481
  import { join as join18 } from "node:path";
11482
11482
  import { tmpdir as tmpdir2 } from "node:os";
11483
11483
  function runProcess(cmd, args, options) {
11484
- return new Promise((resolve32) => {
11484
+ return new Promise((resolve33) => {
11485
11485
  const proc = spawn6(cmd, args, {
11486
11486
  cwd: options.cwd,
11487
11487
  timeout: options.timeout,
@@ -11511,7 +11511,7 @@ function runProcess(cmd, args, options) {
11511
11511
  }
11512
11512
  });
11513
11513
  proc.on("error", (err) => {
11514
- resolve32({
11514
+ resolve33({
11515
11515
  stdout,
11516
11516
  stderr: stderr || err.message,
11517
11517
  exitCode: 1,
@@ -11523,7 +11523,7 @@ function runProcess(cmd, args, options) {
11523
11523
  if (signal === "SIGTERM" || signal === "SIGKILL") {
11524
11524
  timedOut = true;
11525
11525
  }
11526
- resolve32({
11526
+ resolve33({
11527
11527
  stdout,
11528
11528
  stderr,
11529
11529
  exitCode: code ?? (timedOut ? 124 : 1),
@@ -12006,7 +12006,7 @@ Justification: ${justification || "(none provided)"}`,
12006
12006
  })();
12007
12007
  const ipfsResult = await Promise.race([
12008
12008
  ipfsPromise,
12009
- new Promise((resolve32) => setTimeout(() => resolve32(null), 2e3))
12009
+ new Promise((resolve33) => setTimeout(() => resolve33(null), 2e3))
12010
12010
  ]);
12011
12011
  if (ipfsResult && ipfsResult.success) {
12012
12012
  const cidData = JSON.parse(ipfsResult.output);
@@ -12450,7 +12450,7 @@ print("__OA_REPL_READY__")
12450
12450
  return;
12451
12451
  const sockId = randomBytes3(8).toString("hex");
12452
12452
  this.ipcPath = join20(tmpdir3(), `oa-repl-ipc-${sockId}.sock`);
12453
- return new Promise((resolve32, reject) => {
12453
+ return new Promise((resolve33, reject) => {
12454
12454
  this.ipcServer = createServer((conn) => {
12455
12455
  let buffer = new Uint8Array(0);
12456
12456
  conn.on("data", (chunk) => {
@@ -12466,7 +12466,7 @@ print("__OA_REPL_READY__")
12466
12466
  });
12467
12467
  });
12468
12468
  this.ipcServer.on("error", reject);
12469
- this.ipcServer.listen(this.ipcPath, () => resolve32());
12469
+ this.ipcServer.listen(this.ipcPath, () => resolve33());
12470
12470
  });
12471
12471
  }
12472
12472
  async processIpcBuffer(conn, input) {
@@ -12529,9 +12529,9 @@ print("__OA_REPL_READY__")
12529
12529
  }
12530
12530
  // ── Code execution ─────────────────────────────────────────────────────
12531
12531
  executeCode(code, isInit = false) {
12532
- return new Promise((resolve32) => {
12532
+ return new Promise((resolve33) => {
12533
12533
  if (!this.proc?.stdin || !this.proc?.stdout || !this.proc?.stderr) {
12534
- resolve32({ success: false, output: "REPL process not available", error: "No process", durationMs: 0 });
12534
+ resolve33({ success: false, output: "REPL process not available", error: "No process", durationMs: 0 });
12535
12535
  return;
12536
12536
  }
12537
12537
  const sentinel = `__OA_SENTINEL_${randomBytes3(6).toString("hex")}__`;
@@ -12541,7 +12541,7 @@ print("__OA_REPL_READY__")
12541
12541
  const timeout = setTimeout(() => {
12542
12542
  if (!resolved) {
12543
12543
  resolved = true;
12544
- resolve32({
12544
+ resolve33({
12545
12545
  success: false,
12546
12546
  output: stdout || "Execution timed out",
12547
12547
  error: `Timeout after ${this.execTimeout / 1e3}s`,
@@ -12558,13 +12558,13 @@ print("__OA_REPL_READY__")
12558
12558
  if (isInit) {
12559
12559
  const ready = cleanOutput.includes("__OA_REPL_READY__");
12560
12560
  const displayOutput = cleanOutput.replace("__OA_REPL_READY__", "").trim();
12561
- resolve32({
12561
+ resolve33({
12562
12562
  success: ready,
12563
12563
  output: displayOutput || "REPL initialized",
12564
12564
  durationMs: 0
12565
12565
  });
12566
12566
  } else {
12567
- resolve32({
12567
+ resolve33({
12568
12568
  success: true,
12569
12569
  output: cleanOutput || "(no output)",
12570
12570
  durationMs: 0
@@ -12573,7 +12573,7 @@ print("__OA_REPL_READY__")
12573
12573
  }
12574
12574
  if (stdout.length > 2e5) {
12575
12575
  cleanup();
12576
- resolve32({
12576
+ resolve33({
12577
12577
  success: true,
12578
12578
  output: stdout.slice(0, 2e5) + "\n[output truncated at 200KB]",
12579
12579
  durationMs: 0
@@ -16812,6 +16812,7 @@ train.py reverted to last kept state. Ready for next experiment.`,
16812
16812
  import { execSync as execSync18, exec as execCb } from "node:child_process";
16813
16813
  import { readFile as readFile15, writeFile as writeFile15, mkdir as mkdir11 } from "node:fs/promises";
16814
16814
  import { resolve as resolve22, join as join32 } from "node:path";
16815
+ import { homedir as homedir8 } from "node:os";
16815
16816
  import { randomBytes as randomBytes4 } from "node:crypto";
16816
16817
  function isValidCron(expr) {
16817
16818
  const parts = expr.trim().split(/\s+/);
@@ -16941,6 +16942,31 @@ async function saveStore(workingDir, store) {
16941
16942
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
16942
16943
  await writeFile15(join32(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
16943
16944
  }
16945
+ function globalStoreDir() {
16946
+ return join32(homedir8(), ".open-agents", "scheduled");
16947
+ }
16948
+ async function loadGlobalStore() {
16949
+ try {
16950
+ const raw = await readFile15(join32(globalStoreDir(), "tasks.json"), "utf-8");
16951
+ return JSON.parse(raw);
16952
+ } catch {
16953
+ return { tasks: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
16954
+ }
16955
+ }
16956
+ async function saveGlobalStore(store) {
16957
+ const dir = globalStoreDir();
16958
+ await mkdir11(dir, { recursive: true });
16959
+ await mkdir11(join32(dir, "logs"), { recursive: true });
16960
+ store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
16961
+ await writeFile15(join32(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
16962
+ }
16963
+ async function loadAllStores(workingDir) {
16964
+ const [local, global] = await Promise.all([
16965
+ loadStore(workingDir),
16966
+ loadGlobalStore()
16967
+ ]);
16968
+ return { local, global };
16969
+ }
16944
16970
  var SCHEDULE_PRESETS, CRON_MARKER, SchedulerTool;
16945
16971
  var init_scheduler = __esm({
16946
16972
  "packages/execution/dist/tools/scheduler.js"() {
@@ -16964,7 +16990,7 @@ var init_scheduler = __esm({
16964
16990
  CRON_MARKER = "# OPEN-AGENTS-SCHEDULED:";
16965
16991
  SchedulerTool = class {
16966
16992
  name = "scheduler";
16967
- description = "Schedule tasks for automatic future execution using OS-level cron. Actions: 'create' a new scheduled task, 'list' all scheduled tasks, 'cancel' a task by ID, 'pause'/'resume' a task. Schedules: use presets ('daily', 'every 5 minutes', 'hourly', 'weekly'), natural language ('in 30m', 'at 14:30'), or raw cron expressions ('0 */2 * * *'). Tasks launch the agent automatically at the scheduled time.";
16993
+ description = "Schedule tasks for automatic future execution using OS-level cron. Actions: 'create' a new scheduled task, 'list' all scheduled tasks, 'cancel' a task by ID, 'pause'/'resume' a task. Schedules: use presets ('daily', 'every 5 minutes', 'hourly', 'weekly'), natural language ('in 30m', 'at 14:30'), or raw cron expressions ('0 */2 * * *'). Scope: 'local' (default, stored in .oa/) or 'global' (stored in ~/.open-agents/, visible from all projects). Tasks launch the agent automatically at the scheduled time.";
16968
16994
  parameters = {
16969
16995
  type: "object",
16970
16996
  properties: {
@@ -16992,6 +17018,11 @@ var init_scheduler = __esm({
16992
17018
  one_shot: {
16993
17019
  type: "boolean",
16994
17020
  description: "If true, task auto-removes after first execution"
17021
+ },
17022
+ scope: {
17023
+ type: "string",
17024
+ enum: ["local", "global"],
17025
+ description: "Scope: 'local' (project .oa/, default) or 'global' (~/.open-agents/, visible from all projects)"
16995
17026
  }
16996
17027
  },
16997
17028
  required: ["action"]
@@ -17053,6 +17084,7 @@ var init_scheduler = __esm({
17053
17084
  const id = `sched-${randomBytes4(4).toString("hex")}`;
17054
17085
  const oneShot = Boolean(args["one_shot"]);
17055
17086
  const maxRuns = typeof args["max_runs"] === "number" ? args["max_runs"] : void 0;
17087
+ const scope = String(args["scope"] ?? "local");
17056
17088
  const newTask = {
17057
17089
  id,
17058
17090
  task,
@@ -17062,11 +17094,19 @@ var init_scheduler = __esm({
17062
17094
  enabled: true,
17063
17095
  runCount: 0,
17064
17096
  maxRuns,
17065
- oneShot: oneShot || void 0
17097
+ oneShot: oneShot || void 0,
17098
+ scope,
17099
+ projectDir: resolve22(this.workingDir)
17066
17100
  };
17067
- const store = await loadStore(this.workingDir);
17068
- store.tasks.push(newTask);
17069
- await saveStore(this.workingDir, store);
17101
+ if (scope === "global") {
17102
+ const store = await loadGlobalStore();
17103
+ store.tasks.push(newTask);
17104
+ await saveGlobalStore(store);
17105
+ } else {
17106
+ const store = await loadStore(this.workingDir);
17107
+ store.tasks.push(newTask);
17108
+ await saveStore(this.workingDir, store);
17109
+ }
17070
17110
  installCronJob(newTask, this.workingDir);
17071
17111
  return {
17072
17112
  success: true,
@@ -17075,6 +17115,7 @@ var init_scheduler = __esm({
17075
17115
  ` ID: ${id}`,
17076
17116
  ` Task: ${task}`,
17077
17117
  ` Schedule: ${describeCron(cronExpr)} (${cronExpr})`,
17118
+ ` Scope: ${scope}${scope === "global" ? " (visible from all projects)" : " (this project only)"}`,
17078
17119
  oneShot ? ` Mode: one-shot (auto-removes after first run)` : "",
17079
17120
  maxRuns ? ` Max runs: ${maxRuns}` : "",
17080
17121
  ` Status: enabled`,
@@ -17086,28 +17127,53 @@ var init_scheduler = __esm({
17086
17127
  };
17087
17128
  }
17088
17129
  async listTasks(start) {
17089
- const store = await loadStore(this.workingDir);
17130
+ const { local, global } = await loadAllStores(this.workingDir);
17090
17131
  const cronJobs = listCronJobs();
17091
- if (store.tasks.length === 0) {
17132
+ const totalCount = local.tasks.length + global.tasks.length;
17133
+ if (totalCount === 0) {
17092
17134
  return {
17093
17135
  success: true,
17094
17136
  output: "No scheduled tasks. Use scheduler(action='create', task='...', schedule='daily') to create one.",
17095
17137
  durationMs: performance.now() - start
17096
17138
  };
17097
17139
  }
17098
- const lines = [`Scheduled Tasks (${store.tasks.length}):
17099
- `];
17100
- for (const t of store.tasks) {
17101
- const status = t.enabled ? "enabled" : "PAUSED";
17102
- const cronInstalled = cronJobs.some((j) => j.id === t.id);
17103
- const cronStatus = cronInstalled ? "" : " [cron not installed]";
17104
- lines.push(` [${t.id}] ${status}${cronStatus}`);
17105
- lines.push(` Task: ${t.task.slice(0, 100)}${t.task.length > 100 ? "..." : ""}`);
17106
- lines.push(` Schedule: ${t.nextRunDescription} (${t.schedule})`);
17107
- lines.push(` Runs: ${t.runCount}${t.maxRuns ? `/${t.maxRuns}` : ""}${t.oneShot ? " (one-shot)" : ""}`);
17108
- if (t.lastRun)
17109
- lines.push(` Last run: ${t.lastRun}`);
17110
- lines.push("");
17140
+ const lines = [];
17141
+ if (local.tasks.length > 0) {
17142
+ lines.push(`Local Tasks \u2014 this project (${local.tasks.length}):
17143
+ `);
17144
+ for (const t of local.tasks) {
17145
+ const status = t.enabled ? "enabled" : "PAUSED";
17146
+ const cronInstalled = cronJobs.some((j) => j.id === t.id);
17147
+ const cronStatus = cronInstalled ? "" : " [cron not installed]";
17148
+ lines.push(` [${t.id}] ${status}${cronStatus} [local]`);
17149
+ lines.push(` Task: ${t.task.slice(0, 100)}${t.task.length > 100 ? "..." : ""}`);
17150
+ lines.push(` Schedule: ${t.nextRunDescription} (${t.schedule})`);
17151
+ lines.push(` Runs: ${t.runCount}${t.maxRuns ? `/${t.maxRuns}` : ""}${t.oneShot ? " (one-shot)" : ""}`);
17152
+ if (t.lastRun)
17153
+ lines.push(` Last run: ${t.lastRun}`);
17154
+ lines.push("");
17155
+ }
17156
+ }
17157
+ if (global.tasks.length > 0) {
17158
+ lines.push(`Global Tasks \u2014 shared across projects (${global.tasks.length}):
17159
+ `);
17160
+ for (const t of global.tasks) {
17161
+ const status = t.enabled ? "enabled" : "PAUSED";
17162
+ const cronInstalled = cronJobs.some((j) => j.id === t.id);
17163
+ const cronStatus = cronInstalled ? "" : " [cron not installed]";
17164
+ const isThisProject = t.projectDir === resolve22(this.workingDir);
17165
+ const origin = isThisProject ? " [this project]" : t.projectDir ? ` [from: ${t.projectDir}]` : "";
17166
+ lines.push(` [${t.id}] ${status}${cronStatus} [global]${origin}`);
17167
+ lines.push(` Task: ${t.task.slice(0, 100)}${t.task.length > 100 ? "..." : ""}`);
17168
+ lines.push(` Schedule: ${t.nextRunDescription} (${t.schedule})`);
17169
+ lines.push(` Runs: ${t.runCount}${t.maxRuns ? `/${t.maxRuns}` : ""}${t.oneShot ? " (one-shot)" : ""}`);
17170
+ if (t.lastRun)
17171
+ lines.push(` Last run: ${t.lastRun}`);
17172
+ if (!isThisProject && t.projectDir) {
17173
+ lines.push(` \u26A0 NOT scoped to this project \u2014 override with caution`);
17174
+ }
17175
+ lines.push("");
17176
+ }
17111
17177
  }
17112
17178
  return {
17113
17179
  success: true,
@@ -17668,7 +17734,7 @@ ${sections.join("\n")}`,
17668
17734
  const description = String(args["description"] ?? "");
17669
17735
  const category = args["category"] ?? "followup";
17670
17736
  const priority = args["priority"] ?? "normal";
17671
- const notes = args["notes"] ?? void 0;
17737
+ const notes2 = args["notes"] ?? void 0;
17672
17738
  const relatedFilesStr = args["related_files"] ?? "";
17673
17739
  const relatedFiles = relatedFilesStr ? relatedFilesStr.split(",").map((f) => f.trim()).filter(Boolean) : void 0;
17674
17740
  let expiresAt;
@@ -17701,7 +17767,7 @@ ${sections.join("\n")}`,
17701
17767
  expiresAt,
17702
17768
  relatedFiles,
17703
17769
  status: "active",
17704
- notes
17770
+ notes: notes2
17705
17771
  };
17706
17772
  const store = await loadAttentionStore(this.workingDir);
17707
17773
  store.items.push(item);
@@ -18395,6 +18461,7 @@ var init_factory = __esm({
18395
18461
  import { execSync as execSync21 } from "node:child_process";
18396
18462
  import { readFile as readFile18, writeFile as writeFile18, mkdir as mkdir14 } from "node:fs/promises";
18397
18463
  import { resolve as resolve26, join as join37 } from "node:path";
18464
+ import { homedir as homedir9 } from "node:os";
18398
18465
  import { randomBytes as randomBytes7 } from "node:crypto";
18399
18466
  function isValidCron2(expr) {
18400
18467
  const parts = expr.trim().split(/\s+/);
@@ -18523,6 +18590,31 @@ async function saveStore2(workingDir, store) {
18523
18590
  store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
18524
18591
  await writeFile18(join37(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
18525
18592
  }
18593
+ function globalCronDir() {
18594
+ return join37(homedir9(), ".open-agents", "cron-agents");
18595
+ }
18596
+ async function loadGlobalCronStore() {
18597
+ try {
18598
+ const raw = await readFile18(join37(globalCronDir(), "store.json"), "utf-8");
18599
+ return JSON.parse(raw);
18600
+ } catch {
18601
+ return { jobs: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
18602
+ }
18603
+ }
18604
+ async function saveGlobalCronStore(store) {
18605
+ const dir = globalCronDir();
18606
+ await mkdir14(dir, { recursive: true });
18607
+ await mkdir14(join37(dir, "logs"), { recursive: true });
18608
+ store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
18609
+ await writeFile18(join37(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
18610
+ }
18611
+ async function loadAllCronStores(workingDir) {
18612
+ const [local, global] = await Promise.all([
18613
+ loadStore2(workingDir),
18614
+ loadGlobalCronStore()
18615
+ ]);
18616
+ return { local, global };
18617
+ }
18526
18618
  var LONG_HORIZON_PRESETS, CRON_AGENT_MARKER, CronAgentTool;
18527
18619
  var init_cron_agent = __esm({
18528
18620
  "packages/execution/dist/tools/cron-agent.js"() {
@@ -18591,6 +18683,11 @@ var init_cron_agent = __esm({
18591
18683
  type: "array",
18592
18684
  items: { type: "string" },
18593
18685
  description: "Tags for organizing jobs (for 'create')"
18686
+ },
18687
+ scope: {
18688
+ type: "string",
18689
+ enum: ["local", "global"],
18690
+ description: "Scope: 'local' (project .oa/, default) or 'global' (~/.open-agents/, visible from all projects)"
18594
18691
  }
18595
18692
  },
18596
18693
  required: ["action"]
@@ -18659,6 +18756,7 @@ var init_cron_agent = __esm({
18659
18756
  const verifyCommand = args["verify_command"] ? String(args["verify_command"]) : void 0;
18660
18757
  const maxRuns = typeof args["max_runs"] === "number" ? args["max_runs"] : 0;
18661
18758
  const tags = Array.isArray(args["tags"]) ? args["tags"] : [];
18759
+ const scope = String(args["scope"] ?? "local");
18662
18760
  const job = {
18663
18761
  id,
18664
18762
  task,
@@ -18672,11 +18770,19 @@ var init_cron_agent = __esm({
18672
18770
  runCount: 0,
18673
18771
  maxRuns,
18674
18772
  history: [],
18675
- tags
18773
+ tags,
18774
+ scope,
18775
+ projectDir: resolve26(this.workingDir)
18676
18776
  };
18677
- const store = await loadStore2(this.workingDir);
18678
- store.jobs.push(job);
18679
- await saveStore2(this.workingDir, store);
18777
+ if (scope === "global") {
18778
+ const store = await loadGlobalCronStore();
18779
+ store.jobs.push(job);
18780
+ await saveGlobalCronStore(store);
18781
+ } else {
18782
+ const store = await loadStore2(this.workingDir);
18783
+ store.jobs.push(job);
18784
+ await saveStore2(this.workingDir, store);
18785
+ }
18680
18786
  installCronAgentJob(job, this.workingDir);
18681
18787
  return {
18682
18788
  success: true,
@@ -18700,19 +18806,19 @@ var init_cron_agent = __esm({
18700
18806
  };
18701
18807
  }
18702
18808
  async listJobs(start) {
18703
- const store = await loadStore2(this.workingDir);
18704
- if (store.jobs.length === 0) {
18809
+ const { local, global } = await loadAllCronStores(this.workingDir);
18810
+ const totalCount = local.jobs.length + global.jobs.length;
18811
+ if (totalCount === 0) {
18705
18812
  return {
18706
18813
  success: true,
18707
18814
  output: "No cron agent jobs. Use cron_agent(action='create', ...) to schedule one.",
18708
18815
  durationMs: performance.now() - start
18709
18816
  };
18710
18817
  }
18711
- const lines = [`Cron Agent Jobs (${store.jobs.length}):
18712
- `];
18713
- for (const job of store.jobs) {
18818
+ const lines = [];
18819
+ const formatJob = (job, scopeLabel, isThisProject) => {
18714
18820
  const statusIcon = job.status === "active" ? "\u25CF" : job.status === "completed" ? "\u2714" : job.status === "paused" ? "\u23F8" : "\u2716";
18715
- lines.push(` ${statusIcon} [${job.id}] ${job.status.toUpperCase()}`);
18821
+ lines.push(` ${statusIcon} [${job.id}] ${job.status.toUpperCase()} [${scopeLabel}]`);
18716
18822
  lines.push(` Goal: ${job.goal.slice(0, 80)}${job.goal.length > 80 ? "..." : ""}`);
18717
18823
  lines.push(` Schedule: ${job.scheduleDescription}`);
18718
18824
  lines.push(` Runs: ${job.runCount}${job.maxRuns > 0 ? `/${job.maxRuns}` : ""}`);
@@ -18720,7 +18826,25 @@ var init_cron_agent = __esm({
18720
18826
  lines.push(` Last run: ${job.lastRunAt}`);
18721
18827
  if (job.tags.length > 0)
18722
18828
  lines.push(` Tags: ${job.tags.join(", ")}`);
18829
+ if (!isThisProject && job.projectDir) {
18830
+ lines.push(` Origin: ${job.projectDir}`);
18831
+ lines.push(` \u26A0 NOT scoped to this project \u2014 override with caution`);
18832
+ }
18723
18833
  lines.push("");
18834
+ };
18835
+ if (local.jobs.length > 0) {
18836
+ lines.push(`Local Cron Jobs \u2014 this project (${local.jobs.length}):
18837
+ `);
18838
+ for (const job of local.jobs)
18839
+ formatJob(job, "local", true);
18840
+ }
18841
+ if (global.jobs.length > 0) {
18842
+ lines.push(`Global Cron Jobs \u2014 shared (${global.jobs.length}):
18843
+ `);
18844
+ for (const job of global.jobs) {
18845
+ const isThisProject = job.projectDir === resolve26(this.workingDir);
18846
+ formatJob(job, isThisProject ? "global, this project" : "global", isThisProject);
18847
+ }
18724
18848
  }
18725
18849
  return {
18726
18850
  success: true,
@@ -18856,6 +18980,575 @@ ${truncated}`, durationMs: performance.now() - start };
18856
18980
  }
18857
18981
  });
18858
18982
 
18983
+ // packages/execution/dist/tools/file-explore.js
18984
+ import { readFile as readFile19 } from "node:fs/promises";
18985
+ import { resolve as resolve27 } from "node:path";
18986
+ import { execFile as execFile4 } from "node:child_process";
18987
+ import { promisify as promisify3 } from "node:util";
18988
+ function getPatterns(filePath) {
18989
+ if (/\.(ts|tsx|js|jsx|mjs|cjs)$/.test(filePath))
18990
+ return SIG_PATTERNS.ts;
18991
+ if (/\.py$/.test(filePath))
18992
+ return SIG_PATTERNS.py;
18993
+ if (/\.rs$/.test(filePath))
18994
+ return SIG_PATTERNS.rs;
18995
+ if (/\.go$/.test(filePath))
18996
+ return SIG_PATTERNS.go;
18997
+ return SIG_PATTERNS.default;
18998
+ }
18999
+ function clearExploreNotes() {
19000
+ sessionNotes.length = 0;
19001
+ }
19002
+ function getExploreNotes() {
19003
+ return sessionNotes;
19004
+ }
19005
+ var execFileAsync3, sessionNotes, SIG_PATTERNS, FileExploreTool;
19006
+ var init_file_explore = __esm({
19007
+ "packages/execution/dist/tools/file-explore.js"() {
19008
+ "use strict";
19009
+ execFileAsync3 = promisify3(execFile4);
19010
+ sessionNotes = [];
19011
+ SIG_PATTERNS = {
19012
+ ts: [
19013
+ /^\s*(export\s+)?(async\s+)?function\s+\w+/,
19014
+ /^\s*(export\s+)?(abstract\s+)?class\s+\w+/,
19015
+ /^\s*(export\s+)?(const|let|var)\s+\w+\s*[:=]/,
19016
+ /^\s*(export\s+)?interface\s+\w+/,
19017
+ /^\s*(export\s+)?type\s+\w+\s*=/,
19018
+ /^\s*(export\s+)?enum\s+\w+/,
19019
+ /^\s*(?:public|private|protected|static|async|get|set)\s+\w+\s*[(<]/
19020
+ ],
19021
+ py: [
19022
+ /^\s*def\s+\w+/,
19023
+ /^\s*class\s+\w+/,
19024
+ /^\s*async\s+def\s+\w+/,
19025
+ /^[A-Z_][A-Z_0-9]*\s*=/
19026
+ ],
19027
+ rs: [
19028
+ /^\s*(pub\s+)?(async\s+)?fn\s+\w+/,
19029
+ /^\s*(pub\s+)?struct\s+\w+/,
19030
+ /^\s*(pub\s+)?enum\s+\w+/,
19031
+ /^\s*(pub\s+)?trait\s+\w+/,
19032
+ /^\s*impl\s+/
19033
+ ],
19034
+ go: [
19035
+ /^\s*func\s+/,
19036
+ /^\s*type\s+\w+\s+struct/,
19037
+ /^\s*type\s+\w+\s+interface/
19038
+ ],
19039
+ default: [
19040
+ /^\s*(export\s+)?(function|class|const|let|var|def|fn|pub|type|interface|enum|struct|trait|impl)\s+/
19041
+ ]
19042
+ };
19043
+ FileExploreTool = class {
19044
+ name = "file_explore";
19045
+ description = "Explore large files without reading them entirely into context. Strategies: 'overview' (structural skeleton \u2014 imports, exports, signatures), 'search' (grep pattern with \xB1N context lines), 'chunk' (read specific line range, auto-saved to working notes), 'outline' (function/class/method signatures only), 'notes' (show accumulated findings from this session). Use this INSTEAD of file_read for files > 200 lines. Pattern: overview \u2192 search for target \u2192 chunk to read details \u2192 note findings.";
19046
+ parameters = {
19047
+ type: "object",
19048
+ properties: {
19049
+ path: {
19050
+ type: "string",
19051
+ description: "File path to explore"
19052
+ },
19053
+ strategy: {
19054
+ type: "string",
19055
+ enum: ["overview", "search", "chunk", "outline", "notes"],
19056
+ description: "Exploration strategy"
19057
+ },
19058
+ query: {
19059
+ type: "string",
19060
+ description: "Search pattern (for 'search' strategy) or note text (for 'chunk' with note)"
19061
+ },
19062
+ offset: {
19063
+ type: "number",
19064
+ description: "Starting line number, 1-based (for 'chunk' strategy)"
19065
+ },
19066
+ limit: {
19067
+ type: "number",
19068
+ description: "Number of lines to read (for 'chunk', default 50)"
19069
+ },
19070
+ context_lines: {
19071
+ type: "number",
19072
+ description: "Lines of context around each match (for 'search', default 5)"
19073
+ },
19074
+ note: {
19075
+ type: "string",
19076
+ description: "Working note to save about this chunk (for 'chunk' strategy)"
19077
+ }
19078
+ },
19079
+ required: ["strategy"]
19080
+ };
19081
+ workingDir;
19082
+ constructor(workingDir) {
19083
+ this.workingDir = workingDir;
19084
+ }
19085
+ async execute(args) {
19086
+ const strategy = String(args["strategy"] ?? "overview");
19087
+ const filePath = String(args["path"] ?? "");
19088
+ const start = performance.now();
19089
+ switch (strategy) {
19090
+ case "overview":
19091
+ return this.overview(filePath, start);
19092
+ case "search":
19093
+ return this.search(filePath, String(args["query"] ?? ""), args, start);
19094
+ case "chunk":
19095
+ return this.chunk(filePath, args, start);
19096
+ case "outline":
19097
+ return this.outline(filePath, start);
19098
+ case "notes":
19099
+ return this.showNotes(filePath, start);
19100
+ default:
19101
+ return {
19102
+ success: false,
19103
+ output: "",
19104
+ error: `Unknown strategy '${strategy}'. Use: overview, search, chunk, outline, notes`,
19105
+ durationMs: performance.now() - start
19106
+ };
19107
+ }
19108
+ }
19109
+ /**
19110
+ * overview: Read structural skeleton — first 30 lines (imports/config),
19111
+ * all signature lines, last 20 lines (exports/module boundary).
19112
+ */
19113
+ async overview(filePath, start) {
19114
+ if (!filePath)
19115
+ return { success: false, output: "", error: "path required for overview", durationMs: performance.now() - start };
19116
+ try {
19117
+ const fullPath = resolve27(this.workingDir, filePath);
19118
+ const content = await readFile19(fullPath, "utf-8");
19119
+ const lines = content.split("\n");
19120
+ const total = lines.length;
19121
+ const HEAD = Math.min(30, total);
19122
+ const TAIL = Math.min(20, Math.max(0, total - HEAD));
19123
+ const parts = [];
19124
+ parts.push(`# ${filePath} (${total} lines)
19125
+ `);
19126
+ parts.push("## Head (lines 1-" + HEAD + ")");
19127
+ for (let i = 0; i < HEAD; i++) {
19128
+ parts.push(`${String(i + 1).padStart(6)} | ${lines[i]}`);
19129
+ }
19130
+ if (total > HEAD + TAIL) {
19131
+ const patterns = getPatterns(filePath);
19132
+ const sigs = [];
19133
+ for (let i = HEAD; i < total - TAIL; i++) {
19134
+ const line = lines[i];
19135
+ if (patterns.some((p) => p.test(line))) {
19136
+ sigs.push(`${String(i + 1).padStart(6)} | ${line}`);
19137
+ }
19138
+ }
19139
+ if (sigs.length > 0) {
19140
+ parts.push(`
19141
+ ## Signatures (lines ${HEAD + 1}-${total - TAIL}) \u2014 ${sigs.length} found`);
19142
+ parts.push(...sigs);
19143
+ } else {
19144
+ parts.push(`
19145
+ ## Middle (lines ${HEAD + 1}-${total - TAIL}) \u2014 ${total - HEAD - TAIL} lines, no signatures detected`);
19146
+ }
19147
+ }
19148
+ if (TAIL > 0) {
19149
+ const tailStart = total - TAIL;
19150
+ parts.push(`
19151
+ ## Tail (lines ${tailStart + 1}-${total})`);
19152
+ for (let i = tailStart; i < total; i++) {
19153
+ parts.push(`${String(i + 1).padStart(6)} | ${lines[i]}`);
19154
+ }
19155
+ }
19156
+ parts.push(`
19157
+ [Use file_explore(strategy='search', query='...') to find specific sections]`);
19158
+ parts.push(`[Use file_explore(strategy='chunk', offset=N, limit=50) to read a section]`);
19159
+ return {
19160
+ success: true,
19161
+ output: parts.join("\n"),
19162
+ durationMs: performance.now() - start
19163
+ };
19164
+ } catch (error) {
19165
+ return {
19166
+ success: false,
19167
+ output: "",
19168
+ error: error instanceof Error ? error.message : String(error),
19169
+ durationMs: performance.now() - start
19170
+ };
19171
+ }
19172
+ }
19173
+ /**
19174
+ * search: Grep for pattern with context lines around each match.
19175
+ */
19176
+ async search(filePath, query, args, start) {
19177
+ if (!query)
19178
+ return { success: false, output: "", error: "query required for search strategy", durationMs: performance.now() - start };
19179
+ const contextLines = Number(args["context_lines"] ?? 5);
19180
+ const searchPath = filePath ? resolve27(this.workingDir, filePath) : this.workingDir;
19181
+ try {
19182
+ const rgArgs = [
19183
+ "--line-number",
19184
+ "--no-heading",
19185
+ "--color=never",
19186
+ "-C",
19187
+ String(contextLines)
19188
+ ];
19189
+ if (filePath) {
19190
+ rgArgs.push(query, searchPath);
19191
+ } else {
19192
+ rgArgs.push(query, this.workingDir);
19193
+ }
19194
+ const { stdout } = await execFileAsync3("rg", rgArgs, {
19195
+ cwd: this.workingDir,
19196
+ maxBuffer: 1024 * 1024
19197
+ });
19198
+ const lines = stdout.split("\n").filter((l) => l.length > 0);
19199
+ const matchCount = lines.filter((l) => /^\d+:/.test(l) || /:\d+:/.test(l)).length;
19200
+ const MAX = 80;
19201
+ const truncated = lines.length > MAX;
19202
+ const output = lines.slice(0, MAX).join("\n");
19203
+ const result = [
19204
+ `Found ${matchCount} matches for "${query}"${filePath ? ` in ${filePath}` : ""}:`,
19205
+ "",
19206
+ truncated ? output + `
19207
+
19208
+ [Truncated \u2014 ${lines.length - MAX} more lines]` : output,
19209
+ "",
19210
+ `[Use file_explore(strategy='chunk', path='...', offset=N) to read around a specific match]`
19211
+ ].join("\n");
19212
+ return {
19213
+ success: true,
19214
+ output: result,
19215
+ durationMs: performance.now() - start
19216
+ };
19217
+ } catch (error) {
19218
+ const err = error;
19219
+ if (err.code === 1) {
19220
+ return {
19221
+ success: true,
19222
+ output: `No matches for "${query}"${filePath ? ` in ${filePath}` : ""}.`,
19223
+ durationMs: performance.now() - start
19224
+ };
19225
+ }
19226
+ try {
19227
+ const grepArgs = ["-rn", "--color=never", `-C${contextLines}`];
19228
+ if (filePath) {
19229
+ grepArgs.push(query, searchPath);
19230
+ } else {
19231
+ grepArgs.push(query, this.workingDir);
19232
+ }
19233
+ const { stdout } = await execFileAsync3("grep", grepArgs, {
19234
+ cwd: this.workingDir,
19235
+ maxBuffer: 1024 * 1024
19236
+ });
19237
+ return {
19238
+ success: true,
19239
+ output: stdout.split("\n").slice(0, 80).join("\n"),
19240
+ durationMs: performance.now() - start
19241
+ };
19242
+ } catch {
19243
+ return {
19244
+ success: true,
19245
+ output: `No matches for "${query}".`,
19246
+ durationMs: performance.now() - start
19247
+ };
19248
+ }
19249
+ }
19250
+ }
19251
+ /**
19252
+ * chunk: Read a specific line range and optionally save a working note.
19253
+ */
19254
+ async chunk(filePath, args, start) {
19255
+ if (!filePath)
19256
+ return { success: false, output: "", error: "path required for chunk strategy", durationMs: performance.now() - start };
19257
+ const offset = Number(args["offset"] ?? 1);
19258
+ const limit = Number(args["limit"] ?? 50);
19259
+ const note = args["note"];
19260
+ try {
19261
+ const fullPath = resolve27(this.workingDir, filePath);
19262
+ const content = await readFile19(fullPath, "utf-8");
19263
+ const allLines = content.split("\n");
19264
+ const total = allLines.length;
19265
+ const startIdx = Math.max(0, offset - 1);
19266
+ const endIdx = Math.min(total, startIdx + limit);
19267
+ const chunk = allLines.slice(startIdx, endIdx);
19268
+ const numbered = chunk.map((line, i) => `${String(startIdx + i + 1).padStart(6)} | ${line}`).join("\n");
19269
+ if (note) {
19270
+ sessionNotes.push({
19271
+ file: filePath,
19272
+ lineRange: [startIdx + 1, endIdx],
19273
+ finding: note,
19274
+ timestamp: Date.now()
19275
+ });
19276
+ }
19277
+ const nav = [];
19278
+ if (startIdx > 0) {
19279
+ nav.push(`[Previous: file_explore(strategy='chunk', path='${filePath}', offset=${Math.max(1, startIdx + 1 - limit)}, limit=${limit})]`);
19280
+ }
19281
+ if (endIdx < total) {
19282
+ nav.push(`[Next: file_explore(strategy='chunk', path='${filePath}', offset=${endIdx + 1}, limit=${limit})]`);
19283
+ }
19284
+ nav.push(`[${total} total lines \u2014 showing ${startIdx + 1}-${endIdx}]`);
19285
+ if (sessionNotes.length > 0) {
19286
+ nav.push(`[${sessionNotes.length} working notes \u2014 file_explore(strategy='notes') to review]`);
19287
+ }
19288
+ return {
19289
+ success: true,
19290
+ output: numbered + "\n\n" + nav.join("\n"),
19291
+ durationMs: performance.now() - start
19292
+ };
19293
+ } catch (error) {
19294
+ return {
19295
+ success: false,
19296
+ output: "",
19297
+ error: error instanceof Error ? error.message : String(error),
19298
+ durationMs: performance.now() - start
19299
+ };
19300
+ }
19301
+ }
19302
+ /**
19303
+ * outline: Extract only function/class/method/export signatures.
19304
+ */
19305
+ async outline(filePath, start) {
19306
+ if (!filePath)
19307
+ return { success: false, output: "", error: "path required for outline", durationMs: performance.now() - start };
19308
+ try {
19309
+ const fullPath = resolve27(this.workingDir, filePath);
19310
+ const content = await readFile19(fullPath, "utf-8");
19311
+ const lines = content.split("\n");
19312
+ const patterns = getPatterns(filePath);
19313
+ const sigs = [];
19314
+ for (let i = 0; i < lines.length; i++) {
19315
+ const line = lines[i];
19316
+ if (patterns.some((p) => p.test(line))) {
19317
+ sigs.push(`${String(i + 1).padStart(6)} | ${line.trimEnd()}`);
19318
+ }
19319
+ }
19320
+ if (sigs.length === 0) {
19321
+ return {
19322
+ success: true,
19323
+ output: `${filePath}: ${lines.length} lines, no recognizable signatures found.
19324
+ [Use file_explore(strategy='overview') for a broader view]`,
19325
+ durationMs: performance.now() - start
19326
+ };
19327
+ }
19328
+ return {
19329
+ success: true,
19330
+ output: `# ${filePath} \u2014 ${sigs.length} signatures (${lines.length} total lines)
19331
+
19332
+ ` + sigs.join("\n") + `
19333
+
19334
+ [Use file_explore(strategy='chunk', offset=N) to read around a specific signature]`,
19335
+ durationMs: performance.now() - start
19336
+ };
19337
+ } catch (error) {
19338
+ return {
19339
+ success: false,
19340
+ output: "",
19341
+ error: error instanceof Error ? error.message : String(error),
19342
+ durationMs: performance.now() - start
19343
+ };
19344
+ }
19345
+ }
19346
+ /**
19347
+ * notes: Show accumulated working notes from this exploration session.
19348
+ */
19349
+ showNotes(filePath, start) {
19350
+ const notes2 = filePath ? sessionNotes.filter((n) => n.file === filePath) : sessionNotes;
19351
+ if (notes2.length === 0) {
19352
+ return {
19353
+ success: true,
19354
+ output: "No working notes yet. Use file_explore(strategy='chunk', note='your finding') to save notes as you explore.",
19355
+ durationMs: performance.now() - start
19356
+ };
19357
+ }
19358
+ const parts = [`# Working Notes (${notes2.length})
19359
+ `];
19360
+ for (const n of notes2) {
19361
+ parts.push(`- **${n.file}** lines ${n.lineRange[0]}-${n.lineRange[1]}: ${n.finding}`);
19362
+ }
19363
+ return {
19364
+ success: true,
19365
+ output: parts.join("\n"),
19366
+ durationMs: performance.now() - start
19367
+ };
19368
+ }
19369
+ };
19370
+ }
19371
+ });
19372
+
19373
+ // packages/execution/dist/tools/working-notes.js
19374
+ function getWorkingNotes() {
19375
+ return notes;
19376
+ }
19377
+ function getWorkingNotesSummary() {
19378
+ if (notes.length === 0)
19379
+ return "";
19380
+ const parts = [`Working notes (${notes.length}):`];
19381
+ for (const n of notes) {
19382
+ const loc = n.file ? ` [${n.file}${n.line ? `:${n.line}` : ""}]` : "";
19383
+ parts.push(`- [${n.category}] ${n.content.slice(0, 150)}${loc}`);
19384
+ }
19385
+ return parts.join("\n");
19386
+ }
19387
+ function clearWorkingNotes() {
19388
+ notes.length = 0;
19389
+ noteCounter = 0;
19390
+ }
19391
+ var noteCounter, notes, WorkingNotesTool;
19392
+ var init_working_notes = __esm({
19393
+ "packages/execution/dist/tools/working-notes.js"() {
19394
+ "use strict";
19395
+ noteCounter = 0;
19396
+ notes = [];
19397
+ WorkingNotesTool = class {
19398
+ name = "working_notes";
19399
+ description = "In-task scratchpad for tracking discoveries, decisions, and TODOs. Notes persist across tool calls and survive context compaction. Actions: 'add' a note, 'list' all notes, 'search' notes by keyword, 'clear' all notes, 'summary' get a compact summary. Use this to maintain signal when exploring large codebases \u2014 note findings as you go so you don't lose them to context limits.";
19400
+ parameters = {
19401
+ type: "object",
19402
+ properties: {
19403
+ action: {
19404
+ type: "string",
19405
+ enum: ["add", "list", "search", "clear", "summary"],
19406
+ description: "Action to perform (default: 'list')"
19407
+ },
19408
+ content: {
19409
+ type: "string",
19410
+ description: "Note content (for 'add') or search query (for 'search')"
19411
+ },
19412
+ category: {
19413
+ type: "string",
19414
+ enum: ["finding", "todo", "question", "decision", "blocker"],
19415
+ description: "Note category (for 'add', default: 'finding')"
19416
+ },
19417
+ file: {
19418
+ type: "string",
19419
+ description: "Related file path (for 'add')"
19420
+ },
19421
+ line: {
19422
+ type: "number",
19423
+ description: "Related line number (for 'add')"
19424
+ }
19425
+ },
19426
+ required: []
19427
+ };
19428
+ async execute(args) {
19429
+ const action = String(args["action"] ?? "list");
19430
+ const start = performance.now();
19431
+ switch (action) {
19432
+ case "add": {
19433
+ const content = String(args["content"] ?? "");
19434
+ if (!content)
19435
+ return { success: false, output: "", error: "content required", durationMs: performance.now() - start };
19436
+ const note = {
19437
+ id: ++noteCounter,
19438
+ category: String(args["category"] ?? "finding"),
19439
+ content,
19440
+ file: args["file"],
19441
+ line: args["line"],
19442
+ timestamp: Date.now()
19443
+ };
19444
+ notes.push(note);
19445
+ return {
19446
+ success: true,
19447
+ output: `Note #${note.id} added [${note.category}]${note.file ? ` (${note.file}${note.line ? `:${note.line}` : ""})` : ""}: ${content.slice(0, 100)}`,
19448
+ durationMs: performance.now() - start
19449
+ };
19450
+ }
19451
+ case "list": {
19452
+ if (notes.length === 0) {
19453
+ return {
19454
+ success: true,
19455
+ output: "No working notes. Use working_notes(action='add', content='...') to start tracking findings.",
19456
+ durationMs: performance.now() - start
19457
+ };
19458
+ }
19459
+ const lines = [`Working Notes (${notes.length}):
19460
+ `];
19461
+ for (const n of notes) {
19462
+ const loc = n.file ? ` @ ${n.file}${n.line ? `:${n.line}` : ""}` : "";
19463
+ lines.push(` #${n.id} [${n.category}]${loc}: ${n.content}`);
19464
+ }
19465
+ return {
19466
+ success: true,
19467
+ output: lines.join("\n"),
19468
+ durationMs: performance.now() - start
19469
+ };
19470
+ }
19471
+ case "search": {
19472
+ const query = String(args["content"] ?? "").toLowerCase();
19473
+ if (!query)
19474
+ return { success: false, output: "", error: "content (search query) required", durationMs: performance.now() - start };
19475
+ const matches = notes.filter((n) => n.content.toLowerCase().includes(query) || n.file && n.file.toLowerCase().includes(query) || n.category.toLowerCase().includes(query));
19476
+ if (matches.length === 0) {
19477
+ return {
19478
+ success: true,
19479
+ output: `No notes matching "${query}".`,
19480
+ durationMs: performance.now() - start
19481
+ };
19482
+ }
19483
+ const lines = [`Notes matching "${query}" (${matches.length}):
19484
+ `];
19485
+ for (const n of matches) {
19486
+ const loc = n.file ? ` @ ${n.file}${n.line ? `:${n.line}` : ""}` : "";
19487
+ lines.push(` #${n.id} [${n.category}]${loc}: ${n.content}`);
19488
+ }
19489
+ return {
19490
+ success: true,
19491
+ output: lines.join("\n"),
19492
+ durationMs: performance.now() - start
19493
+ };
19494
+ }
19495
+ case "clear": {
19496
+ const count = notes.length;
19497
+ notes.length = 0;
19498
+ noteCounter = 0;
19499
+ return {
19500
+ success: true,
19501
+ output: `Cleared ${count} working notes.`,
19502
+ durationMs: performance.now() - start
19503
+ };
19504
+ }
19505
+ case "summary": {
19506
+ if (notes.length === 0) {
19507
+ return {
19508
+ success: true,
19509
+ output: "No working notes to summarize.",
19510
+ durationMs: performance.now() - start
19511
+ };
19512
+ }
19513
+ const groups = /* @__PURE__ */ new Map();
19514
+ for (const n of notes) {
19515
+ const list = groups.get(n.category) ?? [];
19516
+ list.push(n);
19517
+ groups.set(n.category, list);
19518
+ }
19519
+ const parts = [`Working Notes Summary (${notes.length} total):
19520
+ `];
19521
+ for (const [cat, items] of groups) {
19522
+ parts.push(` ${cat.toUpperCase()} (${items.length}):`);
19523
+ for (const n of items) {
19524
+ const loc = n.file ? ` [${n.file}${n.line ? `:${n.line}` : ""}]` : "";
19525
+ parts.push(` - ${n.content.slice(0, 120)}${loc}`);
19526
+ }
19527
+ }
19528
+ const files = new Set(notes.filter((n) => n.file).map((n) => n.file));
19529
+ if (files.size > 0) {
19530
+ parts.push(`
19531
+ Files referenced: ${[...files].join(", ")}`);
19532
+ }
19533
+ return {
19534
+ success: true,
19535
+ output: parts.join("\n"),
19536
+ durationMs: performance.now() - start
19537
+ };
19538
+ }
19539
+ default:
19540
+ return {
19541
+ success: false,
19542
+ output: "",
19543
+ error: `Unknown action '${action}'. Use: add, list, search, clear, summary`,
19544
+ durationMs: performance.now() - start
19545
+ };
19546
+ }
19547
+ }
19548
+ };
19549
+ }
19550
+ });
19551
+
18859
19552
  // packages/execution/dist/tools/fortemi-bridge.js
18860
19553
  import { existsSync as existsSync24, readFileSync as readFileSync17 } from "node:fs";
18861
19554
  import { join as join38 } from "node:path";
@@ -19012,7 +19705,7 @@ import { spawn as spawn13 } from "node:child_process";
19012
19705
  async function runShell(options) {
19013
19706
  const { command, args = [], cwd: cwd4, env, timeoutMs = DEFAULT_TIMEOUT_MS } = options;
19014
19707
  const mergedEnv = env ? { ...process.env, ...env } : process.env;
19015
- return new Promise((resolve32) => {
19708
+ return new Promise((resolve33) => {
19016
19709
  const start = Date.now();
19017
19710
  let timedOut = false;
19018
19711
  const child = spawn13(command, args, {
@@ -19036,7 +19729,7 @@ async function runShell(options) {
19036
19729
  clearTimeout(timer);
19037
19730
  const durationMs = Date.now() - start;
19038
19731
  const exitCode = timedOut ? -1 : code ?? -1;
19039
- resolve32({
19732
+ resolve33({
19040
19733
  stdout,
19041
19734
  stderr,
19042
19735
  exitCode,
@@ -19048,7 +19741,7 @@ async function runShell(options) {
19048
19741
  child.on("error", (err) => {
19049
19742
  clearTimeout(timer);
19050
19743
  const durationMs = Date.now() - start;
19051
- resolve32({
19744
+ resolve33({
19052
19745
  stdout,
19053
19746
  stderr: stderr + err.message,
19054
19747
  exitCode: -1,
@@ -19163,7 +19856,7 @@ async function applyUnifiedDiff(patch) {
19163
19856
  }
19164
19857
  function runWithStdin(options) {
19165
19858
  const { command, args, cwd: cwd4, stdin } = options;
19166
- return new Promise((resolve32) => {
19859
+ return new Promise((resolve33) => {
19167
19860
  const child = spawn14(command, args, {
19168
19861
  cwd: cwd4,
19169
19862
  stdio: ["pipe", "pipe", "pipe"]
@@ -19180,10 +19873,10 @@ function runWithStdin(options) {
19180
19873
  child.stdin.end();
19181
19874
  child.on("close", (code) => {
19182
19875
  const exitCode = code ?? -1;
19183
- resolve32({ success: exitCode === 0, exitCode, stdout, stderr });
19876
+ resolve33({ success: exitCode === 0, exitCode, stdout, stderr });
19184
19877
  });
19185
19878
  child.on("error", (err) => {
19186
- resolve32({ success: false, exitCode: -1, stdout, stderr: err.message });
19879
+ resolve33({ success: false, exitCode: -1, stdout, stderr: err.message });
19187
19880
  });
19188
19881
  });
19189
19882
  }
@@ -19631,6 +20324,7 @@ __export(dist_exports, {
19631
20324
  ExploreToolsTool: () => ExploreToolsTool,
19632
20325
  FactoryTool: () => FactoryTool,
19633
20326
  FileEditTool: () => FileEditTool,
20327
+ FileExploreTool: () => FileExploreTool,
19634
20328
  FilePatchTool: () => FilePatchTool,
19635
20329
  FileReadTool: () => FileReadTool,
19636
20330
  FileWriteTool: () => FileWriteTool,
@@ -19673,10 +20367,13 @@ __export(dist_exports, {
19673
20367
  WebCrawlTool: () => WebCrawlTool,
19674
20368
  WebFetchTool: () => WebFetchTool,
19675
20369
  WebSearchTool: () => WebSearchTool,
20370
+ WorkingNotesTool: () => WorkingNotesTool,
19676
20371
  applyPatch: () => applyPatch,
19677
20372
  buildCustomTools: () => buildCustomTools,
19678
20373
  buildSkillsSummary: () => buildSkillsSummary,
19679
20374
  checkDesktopDeps: () => checkDesktopDeps,
20375
+ clearExploreNotes: () => clearExploreNotes,
20376
+ clearWorkingNotes: () => clearWorkingNotes,
19680
20377
  createFortemiBridgeTools: () => createFortemiBridgeTools,
19681
20378
  createWorktree: () => createWorktree,
19682
20379
  detectSearchProvider: () => detectSearchProvider,
@@ -19686,6 +20383,9 @@ __export(dist_exports, {
19686
20383
  ensureDepsForGroup: () => ensureDepsForGroup,
19687
20384
  getActiveAttentionItems: () => getActiveAttentionItems,
19688
20385
  getDueReminders: () => getDueReminders,
20386
+ getExploreNotes: () => getExploreNotes,
20387
+ getWorkingNotes: () => getWorkingNotes,
20388
+ getWorkingNotesSummary: () => getWorkingNotesSummary,
19689
20389
  isFortemiAvailable: () => isFortemiAvailable,
19690
20390
  isImagePath: () => isImagePath,
19691
20391
  listCustomToolFiles: () => listCustomToolFiles,
@@ -19762,6 +20462,8 @@ var init_dist2 = __esm({
19762
20462
  init_opencode();
19763
20463
  init_factory();
19764
20464
  init_cron_agent();
20465
+ init_file_explore();
20466
+ init_working_notes();
19765
20467
  init_nexus();
19766
20468
  init_fortemi_bridge();
19767
20469
  init_system_deps();
@@ -20745,13 +21447,13 @@ var init_plannerRunner = __esm({
20745
21447
  });
20746
21448
 
20747
21449
  // packages/retrieval/dist/grep-search.js
20748
- import { execFile as execFile4 } from "node:child_process";
20749
- import { promisify as promisify3 } from "node:util";
20750
- var execFileAsync3, GrepSearch;
21450
+ import { execFile as execFile5 } from "node:child_process";
21451
+ import { promisify as promisify4 } from "node:util";
21452
+ var execFileAsync4, GrepSearch;
20751
21453
  var init_grep_search2 = __esm({
20752
21454
  "packages/retrieval/dist/grep-search.js"() {
20753
21455
  "use strict";
20754
- execFileAsync3 = promisify3(execFile4);
21456
+ execFileAsync4 = promisify4(execFile5);
20755
21457
  GrepSearch = class {
20756
21458
  rootDir;
20757
21459
  constructor(rootDir) {
@@ -20773,7 +21475,7 @@ var init_grep_search2 = __esm({
20773
21475
  }
20774
21476
  args.push(pattern, this.rootDir);
20775
21477
  try {
20776
- const { stdout } = await execFileAsync3("rg", args, {
21478
+ const { stdout } = await execFileAsync4("rg", args, {
20777
21479
  maxBuffer: 10 * 1024 * 1024
20778
21480
  });
20779
21481
  return this.parseRipgrepOutput(stdout);
@@ -20834,8 +21536,8 @@ var init_code_retriever = __esm({
20834
21536
  });
20835
21537
  }
20836
21538
  async getFileContent(filePath, startLine, endLine) {
20837
- const { readFile: readFile23 } = await import("node:fs/promises");
20838
- const content = await readFile23(filePath, "utf-8");
21539
+ const { readFile: readFile24 } = await import("node:fs/promises");
21540
+ const content = await readFile24(filePath, "utf-8");
20839
21541
  if (startLine === void 0)
20840
21542
  return content;
20841
21543
  const lines = content.split("\n");
@@ -20848,9 +21550,9 @@ var init_code_retriever = __esm({
20848
21550
  });
20849
21551
 
20850
21552
  // packages/retrieval/dist/lexicalSearch.js
20851
- import { execFile as execFile5 } from "node:child_process";
20852
- import { promisify as promisify4 } from "node:util";
20853
- import { readFile as readFile19, readdir as readdir5, stat as stat3 } from "node:fs/promises";
21553
+ import { execFile as execFile6 } from "node:child_process";
21554
+ import { promisify as promisify5 } from "node:util";
21555
+ import { readFile as readFile20, readdir as readdir5, stat as stat3 } from "node:fs/promises";
20854
21556
  import { join as join40, extname as extname7 } from "node:path";
20855
21557
  async function searchByPath(pathPattern, options) {
20856
21558
  const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
@@ -20893,7 +21595,7 @@ async function runSearch(pattern, kind, options) {
20893
21595
  }
20894
21596
  async function isRipgrepAvailable() {
20895
21597
  try {
20896
- await execFileAsync4("rg", ["--version"], { timeout: 2e3 });
21598
+ await execFileAsync5("rg", ["--version"], { timeout: 2e3 });
20897
21599
  return true;
20898
21600
  } catch {
20899
21601
  return false;
@@ -20913,7 +21615,7 @@ async function searchWithRipgrep(pattern, kind, options) {
20913
21615
  args.push(pattern, options.rootDir);
20914
21616
  let stdout;
20915
21617
  try {
20916
- const result = await execFileAsync4("rg", args, {
21618
+ const result = await execFileAsync5("rg", args, {
20917
21619
  maxBuffer: 20 * 1024 * 1024,
20918
21620
  timeout: 1e4
20919
21621
  });
@@ -20956,7 +21658,7 @@ async function searchWithNodeFallback(pattern, kind, options) {
20956
21658
  if (results.length >= maxMatches)
20957
21659
  break;
20958
21660
  try {
20959
- const content = await readFile19(filePath, "utf-8");
21661
+ const content = await readFile20(filePath, "utf-8");
20960
21662
  const contentLines = content.split("\n");
20961
21663
  for (let i = 0; i < contentLines.length; i++) {
20962
21664
  if (results.length >= maxMatches)
@@ -21023,11 +21725,11 @@ function matchesGlob(filePath, glob2) {
21023
21725
  return false;
21024
21726
  }
21025
21727
  }
21026
- var execFileAsync4, DEFAULT_INCLUDE_GLOBS, DEFAULT_EXCLUDE_GLOBS, DEFAULT_MAX_MATCHES, ALWAYS_SKIP, ALL_CODE_EXTS;
21728
+ var execFileAsync5, DEFAULT_INCLUDE_GLOBS, DEFAULT_EXCLUDE_GLOBS, DEFAULT_MAX_MATCHES, ALWAYS_SKIP, ALL_CODE_EXTS;
21027
21729
  var init_lexicalSearch = __esm({
21028
21730
  "packages/retrieval/dist/lexicalSearch.js"() {
21029
21731
  "use strict";
21030
- execFileAsync4 = promisify4(execFile5);
21732
+ execFileAsync5 = promisify5(execFile6);
21031
21733
  DEFAULT_INCLUDE_GLOBS = ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.py"];
21032
21734
  DEFAULT_EXCLUDE_GLOBS = ["node_modules", "dist", ".git", "build", "coverage"];
21033
21735
  DEFAULT_MAX_MATCHES = 50;
@@ -21299,7 +22001,7 @@ var init_graphExpand = __esm({
21299
22001
  });
21300
22002
 
21301
22003
  // packages/retrieval/dist/snippetPacker.js
21302
- import { readFile as readFile20 } from "node:fs/promises";
22004
+ import { readFile as readFile21 } from "node:fs/promises";
21303
22005
  import { join as join41 } from "node:path";
21304
22006
  async function packSnippets(requests, opts = {}) {
21305
22007
  const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
@@ -21329,7 +22031,7 @@ async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINE
21329
22031
  const absPath = req.filePath.startsWith("/") ? req.filePath : join41(repoRoot, req.filePath);
21330
22032
  let content;
21331
22033
  try {
21332
- content = await readFile20(absPath, "utf-8");
22034
+ content = await readFile21(absPath, "utf-8");
21333
22035
  } catch {
21334
22036
  return null;
21335
22037
  }
@@ -21864,9 +22566,9 @@ var init_verifierRunner = __esm({
21864
22566
  async executeTests(patch, repoRoot) {
21865
22567
  if (patch.testsToRun.length === 0)
21866
22568
  return "(no tests specified)";
21867
- const { execFile: execFile6 } = await import("node:child_process");
21868
- const { promisify: promisify6 } = await import("node:util");
21869
- const execFileAsync5 = promisify6(execFile6);
22569
+ const { execFile: execFile7 } = await import("node:child_process");
22570
+ const { promisify: promisify7 } = await import("node:util");
22571
+ const execFileAsync6 = promisify7(execFile7);
21870
22572
  const outputs = [];
21871
22573
  const workDir = this.options.workingDir || repoRoot;
21872
22574
  for (const cmd of patch.testsToRun.slice(0, 3)) {
@@ -21875,7 +22577,7 @@ var init_verifierRunner = __esm({
21875
22577
  const [bin, ...args] = parts;
21876
22578
  if (!bin)
21877
22579
  continue;
21878
- const { stdout, stderr } = await execFileAsync5(bin, args, {
22580
+ const { stdout, stderr } = await execFileAsync6(bin, args, {
21879
22581
  cwd: workDir,
21880
22582
  timeout: 6e4,
21881
22583
  maxBuffer: 1024 * 1024
@@ -22555,6 +23257,7 @@ var init_agenticRunner = __esm({
22555
23257
  init_dist();
22556
23258
  init_personality();
22557
23259
  init_promptLoader();
23260
+ init_dist2();
22558
23261
  SYSTEM_PROMPT = loadPrompt("agentic/system-large.md");
22559
23262
  SYSTEM_PROMPT_MEDIUM = loadPrompt("agentic/system-medium.md");
22560
23263
  SYSTEM_PROMPT_SMALL = loadPrompt("agentic/system-small.md");
@@ -22875,8 +23578,8 @@ ${this.options.dynamicContext}`,
22875
23578
  async waitIfPaused() {
22876
23579
  if (!this._paused)
22877
23580
  return true;
22878
- await new Promise((resolve32) => {
22879
- this._pauseResolve = resolve32;
23581
+ await new Promise((resolve33) => {
23582
+ this._pauseResolve = resolve33;
22880
23583
  });
22881
23584
  return !this.aborted;
22882
23585
  }
@@ -23909,14 +24612,14 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
23909
24612
  waitForSudoPassword(timeoutMs = 12e4) {
23910
24613
  if (this._sudoPassword)
23911
24614
  return Promise.resolve(this._sudoPassword);
23912
- return new Promise((resolve32) => {
24615
+ return new Promise((resolve33) => {
23913
24616
  const timer = setTimeout(() => {
23914
24617
  this._sudoResolve = null;
23915
- resolve32(null);
24618
+ resolve33(null);
23916
24619
  }, timeoutMs);
23917
24620
  this._sudoResolve = (pw) => {
23918
24621
  clearTimeout(timer);
23919
- resolve32(pw);
24622
+ resolve33(pw);
23920
24623
  };
23921
24624
  });
23922
24625
  }
@@ -24224,6 +24927,18 @@ ${tail}`;
24224
24927
  const fileRegistryStr = this.formatFileRegistry();
24225
24928
  if (fileRegistryStr)
24226
24929
  enrichments.push(fileRegistryStr);
24930
+ try {
24931
+ const notesSummary = getWorkingNotesSummary();
24932
+ if (notesSummary)
24933
+ enrichments.push(notesSummary);
24934
+ const exploreNotes = getExploreNotes();
24935
+ if (exploreNotes.length > 0) {
24936
+ const exploreStr = `File exploration notes (${exploreNotes.length}):
24937
+ ` + exploreNotes.map((n) => `- ${n.file} lines ${n.lineRange[0]}-${n.lineRange[1]}: ${n.finding}`).join("\n");
24938
+ enrichments.push(exploreStr);
24939
+ }
24940
+ } catch {
24941
+ }
24227
24942
  if (tier === "large") {
24228
24943
  const memexIndexStr = this.formatMemexIndex();
24229
24944
  if (memexIndexStr)
@@ -25616,12 +26331,12 @@ var init_nexusBackend = __esm({
25616
26331
  const deadline = Date.now() + (request.timeoutMs ?? 12e4);
25617
26332
  try {
25618
26333
  while (!done && Date.now() < deadline) {
25619
- await new Promise((resolve32) => {
26334
+ await new Promise((resolve33) => {
25620
26335
  let resolved = false;
25621
26336
  const finish = () => {
25622
26337
  if (!resolved) {
25623
26338
  resolved = true;
25624
- resolve32();
26339
+ resolve33();
25625
26340
  }
25626
26341
  };
25627
26342
  let watcher = null;
@@ -26561,7 +27276,7 @@ __export(listen_exports, {
26561
27276
  import { spawn as spawn15, execSync as execSync22 } from "node:child_process";
26562
27277
  import { existsSync as existsSync28, mkdirSync as mkdirSync8, writeFileSync as writeFileSync9, readdirSync as readdirSync6 } from "node:fs";
26563
27278
  import { join as join43, dirname as dirname13 } from "node:path";
26564
- import { homedir as homedir8 } from "node:os";
27279
+ import { homedir as homedir10 } from "node:os";
26565
27280
  import { fileURLToPath as fileURLToPath8 } from "node:url";
26566
27281
  import { EventEmitter } from "node:events";
26567
27282
  import { createInterface as createInterface2 } from "node:readline";
@@ -26673,7 +27388,7 @@ function findLiveWhisperScript() {
26673
27388
  }
26674
27389
  } catch {
26675
27390
  }
26676
- const nvmBase = join43(homedir8(), ".nvm", "versions", "node");
27391
+ const nvmBase = join43(homedir10(), ".nvm", "versions", "node");
26677
27392
  if (existsSync28(nvmBase)) {
26678
27393
  try {
26679
27394
  for (const ver of readdirSync6(nvmBase)) {
@@ -26703,9 +27418,9 @@ function ensureTranscribeCliBackground() {
26703
27418
  }
26704
27419
  try {
26705
27420
  const { exec: exec4 } = await import("node:child_process");
26706
- return new Promise((resolve32) => {
27421
+ return new Promise((resolve33) => {
26707
27422
  exec4("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
26708
- resolve32(!err);
27423
+ resolve33(!err);
26709
27424
  });
26710
27425
  });
26711
27426
  } catch {
@@ -26764,7 +27479,7 @@ var init_listen = __esm({
26764
27479
  return this._ready;
26765
27480
  }
26766
27481
  async start() {
26767
- return new Promise((resolve32, reject) => {
27482
+ return new Promise((resolve33, reject) => {
26768
27483
  const timeout = setTimeout(() => {
26769
27484
  reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
26770
27485
  }, 3e5);
@@ -26792,7 +27507,7 @@ var init_listen = __esm({
26792
27507
  this._ready = true;
26793
27508
  clearTimeout(timeout);
26794
27509
  this.emit("ready");
26795
- resolve32();
27510
+ resolve33();
26796
27511
  break;
26797
27512
  case "transcript":
26798
27513
  this.emit("transcript", {
@@ -26927,7 +27642,7 @@ var init_listen = __esm({
26927
27642
  }
26928
27643
  } catch {
26929
27644
  }
26930
- const nvmBase = join43(homedir8(), ".nvm", "versions", "node");
27645
+ const nvmBase = join43(homedir10(), ".nvm", "versions", "node");
26931
27646
  if (existsSync28(nvmBase)) {
26932
27647
  try {
26933
27648
  const { readdirSync: readdirSync18 } = await import("node:fs");
@@ -26996,11 +27711,11 @@ var init_listen = __esm({
26996
27711
  this.liveTranscriber.on("error", (err) => {
26997
27712
  this.emit("error", err);
26998
27713
  });
26999
- await new Promise((resolve32, reject) => {
27714
+ await new Promise((resolve33, reject) => {
27000
27715
  const timeout = setTimeout(() => reject(new Error("Model load timeout (60s)")), 6e4);
27001
27716
  this.liveTranscriber.on("ready", () => {
27002
27717
  clearTimeout(timeout);
27003
- resolve32();
27718
+ resolve33();
27004
27719
  });
27005
27720
  this.liveTranscriber.on("error", (err) => {
27006
27721
  clearTimeout(timeout);
@@ -27162,11 +27877,11 @@ transcribe-cli error: ${transcribeCliError}` : "";
27162
27877
  sampleWidth: 2,
27163
27878
  chunkDuration: 3
27164
27879
  });
27165
- await new Promise((resolve32, reject) => {
27880
+ await new Promise((resolve33, reject) => {
27166
27881
  const timeout = setTimeout(() => reject(new Error("Model load timeout (60s)")), 6e4);
27167
27882
  transcriber.on("ready", () => {
27168
27883
  clearTimeout(timeout);
27169
- resolve32();
27884
+ resolve33();
27170
27885
  });
27171
27886
  transcriber.on("error", (err) => {
27172
27887
  clearTimeout(timeout);
@@ -32137,8 +32852,8 @@ var init_voice_session = __esm({
32137
32852
  this.server.keepAliveTimeout = 0;
32138
32853
  this.wss = new import_websocket_server.default({ server: this.server, path: "/ws" });
32139
32854
  this.wss.on("connection", (ws, req) => this.handleWSConnection(ws, req));
32140
- await new Promise((resolve32, reject) => {
32141
- this.server.listen(port, "127.0.0.1", () => resolve32());
32855
+ await new Promise((resolve33, reject) => {
32856
+ this.server.listen(port, "127.0.0.1", () => resolve33());
32142
32857
  this.server.on("error", reject);
32143
32858
  });
32144
32859
  try {
@@ -32356,7 +33071,7 @@ var init_voice_session = __esm({
32356
33071
  }
32357
33072
  // ── Cloudflared tunnel ────────────────────────────────────────────────
32358
33073
  startCloudflared(port) {
32359
- return new Promise((resolve32, reject) => {
33074
+ return new Promise((resolve33, reject) => {
32360
33075
  const timeout = setTimeout(() => {
32361
33076
  reject(new Error("Cloudflared tunnel start timeout (30s)"));
32362
33077
  }, 3e4);
@@ -32374,7 +33089,7 @@ var init_voice_session = __esm({
32374
33089
  if (urlMatch && !urlFound) {
32375
33090
  urlFound = true;
32376
33091
  clearTimeout(timeout);
32377
- resolve32(urlMatch[0]);
33092
+ resolve33(urlMatch[0]);
32378
33093
  }
32379
33094
  };
32380
33095
  this.cloudflaredProcess.stdout?.on("data", handleOutput);
@@ -32414,13 +33129,13 @@ var init_voice_session = __esm({
32414
33129
  }
32415
33130
  // ── Helpers ───────────────────────────────────────────────────────────
32416
33131
  findFreePort() {
32417
- return new Promise((resolve32, reject) => {
33132
+ return new Promise((resolve33, reject) => {
32418
33133
  const srv = createServer2();
32419
33134
  srv.listen(0, "127.0.0.1", () => {
32420
33135
  const addr = srv.address();
32421
33136
  if (addr && typeof addr === "object") {
32422
33137
  const port = addr.port;
32423
- srv.close(() => resolve32(port));
33138
+ srv.close(() => resolve33(port));
32424
33139
  } else {
32425
33140
  srv.close(() => reject(new Error("Could not find free port")));
32426
33141
  }
@@ -32543,8 +33258,8 @@ async function collectSystemMetricsAsync() {
32543
33258
  vramUtilization: 0
32544
33259
  };
32545
33260
  try {
32546
- const smi = await new Promise((resolve32, reject) => {
32547
- exec("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve32(stdout));
33261
+ const smi = await new Promise((resolve33, reject) => {
33262
+ exec("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve33(stdout));
32548
33263
  });
32549
33264
  const line = smi.trim().split("\n")[0];
32550
33265
  if (line) {
@@ -32692,8 +33407,8 @@ var init_expose = __esm({
32692
33407
  throw new Error("Gateway already running");
32693
33408
  const port = await this.findFreePort();
32694
33409
  this.server = this.createProxyServer(port);
32695
- await new Promise((resolve32, reject) => {
32696
- this.server.listen(port, "127.0.0.1", () => resolve32());
33410
+ await new Promise((resolve33, reject) => {
33411
+ this.server.listen(port, "127.0.0.1", () => resolve33());
32697
33412
  this.server.on("error", reject);
32698
33413
  });
32699
33414
  let lastStartErr;
@@ -32755,8 +33470,8 @@ var init_expose = __esm({
32755
33470
  this._cloudflaredPid = state.pid;
32756
33471
  this._proxyPort = state.proxyPort;
32757
33472
  this.server = this.createProxyServer(state.proxyPort);
32758
- await new Promise((resolve32, reject) => {
32759
- this.server.listen(state.proxyPort, "127.0.0.1", () => resolve32());
33473
+ await new Promise((resolve33, reject) => {
33474
+ this.server.listen(state.proxyPort, "127.0.0.1", () => resolve33());
32760
33475
  this.server.on("error", reject);
32761
33476
  });
32762
33477
  this._stats.status = "active";
@@ -32781,8 +33496,8 @@ var init_expose = __esm({
32781
33496
  }
32782
33497
  this._cloudflaredPid = null;
32783
33498
  if (this.server) {
32784
- await new Promise((resolve32) => {
32785
- this.server.close(() => resolve32());
33499
+ await new Promise((resolve33) => {
33500
+ this.server.close(() => resolve33());
32786
33501
  });
32787
33502
  this.server = null;
32788
33503
  }
@@ -33114,7 +33829,7 @@ var init_expose = __esm({
33114
33829
  _proxyPort = 0;
33115
33830
  startCloudflared(port) {
33116
33831
  this._proxyPort = port;
33117
- return new Promise((resolve32, reject) => {
33832
+ return new Promise((resolve33, reject) => {
33118
33833
  const timeout = setTimeout(() => {
33119
33834
  reject(new Error("Cloudflared tunnel start timeout (30s)"));
33120
33835
  }, 3e4);
@@ -33143,7 +33858,7 @@ var init_expose = __esm({
33143
33858
  this.cloudflaredProcess?.unref();
33144
33859
  this.cloudflaredProcess?.stdout?.destroy();
33145
33860
  this.cloudflaredProcess?.stderr?.destroy();
33146
- resolve32(urlMatch[0]);
33861
+ resolve33(urlMatch[0]);
33147
33862
  }
33148
33863
  };
33149
33864
  this.cloudflaredProcess.stdout?.on("data", handleOutput);
@@ -33232,13 +33947,13 @@ ${this.formatConnectionInfo()}`);
33232
33947
  }
33233
33948
  // ── Helpers ─────────────────────────────────────────────────────────────
33234
33949
  findFreePort() {
33235
- return new Promise((resolve32, reject) => {
33950
+ return new Promise((resolve33, reject) => {
33236
33951
  const srv = createServer3();
33237
33952
  srv.listen(0, "127.0.0.1", () => {
33238
33953
  const addr = srv.address();
33239
33954
  if (addr && typeof addr === "object") {
33240
33955
  const port = addr.port;
33241
- srv.close(() => resolve32(port));
33956
+ srv.close(() => resolve33(port));
33242
33957
  } else {
33243
33958
  srv.close(() => reject(new Error("Could not find free port")));
33244
33959
  }
@@ -34185,8 +34900,8 @@ var init_peer_mesh = __esm({
34185
34900
  this.wss.on("connection", (ws, req) => {
34186
34901
  this.handleInboundConnection(ws, req.url ?? "");
34187
34902
  });
34188
- await new Promise((resolve32, reject) => {
34189
- this.server.listen(port, "127.0.0.1", () => resolve32());
34903
+ await new Promise((resolve33, reject) => {
34904
+ this.server.listen(port, "127.0.0.1", () => resolve33());
34190
34905
  this.server.on("error", reject);
34191
34906
  });
34192
34907
  this.pingTimer = setInterval(() => this.pingAll(), PING_INTERVAL_MS);
@@ -34225,7 +34940,7 @@ var init_peer_mesh = __esm({
34225
34940
  this.wss = null;
34226
34941
  }
34227
34942
  if (this.server) {
34228
- await new Promise((resolve32) => this.server.close(() => resolve32()));
34943
+ await new Promise((resolve33) => this.server.close(() => resolve33()));
34229
34944
  this.server = null;
34230
34945
  }
34231
34946
  this.emit("stopped");
@@ -34243,7 +34958,7 @@ var init_peer_mesh = __esm({
34243
34958
  if (!wsUrl.includes("/p2p"))
34244
34959
  wsUrl += "/p2p";
34245
34960
  wsUrl += `?key=${encodeURIComponent(this._authKey)}`;
34246
- return new Promise((resolve32, reject) => {
34961
+ return new Promise((resolve33, reject) => {
34247
34962
  const ws = new import_websocket.default(wsUrl, { handshakeTimeout: 1e4 });
34248
34963
  let resolved = false;
34249
34964
  const timeout = setTimeout(() => {
@@ -34283,7 +34998,7 @@ var init_peer_mesh = __esm({
34283
34998
  this.connections.set(peer.peerId, ws);
34284
34999
  this.setupPeerHandlers(ws, peer.peerId);
34285
35000
  this.emit("peer_connected", peer);
34286
- resolve32(peer);
35001
+ resolve33(peer);
34287
35002
  } else {
34288
35003
  this.handleMessage(msg, ws);
34289
35004
  }
@@ -34338,12 +35053,12 @@ var init_peer_mesh = __esm({
34338
35053
  throw new Error(`Peer ${peerId} not connected`);
34339
35054
  }
34340
35055
  const msgId = randomBytes11(8).toString("hex");
34341
- return new Promise((resolve32, reject) => {
35056
+ return new Promise((resolve33, reject) => {
34342
35057
  const timeout = setTimeout(() => {
34343
35058
  this.pendingRequests.delete(msgId);
34344
35059
  reject(new Error(`Inference timeout (${timeoutMs}ms)`));
34345
35060
  }, timeoutMs);
34346
- this.pendingRequests.set(msgId, { resolve: resolve32, reject, timeout, chunks: [] });
35061
+ this.pendingRequests.set(msgId, { resolve: resolve33, reject, timeout, chunks: [] });
34347
35062
  this.sendMsg(ws, "infer_request", request, msgId);
34348
35063
  });
34349
35064
  }
@@ -34565,13 +35280,13 @@ var init_peer_mesh = __esm({
34565
35280
  ws.send(JSON.stringify(msg));
34566
35281
  }
34567
35282
  findFreePort() {
34568
- return new Promise((resolve32, reject) => {
35283
+ return new Promise((resolve33, reject) => {
34569
35284
  const srv = createServer4();
34570
35285
  srv.listen(0, "127.0.0.1", () => {
34571
35286
  const addr = srv.address();
34572
35287
  if (addr && typeof addr === "object") {
34573
35288
  const port = addr.port;
34574
- srv.close(() => resolve32(port));
35289
+ srv.close(() => resolve33(port));
34575
35290
  } else {
34576
35291
  srv.close(() => reject(new Error("Could not find free port")));
34577
35292
  }
@@ -35817,7 +36532,7 @@ __export(oa_directory_exports, {
35817
36532
  });
35818
36533
  import { existsSync as existsSync32, mkdirSync as mkdirSync11, readFileSync as readFileSync23, writeFileSync as writeFileSync12, readdirSync as readdirSync8, statSync as statSync11, unlinkSync as unlinkSync6 } from "node:fs";
35819
36534
  import { join as join48, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
35820
- import { homedir as homedir9 } from "node:os";
36535
+ import { homedir as homedir11 } from "node:os";
35821
36536
  function initOaDirectory(repoRoot) {
35822
36537
  const oaPath = join48(repoRoot, OA_DIR);
35823
36538
  for (const sub of SUBDIRS) {
@@ -35857,7 +36572,7 @@ function saveProjectSettings(repoRoot, settings) {
35857
36572
  writeFileSync12(join48(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
35858
36573
  }
35859
36574
  function loadGlobalSettings() {
35860
- const settingsPath = join48(homedir9(), ".open-agents", "settings.json");
36575
+ const settingsPath = join48(homedir11(), ".open-agents", "settings.json");
35861
36576
  try {
35862
36577
  if (existsSync32(settingsPath)) {
35863
36578
  return JSON.parse(readFileSync23(settingsPath, "utf-8"));
@@ -35867,7 +36582,7 @@ function loadGlobalSettings() {
35867
36582
  return {};
35868
36583
  }
35869
36584
  function saveGlobalSettings(settings) {
35870
- const dir = join48(homedir9(), ".open-agents");
36585
+ const dir = join48(homedir11(), ".open-agents");
35871
36586
  mkdirSync11(dir, { recursive: true });
35872
36587
  const existing = loadGlobalSettings();
35873
36588
  const merged = { ...existing, ...settings };
@@ -36247,13 +36962,13 @@ function recordUsage(kind, value, opts) {
36247
36962
  }
36248
36963
  saveUsageFile(filePath, data);
36249
36964
  };
36250
- update(join48(homedir9(), ".open-agents", USAGE_HISTORY_FILE));
36965
+ update(join48(homedir11(), ".open-agents", USAGE_HISTORY_FILE));
36251
36966
  if (opts?.repoRoot) {
36252
36967
  update(join48(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
36253
36968
  }
36254
36969
  }
36255
36970
  function loadUsageHistory(kind, repoRoot) {
36256
- const globalPath = join48(homedir9(), ".open-agents", USAGE_HISTORY_FILE);
36971
+ const globalPath = join48(homedir11(), ".open-agents", USAGE_HISTORY_FILE);
36257
36972
  const globalData = loadUsageFile(globalPath);
36258
36973
  const localData = repoRoot ? loadUsageFile(join48(repoRoot, OA_DIR, USAGE_HISTORY_FILE)) : { records: [] };
36259
36974
  const map = /* @__PURE__ */ new Map();
@@ -36286,7 +37001,7 @@ function deleteUsageRecord(kind, value, repoRoot) {
36286
37001
  saveUsageFile(filePath, data);
36287
37002
  }
36288
37003
  };
36289
- remove(join48(homedir9(), ".open-agents", USAGE_HISTORY_FILE));
37004
+ remove(join48(homedir11(), ".open-agents", USAGE_HISTORY_FILE));
36290
37005
  if (repoRoot) {
36291
37006
  remove(join48(repoRoot, OA_DIR, USAGE_HISTORY_FILE));
36292
37007
  }
@@ -36337,10 +37052,10 @@ var init_oa_directory = __esm({
36337
37052
  // packages/cli/dist/tui/setup.js
36338
37053
  import * as readline from "node:readline";
36339
37054
  import { execSync as execSync24, spawn as spawn18, exec as exec2 } from "node:child_process";
36340
- import { promisify as promisify5 } from "node:util";
37055
+ import { promisify as promisify6 } from "node:util";
36341
37056
  import { existsSync as existsSync33, writeFileSync as writeFileSync13, readFileSync as readFileSync24, appendFileSync as appendFileSync2, mkdirSync as mkdirSync12 } from "node:fs";
36342
37057
  import { join as join49 } from "node:path";
36343
- import { homedir as homedir10, platform } from "node:os";
37058
+ import { homedir as homedir12, platform } from "node:os";
36344
37059
  function detectSystemSpecs() {
36345
37060
  let totalRamGB = 0;
36346
37061
  let availableRamGB = 0;
@@ -36477,12 +37192,12 @@ function modelSupportsToolCalling(modelName) {
36477
37192
  return false;
36478
37193
  }
36479
37194
  function ask(rl, question) {
36480
- return new Promise((resolve32) => {
36481
- rl.question(question, (answer) => resolve32(answer.trim()));
37195
+ return new Promise((resolve33) => {
37196
+ rl.question(question, (answer) => resolve33(answer.trim()));
36482
37197
  });
36483
37198
  }
36484
37199
  function askSecret(rl, question) {
36485
- return new Promise((resolve32) => {
37200
+ return new Promise((resolve33) => {
36486
37201
  process.stdout.write(question);
36487
37202
  let secret = "";
36488
37203
  const stdin = process.stdin;
@@ -36500,7 +37215,7 @@ function askSecret(rl, question) {
36500
37215
  stdin.setRawMode(hadRawMode ?? false);
36501
37216
  }
36502
37217
  process.stdout.write("\n");
36503
- resolve32(secret.trim());
37218
+ resolve33(secret.trim());
36504
37219
  return;
36505
37220
  } else if (c3 === "") {
36506
37221
  stdin.removeListener("data", onData);
@@ -36508,7 +37223,7 @@ function askSecret(rl, question) {
36508
37223
  stdin.setRawMode(hadRawMode ?? false);
36509
37224
  }
36510
37225
  process.stdout.write("\n");
36511
- resolve32("");
37226
+ resolve33("");
36512
37227
  return;
36513
37228
  } else if (c3 === "\x7F" || c3 === "\b") {
36514
37229
  if (secret.length > 0) {
@@ -36743,7 +37458,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
36743
37458
  return false;
36744
37459
  }
36745
37460
  for (let i = 0; i < 5; i++) {
36746
- await new Promise((resolve32) => setTimeout(resolve32, 2e3));
37461
+ await new Promise((resolve33) => setTimeout(resolve33, 2e3));
36747
37462
  try {
36748
37463
  const resp = await fetch(`${backendUrl}/api/tags`, {
36749
37464
  signal: AbortSignal.timeout(3e3)
@@ -37204,7 +37919,7 @@ async function doSetup(config, rl) {
37204
37919
  try {
37205
37920
  const child = spawn18("ollama", ["serve"], { stdio: "ignore", detached: true });
37206
37921
  child.unref();
37207
- await new Promise((resolve32) => setTimeout(resolve32, 3e3));
37922
+ await new Promise((resolve33) => setTimeout(resolve33, 3e3));
37208
37923
  try {
37209
37924
  models = await fetchOllamaModels(config.backendUrl);
37210
37925
  process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
@@ -37232,7 +37947,7 @@ async function doSetup(config, rl) {
37232
37947
  try {
37233
37948
  const child = spawn18("ollama", ["serve"], { stdio: "ignore", detached: true });
37234
37949
  child.unref();
37235
- await new Promise((resolve32) => setTimeout(resolve32, 3e3));
37950
+ await new Promise((resolve33) => setTimeout(resolve33, 3e3));
37236
37951
  try {
37237
37952
  models = await fetchOllamaModels(config.backendUrl);
37238
37953
  process.stdout.write(` ${c2.green("\u2714")} Ollama is running.
@@ -37380,7 +38095,7 @@ async function doSetup(config, rl) {
37380
38095
  `PARAMETER num_predict ${numPredict}`,
37381
38096
  `PARAMETER stop "<|endoftext|>"`
37382
38097
  ].join("\n");
37383
- const modelDir2 = join49(homedir10(), ".open-agents", "models");
38098
+ const modelDir2 = join49(homedir12(), ".open-agents", "models");
37384
38099
  mkdirSync12(modelDir2, { recursive: true });
37385
38100
  const modelfilePath = join49(modelDir2, `Modelfile.${customName}`);
37386
38101
  writeFileSync13(modelfilePath, modelfileContent + "\n", "utf8");
@@ -37428,7 +38143,7 @@ async function isModelAvailable(config) {
37428
38143
  }
37429
38144
  function isFirstRun() {
37430
38145
  try {
37431
- return !existsSync33(join49(homedir10(), ".open-agents", "config.json"));
38146
+ return !existsSync33(join49(homedir12(), ".open-agents", "config.json"));
37432
38147
  } catch {
37433
38148
  return true;
37434
38149
  }
@@ -37465,7 +38180,7 @@ function detectPkgManager() {
37465
38180
  return null;
37466
38181
  }
37467
38182
  function getVenvDir() {
37468
- return join49(homedir10(), ".open-agents", "venv");
38183
+ return join49(homedir12(), ".open-agents", "venv");
37469
38184
  }
37470
38185
  function hasVenvModule() {
37471
38186
  try {
@@ -37490,7 +38205,7 @@ function ensureVenv(log) {
37490
38205
  return null;
37491
38206
  }
37492
38207
  try {
37493
- mkdirSync12(join49(homedir10(), ".open-agents"), { recursive: true });
38208
+ mkdirSync12(join49(homedir12(), ".open-agents"), { recursive: true });
37494
38209
  execSync24(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
37495
38210
  execSync24(`"${join49(venvDir, "bin", "pip")}" install --upgrade pip`, {
37496
38211
  stdio: "pipe",
@@ -37756,9 +38471,9 @@ function ensureCloudflaredBackground(onInfo) {
37756
38471
  const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
37757
38472
  const cfArch = archMap[arch] ?? "amd64";
37758
38473
  try {
37759
- 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 });
37760
- if (!process.env.PATH?.includes(`${homedir10()}/.local/bin`)) {
37761
- process.env.PATH = `${homedir10()}/.local/bin:${process.env.PATH}`;
38474
+ execSync24(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir12()}/.local/bin" && mv /tmp/cloudflared "${homedir12()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
38475
+ if (!process.env.PATH?.includes(`${homedir12()}/.local/bin`)) {
38476
+ process.env.PATH = `${homedir12()}/.local/bin:${process.env.PATH}`;
37762
38477
  }
37763
38478
  if (hasCmd("cloudflared")) {
37764
38479
  log("cloudflared installed.");
@@ -37853,7 +38568,7 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
37853
38568
  `PARAMETER num_predict ${numPredict}`,
37854
38569
  `PARAMETER stop "<|endoftext|>"`
37855
38570
  ].join("\n");
37856
- const modelDir2 = join49(homedir10(), ".open-agents", "models");
38571
+ const modelDir2 = join49(homedir12(), ".open-agents", "models");
37857
38572
  mkdirSync12(modelDir2, { recursive: true });
37858
38573
  const modelfilePath = join49(modelDir2, `Modelfile.${customName}`);
37859
38574
  writeFileSync13(modelfilePath, modelfileContent + "\n", "utf8");
@@ -37930,7 +38645,7 @@ async function ensureNeovim() {
37930
38645
  const platform5 = process.platform;
37931
38646
  const arch = process.arch;
37932
38647
  if (platform5 === "linux") {
37933
- const binDir = join49(homedir10(), ".local", "bin");
38648
+ const binDir = join49(homedir12(), ".local", "bin");
37934
38649
  const nvimDest = join49(binDir, "nvim");
37935
38650
  try {
37936
38651
  mkdirSync12(binDir, { recursive: true });
@@ -38002,7 +38717,7 @@ async function ensureNeovim() {
38002
38717
  }
38003
38718
  function ensurePathInShellRc(binDir) {
38004
38719
  const shell = process.env.SHELL ?? "";
38005
- const rcFile = shell.includes("zsh") ? join49(homedir10(), ".zshrc") : join49(homedir10(), ".bashrc");
38720
+ const rcFile = shell.includes("zsh") ? join49(homedir12(), ".zshrc") : join49(homedir12(), ".bashrc");
38006
38721
  try {
38007
38722
  const rcContent = existsSync33(rcFile) ? readFileSync24(rcFile, "utf8") : "";
38008
38723
  if (rcContent.includes(binDir))
@@ -38023,7 +38738,7 @@ var init_setup = __esm({
38023
38738
  init_render();
38024
38739
  init_config();
38025
38740
  init_dist();
38026
- execAsync = promisify5(exec2);
38741
+ execAsync = promisify6(exec2);
38027
38742
  QWEN_VARIANTS = [
38028
38743
  { tag: "qwen3.5:0.8b", sizeGB: 1, label: "0.8B params (1.0 GB)", cloud: false },
38029
38744
  { tag: "qwen3.5:2b", sizeGB: 2.7, label: "2B params (2.7 GB)", cloud: false },
@@ -38221,7 +38936,7 @@ function tuiSelect(opts) {
38221
38936
  const maxVisible = opts.maxVisible ?? Math.max(3, contentArea - selectChrome);
38222
38937
  let scrollOffset = 0;
38223
38938
  let lastRenderedLines = 0;
38224
- return new Promise((resolve32) => {
38939
+ return new Promise((resolve33) => {
38225
38940
  const stdin = process.stdin;
38226
38941
  const hadRawMode = stdin.isRaw;
38227
38942
  const savedRlListeners = [];
@@ -38396,7 +39111,7 @@ function tuiSelect(opts) {
38396
39111
  if (!isSkippable(itemIdx) && matchSet.has(itemIdx)) {
38397
39112
  cursor = itemIdx;
38398
39113
  cleanup();
38399
- resolve32({ confirmed: true, key: items[cursor].key, index: cursor });
39114
+ resolve33({ confirmed: true, key: items[cursor].key, index: cursor });
38400
39115
  return;
38401
39116
  } else if (!isSkippable(itemIdx)) {
38402
39117
  cursor = itemIdx;
@@ -38472,7 +39187,7 @@ function tuiSelect(opts) {
38472
39187
  items.splice(deletedIdx, 1);
38473
39188
  if (items.length === 0) {
38474
39189
  cleanup();
38475
- resolve32({ confirmed: false, key: null, index: -1 });
39190
+ resolve33({ confirmed: false, key: null, index: -1 });
38476
39191
  return;
38477
39192
  }
38478
39193
  updateFilter();
@@ -38561,7 +39276,7 @@ function tuiSelect(opts) {
38561
39276
  } else if (seq === "\r" || seq === "\n") {
38562
39277
  if (!isSkippable(cursor) && matchSet.has(cursor)) {
38563
39278
  cleanup();
38564
- resolve32({ confirmed: true, key: items[cursor].key, index: cursor });
39279
+ resolve33({ confirmed: true, key: items[cursor].key, index: cursor });
38565
39280
  }
38566
39281
  } else if (seq === "\x1B" || seq === "\x1B\x1B") {
38567
39282
  if (filter) {
@@ -38574,14 +39289,14 @@ function tuiSelect(opts) {
38574
39289
  render();
38575
39290
  } else if (hasBreadcrumbs) {
38576
39291
  cleanup();
38577
- resolve32({ confirmed: false, key: "__back__", index: cursor });
39292
+ resolve33({ confirmed: false, key: "__back__", index: cursor });
38578
39293
  } else {
38579
39294
  cleanup();
38580
- resolve32({ confirmed: false, key: null, index: cursor });
39295
+ resolve33({ confirmed: false, key: null, index: cursor });
38581
39296
  }
38582
39297
  } else if (seq === "") {
38583
39298
  cleanup();
38584
- resolve32({ confirmed: false, key: null, index: cursor });
39299
+ resolve33({ confirmed: false, key: null, index: cursor });
38585
39300
  } else if (seq === "\x7F" || seq === "\b") {
38586
39301
  if (filter.length > 0) {
38587
39302
  filter = filter.slice(0, -1);
@@ -38595,7 +39310,7 @@ function tuiSelect(opts) {
38595
39310
  render();
38596
39311
  } else if (hasBreadcrumbs) {
38597
39312
  cleanup();
38598
- resolve32({ confirmed: false, key: "__back__", index: cursor });
39313
+ resolve33({ confirmed: false, key: "__back__", index: cursor });
38599
39314
  }
38600
39315
  } else if (seq.length === 1 && seq.charCodeAt(0) >= 32 && seq.charCodeAt(0) < 127) {
38601
39316
  if (opts.onCustomKey && !isSkippable(cursor) && matchSet.has(cursor)) {
@@ -38603,7 +39318,7 @@ function tuiSelect(opts) {
38603
39318
  done: () => render(),
38604
39319
  resolve: (result) => {
38605
39320
  cleanup();
38606
- resolve32(result);
39321
+ resolve33(result);
38607
39322
  },
38608
39323
  getInput: (prompt, prefill) => getInputFromUser(prompt, prefill),
38609
39324
  render: () => render(),
@@ -38720,7 +39435,7 @@ var init_tui_select = __esm({
38720
39435
 
38721
39436
  // packages/cli/dist/tui/drop-panel.js
38722
39437
  import { existsSync as existsSync34 } from "node:fs";
38723
- import { extname as extname9, resolve as resolve27 } from "node:path";
39438
+ import { extname as extname9, resolve as resolve28 } from "node:path";
38724
39439
  function ansi4(code, text) {
38725
39440
  return isTTY4 ? `\x1B[${code}m${text}\x1B[0m` : text;
38726
39441
  }
@@ -38833,7 +39548,7 @@ function showDropPanel(opts) {
38833
39548
  if (filePath.startsWith("file://")) {
38834
39549
  filePath = decodeURIComponent(filePath.slice(7));
38835
39550
  }
38836
- filePath = resolve27(filePath);
39551
+ filePath = resolve28(filePath);
38837
39552
  if (!existsSync34(filePath)) {
38838
39553
  errorMsg = `File not found: ${filePath}`;
38839
39554
  render();
@@ -39145,12 +39860,12 @@ function stopNeovimMode() {
39145
39860
  } catch {
39146
39861
  }
39147
39862
  const s = _state;
39148
- return new Promise((resolve32) => {
39863
+ return new Promise((resolve33) => {
39149
39864
  setTimeout(() => {
39150
39865
  if (s && !s.cleanedUp) {
39151
39866
  doCleanup(s);
39152
39867
  }
39153
- resolve32();
39868
+ resolve33();
39154
39869
  }, 300);
39155
39870
  });
39156
39871
  }
@@ -39386,7 +40101,7 @@ __export(voice_exports, {
39386
40101
  });
39387
40102
  import { existsSync as existsSync36, mkdirSync as mkdirSync13, writeFileSync as writeFileSync14, readFileSync as readFileSync25, unlinkSync as unlinkSync8, readdirSync as readdirSync9, renameSync, statSync as statSync12 } from "node:fs";
39388
40103
  import { join as join51, dirname as dirname17 } from "node:path";
39389
- import { homedir as homedir11, tmpdir as tmpdir9, platform as platform2 } from "node:os";
40104
+ import { homedir as homedir13, tmpdir as tmpdir9, platform as platform2 } from "node:os";
39390
40105
  import { execSync as execSync26, spawn as nodeSpawn } from "node:child_process";
39391
40106
  import { createRequire } from "node:module";
39392
40107
  function sanitizeForTTS(text) {
@@ -39410,7 +40125,7 @@ function listVoiceModels() {
39410
40125
  }));
39411
40126
  }
39412
40127
  function voiceDir() {
39413
- return join51(homedir11(), ".open-agents", "voice");
40128
+ return join51(homedir13(), ".open-agents", "voice");
39414
40129
  }
39415
40130
  function modelsDir() {
39416
40131
  return join51(voiceDir(), "models");
@@ -40406,7 +41121,7 @@ var init_voice = __esm({
40406
41121
  }
40407
41122
  p = p.replace(/\\ /g, " ");
40408
41123
  if (p.startsWith("~/") || p === "~") {
40409
- p = join51(homedir11(), p.slice(1));
41124
+ p = join51(homedir13(), p.slice(1));
40410
41125
  }
40411
41126
  if (!existsSync36(p)) {
40412
41127
  return `File not found: ${p}
@@ -40821,7 +41536,7 @@ var init_voice = __esm({
40821
41536
  this.speaking = false;
40822
41537
  }
40823
41538
  sleep(ms) {
40824
- return new Promise((resolve32) => setTimeout(resolve32, ms));
41539
+ return new Promise((resolve33) => setTimeout(resolve33, ms));
40825
41540
  }
40826
41541
  // -------------------------------------------------------------------------
40827
41542
  // Synthesis pipeline
@@ -41087,7 +41802,7 @@ var init_voice = __esm({
41087
41802
  const cmd = this.getPlayCommand(path);
41088
41803
  if (!cmd)
41089
41804
  return;
41090
- return new Promise((resolve32) => {
41805
+ return new Promise((resolve33) => {
41091
41806
  const child = nodeSpawn(cmd[0], cmd.slice(1), {
41092
41807
  stdio: "ignore",
41093
41808
  detached: false
@@ -41096,12 +41811,12 @@ var init_voice = __esm({
41096
41811
  child.on("close", () => {
41097
41812
  if (this.currentPlayback === child)
41098
41813
  this.currentPlayback = null;
41099
- resolve32();
41814
+ resolve33();
41100
41815
  });
41101
41816
  child.on("error", () => {
41102
41817
  if (this.currentPlayback === child)
41103
41818
  this.currentPlayback = null;
41104
- resolve32();
41819
+ resolve33();
41105
41820
  });
41106
41821
  setTimeout(() => {
41107
41822
  if (this.currentPlayback === child) {
@@ -41111,7 +41826,7 @@ var init_voice = __esm({
41111
41826
  }
41112
41827
  this.currentPlayback = null;
41113
41828
  }
41114
- resolve32();
41829
+ resolve33();
41115
41830
  }, 15e3);
41116
41831
  });
41117
41832
  }
@@ -41186,7 +41901,7 @@ var init_voice = __esm({
41186
41901
  /** Non-blocking shell execution — async alternative to execSync.
41187
41902
  * Returns stdout string on exit 0, rejects otherwise. */
41188
41903
  asyncShell(command, timeoutMs = 3e4) {
41189
- return new Promise((resolve32, reject) => {
41904
+ return new Promise((resolve33, reject) => {
41190
41905
  const proc = nodeSpawn("sh", ["-c", command], {
41191
41906
  stdio: ["ignore", "pipe", "pipe"],
41192
41907
  cwd: tmpdir9()
@@ -41207,7 +41922,7 @@ var init_voice = __esm({
41207
41922
  proc.on("close", (code) => {
41208
41923
  clearTimeout(timer);
41209
41924
  if (code === 0)
41210
- resolve32(stdout.trim());
41925
+ resolve33(stdout.trim());
41211
41926
  else
41212
41927
  reject(new Error(stderr.slice(0, 300) || `Exit code ${code}`));
41213
41928
  });
@@ -41692,7 +42407,7 @@ if __name__ == '__main__':
41692
42407
  const venvPy = luxttsVenvPy();
41693
42408
  if (!existsSync36(venvPy))
41694
42409
  return false;
41695
- return new Promise((resolve32) => {
42410
+ return new Promise((resolve33) => {
41696
42411
  const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
41697
42412
  const daemon = nodeSpawn(venvPy, [luxttsInferScript()], {
41698
42413
  stdio: ["pipe", "pipe", "pipe"],
@@ -41711,7 +42426,7 @@ if __name__ == '__main__':
41711
42426
  try {
41712
42427
  const msg = JSON.parse(line);
41713
42428
  if (msg.type === "ready") {
41714
- resolve32(true);
42429
+ resolve33(true);
41715
42430
  } else if (msg.type === "result" || msg.type === "error") {
41716
42431
  const pending = this._luxttsPending.get(msg.id);
41717
42432
  if (pending) {
@@ -41735,25 +42450,25 @@ if __name__ == '__main__':
41735
42450
  });
41736
42451
  daemon.on("error", () => {
41737
42452
  this._luxttsDaemon = null;
41738
- resolve32(false);
42453
+ resolve33(false);
41739
42454
  });
41740
42455
  setTimeout(() => {
41741
42456
  if (this._luxttsDaemon === daemon && !this._luxttsPending.has("__ready__")) {
41742
- resolve32(false);
42457
+ resolve33(false);
41743
42458
  }
41744
42459
  }, 6e4);
41745
42460
  });
41746
42461
  }
41747
42462
  /** Send a request to the LuxTTS daemon and await the response */
41748
42463
  luxttsRequest(req) {
41749
- return new Promise((resolve32, reject) => {
42464
+ return new Promise((resolve33, reject) => {
41750
42465
  if (!this._luxttsDaemon || this._luxttsDaemon.killed) {
41751
42466
  reject(new Error("LuxTTS daemon not running"));
41752
42467
  return;
41753
42468
  }
41754
42469
  const id = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
41755
42470
  req.id = id;
41756
- this._luxttsPending.set(id, { resolve: resolve32, reject });
42471
+ this._luxttsPending.set(id, { resolve: resolve33, reject });
41757
42472
  this._luxttsDaemon.stdin.write(JSON.stringify(req) + "\n");
41758
42473
  setTimeout(() => {
41759
42474
  if (this._luxttsPending.has(id)) {
@@ -44777,9 +45492,9 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
44777
45492
  }
44778
45493
  const { basename: basename16, join: pathJoin } = await import("node:path");
44779
45494
  const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync22, existsSync: exists } = await import("node:fs");
44780
- const { homedir: homedir16 } = await import("node:os");
45495
+ const { homedir: homedir18 } = await import("node:os");
44781
45496
  const modelName = basename16(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
44782
- const destDir = pathJoin(homedir16(), ".open-agents", "voice", "models", modelName);
45497
+ const destDir = pathJoin(homedir18(), ".open-agents", "voice", "models", modelName);
44783
45498
  if (!exists(destDir))
44784
45499
  mkdirSync22(destDir, { recursive: true });
44785
45500
  copyFileSync2(onnxDrop.path, pathJoin(destDir, "model.onnx"));
@@ -45680,11 +46395,11 @@ async function handleUpdate(subcommand, ctx) {
45680
46395
  const targetVersion = info?.latestVersion ?? currentVersion;
45681
46396
  const installOverlay = startInstallOverlay(targetVersion);
45682
46397
  let installError = "";
45683
- const runInstall2 = (cmd) => new Promise((resolve32) => {
46398
+ const runInstall2 = (cmd) => new Promise((resolve33) => {
45684
46399
  const child = exec4(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
45685
46400
  if (err)
45686
46401
  installError = (stderr || err.message || "").trim();
45687
- resolve32(!err);
46402
+ resolve33(!err);
45688
46403
  });
45689
46404
  child.stdout?.on("data", (chunk) => {
45690
46405
  const text = String(chunk);
@@ -45778,8 +46493,8 @@ async function handleUpdate(subcommand, ctx) {
45778
46493
  }
45779
46494
  if (doRebuild) {
45780
46495
  installOverlay.setStatus("Rebuilding native modules...");
45781
- await new Promise((resolve32) => {
45782
- const child = exec4(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve32(true));
46496
+ await new Promise((resolve33) => {
46497
+ const child = exec4(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve33(true));
45783
46498
  child.stdout?.resume();
45784
46499
  child.stderr?.resume();
45785
46500
  });
@@ -45810,8 +46525,8 @@ async function handleUpdate(subcommand, ctx) {
45810
46525
  const venvPip = pathJoin(venvDir, "bin", "pip");
45811
46526
  if (fsExists(venvPip)) {
45812
46527
  installOverlay.setStatus("Upgrading Python packages...");
45813
- await new Promise((resolve32) => {
45814
- const child = exec4(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve32(!err));
46528
+ await new Promise((resolve33) => {
46529
+ const child = exec4(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve33(!err));
45815
46530
  child.stdout?.resume();
45816
46531
  child.stderr?.resume();
45817
46532
  });
@@ -46207,16 +46922,16 @@ async function showExposeDashboard(gateway, rl, ctx) {
46207
46922
  renderDashboard();
46208
46923
  }, 1e3);
46209
46924
  let stopGateway = false;
46210
- await new Promise((resolve32) => {
46925
+ await new Promise((resolve33) => {
46211
46926
  const onData = (data) => {
46212
46927
  const key = data.toString();
46213
46928
  if (key === "q" || key === "Q" || key === "\x1B" || key === "") {
46214
- resolve32();
46929
+ resolve33();
46215
46930
  return;
46216
46931
  }
46217
46932
  if (key === "s" || key === "S") {
46218
46933
  stopGateway = true;
46219
- resolve32();
46934
+ resolve33();
46220
46935
  return;
46221
46936
  }
46222
46937
  if (key === "c" || key === "C") {
@@ -46267,8 +46982,8 @@ async function showExposeDashboard(gateway, rl, ctx) {
46267
46982
  process.stdout.write("\x1B[?1002h\x1B[?1006h");
46268
46983
  }
46269
46984
  };
46270
- const origResolve = resolve32;
46271
- resolve32 = (() => {
46985
+ const origResolve = resolve33;
46986
+ resolve33 = (() => {
46272
46987
  cleanup();
46273
46988
  origResolve();
46274
46989
  });
@@ -46326,7 +47041,7 @@ var init_commands = __esm({
46326
47041
  import { existsSync as existsSync38, readFileSync as readFileSync27, readdirSync as readdirSync11 } from "node:fs";
46327
47042
  import { join as join53, basename as basename10 } from "node:path";
46328
47043
  import { execSync as execSync27 } from "node:child_process";
46329
- import { homedir as homedir13, platform as platform3, release } from "node:os";
47044
+ import { homedir as homedir15, platform as platform3, release } from "node:os";
46330
47045
  function getModelTier(modelName) {
46331
47046
  const m = modelName.toLowerCase();
46332
47047
  const sizeMatch = m.match(/\b(\d+)b\b/);
@@ -46413,7 +47128,7 @@ function loadMemoryContext(repoRoot) {
46413
47128
  if (legacyEntries)
46414
47129
  sections.push(legacyEntries);
46415
47130
  }
46416
- const globalMemDir = join53(homedir13(), ".open-agents", "memory");
47131
+ const globalMemDir = join53(homedir15(), ".open-agents", "memory");
46417
47132
  const globalEntries = loadMemoryDir(globalMemDir, "global");
46418
47133
  if (globalEntries)
46419
47134
  sections.push(globalEntries);
@@ -52133,7 +52848,7 @@ var init_tool_policy = __esm({
52133
52848
 
52134
52849
  // packages/cli/dist/tui/telegram-bridge.js
52135
52850
  import { mkdirSync as mkdirSync19, existsSync as existsSync44, unlinkSync as unlinkSync10, readdirSync as readdirSync16, statSync as statSync14 } from "node:fs";
52136
- import { join as join60, resolve as resolve28 } from "node:path";
52851
+ import { join as join60, resolve as resolve29 } from "node:path";
52137
52852
  import { writeFile as writeFileAsync } from "node:fs/promises";
52138
52853
  function convertMarkdownToTelegramHTML(md) {
52139
52854
  let html = md;
@@ -52376,7 +53091,7 @@ with summary "no_reply" to silently skip without responding.
52376
53091
  this.agentConfig = agentConfig;
52377
53092
  this.repoRoot = repoRoot;
52378
53093
  this.toolPolicyConfig = toolPolicyConfig;
52379
- this.mediaCacheDir = resolve28(repoRoot || ".", ".oa", "telegram-media-cache");
53094
+ this.mediaCacheDir = resolve29(repoRoot || ".", ".oa", "telegram-media-cache");
52380
53095
  }
52381
53096
  /** Set admin user ID filter */
52382
53097
  setAdmin(userId) {
@@ -53612,7 +54327,7 @@ var init_braille_spinner = __esm({
53612
54327
  // packages/cli/dist/tui/system-metrics.js
53613
54328
  import { loadavg as loadavg3, cpus as cpus3, totalmem as totalmem4, freemem as freemem3, platform as platform4 } from "node:os";
53614
54329
  import { exec as exec3 } from "node:child_process";
53615
- import { readFile as readFile21 } from "node:fs/promises";
54330
+ import { readFile as readFile22 } from "node:fs/promises";
53616
54331
  function formatRate(bytesPerSec) {
53617
54332
  if (bytesPerSec < 1024)
53618
54333
  return `${Math.round(bytesPerSec)}B`;
@@ -53624,7 +54339,7 @@ function formatRate(bytesPerSec) {
53624
54339
  }
53625
54340
  async function readProcNetDev() {
53626
54341
  try {
53627
- const data = await readFile21("/proc/net/dev", "utf8");
54342
+ const data = await readFile22("/proc/net/dev", "utf8");
53628
54343
  let rxTotal = 0;
53629
54344
  let txTotal = 0;
53630
54345
  for (const line of data.split("\n")) {
@@ -53662,8 +54377,8 @@ async function collectNetworkMetrics() {
53662
54377
  }
53663
54378
  if (plat === "darwin") {
53664
54379
  try {
53665
- const output = await new Promise((resolve32, reject) => {
53666
- exec3("netstat -ib 2>/dev/null | head -30", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve32(stdout));
54380
+ const output = await new Promise((resolve33, reject) => {
54381
+ exec3("netstat -ib 2>/dev/null | head -30", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve33(stdout));
53667
54382
  });
53668
54383
  let rxBytes = 0, txBytes = 0;
53669
54384
  for (const line of output.split("\n")) {
@@ -53697,8 +54412,8 @@ async function collectGpuMetrics() {
53697
54412
  if (_nvidiaSmiAvailable === false)
53698
54413
  return noGpu;
53699
54414
  try {
53700
- const smi = await new Promise((resolve32, reject) => {
53701
- exec3("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve32(stdout));
54415
+ const smi = await new Promise((resolve33, reject) => {
54416
+ exec3("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve33(stdout));
53702
54417
  });
53703
54418
  _nvidiaSmiAvailable = true;
53704
54419
  const line = smi.trim().split("\n")[0];
@@ -56347,13 +57062,13 @@ var init_mouse_filter = __esm({
56347
57062
  import * as readline2 from "node:readline";
56348
57063
  import { Writable } from "node:stream";
56349
57064
  import { cwd } from "node:process";
56350
- import { resolve as resolve29, join as join61, dirname as dirname19, extname as extname10 } from "node:path";
57065
+ import { resolve as resolve30, join as join61, dirname as dirname19, extname as extname10 } from "node:path";
56351
57066
  import { createRequire as createRequire2 } from "node:module";
56352
57067
  import { fileURLToPath as fileURLToPath12 } from "node:url";
56353
57068
  import { readFileSync as readFileSync34, writeFileSync as writeFileSync19, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync17, mkdirSync as mkdirSync20 } from "node:fs";
56354
57069
  import { existsSync as existsSync45 } from "node:fs";
56355
57070
  import { execSync as execSync30 } from "node:child_process";
56356
- import { homedir as homedir14 } from "node:os";
57071
+ import { homedir as homedir16 } from "node:os";
56357
57072
  function formatTimeAgo(date) {
56358
57073
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
56359
57074
  if (seconds < 60)
@@ -56502,6 +57217,9 @@ function buildTools(repoRoot, config, contextWindowSize) {
56502
57217
  new OpenCodeTool(repoRoot),
56503
57218
  new FactoryTool(repoRoot),
56504
57219
  new CronAgentTool(repoRoot),
57220
+ // Chunked file exploration + working notes
57221
+ new FileExploreTool(repoRoot),
57222
+ new WorkingNotesTool(),
56505
57223
  // Nexus P2P networking + x402 micropayments
56506
57224
  new NexusTool(repoRoot)
56507
57225
  ];
@@ -57651,7 +58369,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
57651
58369
  } };
57652
58370
  }
57653
58371
  async function startInteractive(config, repoPath) {
57654
- const repoRoot = resolve29(repoPath ?? cwd());
58372
+ const repoRoot = resolve30(repoPath ?? cwd());
57655
58373
  const resumeFlag = process.env.__OA_RESUMED ?? "";
57656
58374
  const isResumed = resumeFlag !== "";
57657
58375
  const hasTaskToResume = resumeFlag === "1";
@@ -57823,14 +58541,14 @@ async function startInteractive(config, repoPath) {
57823
58541
  renderInfo(msg);
57824
58542
  statusBar.endContentWrite();
57825
58543
  }
57826
- }, () => new Promise((resolve32) => {
58544
+ }, () => new Promise((resolve33) => {
57827
58545
  depSudoPromptPending = true;
57828
58546
  depSudoResolver = (pw) => {
57829
58547
  depSudoPromptPending = false;
57830
58548
  depSudoResolver = null;
57831
58549
  if (pw)
57832
58550
  sessionSudoPassword = pw;
57833
- resolve32(pw);
58551
+ resolve33(pw);
57834
58552
  };
57835
58553
  const pwPrompt1 = ` ${c2.bold(c2.yellow("\u{1F511} Password needed for dependency install:"))}
57836
58554
  `;
@@ -58118,7 +58836,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
58118
58836
  const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
58119
58837
  return [hits, line];
58120
58838
  }
58121
- const HISTORY_DIR = join61(homedir14(), ".open-agents");
58839
+ const HISTORY_DIR = join61(homedir16(), ".open-agents");
58122
58840
  const HISTORY_FILE = join61(HISTORY_DIR, "repl-history");
58123
58841
  const MAX_HISTORY_LINES = 500;
58124
58842
  let savedHistory = [];
@@ -59634,7 +60352,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
59634
60352
  } catch {
59635
60353
  }
59636
60354
  try {
59637
- const voiceDir2 = join61(homedir14(), ".open-agents", "voice");
60355
+ const voiceDir2 = join61(homedir16(), ".open-agents", "voice");
59638
60356
  const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
59639
60357
  for (const pf of voicePidFiles) {
59640
60358
  const pidPath = join61(voiceDir2, pf);
@@ -60037,8 +60755,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
60037
60755
  }
60038
60756
  }
60039
60757
  const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
60040
- const isImage = isImagePath(cleanPath) && existsSync45(resolve29(repoRoot, cleanPath));
60041
- const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync45(resolve29(repoRoot, cleanPath));
60758
+ const isImage = isImagePath(cleanPath) && existsSync45(resolve30(repoRoot, cleanPath));
60759
+ const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync45(resolve30(repoRoot, cleanPath));
60042
60760
  if (activeTask) {
60043
60761
  if (activeTask.runner.isPaused) {
60044
60762
  activeTask.runner.resume();
@@ -60046,7 +60764,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
60046
60764
  }
60047
60765
  if (isImage) {
60048
60766
  try {
60049
- const imgPath = resolve29(repoRoot, cleanPath);
60767
+ const imgPath = resolve30(repoRoot, cleanPath);
60050
60768
  const imgBuffer = readFileSync34(imgPath);
60051
60769
  const base64 = imgBuffer.toString("base64");
60052
60770
  const ext = extname10(cleanPath).toLowerCase();
@@ -60060,7 +60778,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
60060
60778
  } else if (isMedia) {
60061
60779
  writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
60062
60780
  const engine = getListenEngine();
60063
- const result = await engine.transcribeFile(resolve29(repoRoot, cleanPath), repoRoot);
60781
+ const result = await engine.transcribeFile(resolve30(repoRoot, cleanPath), repoRoot);
60064
60782
  if (result) {
60065
60783
  const transcript = `[Transcription of ${cleanPath}]
60066
60784
  ${result.text}`;
@@ -60204,7 +60922,7 @@ ${result.text}`;
60204
60922
  const ext = cleanPath.toLowerCase().split(".").pop() || "";
60205
60923
  if (cloneExts.includes("." + ext)) {
60206
60924
  writeContent(() => renderInfo(`Setting voice clone reference: ${cleanPath}`));
60207
- const msg = await voiceEngine.setCloneVoice(resolve29(repoRoot, cleanPath));
60925
+ const msg = await voiceEngine.setCloneVoice(resolve30(repoRoot, cleanPath));
60208
60926
  writeContent(() => renderInfo(msg));
60209
60927
  showPrompt();
60210
60928
  return;
@@ -60213,7 +60931,7 @@ ${result.text}`;
60213
60931
  if (isMedia && fullInput === input) {
60214
60932
  writeContent(() => renderInfo(`Transcribing: ${cleanPath}...`));
60215
60933
  const engine = getListenEngine();
60216
- const result = await engine.transcribeFile(resolve29(repoRoot, cleanPath), repoRoot);
60934
+ const result = await engine.transcribeFile(resolve30(repoRoot, cleanPath), repoRoot);
60217
60935
  if (result) {
60218
60936
  fullInput = `The user has provided an audio/video file: ${cleanPath}.
60219
60937
 
@@ -60499,7 +61217,7 @@ ${c2.dim("(Use /quit to exit)")}
60499
61217
  };
60500
61218
  }
60501
61219
  async function runWithTUI(task, config, repoPath) {
60502
- const repoRoot = resolve29(repoPath ?? cwd());
61220
+ const repoRoot = resolve30(repoPath ?? cwd());
60503
61221
  const needsSetup = isFirstRun() || !await isModelAvailable(config);
60504
61222
  if (needsSetup && config.backendType === "ollama") {
60505
61223
  const setupModel = await runSetupWizard(config);
@@ -60882,7 +61600,7 @@ var init_run = __esm({
60882
61600
  // packages/indexer/dist/codebase-indexer.js
60883
61601
  import { glob } from "glob";
60884
61602
  import ignore from "ignore";
60885
- import { readFile as readFile22, stat as stat4 } from "node:fs/promises";
61603
+ import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
60886
61604
  import { createHash as createHash4 } from "node:crypto";
60887
61605
  import { join as join62, relative as relative3, extname as extname11, basename as basename15 } from "node:path";
60888
61606
  var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
@@ -60928,7 +61646,7 @@ var init_codebase_indexer = __esm({
60928
61646
  const ig = ignore.default();
60929
61647
  if (this.config.respectGitignore) {
60930
61648
  try {
60931
- const gitignoreContent = await readFile22(join62(this.config.rootDir, ".gitignore"), "utf-8");
61649
+ const gitignoreContent = await readFile23(join62(this.config.rootDir, ".gitignore"), "utf-8");
60932
61650
  ig.add(gitignoreContent);
60933
61651
  } catch {
60934
61652
  }
@@ -60948,7 +61666,7 @@ var init_codebase_indexer = __esm({
60948
61666
  const fileStat = await stat4(fullPath);
60949
61667
  if (fileStat.size > this.config.maxFileSize)
60950
61668
  continue;
60951
- const content = await readFile22(fullPath);
61669
+ const content = await readFile23(fullPath);
60952
61670
  const hash = createHash4("sha256").update(content).digest("hex");
60953
61671
  const ext = extname11(relativePath);
60954
61672
  indexed.push({
@@ -61071,11 +61789,11 @@ var index_repo_exports = {};
61071
61789
  __export(index_repo_exports, {
61072
61790
  indexRepoCommand: () => indexRepoCommand
61073
61791
  });
61074
- import { resolve as resolve30 } from "node:path";
61792
+ import { resolve as resolve31 } from "node:path";
61075
61793
  import { existsSync as existsSync46, statSync as statSync15 } from "node:fs";
61076
61794
  import { cwd as cwd2 } from "node:process";
61077
61795
  async function indexRepoCommand(opts, _config) {
61078
- const repoRoot = resolve30(opts.repoPath ?? cwd2());
61796
+ const repoRoot = resolve31(opts.repoPath ?? cwd2());
61079
61797
  printHeader("Index Repository");
61080
61798
  printInfo(`Indexing: ${repoRoot}`);
61081
61799
  if (!existsSync46(repoRoot)) {
@@ -61330,8 +62048,8 @@ var config_exports = {};
61330
62048
  __export(config_exports, {
61331
62049
  configCommand: () => configCommand
61332
62050
  });
61333
- import { join as join63, resolve as resolve31 } from "node:path";
61334
- import { homedir as homedir15 } from "node:os";
62051
+ import { join as join63, resolve as resolve32 } from "node:path";
62052
+ import { homedir as homedir17 } from "node:os";
61335
62053
  import { cwd as cwd3 } from "node:process";
61336
62054
  function redactIfSensitive(key, value) {
61337
62055
  if (SENSITIVE_KEYS.has(key) && typeof value === "string" && value.length > 0) {
@@ -61363,7 +62081,7 @@ async function configCommand(opts, config) {
61363
62081
  return handleShow(opts, config);
61364
62082
  }
61365
62083
  function handleShow(opts, config) {
61366
- const repoRoot = resolve31(opts.repoPath ?? cwd3());
62084
+ const repoRoot = resolve32(opts.repoPath ?? cwd3());
61367
62085
  printHeader("Configuration");
61368
62086
  const resolved = resolveSettings(repoRoot);
61369
62087
  printSection("Core Inference");
@@ -61413,7 +62131,7 @@ function handleShow(opts, config) {
61413
62131
  }
61414
62132
  }
61415
62133
  printSection("Config File");
61416
- printInfo(`~/.open-agents/config.json (${join63(homedir15(), ".open-agents", "config.json")})`);
62134
+ printInfo(`~/.open-agents/config.json (${join63(homedir17(), ".open-agents", "config.json")})`);
61417
62135
  printSection("Priority Chain");
61418
62136
  printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
61419
62137
  printInfo(" 2. Project .oa/settings.json (--local)");
@@ -61446,7 +62164,7 @@ function handleSet(opts, _config) {
61446
62164
  process.exit(1);
61447
62165
  }
61448
62166
  if (opts.local) {
61449
- const repoRoot = resolve31(opts.repoPath ?? cwd3());
62167
+ const repoRoot = resolve32(opts.repoPath ?? cwd3());
61450
62168
  try {
61451
62169
  initOaDirectory(repoRoot);
61452
62170
  const coerced = coerceForSettings(key, value);
@@ -61644,7 +62362,7 @@ async function serveVllm(opts, config) {
61644
62362
  await runVllmServer(args, opts.verbose ?? false);
61645
62363
  }
61646
62364
  async function runVllmServer(args, verbose) {
61647
- return new Promise((resolve32, reject) => {
62365
+ return new Promise((resolve33, reject) => {
61648
62366
  const child = spawn19("python", args, {
61649
62367
  stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
61650
62368
  env: { ...process.env }
@@ -61679,10 +62397,10 @@ async function runVllmServer(args, verbose) {
61679
62397
  child.once("exit", (code, signal) => {
61680
62398
  if (signal) {
61681
62399
  printInfo(`vLLM server stopped by signal ${signal}`);
61682
- resolve32();
62400
+ resolve33();
61683
62401
  } else if (code === 0) {
61684
62402
  printSuccess("vLLM server exited cleanly");
61685
- resolve32();
62403
+ resolve33();
61686
62404
  } else {
61687
62405
  printError(`vLLM server exited with code ${code}`);
61688
62406
  reject(new Error(`vLLM exited with code ${code}`));