open-agents-ai 0.150.0 → 0.152.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +612 -186
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -18541,9 +18541,9 @@ function getVersion(binary) {
18541
18541
  }
18542
18542
  }
18543
18543
  function installOpencode() {
18544
- const platform5 = process.platform;
18544
+ const platform6 = process.platform;
18545
18545
  try {
18546
- if (platform5 === "win32") {
18546
+ if (platform6 === "win32") {
18547
18547
  execSync19('powershell -Command "irm https://opencode.ai/install | iex"', {
18548
18548
  stdio: "pipe",
18549
18549
  timeout: 12e4
@@ -18815,9 +18815,9 @@ function getVersion2(binary) {
18815
18815
  }
18816
18816
  }
18817
18817
  function installDroid() {
18818
- const platform5 = process.platform;
18818
+ const platform6 = process.platform;
18819
18819
  try {
18820
- if (platform5 === "win32") {
18820
+ if (platform6 === "win32") {
18821
18821
  execSync20('powershell -Command "irm https://app.factory.ai/cli/windows | iex"', {
18822
18822
  stdio: "pipe",
18823
18823
  timeout: 12e4
@@ -20524,6 +20524,301 @@ var init_repo_map = __esm({
20524
20524
  }
20525
20525
  });
20526
20526
 
20527
+ // packages/execution/dist/tools/process-health.js
20528
+ import { execSync as execSync22 } from "node:child_process";
20529
+ function getSystemStatus() {
20530
+ const lines = ["# System Health\n"];
20531
+ try {
20532
+ const uptime2 = execSync22("uptime", { encoding: "utf-8", timeout: 3e3 }).trim();
20533
+ const loadMatch = uptime2.match(/load average:\s*([\d.]+),\s*([\d.]+),\s*([\d.]+)/);
20534
+ if (loadMatch) {
20535
+ lines.push(`CPU Load: ${loadMatch[1]} (1m) ${loadMatch[2]} (5m) ${loadMatch[3]} (15m)`);
20536
+ }
20537
+ } catch {
20538
+ }
20539
+ try {
20540
+ const cpuCount = __require("node:os").cpus().length;
20541
+ lines.push(`CPU Cores: ${cpuCount}`);
20542
+ } catch {
20543
+ }
20544
+ try {
20545
+ const mem = execSync22("free -h | head -2", { encoding: "utf-8", timeout: 3e3 }).trim();
20546
+ lines.push(`
20547
+ ${mem}`);
20548
+ } catch {
20549
+ }
20550
+ try {
20551
+ const top = execSync22("ps aux --sort=-%cpu | head -8", { encoding: "utf-8", timeout: 3e3 }).trim();
20552
+ lines.push(`
20553
+ Top processes by CPU:
20554
+ ${top}`);
20555
+ } catch {
20556
+ }
20557
+ try {
20558
+ const nodeCount = execSync22("ps aux | grep 'node ' | grep -v grep | wc -l", { encoding: "utf-8", timeout: 3e3 }).trim();
20559
+ lines.push(`
20560
+ Node.js processes: ${nodeCount}`);
20561
+ } catch {
20562
+ }
20563
+ return lines.join("\n");
20564
+ }
20565
+ function findOrphans() {
20566
+ try {
20567
+ const psOutput = execSync22(`ps -eo pid,ppid,%cpu,%mem,etime,args --no-headers 2>/dev/null | grep -E "${OA_PATTERNS}" | grep -v grep`, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
20568
+ if (!psOutput)
20569
+ return "No OA-related orphan processes found.";
20570
+ const myPid = process.pid;
20571
+ const myPpid = process.ppid;
20572
+ const lines = ["OA-related processes:\n"];
20573
+ lines.push(" PID PPID CPU% MEM% ELAPSED COMMAND");
20574
+ lines.push(" " + "-".repeat(75));
20575
+ for (const line of psOutput.split("\n")) {
20576
+ const parts = line.trim().split(/\s+/);
20577
+ const pid = parseInt(parts[0], 10);
20578
+ if (pid === myPid || pid === myPpid)
20579
+ continue;
20580
+ const ppid = parts[1];
20581
+ const cpu = parts[2];
20582
+ const mem = parts[3];
20583
+ const elapsed = parts[4];
20584
+ const cmd = parts.slice(5).join(" ");
20585
+ const shortCmd = cmd.length > 50 ? cmd.slice(0, 47) + "..." : cmd;
20586
+ const isHot = parseFloat(cpu) > 10 ? " \u26A0 HIGH CPU" : "";
20587
+ lines.push(` ${String(pid).padStart(7)} ${String(ppid).padStart(7)} ${String(cpu).padStart(6)} ${String(mem).padStart(5)} ${String(elapsed).padStart(9)} ${shortCmd}${isHot}`);
20588
+ }
20589
+ lines.push(`
20590
+ To kill a process: process_health(action='kill', pid=PID)`);
20591
+ lines.push(`Or from the prompt: /destroy processes --global`);
20592
+ return lines.join("\n");
20593
+ } catch {
20594
+ return "Could not scan for orphan processes.";
20595
+ }
20596
+ }
20597
+ function killProcess(pid) {
20598
+ try {
20599
+ try {
20600
+ process.kill(-pid, "SIGTERM");
20601
+ } catch {
20602
+ }
20603
+ process.kill(pid, "SIGTERM");
20604
+ try {
20605
+ execSync22(`sleep 1 && kill -0 ${pid} 2>/dev/null && kill -9 ${pid} 2>/dev/null`, {
20606
+ timeout: 3e3,
20607
+ stdio: "pipe"
20608
+ });
20609
+ } catch {
20610
+ }
20611
+ return `Killed PID ${pid} (SIGTERM \u2192 SIGKILL)`;
20612
+ } catch (err) {
20613
+ return `Failed to kill PID ${pid}: ${err instanceof Error ? err.message : String(err)}`;
20614
+ }
20615
+ }
20616
+ var OA_PATTERNS, ProcessHealthTool;
20617
+ var init_process_health = __esm({
20618
+ "packages/execution/dist/tools/process-health.js"() {
20619
+ "use strict";
20620
+ OA_PATTERNS = [
20621
+ "open-agents",
20622
+ "nexus-daemon",
20623
+ "vitest",
20624
+ "jest",
20625
+ "esbuild.*--service",
20626
+ "python3 -u -i",
20627
+ "chromium.*headless",
20628
+ "chrome.*headless",
20629
+ "crawlee-scraper",
20630
+ "web_scrape",
20631
+ "start-moondream",
20632
+ "live-whisper"
20633
+ ].join("|");
20634
+ ProcessHealthTool = class {
20635
+ name = "process_health";
20636
+ description = "Check system CPU/memory load and find orphaned processes. Actions: 'status' (CPU + memory + top processes), 'orphans' (find stale OA-related processes), 'kill' (kill a specific PID). Use this when the system feels slow or when a shell command seems stuck.";
20637
+ parameters = {
20638
+ type: "object",
20639
+ properties: {
20640
+ action: {
20641
+ type: "string",
20642
+ enum: ["status", "orphans", "kill"],
20643
+ description: "Action (default: status)"
20644
+ },
20645
+ pid: {
20646
+ type: "number",
20647
+ description: "Process ID to kill (for 'kill' action)"
20648
+ }
20649
+ },
20650
+ required: []
20651
+ };
20652
+ async execute(args) {
20653
+ const action = String(args["action"] ?? "status");
20654
+ const start = performance.now();
20655
+ try {
20656
+ switch (action) {
20657
+ case "status":
20658
+ return { success: true, output: getSystemStatus(), durationMs: performance.now() - start };
20659
+ case "orphans":
20660
+ return { success: true, output: findOrphans(), durationMs: performance.now() - start };
20661
+ case "kill": {
20662
+ const pid = Number(args["pid"]);
20663
+ if (!pid || pid <= 10)
20664
+ return { success: false, output: "", error: "Valid PID required", durationMs: performance.now() - start };
20665
+ if (pid === process.pid || pid === process.ppid) {
20666
+ return { success: false, output: "", error: "Cannot kill self or parent process", durationMs: performance.now() - start };
20667
+ }
20668
+ return { success: true, output: killProcess(pid), durationMs: performance.now() - start };
20669
+ }
20670
+ default:
20671
+ return { success: false, output: "", error: `Unknown action: ${action}`, durationMs: performance.now() - start };
20672
+ }
20673
+ } catch (err) {
20674
+ return { success: false, output: "", error: String(err instanceof Error ? err.message : err), durationMs: performance.now() - start };
20675
+ }
20676
+ }
20677
+ };
20678
+ }
20679
+ });
20680
+
20681
+ // packages/execution/dist/tools/environment-snapshot.js
20682
+ import { execSync as execSync23 } from "node:child_process";
20683
+ import { cpus, totalmem, freemem, hostname as hostname2, platform, arch, uptime } from "node:os";
20684
+ import { statfsSync } from "node:fs";
20685
+ function collectSnapshot(workingDir) {
20686
+ const now = /* @__PURE__ */ new Date();
20687
+ const cpuInfo = cpus();
20688
+ const totalRAM = totalmem();
20689
+ const freeRAM = freemem();
20690
+ let load1 = 0, load5 = 0, load15 = 0;
20691
+ try {
20692
+ const loadavg4 = __require("node:os").loadavg();
20693
+ load1 = loadavg4[0];
20694
+ load5 = loadavg4[1];
20695
+ load15 = loadavg4[2];
20696
+ } catch {
20697
+ }
20698
+ let gpu = void 0;
20699
+ try {
20700
+ const nvOut = execSync23("nvidia-smi --query-gpu=name,memory.total,memory.used,temperature.gpu --format=csv,noheader,nounits", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split(",").map((s) => s.trim());
20701
+ if (nvOut.length >= 3) {
20702
+ gpu = {
20703
+ name: nvOut[0],
20704
+ vramTotalMB: parseInt(nvOut[1], 10),
20705
+ vramUsedMB: parseInt(nvOut[2], 10),
20706
+ vramUsedPercent: Math.round(parseInt(nvOut[2], 10) / parseInt(nvOut[1], 10) * 100),
20707
+ tempC: nvOut[3] ? parseInt(nvOut[3], 10) : void 0
20708
+ };
20709
+ }
20710
+ } catch {
20711
+ }
20712
+ let battery = void 0;
20713
+ try {
20714
+ if (platform() === "linux") {
20715
+ const cap = execSync23("cat /sys/class/power_supply/BAT0/capacity 2>/dev/null", { encoding: "utf-8", timeout: 1e3 }).trim();
20716
+ const status = execSync23("cat /sys/class/power_supply/BAT0/status 2>/dev/null", { encoding: "utf-8", timeout: 1e3 }).trim();
20717
+ if (cap)
20718
+ battery = { percent: parseInt(cap, 10), charging: status === "Charging" || status === "Full" };
20719
+ } else if (platform() === "darwin") {
20720
+ const pmOut = execSync23("pmset -g batt", { encoding: "utf-8", timeout: 2e3 });
20721
+ const match = pmOut.match(/(\d+)%;\s*(charging|discharging|charged)/i);
20722
+ if (match)
20723
+ battery = { percent: parseInt(match[1], 10), charging: match[2].toLowerCase() !== "discharging" };
20724
+ }
20725
+ } catch {
20726
+ }
20727
+ let disk = { availableGB: 0, totalGB: 0, usedPercent: 0 };
20728
+ try {
20729
+ const stats = statfsSync(workingDir || "/");
20730
+ const totalBytes = stats.blocks * stats.bsize;
20731
+ const availBytes = stats.bavail * stats.bsize;
20732
+ disk = {
20733
+ totalGB: Math.round(totalBytes / 1024 ** 3),
20734
+ availableGB: Math.round(availBytes / 1024 ** 3),
20735
+ usedPercent: Math.round((1 - availBytes / totalBytes) * 100)
20736
+ };
20737
+ } catch {
20738
+ }
20739
+ let processInfo = { total: 0, nodeCount: 0, oaSpawned: 0, topCpu: [] };
20740
+ try {
20741
+ const psLines = execSync23("ps -eo pid,%cpu,args --sort=-%cpu --no-headers 2>/dev/null | head -50", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n");
20742
+ const total = parseInt(execSync23("ps aux | wc -l", { encoding: "utf-8", timeout: 2e3 }).trim(), 10);
20743
+ let nodeCount = 0;
20744
+ let oaSpawned = 0;
20745
+ const topCpu = [];
20746
+ const oaPattern = /open-agents|nexus-daemon|vitest|esbuild.*service|python3 -u -i|start-moondream|live-whisper/;
20747
+ for (const line of psLines) {
20748
+ const parts = line.trim().split(/\s+/);
20749
+ if (parts.length < 3)
20750
+ continue;
20751
+ const pid = parseInt(parts[0], 10);
20752
+ const cpu = parseFloat(parts[1]);
20753
+ const cmd = parts.slice(2).join(" ");
20754
+ if (/node\b/.test(cmd))
20755
+ nodeCount++;
20756
+ if (oaPattern.test(cmd))
20757
+ oaSpawned++;
20758
+ if (cpu > 1 && topCpu.length < 5) {
20759
+ topCpu.push({ pid, cpu, cmd: cmd.slice(0, 60) });
20760
+ }
20761
+ }
20762
+ processInfo = { total, nodeCount, oaSpawned, topCpu };
20763
+ } catch {
20764
+ }
20765
+ let uptimeStr = "";
20766
+ const secs = uptime();
20767
+ const days = Math.floor(secs / 86400);
20768
+ const hours = Math.floor(secs % 86400 / 3600);
20769
+ uptimeStr = days > 0 ? `${days}d ${hours}h` : `${hours}h ${Math.floor(secs % 3600 / 60)}m`;
20770
+ return {
20771
+ timestamp: now.toISOString(),
20772
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
20773
+ uptime: uptimeStr,
20774
+ cpu: {
20775
+ model: cpuInfo[0]?.model?.replace(/\s+/g, " ").trim() ?? "unknown",
20776
+ cores: cpuInfo.length,
20777
+ load1m: Math.round(load1 * 100) / 100,
20778
+ load5m: Math.round(load5 * 100) / 100,
20779
+ load15m: Math.round(load15 * 100) / 100
20780
+ },
20781
+ ram: {
20782
+ totalGB: Math.round(totalRAM / 1024 ** 3),
20783
+ availableGB: Math.round(freeRAM / 1024 ** 3),
20784
+ usedPercent: Math.round((1 - freeRAM / totalRAM) * 100)
20785
+ },
20786
+ gpu,
20787
+ battery,
20788
+ disk,
20789
+ network: { hostname: hostname2(), platform: platform(), arch: arch() },
20790
+ processes: processInfo
20791
+ };
20792
+ }
20793
+ function formatSnapshotForContext(snap) {
20794
+ const lines = [];
20795
+ lines.push(`<environment>`);
20796
+ lines.push(`Time: ${snap.timestamp.replace("T", " ").replace(/\.\d+Z$/, "Z")} (${snap.timezone})`);
20797
+ lines.push(`System: ${snap.network.platform}/${snap.network.arch} | ${snap.cpu.cores} cores | ${snap.cpu.model.slice(0, 40)}`);
20798
+ lines.push(`CPU Load: ${snap.cpu.load1m} (1m) ${snap.cpu.load5m} (5m) \u2014 ${snap.cpu.load1m > snap.cpu.cores * 0.8 ? "HIGH" : "normal"}`);
20799
+ lines.push(`RAM: ${snap.ram.availableGB}GB free / ${snap.ram.totalGB}GB (${snap.ram.usedPercent}% used)`);
20800
+ if (snap.gpu) {
20801
+ lines.push(`GPU: ${snap.gpu.name} | ${snap.gpu.vramUsedMB}MB / ${snap.gpu.vramTotalMB}MB VRAM (${snap.gpu.vramUsedPercent}%)${snap.gpu.tempC ? ` ${snap.gpu.tempC}\xB0C` : ""}`);
20802
+ }
20803
+ if (snap.battery) {
20804
+ const icon = snap.battery.charging ? "\u26A1" : snap.battery.percent < 20 ? "\u{1FAAB}" : "\u{1F50B}";
20805
+ lines.push(`Battery: ${icon} ${snap.battery.percent}% ${snap.battery.charging ? "(charging)" : "(discharging)"}`);
20806
+ }
20807
+ lines.push(`Disk: ${snap.disk.availableGB}GB free / ${snap.disk.totalGB}GB (${snap.disk.usedPercent}% used)`);
20808
+ lines.push(`Processes: ${snap.processes.total} total | ${snap.processes.nodeCount} node | ${snap.processes.oaSpawned} OA-spawned`);
20809
+ lines.push(`Uptime: ${snap.uptime}`);
20810
+ if (snap.processes.topCpu.length > 0) {
20811
+ lines.push(`Top CPU: ${snap.processes.topCpu.map((p) => `${p.cmd.slice(0, 25)}(${p.cpu}%)`).join(", ")}`);
20812
+ }
20813
+ lines.push(`</environment>`);
20814
+ return lines.join("\n");
20815
+ }
20816
+ var init_environment_snapshot = __esm({
20817
+ "packages/execution/dist/tools/environment-snapshot.js"() {
20818
+ "use strict";
20819
+ }
20820
+ });
20821
+
20527
20822
  // packages/execution/dist/tools/fortemi-bridge.js
20528
20823
  import { existsSync as existsSync27, readFileSync as readFileSync20 } from "node:fs";
20529
20824
  import { join as join41 } from "node:path";
@@ -21321,6 +21616,7 @@ __export(dist_exports, {
21321
21616
  OcrPdfTool: () => OcrPdfTool,
21322
21617
  OpenCodeTool: () => OpenCodeTool,
21323
21618
  PdfToTextTool: () => PdfToTextTool,
21619
+ ProcessHealthTool: () => ProcessHealthTool,
21324
21620
  ReflectionIntegrityTool: () => ReflectionIntegrityTool,
21325
21621
  ReminderTool: () => ReminderTool,
21326
21622
  ReplTool: () => ReplTool,
@@ -21353,6 +21649,7 @@ __export(dist_exports, {
21353
21649
  checkDesktopDeps: () => checkDesktopDeps,
21354
21650
  clearExploreNotes: () => clearExploreNotes,
21355
21651
  clearWorkingNotes: () => clearWorkingNotes,
21652
+ collectSnapshot: () => collectSnapshot,
21356
21653
  createFortemiBridgeTools: () => createFortemiBridgeTools,
21357
21654
  createWorktree: () => createWorktree,
21358
21655
  detectSearchProvider: () => detectSearchProvider,
@@ -21360,6 +21657,7 @@ __export(dist_exports, {
21360
21657
  ensureAllDesktopDeps: () => ensureAllDesktopDeps,
21361
21658
  ensureCommand: () => ensureCommand,
21362
21659
  ensureDepsForGroup: () => ensureDepsForGroup,
21660
+ formatSnapshotForContext: () => formatSnapshotForContext,
21363
21661
  getActiveAttentionItems: () => getActiveAttentionItems,
21364
21662
  getDueReminders: () => getDueReminders,
21365
21663
  getExploreNotes: () => getExploreNotes,
@@ -21458,6 +21756,8 @@ var init_dist2 = __esm({
21458
21756
  init_semantic_map();
21459
21757
  init_change_log();
21460
21758
  init_repo_map();
21759
+ init_process_health();
21760
+ init_environment_snapshot();
21461
21761
  init_nexus();
21462
21762
  init_fortemi_bridge();
21463
21763
  init_system_deps();
@@ -28267,7 +28567,7 @@ __export(listen_exports, {
28267
28567
  isVideoPath: () => isVideoPath,
28268
28568
  waitForTranscribeCli: () => waitForTranscribeCli
28269
28569
  });
28270
- import { spawn as spawn15, execSync as execSync22 } from "node:child_process";
28570
+ import { spawn as spawn15, execSync as execSync24 } from "node:child_process";
28271
28571
  import { existsSync as existsSync31, mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, readdirSync as readdirSync7 } from "node:fs";
28272
28572
  import { join as join46, dirname as dirname14 } from "node:path";
28273
28573
  import { homedir as homedir10 } from "node:os";
@@ -28286,10 +28586,10 @@ function isTranscribablePath(path) {
28286
28586
  return isAudioPath(path) || isVideoPath(path);
28287
28587
  }
28288
28588
  function findMicCaptureCommand() {
28289
- const platform5 = process.platform;
28290
- if (platform5 === "linux") {
28589
+ const platform6 = process.platform;
28590
+ if (platform6 === "linux") {
28291
28591
  try {
28292
- execSync22("which arecord", { stdio: "pipe" });
28592
+ execSync24("which arecord", { stdio: "pipe" });
28293
28593
  return {
28294
28594
  cmd: "arecord",
28295
28595
  args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
@@ -28297,9 +28597,9 @@ function findMicCaptureCommand() {
28297
28597
  } catch {
28298
28598
  }
28299
28599
  }
28300
- if (platform5 === "darwin") {
28600
+ if (platform6 === "darwin") {
28301
28601
  try {
28302
- execSync22("which sox", { stdio: "pipe" });
28602
+ execSync24("which sox", { stdio: "pipe" });
28303
28603
  return {
28304
28604
  cmd: "sox",
28305
28605
  args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
@@ -28308,8 +28608,8 @@ function findMicCaptureCommand() {
28308
28608
  }
28309
28609
  }
28310
28610
  try {
28311
- execSync22("which ffmpeg", { stdio: "pipe" });
28312
- if (platform5 === "linux") {
28611
+ execSync24("which ffmpeg", { stdio: "pipe" });
28612
+ if (platform6 === "linux") {
28313
28613
  return {
28314
28614
  cmd: "ffmpeg",
28315
28615
  args: [
@@ -28328,7 +28628,7 @@ function findMicCaptureCommand() {
28328
28628
  "pipe:1"
28329
28629
  ]
28330
28630
  };
28331
- } else if (platform5 === "darwin") {
28631
+ } else if (platform6 === "darwin") {
28332
28632
  return {
28333
28633
  cmd: "ffmpeg",
28334
28634
  args: [
@@ -28367,7 +28667,7 @@ function findLiveWhisperScript() {
28367
28667
  return p;
28368
28668
  }
28369
28669
  try {
28370
- const globalRoot = execSync22("npm root -g", {
28670
+ const globalRoot = execSync24("npm root -g", {
28371
28671
  encoding: "utf-8",
28372
28672
  timeout: 5e3,
28373
28673
  stdio: ["pipe", "pipe", "pipe"]
@@ -28400,7 +28700,7 @@ function ensureTranscribeCliBackground() {
28400
28700
  return;
28401
28701
  _bgInstallPromise = (async () => {
28402
28702
  try {
28403
- const globalRoot = execSync22("npm root -g", {
28703
+ const globalRoot = execSync24("npm root -g", {
28404
28704
  encoding: "utf-8",
28405
28705
  timeout: 5e3,
28406
28706
  stdio: ["pipe", "pipe", "pipe"]
@@ -28606,7 +28906,7 @@ var init_listen = __esm({
28606
28906
  }
28607
28907
  if (!this.transcribeCliAvailable) {
28608
28908
  try {
28609
- execSync22("which transcribe-cli", { stdio: "pipe" });
28909
+ execSync24("which transcribe-cli", { stdio: "pipe" });
28610
28910
  this.transcribeCliAvailable = true;
28611
28911
  } catch {
28612
28912
  this.transcribeCliAvailable = false;
@@ -28623,7 +28923,7 @@ var init_listen = __esm({
28623
28923
  } catch {
28624
28924
  }
28625
28925
  try {
28626
- const globalRoot = execSync22("npm root -g", {
28926
+ const globalRoot = execSync24("npm root -g", {
28627
28927
  encoding: "utf-8",
28628
28928
  timeout: 5e3,
28629
28929
  stdio: ["pipe", "pipe", "pipe"]
@@ -28673,7 +28973,7 @@ var init_listen = __esm({
28673
28973
  }
28674
28974
  if (!tc) {
28675
28975
  try {
28676
- execSync22("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
28976
+ execSync24("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
28677
28977
  this.transcribeCliAvailable = null;
28678
28978
  tc = await this.loadTranscribeCli();
28679
28979
  } catch {
@@ -28856,7 +29156,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
28856
29156
  }
28857
29157
  if (!tc) {
28858
29158
  try {
28859
- execSync22("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
29159
+ execSync24("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
28860
29160
  this.transcribeCliAvailable = null;
28861
29161
  tc = await this.loadTranscribeCli();
28862
29162
  } catch {
@@ -28910,7 +29210,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
28910
29210
  }
28911
29211
  if (!tc) {
28912
29212
  try {
28913
- execSync22("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
29213
+ execSync24("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
28914
29214
  this.transcribeCliAvailable = null;
28915
29215
  tc = await this.loadTranscribeCli();
28916
29216
  } catch {
@@ -33358,7 +33658,9 @@ var init_render = __esm({
33358
33658
  ["/pause", "Pause after current turn finishes (gentle halt, /resume to continue)"],
33359
33659
  ["/stop", "Kill current inference immediately and save state (/resume to continue)"],
33360
33660
  ["/resume", "Resume a paused or stopped task"],
33361
- ["/destroy", "Remove .oa folder, kill all tasks, clear console, and exit"],
33661
+ ["/destroy processes", "Find and kill orphaned OA child processes (this project)"],
33662
+ ["/destroy processes --global", "Kill ALL orphaned OA processes system-wide"],
33663
+ ["/destroy project", "Remove .oa folder, kill all tasks, clear console, and exit"],
33362
33664
  ["/context save", "Force-save session context to .oa/context/"],
33363
33665
  ["/context restore", "Restore context from previous sessions into next task"],
33364
33666
  ["/context show", "Show saved session context status"],
@@ -33415,7 +33717,7 @@ var init_render = __esm({
33415
33717
 
33416
33718
  // packages/cli/dist/tui/voice-session.js
33417
33719
  import { createServer as createServer2 } from "node:http";
33418
- import { spawn as spawn16, execSync as execSync23 } from "node:child_process";
33720
+ import { spawn as spawn16, execSync as execSync25 } from "node:child_process";
33419
33721
  import { EventEmitter as EventEmitter2 } from "node:events";
33420
33722
  function generateFrontendHTML() {
33421
33723
  return `<!DOCTYPE html>
@@ -34147,7 +34449,7 @@ import { spawn as spawn17, exec } from "node:child_process";
34147
34449
  import { EventEmitter as EventEmitter3 } from "node:events";
34148
34450
  import { randomBytes as randomBytes11 } from "node:crypto";
34149
34451
  import { URL as URL2 } from "node:url";
34150
- import { loadavg, cpus, totalmem, freemem } from "node:os";
34452
+ import { loadavg, cpus as cpus2, totalmem as totalmem2, freemem as freemem2 } from "node:os";
34151
34453
  import { existsSync as existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync12, unlinkSync as unlinkSync5, mkdirSync as mkdirSync11, readdirSync as readdirSync8, statSync as statSync11 } from "node:fs";
34152
34454
  import { join as join47 } from "node:path";
34153
34455
  function cleanForwardHeaders(raw, targetHost) {
@@ -34239,9 +34541,9 @@ function parseRateLimitHeaders(headers) {
34239
34541
  }
34240
34542
  async function collectSystemMetricsAsync() {
34241
34543
  const [l1, l5, l15] = loadavg();
34242
- const cores = cpus().length;
34243
- const totalMem = totalmem();
34244
- const freeMem = freemem();
34544
+ const cores = cpus2().length;
34545
+ const totalMem = totalmem2();
34546
+ const freeMem = freemem2();
34245
34547
  const usedMem = totalMem - freeMem;
34246
34548
  const gpu = {
34247
34549
  available: false,
@@ -36784,7 +37086,7 @@ ${activitySummary}
36784
37086
  });
36785
37087
 
36786
37088
  // packages/cli/dist/tui/model-picker.js
36787
- import { totalmem as totalmem2 } from "node:os";
37089
+ import { totalmem as totalmem3 } from "node:os";
36788
37090
  function isImageGenModel(name, family) {
36789
37091
  return IMAGE_GEN_PATTERNS.some((p) => p.test(name) || family && p.test(family));
36790
37092
  }
@@ -36833,15 +37135,15 @@ async function fetchOllamaModels(baseUrl) {
36833
37135
  }
36834
37136
  if (show.model_info) {
36835
37137
  const info = show.model_info;
36836
- const arch = info["general.architecture"];
37138
+ const arch2 = info["general.architecture"];
36837
37139
  const paramCount = info["general.parameter_count"];
36838
37140
  const fileSizeGB = result[i].sizeBytes > 0 ? result[i].sizeBytes / 1024 ** 3 : paramCount ? paramCount * 0.6 / 1024 ** 3 : 4;
36839
- if (arch) {
36840
- const archMax = info[`${arch}.context_length`];
36841
- const nLayers = info[`${arch}.block_count`];
36842
- const nKVHeads = info[`${arch}.attention.head_count_kv`] ?? info[`${arch}.attention.head_count`];
36843
- const keyDim = info[`${arch}.attention.key_length`];
36844
- const valDim = info[`${arch}.attention.value_length`] ?? keyDim;
37141
+ if (arch2) {
37142
+ const archMax = info[`${arch2}.context_length`];
37143
+ const nLayers = info[`${arch2}.block_count`];
37144
+ const nKVHeads = info[`${arch2}.attention.head_count_kv`] ?? info[`${arch2}.attention.head_count`];
37145
+ const keyDim = info[`${arch2}.attention.key_length`];
37146
+ const valDim = info[`${arch2}.attention.value_length`] ?? keyDim;
36845
37147
  if (archMax && nLayers && nKVHeads && keyDim && valDim) {
36846
37148
  const kvBytesPerToken = nLayers * nKVHeads * (keyDim + valDim) * 2;
36847
37149
  result[i].contextLength = estimateRealisticContext(kvBytesPerToken, archMax, fileSizeGB);
@@ -37144,15 +37446,15 @@ async function queryModelContextSize(baseUrl, modelName) {
37144
37446
  }
37145
37447
  if (data.model_info) {
37146
37448
  const info = data.model_info;
37147
- const arch = info["general.architecture"];
37449
+ const arch2 = info["general.architecture"];
37148
37450
  const paramCount = info["general.parameter_count"];
37149
37451
  const modelSizeGB2 = paramCount ? paramCount * 0.6 / 1024 ** 3 : 4;
37150
- if (arch) {
37151
- const archMax = info[`${arch}.context_length`];
37152
- const nLayers = info[`${arch}.block_count`];
37153
- const nKVHeads = info[`${arch}.attention.head_count_kv`] ?? info[`${arch}.attention.head_count`];
37154
- const keyDim = info[`${arch}.attention.key_length`];
37155
- const valDim = info[`${arch}.attention.value_length`] ?? keyDim;
37452
+ if (arch2) {
37453
+ const archMax = info[`${arch2}.context_length`];
37454
+ const nLayers = info[`${arch2}.block_count`];
37455
+ const nKVHeads = info[`${arch2}.attention.head_count_kv`] ?? info[`${arch2}.attention.head_count`];
37456
+ const keyDim = info[`${arch2}.attention.key_length`];
37457
+ const valDim = info[`${arch2}.attention.value_length`] ?? keyDim;
37156
37458
  if (archMax && nLayers && nKVHeads && keyDim && valDim) {
37157
37459
  const kvBytesPerToken = nLayers * nKVHeads * (keyDim + valDim) * 2;
37158
37460
  return estimateRealisticContext(kvBytesPerToken, archMax, modelSizeGB2);
@@ -37169,7 +37471,7 @@ async function queryModelContextSize(baseUrl, modelName) {
37169
37471
  }
37170
37472
  }
37171
37473
  function estimateRealisticContext(kvBytesPerToken, archMax, modelSizeGB2) {
37172
- const totalMemGB = totalmem2() / 1024 ** 3;
37474
+ const totalMemGB = totalmem3() / 1024 ** 3;
37173
37475
  const usableBytes = totalMemGB * 0.7 * 1024 ** 3;
37174
37476
  const maxTokens = Math.floor(usableBytes / kvBytesPerToken);
37175
37477
  let numCtx = Math.max(2048, Math.floor(maxTokens / 1024) * 1024);
@@ -38045,18 +38347,18 @@ var init_oa_directory = __esm({
38045
38347
 
38046
38348
  // packages/cli/dist/tui/setup.js
38047
38349
  import * as readline from "node:readline";
38048
- import { execSync as execSync24, spawn as spawn18, exec as exec2 } from "node:child_process";
38350
+ import { execSync as execSync26, spawn as spawn18, exec as exec2 } from "node:child_process";
38049
38351
  import { promisify as promisify6 } from "node:util";
38050
38352
  import { existsSync as existsSync36, writeFileSync as writeFileSync15, readFileSync as readFileSync27, appendFileSync as appendFileSync2, mkdirSync as mkdirSync14 } from "node:fs";
38051
38353
  import { join as join52 } from "node:path";
38052
- import { homedir as homedir12, platform } from "node:os";
38354
+ import { homedir as homedir12, platform as platform2 } from "node:os";
38053
38355
  function detectSystemSpecs() {
38054
38356
  let totalRamGB = 0;
38055
38357
  let availableRamGB = 0;
38056
38358
  let gpuVramGB = 0;
38057
38359
  let gpuName = "";
38058
38360
  try {
38059
- const memInfo = execSync24("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
38361
+ const memInfo = execSync26("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
38060
38362
  encoding: "utf8",
38061
38363
  timeout: 5e3
38062
38364
  });
@@ -38076,7 +38378,7 @@ function detectSystemSpecs() {
38076
38378
  } catch {
38077
38379
  }
38078
38380
  try {
38079
- const nvidiaSmi = execSync24("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
38381
+ const nvidiaSmi = execSync26("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
38080
38382
  const lines = nvidiaSmi.trim().split("\n");
38081
38383
  if (lines.length > 0) {
38082
38384
  for (const line of lines) {
@@ -38236,7 +38538,7 @@ function askSecret(rl, question) {
38236
38538
  function ensureCurl() {
38237
38539
  if (hasCmd("curl"))
38238
38540
  return true;
38239
- const plat = platform();
38541
+ const plat = platform2();
38240
38542
  if (plat === "win32") {
38241
38543
  process.stdout.write(` ${c2.yellow("\u26A0")} curl not found on Windows \u2014 install it manually.
38242
38544
  `);
@@ -38255,7 +38557,7 @@ function ensureCurl() {
38255
38557
  for (const s of strategies) {
38256
38558
  if (hasCmd(s.check)) {
38257
38559
  try {
38258
- execSync24(s.install, { stdio: "inherit", timeout: 12e4 });
38560
+ execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
38259
38561
  if (hasCmd("curl")) {
38260
38562
  process.stdout.write(` ${c2.green("\u2714")} curl installed via ${s.label}.
38261
38563
  `);
@@ -38269,7 +38571,7 @@ function ensureCurl() {
38269
38571
  }
38270
38572
  if (plat === "darwin") {
38271
38573
  try {
38272
- execSync24("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
38574
+ execSync26("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
38273
38575
  if (hasCmd("curl"))
38274
38576
  return true;
38275
38577
  } catch {
@@ -38280,7 +38582,7 @@ function ensureCurl() {
38280
38582
  return false;
38281
38583
  }
38282
38584
  async function autoInstallOllama(rl) {
38283
- const plat = platform();
38585
+ const plat = platform2();
38284
38586
  if (plat !== "win32" && !ensureCurl()) {
38285
38587
  return false;
38286
38588
  }
@@ -38304,7 +38606,7 @@ function installOllamaLinux() {
38304
38606
 
38305
38607
  `);
38306
38608
  try {
38307
- execSync24("curl -fsSL https://ollama.com/install.sh | sh", {
38609
+ execSync26("curl -fsSL https://ollama.com/install.sh | sh", {
38308
38610
  stdio: "inherit",
38309
38611
  timeout: 3e5
38310
38612
  });
@@ -38332,7 +38634,7 @@ async function installOllamaMac(_rl) {
38332
38634
 
38333
38635
  `);
38334
38636
  try {
38335
- execSync24('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
38637
+ execSync26('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
38336
38638
  if (!hasCmd("brew")) {
38337
38639
  try {
38338
38640
  const brewPrefix = existsSync36("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
@@ -38365,7 +38667,7 @@ async function installOllamaMac(_rl) {
38365
38667
 
38366
38668
  `);
38367
38669
  try {
38368
- execSync24("brew install ollama", {
38670
+ execSync26("brew install ollama", {
38369
38671
  stdio: "inherit",
38370
38672
  timeout: 3e5
38371
38673
  });
@@ -38392,7 +38694,7 @@ function installOllamaWindows() {
38392
38694
 
38393
38695
  `);
38394
38696
  try {
38395
- execSync24('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
38697
+ execSync26('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
38396
38698
  stdio: "inherit",
38397
38699
  timeout: 3e5
38398
38700
  });
@@ -38473,7 +38775,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
38473
38775
  }
38474
38776
  function pullModelWithAutoUpdate(tag) {
38475
38777
  try {
38476
- execSync24(`ollama pull ${tag}`, {
38778
+ execSync26(`ollama pull ${tag}`, {
38477
38779
  stdio: "inherit",
38478
38780
  timeout: 36e5
38479
38781
  // 1 hour max
@@ -38493,7 +38795,7 @@ function pullModelWithAutoUpdate(tag) {
38493
38795
 
38494
38796
  `);
38495
38797
  try {
38496
- execSync24("curl -fsSL https://ollama.com/install.sh | sh", {
38798
+ execSync26("curl -fsSL https://ollama.com/install.sh | sh", {
38497
38799
  stdio: "inherit",
38498
38800
  timeout: 3e5
38499
38801
  // 5 min max for install
@@ -38504,7 +38806,7 @@ function pullModelWithAutoUpdate(tag) {
38504
38806
  process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
38505
38807
 
38506
38808
  `);
38507
- execSync24(`ollama pull ${tag}`, {
38809
+ execSync26(`ollama pull ${tag}`, {
38508
38810
  stdio: "inherit",
38509
38811
  timeout: 36e5
38510
38812
  });
@@ -38588,7 +38890,7 @@ function renderScoreBar(score, width = 20) {
38588
38890
  function ensurePython3() {
38589
38891
  process.stdout.write(` ${c2.cyan("\u25CF")} Installing Python3...
38590
38892
  `);
38591
- const plat = platform();
38893
+ const plat = platform2();
38592
38894
  if (plat === "win32") {
38593
38895
  process.stdout.write(` ${c2.dim("Download Python from https://python.org/downloads/")}
38594
38896
 
@@ -38606,7 +38908,7 @@ function ensurePython3() {
38606
38908
  if (plat === "darwin") {
38607
38909
  if (hasCmd("brew")) {
38608
38910
  try {
38609
- execSync24("brew install python3", { stdio: "inherit", timeout: 3e5 });
38911
+ execSync26("brew install python3", { stdio: "inherit", timeout: 3e5 });
38610
38912
  if (hasCmd("python3")) {
38611
38913
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via Homebrew.
38612
38914
  `);
@@ -38619,7 +38921,7 @@ function ensurePython3() {
38619
38921
  for (const s of strategies) {
38620
38922
  if (hasCmd(s.check)) {
38621
38923
  try {
38622
- execSync24(s.install, { stdio: "inherit", timeout: 12e4 });
38924
+ execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
38623
38925
  if (hasCmd("python3") || hasCmd("python")) {
38624
38926
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via ${s.label}.
38625
38927
  `);
@@ -38635,11 +38937,11 @@ function ensurePython3() {
38635
38937
  }
38636
38938
  function checkPythonVenv() {
38637
38939
  try {
38638
- execSync24("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
38940
+ execSync26("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
38639
38941
  return true;
38640
38942
  } catch {
38641
38943
  try {
38642
- execSync24("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
38944
+ execSync26("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
38643
38945
  return true;
38644
38946
  } catch {
38645
38947
  return false;
@@ -38658,7 +38960,7 @@ function ensurePythonVenv() {
38658
38960
  for (const s of strategies) {
38659
38961
  if (hasCmd(s.check)) {
38660
38962
  try {
38661
- execSync24(s.install, { stdio: "inherit", timeout: 12e4 });
38963
+ execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
38662
38964
  if (checkPythonVenv()) {
38663
38965
  process.stdout.write(` ${c2.green("\u2714")} python3-venv installed via ${s.label}.
38664
38966
  `);
@@ -39094,7 +39396,7 @@ async function doSetup(config, rl) {
39094
39396
  const modelfilePath = join52(modelDir2, `Modelfile.${customName}`);
39095
39397
  writeFileSync15(modelfilePath, modelfileContent + "\n", "utf8");
39096
39398
  process.stdout.write(` ${c2.dim("Creating model...")} `);
39097
- execSync24(`ollama create ${customName} -f ${modelfilePath}`, {
39399
+ execSync26(`ollama create ${customName} -f ${modelfilePath}`, {
39098
39400
  stdio: "pipe",
39099
39401
  timeout: 12e4
39100
39402
  });
@@ -39145,7 +39447,7 @@ function isFirstRun() {
39145
39447
  function hasCmd(cmd) {
39146
39448
  try {
39147
39449
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
39148
- execSync24(whichCmd, { stdio: "pipe", timeout: 3e3 });
39450
+ execSync26(whichCmd, { stdio: "pipe", timeout: 3e3 });
39149
39451
  return true;
39150
39452
  } catch {
39151
39453
  return false;
@@ -39178,7 +39480,7 @@ function getVenvDir() {
39178
39480
  }
39179
39481
  function hasVenvModule() {
39180
39482
  try {
39181
- execSync24("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
39483
+ execSync26("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
39182
39484
  return true;
39183
39485
  } catch {
39184
39486
  return false;
@@ -39200,8 +39502,8 @@ function ensureVenv(log) {
39200
39502
  }
39201
39503
  try {
39202
39504
  mkdirSync14(join52(homedir12(), ".open-agents"), { recursive: true });
39203
- execSync24(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
39204
- execSync24(`"${join52(venvDir, "bin", "pip")}" install --upgrade pip`, {
39505
+ execSync26(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
39506
+ execSync26(`"${join52(venvDir, "bin", "pip")}" install --upgrade pip`, {
39205
39507
  stdio: "pipe",
39206
39508
  timeout: 6e4
39207
39509
  });
@@ -39214,7 +39516,7 @@ function ensureVenv(log) {
39214
39516
  }
39215
39517
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
39216
39518
  try {
39217
- execSync24(`sudo -n ${cmd}`, {
39519
+ execSync26(`sudo -n ${cmd}`, {
39218
39520
  stdio: "pipe",
39219
39521
  timeout: timeoutMs,
39220
39522
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -39227,7 +39529,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
39227
39529
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
39228
39530
  try {
39229
39531
  const escaped = cmd.replace(/'/g, "'\\''");
39230
- execSync24(`sudo -S bash -c '${escaped}'`, {
39532
+ execSync26(`sudo -S bash -c '${escaped}'`, {
39231
39533
  input: password + "\n",
39232
39534
  stdio: ["pipe", "pipe", "pipe"],
39233
39535
  timeout: timeoutMs,
@@ -39334,7 +39636,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
39334
39636
  ok = await sudoInstall(batchCmd, getPassword, log, cachedPasswordRef, 18e4);
39335
39637
  } else {
39336
39638
  try {
39337
- execSync24(batchCmd, { stdio: "pipe", timeout: 18e4 });
39639
+ execSync26(batchCmd, { stdio: "pipe", timeout: 18e4 });
39338
39640
  ok = true;
39339
39641
  } catch {
39340
39642
  ok = false;
@@ -39371,7 +39673,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
39371
39673
  const venvCmds = {
39372
39674
  apt: () => {
39373
39675
  try {
39374
- const pyVer = execSync24(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
39676
+ const pyVer = execSync26(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
39375
39677
  return `apt-get install -y python3-venv python${pyVer}-venv`;
39376
39678
  } catch {
39377
39679
  return "apt-get install -y python3-venv";
@@ -39399,12 +39701,12 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
39399
39701
  const venvPip = join52(venvBin, "pip");
39400
39702
  log("Installing moondream-station in ~/.open-agents/venv...");
39401
39703
  try {
39402
- execSync24(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
39704
+ execSync26(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
39403
39705
  if (existsSync36(venvMoondream)) {
39404
39706
  log("moondream-station installed successfully.");
39405
39707
  } else {
39406
39708
  try {
39407
- const check = execSync24(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
39709
+ const check = execSync26(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
39408
39710
  if (check.includes("moondream")) {
39409
39711
  log("moondream-station package installed.");
39410
39712
  }
@@ -39421,7 +39723,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
39421
39723
  const venvPip2 = join52(venvBin, "pip");
39422
39724
  let ocrStackInstalled = false;
39423
39725
  try {
39424
- execSync24(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
39726
+ execSync26(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
39425
39727
  ocrStackInstalled = true;
39426
39728
  } catch {
39427
39729
  }
@@ -39429,9 +39731,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
39429
39731
  const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
39430
39732
  log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
39431
39733
  try {
39432
- execSync24(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
39734
+ execSync26(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
39433
39735
  try {
39434
- execSync24(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
39736
+ execSync26(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
39435
39737
  log("OCR Python stack installed successfully.");
39436
39738
  } catch {
39437
39739
  log("OCR Python stack install completed but import verification failed.");
@@ -39455,17 +39757,17 @@ function ensureCloudflaredBackground(onInfo) {
39455
39757
  });
39456
39758
  log("Installing cloudflared for live voice sessions...");
39457
39759
  _cloudflaredInstallPromise = (async () => {
39458
- const arch = process.arch;
39459
- const os = platform();
39760
+ const arch2 = process.arch;
39761
+ const os = platform2();
39460
39762
  if (os !== "win32" && !ensureCurl()) {
39461
39763
  log("curl not available \u2014 cannot install cloudflared.");
39462
39764
  return false;
39463
39765
  }
39464
39766
  if (os === "linux") {
39465
39767
  const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
39466
- const cfArch = archMap[arch] ?? "amd64";
39768
+ const cfArch = archMap[arch2] ?? "amd64";
39467
39769
  try {
39468
- 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 });
39770
+ execSync26(`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 });
39469
39771
  if (!process.env.PATH?.includes(`${homedir12()}/.local/bin`)) {
39470
39772
  process.env.PATH = `${homedir12()}/.local/bin:${process.env.PATH}`;
39471
39773
  }
@@ -39476,7 +39778,7 @@ function ensureCloudflaredBackground(onInfo) {
39476
39778
  } catch {
39477
39779
  }
39478
39780
  try {
39479
- execSync24(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
39781
+ execSync26(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
39480
39782
  if (hasCmd("cloudflared")) {
39481
39783
  log("cloudflared installed.");
39482
39784
  return true;
@@ -39485,7 +39787,7 @@ function ensureCloudflaredBackground(onInfo) {
39485
39787
  }
39486
39788
  } else if (os === "darwin") {
39487
39789
  try {
39488
- execSync24("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
39790
+ execSync26("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
39489
39791
  if (hasCmd("cloudflared")) {
39490
39792
  log("cloudflared installed via Homebrew.");
39491
39793
  return true;
@@ -39534,14 +39836,14 @@ async function queryModelKVInfo(backendUrl, modelName) {
39534
39836
  if (!data.model_info)
39535
39837
  return null;
39536
39838
  const info = data.model_info;
39537
- const arch = info["general.architecture"];
39538
- if (!arch)
39839
+ const arch2 = info["general.architecture"];
39840
+ if (!arch2)
39539
39841
  return null;
39540
- const nLayers = info[`${arch}.block_count`];
39541
- const nKVHeads = info[`${arch}.attention.head_count_kv`] ?? info[`${arch}.attention.head_count`];
39542
- const keyDim = info[`${arch}.attention.key_length`];
39543
- const valDim = info[`${arch}.attention.value_length`] ?? keyDim;
39544
- const archMax = info[`${arch}.context_length`];
39842
+ const nLayers = info[`${arch2}.block_count`];
39843
+ const nKVHeads = info[`${arch2}.attention.head_count_kv`] ?? info[`${arch2}.attention.head_count`];
39844
+ const keyDim = info[`${arch2}.attention.key_length`];
39845
+ const valDim = info[`${arch2}.attention.value_length`] ?? keyDim;
39846
+ const archMax = info[`${arch2}.context_length`];
39545
39847
  if (!nLayers || !nKVHeads || !keyDim || !valDim || !archMax)
39546
39848
  return null;
39547
39849
  const kvBytesPerToken = nLayers * nKVHeads * (keyDim + valDim) * 2;
@@ -39627,7 +39929,7 @@ async function ensureExpandedContext(modelName, backendUrl) {
39627
39929
  }
39628
39930
  async function ensureNeovim() {
39629
39931
  try {
39630
- const nvimPath = execSync24("which nvim 2>/dev/null || where nvim 2>nul", {
39932
+ const nvimPath = execSync26("which nvim 2>/dev/null || where nvim 2>nul", {
39631
39933
  encoding: "utf8",
39632
39934
  stdio: "pipe",
39633
39935
  timeout: 5e3
@@ -39636,27 +39938,27 @@ async function ensureNeovim() {
39636
39938
  return nvimPath;
39637
39939
  } catch {
39638
39940
  }
39639
- const platform5 = process.platform;
39640
- const arch = process.arch;
39641
- if (platform5 === "linux") {
39941
+ const platform6 = process.platform;
39942
+ const arch2 = process.arch;
39943
+ if (platform6 === "linux") {
39642
39944
  const binDir = join52(homedir12(), ".local", "bin");
39643
39945
  const nvimDest = join52(binDir, "nvim");
39644
39946
  try {
39645
39947
  mkdirSync14(binDir, { recursive: true });
39646
39948
  } catch {
39647
39949
  }
39648
- const appImageName = arch === "arm64" ? "nvim-linux-arm64.appimage" : "nvim-linux-x86_64.appimage";
39950
+ const appImageName = arch2 === "arm64" ? "nvim-linux-arm64.appimage" : "nvim-linux-x86_64.appimage";
39649
39951
  const url = `https://github.com/neovim/neovim/releases/latest/download/${appImageName}`;
39650
39952
  console.log(` Downloading Neovim (${appImageName})...`);
39651
39953
  try {
39652
- execSync24(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
39653
- execSync24(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
39954
+ execSync26(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
39955
+ execSync26(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
39654
39956
  } catch (err) {
39655
39957
  console.log(` Failed to download Neovim: ${err instanceof Error ? err.message : String(err)}`);
39656
39958
  return null;
39657
39959
  }
39658
39960
  try {
39659
- const ver = execSync24(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
39961
+ const ver = execSync26(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
39660
39962
  console.log(` Installed: ${ver}`);
39661
39963
  } catch {
39662
39964
  console.log(" Warning: nvim binary downloaded but may not work (missing FUSE? Try: nvim --appimage-extract)");
@@ -39667,12 +39969,12 @@ async function ensureNeovim() {
39667
39969
  ensurePathInShellRc(binDir);
39668
39970
  return nvimDest;
39669
39971
  }
39670
- if (platform5 === "darwin") {
39972
+ if (platform6 === "darwin") {
39671
39973
  if (hasCmd("brew")) {
39672
39974
  console.log(" Installing Neovim via Homebrew...");
39673
39975
  try {
39674
- execSync24("brew install neovim", { stdio: "inherit", timeout: 12e4 });
39675
- const nvimPath = execSync24("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
39976
+ execSync26("brew install neovim", { stdio: "inherit", timeout: 12e4 });
39977
+ const nvimPath = execSync26("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
39676
39978
  return nvimPath || null;
39677
39979
  } catch {
39678
39980
  console.log(" brew install neovim failed.");
@@ -39682,11 +39984,11 @@ async function ensureNeovim() {
39682
39984
  console.log(" Homebrew not found. Install Neovim: brew install neovim");
39683
39985
  return null;
39684
39986
  }
39685
- if (platform5 === "win32") {
39987
+ if (platform6 === "win32") {
39686
39988
  if (hasCmd("choco")) {
39687
39989
  console.log(" Installing Neovim via Chocolatey...");
39688
39990
  try {
39689
- execSync24("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
39991
+ execSync26("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
39690
39992
  return "nvim";
39691
39993
  } catch {
39692
39994
  console.log(" choco install neovim failed.");
@@ -39695,7 +39997,7 @@ async function ensureNeovim() {
39695
39997
  if (hasCmd("winget")) {
39696
39998
  console.log(" Installing Neovim via winget...");
39697
39999
  try {
39698
- execSync24("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
40000
+ execSync26("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
39699
40001
  stdio: "inherit",
39700
40002
  timeout: 12e4
39701
40003
  });
@@ -40617,7 +40919,7 @@ var init_drop_panel = __esm({
40617
40919
  import { existsSync as existsSync38, unlinkSync as unlinkSync7 } from "node:fs";
40618
40920
  import { tmpdir as tmpdir8 } from "node:os";
40619
40921
  import { join as join53 } from "node:path";
40620
- import { execSync as execSync25 } from "node:child_process";
40922
+ import { execSync as execSync27 } from "node:child_process";
40621
40923
  function isNeovimActive() {
40622
40924
  return _state !== null && !_state.cleanedUp;
40623
40925
  }
@@ -40635,7 +40937,7 @@ async function startNeovimMode(opts) {
40635
40937
  }
40636
40938
  let nvimPath;
40637
40939
  try {
40638
- nvimPath = execSync25("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
40940
+ nvimPath = execSync27("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
40639
40941
  if (!nvimPath)
40640
40942
  throw new Error();
40641
40943
  } catch {
@@ -41095,8 +41397,8 @@ __export(voice_exports, {
41095
41397
  });
41096
41398
  import { existsSync as existsSync39, mkdirSync as mkdirSync15, writeFileSync as writeFileSync16, readFileSync as readFileSync28, unlinkSync as unlinkSync8, readdirSync as readdirSync10, renameSync, statSync as statSync13 } from "node:fs";
41097
41399
  import { join as join54, dirname as dirname18 } from "node:path";
41098
- import { homedir as homedir13, tmpdir as tmpdir9, platform as platform2 } from "node:os";
41099
- import { execSync as execSync26, spawn as nodeSpawn } from "node:child_process";
41400
+ import { homedir as homedir13, tmpdir as tmpdir9, platform as platform3 } from "node:os";
41401
+ import { execSync as execSync28, spawn as nodeSpawn } from "node:child_process";
41100
41402
  import { createRequire } from "node:module";
41101
41403
  function sanitizeForTTS(text) {
41102
41404
  return text.replace(/^#{1,6}\s+/gm, "").replace(/\*{1,3}([^*]+)\*{1,3}/g, "$1").replace(/_{1,3}([^_]+)_{1,3}/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/^[\s]*[-*+]\s+/gm, "").replace(/^[\s]*\d+\.\s+/gm, "").replace(/^>\s+/gm, "").replace(/^[-*_]{3,}$/gm, "").replace(/\[[ xX]\]\s*/g, "").replace(/[\u{1F600}-\u{1F64F}]/gu, "").replace(/[\u{1F300}-\u{1F5FF}]/gu, "").replace(/[\u{1F680}-\u{1F6FF}]/gu, "").replace(/[\u{1F1E0}-\u{1F1FF}]/gu, "").replace(/[\u{2600}-\u{26FF}]/gu, "").replace(/[\u{2700}-\u{27BF}]/gu, "").replace(/[\u{FE00}-\u{FE0F}]/gu, "").replace(/[\u{1F900}-\u{1F9FF}]/gu, "").replace(/[\u{1FA00}-\u{1FA6F}]/gu, "").replace(/[\u{1FA70}-\u{1FAFF}]/gu, "").replace(/[\u{200D}]/gu, "").replace(/[\u{20E3}]/gu, "").replace(/[✓✔✗✘✕✖⚠️⏸⏹⏵●○◆◇■□▪▫►▼▲◀⬆⬇⬅➡↑↓←→⇐⇒⇑⇓]/g, "").replace(/[─━│┃┌┐└┘├┤┬┴┼╔╗╚╝╠╣╦╩╬⎿⎾▕▏⏐░▒▓█⠀-⣿]/g, "").replace(/\s{2,}/g, " ").trim();
@@ -41137,7 +41439,7 @@ function luxttsVenvDir() {
41137
41439
  return join54(voiceDir(), "luxtts-venv");
41138
41440
  }
41139
41441
  function luxttsVenvPy() {
41140
- return platform2() === "win32" ? join54(luxttsVenvDir(), "Scripts", "python.exe") : join54(luxttsVenvDir(), "bin", "python3");
41442
+ return platform3() === "win32" ? join54(luxttsVenvDir(), "Scripts", "python.exe") : join54(luxttsVenvDir(), "bin", "python3");
41141
41443
  }
41142
41444
  function luxttsRepoDir() {
41143
41445
  return join54(voiceDir(), "LuxTTS");
@@ -42825,7 +43127,7 @@ var init_voice = __esm({
42825
43127
  });
42826
43128
  }
42827
43129
  getPlayCommand(path) {
42828
- const os = platform2();
43130
+ const os = platform3();
42829
43131
  if (os === "darwin")
42830
43132
  return ["afplay", path];
42831
43133
  if (os === "win32") {
@@ -42837,7 +43139,7 @@ var init_voice = __esm({
42837
43139
  }
42838
43140
  for (const player of ["paplay", "pw-play", "aplay"]) {
42839
43141
  try {
42840
- execSync26(`which ${player}`, { stdio: "pipe" });
43142
+ execSync28(`which ${player}`, { stdio: "pipe" });
42841
43143
  return [player, path];
42842
43144
  } catch {
42843
43145
  }
@@ -42858,7 +43160,7 @@ var init_voice = __esm({
42858
43160
  // -------------------------------------------------------------------------
42859
43161
  /** Check if we're on macOS Apple Silicon */
42860
43162
  isMlxCapable() {
42861
- return platform2() === "darwin" && process.arch === "arm64";
43163
+ return platform3() === "darwin" && process.arch === "arm64";
42862
43164
  }
42863
43165
  /** Resolve python3 binary path (cached after first call) */
42864
43166
  findPython3() {
@@ -42866,7 +43168,7 @@ var init_voice = __esm({
42866
43168
  return this.python3Path;
42867
43169
  for (const bin of ["python3", "python"]) {
42868
43170
  try {
42869
- const path = execSync26(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
43171
+ const path = execSync28(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
42870
43172
  if (path) {
42871
43173
  this.python3Path = path;
42872
43174
  return path;
@@ -42932,7 +43234,7 @@ var init_voice = __esm({
42932
43234
  return false;
42933
43235
  }
42934
43236
  try {
42935
- execSync26(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
43237
+ execSync28(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
42936
43238
  this.mlxInstalled = true;
42937
43239
  return true;
42938
43240
  } catch {
@@ -42993,11 +43295,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
42993
43295
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
42994
43296
  ].join("; ");
42995
43297
  try {
42996
- execSync26(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
43298
+ execSync28(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
42997
43299
  } catch (err) {
42998
43300
  try {
42999
43301
  const safeText = cleaned.replace(/'/g, "'\\''");
43000
- execSync26(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
43302
+ execSync28(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
43001
43303
  } catch (err2) {
43002
43304
  return;
43003
43305
  }
@@ -43061,11 +43363,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
43061
43363
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
43062
43364
  ].join("; ");
43063
43365
  try {
43064
- execSync26(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
43366
+ execSync28(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
43065
43367
  } catch {
43066
43368
  try {
43067
43369
  const safeText = cleaned.replace(/'/g, "'\\''");
43068
- execSync26(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
43370
+ execSync28(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
43069
43371
  } catch {
43070
43372
  return null;
43071
43373
  }
@@ -43159,8 +43461,8 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
43159
43461
  pipArgsStr = "torch torchaudio --index-url https://download.pytorch.org/whl/cu124";
43160
43462
  torchDesc = "CUDA (fallback)";
43161
43463
  } catch {
43162
- const arch = process.arch;
43163
- if (arch === "arm64" || arch === "arm") {
43464
+ const arch2 = process.arch;
43465
+ if (arch2 === "arm64" || arch2 === "arm") {
43164
43466
  pipArgsStr = "torch torchaudio";
43165
43467
  torchDesc = "ARM CPU (generic PyPI)";
43166
43468
  } else {
@@ -43632,7 +43934,7 @@ if __name__ == '__main__':
43632
43934
  async ensureRuntime() {
43633
43935
  if (this.ort)
43634
43936
  return;
43635
- const arch = process.arch;
43937
+ const arch2 = process.arch;
43636
43938
  mkdirSync15(voiceDir(), { recursive: true });
43637
43939
  const pkgPath = join54(voiceDir(), "package.json");
43638
43940
  const expectedDeps = {
@@ -43668,7 +43970,7 @@ if __name__ == '__main__':
43668
43970
  const onnxNodeModules = join54(voiceDir(), "node_modules", "onnxruntime-node");
43669
43971
  const onnxInstalled = existsSync39(onnxNodeModules);
43670
43972
  if (onnxInstalled && !await probeOnnx()) {
43671
- throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
43973
+ throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch2}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
43672
43974
  }
43673
43975
  try {
43674
43976
  this.ort = voiceRequire("onnxruntime-node");
@@ -43677,12 +43979,12 @@ if __name__ == '__main__':
43677
43979
  try {
43678
43980
  await this.asyncShell(`cd "${voiceDir()}" && npm install --no-audit --no-fund`, 12e4);
43679
43981
  } catch (err) {
43680
- const archHint = arch !== "x64" ? ` onnxruntime-node may not have prebuilt binaries for ${process.platform}-${arch}.` : "";
43982
+ const archHint = arch2 !== "x64" ? ` onnxruntime-node may not have prebuilt binaries for ${process.platform}-${arch2}.` : "";
43681
43983
  throw new Error(`Failed to install voice dependencies.${archHint} Try manually: cd ${voiceDir()} && npm install
43682
43984
  Error: ${err instanceof Error ? err.message : String(err)}`);
43683
43985
  }
43684
43986
  if (!await probeOnnx()) {
43685
- throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
43987
+ throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch2}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
43686
43988
  }
43687
43989
  try {
43688
43990
  this.ort = voiceRequire("onnxruntime-node");
@@ -43700,7 +44002,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
43700
44002
  const phonemizerMod = voiceRequire("phonemizer");
43701
44003
  this.phonemizeFn = phonemizerMod.phonemize ?? phonemizerMod.default?.phonemize ?? phonemizerMod;
43702
44004
  } catch (err) {
43703
- const archHint = arch !== "x64" ? ` phonemizer WASM may not support ${process.platform}-${arch}.` : "";
44005
+ const archHint = arch2 !== "x64" ? ` phonemizer WASM may not support ${process.platform}-${arch2}.` : "";
43704
44006
  throw new Error(`Failed to install phonemizer.${archHint} Try manually: cd ${voiceDir()} && npm install
43705
44007
  Error: ${err instanceof Error ? err.message : String(err)}`);
43706
44008
  }
@@ -43803,6 +44105,109 @@ function safeLog(text) {
43803
44105
  process.stdout.write(text + "\n");
43804
44106
  }
43805
44107
  }
44108
+ async function destroyOrphanProcesses(ctx, global) {
44109
+ const myPid = process.pid;
44110
+ const myPpid = process.ppid;
44111
+ const cwd4 = ctx.repoRoot || process.cwd();
44112
+ const patterns = [
44113
+ "open-agents.*--non-interactive",
44114
+ // Stale eval/cron OA instances
44115
+ "nexus-daemon\\.mjs",
44116
+ // Detached nexus daemons
44117
+ "vitest",
44118
+ // Orphaned test runners
44119
+ "esbuild.*--service.*--ping",
44120
+ // Leaked esbuild services
44121
+ "python3 -u -i -q",
44122
+ // Orphaned REPL processes (ReplTool)
44123
+ "chromium.*--headless",
44124
+ // Headless Chrome from browser_action/web_crawl
44125
+ "chrome.*--headless",
44126
+ // Chrome from Puppeteer/Playwright scrapers
44127
+ "crawlee-scraper\\.py",
44128
+ // Python crawlee scraper
44129
+ "web_scrape\\.py",
44130
+ // Python web scraper
44131
+ "start-moondream\\.py",
44132
+ // Moondream vision server
44133
+ "live-whisper\\.py",
44134
+ // Whisper ASR server
44135
+ "jest.*--forceExit"
44136
+ // Orphaned Jest runners
44137
+ ];
44138
+ const patternArg = patterns.join("|");
44139
+ let killed = 0;
44140
+ try {
44141
+ const psOutput = nodeExecSync(`ps -eo pid,ppid,lstart,args --no-headers 2>/dev/null | grep -E "${patternArg}" | grep -v grep`, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
44142
+ if (!psOutput)
44143
+ return 0;
44144
+ const lines = psOutput.split("\n").filter((l) => l.trim());
44145
+ const candidates = [];
44146
+ for (const line of lines) {
44147
+ const parts = line.trim().split(/\s+/);
44148
+ const pid = parseInt(parts[0], 10);
44149
+ const ppid = parseInt(parts[1], 10);
44150
+ if (pid === myPid || pid === myPpid)
44151
+ continue;
44152
+ if (pid <= 10)
44153
+ continue;
44154
+ const cmd = parts.slice(6).join(" ");
44155
+ candidates.push({ pid, ppid, cmd });
44156
+ }
44157
+ if (!global) {
44158
+ const localCandidates = [];
44159
+ for (const c3 of candidates) {
44160
+ try {
44161
+ const procCwd = nodeExecSync(`readlink /proc/${c3.pid}/cwd 2>/dev/null`, { encoding: "utf-8", timeout: 2e3 }).trim();
44162
+ if (procCwd.startsWith(cwd4)) {
44163
+ localCandidates.push(c3);
44164
+ }
44165
+ } catch {
44166
+ if (/open-agents|nexus-daemon/.test(c3.cmd)) {
44167
+ localCandidates.push(c3);
44168
+ }
44169
+ }
44170
+ }
44171
+ candidates.length = 0;
44172
+ candidates.push(...localCandidates);
44173
+ }
44174
+ if (candidates.length === 0)
44175
+ return 0;
44176
+ renderInfo(`Found ${candidates.length} orphaned OA process(es)${global ? " (system-wide)" : ""}:`);
44177
+ for (const c3 of candidates) {
44178
+ const shortCmd = c3.cmd.length > 80 ? c3.cmd.slice(0, 77) + "..." : c3.cmd;
44179
+ process.stdout.write(` PID ${c3.pid}: ${shortCmd}
44180
+ `);
44181
+ }
44182
+ for (const c3 of candidates) {
44183
+ try {
44184
+ try {
44185
+ process.kill(-c3.pid, "SIGTERM");
44186
+ } catch {
44187
+ }
44188
+ process.kill(c3.pid, "SIGTERM");
44189
+ killed++;
44190
+ } catch {
44191
+ try {
44192
+ process.kill(c3.pid, "SIGKILL");
44193
+ killed++;
44194
+ } catch {
44195
+ }
44196
+ }
44197
+ }
44198
+ if (killed > 0) {
44199
+ await new Promise((r) => setTimeout(r, 2e3));
44200
+ for (const c3 of candidates) {
44201
+ try {
44202
+ process.kill(c3.pid, "SIGKILL");
44203
+ } catch {
44204
+ }
44205
+ }
44206
+ }
44207
+ } catch {
44208
+ }
44209
+ return killed;
44210
+ }
43806
44211
  async function handleSlashCommand(input, ctx) {
43807
44212
  const trimmed = input.trim();
43808
44213
  if (!trimmed.startsWith("/"))
@@ -45522,11 +45927,26 @@ async function handleSlashCommand(input, ctx) {
45522
45927
  return "handled";
45523
45928
  }
45524
45929
  case "destroy": {
45525
- if (ctx.hasActiveTask?.()) {
45526
- ctx.abortTask?.();
45930
+ const subCmd = (arg || "").toLowerCase().trim();
45931
+ if (subCmd.startsWith("processes") || subCmd.startsWith("procs")) {
45932
+ const isGlobal = subCmd.includes("--global") || subCmd.includes("-g");
45933
+ const killed = await destroyOrphanProcesses(ctx, isGlobal);
45934
+ if (killed === 0) {
45935
+ renderInfo("No orphaned OA processes found.");
45936
+ } else {
45937
+ renderInfo(`Killed ${killed} orphaned OA process(es).`);
45938
+ }
45939
+ return "handled";
45527
45940
  }
45528
- ctx.destroyProject?.();
45529
- return "exit";
45941
+ if (subCmd === "project" || subCmd === "") {
45942
+ if (ctx.hasActiveTask?.()) {
45943
+ ctx.abortTask?.();
45944
+ }
45945
+ ctx.destroyProject?.();
45946
+ return "exit";
45947
+ }
45948
+ renderWarning(`Unknown /destroy target: "${subCmd}". Use: /destroy processes [--global] or /destroy project`);
45949
+ return "handled";
45530
45950
  }
45531
45951
  case "context": {
45532
45952
  const subCmd = arg?.toLowerCase().split(/\s+/)[0] || "";
@@ -47035,7 +47455,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
47035
47455
  }
47036
47456
  }
47037
47457
  async function handleParallel(arg, ctx) {
47038
- const { execSync: execSync31 } = await import("node:child_process");
47458
+ const { execSync: execSync33 } = await import("node:child_process");
47039
47459
  const baseUrl = ctx.config.backendUrl || "http://localhost:11434";
47040
47460
  const isRemote = ctx.config.backendType === "nexus";
47041
47461
  if (isRemote) {
@@ -47059,7 +47479,7 @@ async function handleParallel(arg, ctx) {
47059
47479
  }
47060
47480
  let systemdVal = "";
47061
47481
  try {
47062
- const out = execSync31("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
47482
+ const out = execSync33("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
47063
47483
  const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
47064
47484
  if (match)
47065
47485
  systemdVal = match[1];
@@ -47088,7 +47508,7 @@ async function handleParallel(arg, ctx) {
47088
47508
  }
47089
47509
  const isSystemd = (() => {
47090
47510
  try {
47091
- const out = execSync31("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
47511
+ const out = execSync33("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
47092
47512
  return out === "active" || out === "inactive";
47093
47513
  } catch {
47094
47514
  return false;
@@ -47102,10 +47522,10 @@ async function handleParallel(arg, ctx) {
47102
47522
  const overrideContent = `[Service]
47103
47523
  Environment="OLLAMA_NUM_PARALLEL=${n}"
47104
47524
  `;
47105
- execSync31(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
47106
- execSync31(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
47107
- execSync31("sudo systemctl daemon-reload", { stdio: "pipe" });
47108
- execSync31("sudo systemctl restart ollama.service", { stdio: "pipe" });
47525
+ execSync33(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
47526
+ execSync33(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
47527
+ execSync33("sudo systemctl daemon-reload", { stdio: "pipe" });
47528
+ execSync33("sudo systemctl restart ollama.service", { stdio: "pipe" });
47109
47529
  let ready = false;
47110
47530
  for (let i = 0; i < 30 && !ready; i++) {
47111
47531
  await new Promise((r) => setTimeout(r, 500));
@@ -47132,7 +47552,7 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
47132
47552
  renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n}...`);
47133
47553
  try {
47134
47554
  try {
47135
- execSync31("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
47555
+ execSync33("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
47136
47556
  } catch {
47137
47557
  }
47138
47558
  await new Promise((r) => setTimeout(r, 1e3));
@@ -47681,15 +48101,15 @@ function fmtUptime(ms) {
47681
48101
  return `${Math.floor(sec / 3600)}h ${Math.floor(sec % 3600 / 60)}m`;
47682
48102
  }
47683
48103
  function getLocalSystemMetrics() {
47684
- const cpus4 = nodeOs.cpus();
48104
+ const cpus5 = nodeOs.cpus();
47685
48105
  const loads = nodeOs.loadavg();
47686
48106
  const totalMem = nodeOs.totalmem();
47687
48107
  const freeMem = nodeOs.freemem();
47688
48108
  const usedMem = totalMem - freeMem;
47689
48109
  const result = {
47690
- cpuModel: cpus4[0]?.model?.trim() ?? "unknown",
47691
- cpuCores: cpus4.length,
47692
- cpuUtil: Math.min(100, Math.round(loads[0] / cpus4.length * 100)),
48110
+ cpuModel: cpus5[0]?.model?.trim() ?? "unknown",
48111
+ cpuCores: cpus5.length,
48112
+ cpuUtil: Math.min(100, Math.round(loads[0] / cpus5.length * 100)),
47693
48113
  memTotalGB: Math.round(totalMem / (1024 * 1024 * 1024) * 10) / 10,
47694
48114
  memUsedGB: Math.round(usedMem / (1024 * 1024 * 1024) * 10) / 10,
47695
48115
  memUtil: Math.round(usedMem / totalMem * 100),
@@ -47783,12 +48203,12 @@ async function showExposeDashboard(gateway, rl, ctx) {
47783
48203
  const now = Date.now();
47784
48204
  const w = cols();
47785
48205
  const h = rows();
47786
- const uptime = s ? fmtUptime(now - (s.startedAt || now)) : "0s";
48206
+ const uptime2 = s ? fmtUptime(now - (s.startedAt || now)) : "0s";
47787
48207
  const lines = [];
47788
48208
  const statusDot = !s ? c2.dim("\u25CF") : s.status === "active" ? c2.green("\u25CF") : s.status === "error" ? c2.red("\u25CF") : c2.yellow("\u25CF");
47789
48209
  const statusLabel = s?.status || "unknown";
47790
48210
  lines.push("");
47791
- lines.push(` ${c2.bold("Expose Dashboard")} ${statusDot} ${statusLabel} ${c2.dim("uptime")} ${uptime} ${c2.dim((/* @__PURE__ */ new Date()).toLocaleTimeString())}`);
48211
+ lines.push(` ${c2.bold("Expose Dashboard")} ${statusDot} ${statusLabel} ${c2.dim("uptime")} ${uptime2} ${c2.dim((/* @__PURE__ */ new Date()).toLocaleTimeString())}`);
47792
48212
  const isTunnel = !!gateway.tunnelUrl;
47793
48213
  const isP2P = !!gateway.peerId;
47794
48214
  const endpointId = isTunnel ? gateway.tunnelUrl : isP2P ? gateway.peerId : null;
@@ -47934,18 +48354,18 @@ async function showExposeDashboard(gateway, rl, ctx) {
47934
48354
  const cmd = `/endpoint ${id} --auth ${gateway.authKey ?? ""}`;
47935
48355
  let copied = false;
47936
48356
  try {
47937
- const { execSync: execSync31 } = __require("node:child_process");
47938
- const platform5 = process.platform;
47939
- if (platform5 === "darwin") {
47940
- execSync31("pbcopy", { input: cmd, timeout: 3e3 });
48357
+ const { execSync: execSync33 } = __require("node:child_process");
48358
+ const platform6 = process.platform;
48359
+ if (platform6 === "darwin") {
48360
+ execSync33("pbcopy", { input: cmd, timeout: 3e3 });
47941
48361
  copied = true;
47942
- } else if (platform5 === "win32") {
47943
- execSync31("clip", { input: cmd, timeout: 3e3 });
48362
+ } else if (platform6 === "win32") {
48363
+ execSync33("clip", { input: cmd, timeout: 3e3 });
47944
48364
  copied = true;
47945
48365
  } else {
47946
48366
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
47947
48367
  try {
47948
- execSync31(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
48368
+ execSync33(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
47949
48369
  copied = true;
47950
48370
  break;
47951
48371
  } catch {
@@ -48034,8 +48454,8 @@ var init_commands = __esm({
48034
48454
  // packages/cli/dist/tui/project-context.js
48035
48455
  import { existsSync as existsSync41, readFileSync as readFileSync30, readdirSync as readdirSync12 } from "node:fs";
48036
48456
  import { join as join56, basename as basename11 } from "node:path";
48037
- import { execSync as execSync27 } from "node:child_process";
48038
- import { homedir as homedir15, platform as platform3, release } from "node:os";
48457
+ import { execSync as execSync29 } from "node:child_process";
48458
+ import { homedir as homedir15, platform as platform4, release } from "node:os";
48039
48459
  function getModelTier(modelName) {
48040
48460
  const m = modelName.toLowerCase();
48041
48461
  const sizeMatch = m.match(/\b(\d+)b\b/);
@@ -48080,19 +48500,19 @@ function loadProjectMap(repoRoot) {
48080
48500
  }
48081
48501
  function getGitInfo(repoRoot) {
48082
48502
  try {
48083
- execSync27("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
48503
+ execSync29("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
48084
48504
  } catch {
48085
48505
  return "";
48086
48506
  }
48087
48507
  const lines = [];
48088
48508
  try {
48089
- const branch = execSync27("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
48509
+ const branch = execSync29("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
48090
48510
  if (branch)
48091
48511
  lines.push(`Branch: ${branch}`);
48092
48512
  } catch {
48093
48513
  }
48094
48514
  try {
48095
- const status = execSync27("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
48515
+ const status = execSync29("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
48096
48516
  if (status) {
48097
48517
  const changed = status.split("\n").length;
48098
48518
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -48102,7 +48522,7 @@ function getGitInfo(repoRoot) {
48102
48522
  } catch {
48103
48523
  }
48104
48524
  try {
48105
- const log = execSync27("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
48525
+ const log = execSync29("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
48106
48526
  if (log)
48107
48527
  lines.push(`Recent commits:
48108
48528
  ${log}`);
@@ -48177,7 +48597,7 @@ function getEnvironment(repoRoot) {
48177
48597
  const lines = [
48178
48598
  `Working directory: ${repoRoot}`,
48179
48599
  `Date: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`,
48180
- `Platform: ${platform3()} ${release()}`,
48600
+ `Platform: ${platform4()} ${release()}`,
48181
48601
  `Node: ${process.version}`
48182
48602
  ];
48183
48603
  return lines.join("\n");
@@ -49260,8 +49680,8 @@ function generateMnemonic(seed) {
49260
49680
  }
49261
49681
  function getNodeMnemonic() {
49262
49682
  try {
49263
- const { hostname: hostname2, userInfo: userInfo2 } = __require("node:os");
49264
- return generateMnemonic(`${hostname2()}:${userInfo2().username}`);
49683
+ const { hostname: hostname3, userInfo: userInfo2 } = __require("node:os");
49684
+ return generateMnemonic(`${hostname3()}:${userInfo2().username}`);
49265
49685
  } catch {
49266
49686
  return generateMnemonic("unknown-node");
49267
49687
  }
@@ -50654,7 +51074,7 @@ var init_promptLoader3 = __esm({
50654
51074
  // packages/cli/dist/tui/dream-engine.js
50655
51075
  import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync19, readFileSync as readFileSync33, existsSync as existsSync44, cpSync, rmSync as rmSync2, readdirSync as readdirSync14 } from "node:fs";
50656
51076
  import { join as join60, basename as basename13 } from "node:path";
50657
- import { execSync as execSync28 } from "node:child_process";
51077
+ import { execSync as execSync30 } from "node:child_process";
50658
51078
  function loadAutoresearchMemory(repoRoot) {
50659
51079
  const memoryPath = join60(repoRoot, ".oa", "memory", "autoresearch.json");
50660
51080
  if (!existsSync44(memoryPath))
@@ -51018,7 +51438,7 @@ var init_dream_engine = __esm({
51018
51438
  }
51019
51439
  }
51020
51440
  try {
51021
- const output = execSync28(cmd, {
51441
+ const output = execSync30(cmd, {
51022
51442
  cwd: this.repoRoot,
51023
51443
  timeout: 3e4,
51024
51444
  encoding: "utf-8",
@@ -51795,17 +52215,17 @@ ${summaryResult}
51795
52215
  try {
51796
52216
  mkdirSync19(checkpointDir, { recursive: true });
51797
52217
  try {
51798
- const gitStatus = execSync28("git status --porcelain", {
52218
+ const gitStatus = execSync30("git status --porcelain", {
51799
52219
  cwd: this.repoRoot,
51800
52220
  encoding: "utf-8",
51801
52221
  timeout: 1e4
51802
52222
  });
51803
- const gitDiff = execSync28("git diff", {
52223
+ const gitDiff = execSync30("git diff", {
51804
52224
  cwd: this.repoRoot,
51805
52225
  encoding: "utf-8",
51806
52226
  timeout: 1e4
51807
52227
  });
51808
- const gitHash = execSync28("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
52228
+ const gitHash = execSync30("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
51809
52229
  cwd: this.repoRoot,
51810
52230
  encoding: "utf-8",
51811
52231
  timeout: 5e3
@@ -55319,7 +55739,7 @@ var init_braille_spinner = __esm({
55319
55739
  });
55320
55740
 
55321
55741
  // packages/cli/dist/tui/system-metrics.js
55322
- import { loadavg as loadavg3, cpus as cpus3, totalmem as totalmem4, freemem as freemem3, platform as platform4 } from "node:os";
55742
+ import { loadavg as loadavg3, cpus as cpus4, totalmem as totalmem5, freemem as freemem4, platform as platform5 } from "node:os";
55323
55743
  import { exec as exec3 } from "node:child_process";
55324
55744
  import { readFile as readFile22 } from "node:fs/promises";
55325
55745
  function formatRate(bytesPerSec) {
@@ -55353,7 +55773,7 @@ async function readProcNetDev() {
55353
55773
  }
55354
55774
  async function collectNetworkMetrics() {
55355
55775
  const now = Date.now();
55356
- const plat = platform4();
55776
+ const plat = platform5();
55357
55777
  if (plat === "linux") {
55358
55778
  const snap = await readProcNetDev();
55359
55779
  if (!snap)
@@ -55451,10 +55871,10 @@ function getInstantSnapshot() {
55451
55871
  }
55452
55872
  function collectCpuRam() {
55453
55873
  const [l1] = loadavg3();
55454
- const cores = cpus3().length;
55455
- const cpuModel = cpus3()[0]?.model ?? "";
55456
- const totalMem = totalmem4();
55457
- const usedMem = totalMem - freemem3();
55874
+ const cores = cpus4().length;
55875
+ const cpuModel = cpus4()[0]?.model ?? "";
55876
+ const totalMem = totalmem5();
55877
+ const usedMem = totalMem - freemem4();
55458
55878
  return {
55459
55879
  cpuUtil: Math.min(100, Math.round(l1 / cores * 100)),
55460
55880
  cpuCores: cores,
@@ -55615,7 +56035,7 @@ __export(text_selection_exports, {
55615
56035
  stripAnsi: () => stripAnsi3,
55616
56036
  visibleLength: () => visibleLength
55617
56037
  });
55618
- import { execSync as execSync29 } from "node:child_process";
56038
+ import { execSync as execSync31 } from "node:child_process";
55619
56039
  function stripAnsi3(s) {
55620
56040
  return s.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\)/g, "");
55621
56041
  }
@@ -55624,18 +56044,18 @@ function visibleLength(s) {
55624
56044
  }
55625
56045
  function copyText(text) {
55626
56046
  try {
55627
- const platform5 = process.platform;
55628
- if (platform5 === "darwin") {
55629
- execSync29("pbcopy", { input: text, timeout: 3e3 });
56047
+ const platform6 = process.platform;
56048
+ if (platform6 === "darwin") {
56049
+ execSync31("pbcopy", { input: text, timeout: 3e3 });
55630
56050
  return true;
55631
56051
  }
55632
- if (platform5 === "win32") {
55633
- execSync29("clip", { input: text, timeout: 3e3 });
56052
+ if (platform6 === "win32") {
56053
+ execSync31("clip", { input: text, timeout: 3e3 });
55634
56054
  return true;
55635
56055
  }
55636
56056
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
55637
56057
  try {
55638
- execSync29(tool, { input: text, timeout: 3e3 });
56058
+ execSync31(tool, { input: text, timeout: 3e3 });
55639
56059
  return true;
55640
56060
  } catch {
55641
56061
  continue;
@@ -55644,10 +56064,10 @@ function copyText(text) {
55644
56064
  if (!_clipboardAutoInstallAttempted) {
55645
56065
  _clipboardAutoInstallAttempted = true;
55646
56066
  try {
55647
- execSync29("which apt-get", { timeout: 2e3, stdio: "pipe" });
56067
+ execSync31("which apt-get", { timeout: 2e3, stdio: "pipe" });
55648
56068
  try {
55649
- execSync29("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
55650
- execSync29("xclip -selection clipboard", { input: text, timeout: 3e3 });
56069
+ execSync31("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
56070
+ execSync31("xclip -selection clipboard", { input: text, timeout: 3e3 });
55651
56071
  return true;
55652
56072
  } catch {
55653
56073
  }
@@ -58088,7 +58508,7 @@ import { createRequire as createRequire2 } from "node:module";
58088
58508
  import { fileURLToPath as fileURLToPath12 } from "node:url";
58089
58509
  import { readFileSync as readFileSync37, writeFileSync as writeFileSync21, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync18, mkdirSync as mkdirSync22 } from "node:fs";
58090
58510
  import { existsSync as existsSync48 } from "node:fs";
58091
- import { execSync as execSync30 } from "node:child_process";
58511
+ import { execSync as execSync32 } from "node:child_process";
58092
58512
  import { homedir as homedir16 } from "node:os";
58093
58513
  function formatTimeAgo(date) {
58094
58514
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -58245,6 +58665,7 @@ function buildTools(repoRoot, config, contextWindowSize) {
58245
58665
  new WorkingNotesTool(),
58246
58666
  new SemanticMapTool(repoRoot),
58247
58667
  new RepoMapTool(repoRoot),
58668
+ new ProcessHealthTool(),
58248
58669
  // Nexus P2P networking + x402 micropayments
58249
58670
  new NexusTool(repoRoot)
58250
58671
  ];
@@ -58469,6 +58890,11 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
58469
58890
  const modelTier = getModelTier(config.model);
58470
58891
  const projectCtx = buildProjectContext(repoRoot, taskStores?.contextStores);
58471
58892
  let dynamicContext = formatContextForPrompt(projectCtx, modelTier);
58893
+ try {
58894
+ const snap = collectSnapshot(repoRoot);
58895
+ dynamicContext += "\n\n" + formatSnapshotForContext(snap);
58896
+ } catch {
58897
+ }
58472
58898
  try {
58473
58899
  const { MemoryMetabolismTool: MemoryMetabolismTool2 } = __require("@open-agents/execution");
58474
58900
  const mm = new MemoryMetabolismTool2(repoRoot);
@@ -61360,7 +61786,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
61360
61786
  try {
61361
61787
  if (process.platform === "win32") {
61362
61788
  try {
61363
- execSync30(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
61789
+ execSync32(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
61364
61790
  } catch {
61365
61791
  }
61366
61792
  } else {
@@ -61387,7 +61813,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
61387
61813
  if (pid > 0) {
61388
61814
  if (process.platform === "win32") {
61389
61815
  try {
61390
- execSync30(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
61816
+ execSync32(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
61391
61817
  } catch {
61392
61818
  }
61393
61819
  } else {
@@ -61404,7 +61830,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
61404
61830
  } catch {
61405
61831
  }
61406
61832
  try {
61407
- execSync30(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
61833
+ execSync32(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
61408
61834
  } catch {
61409
61835
  }
61410
61836
  const oaPath = join64(repoRoot, OA_DIR);
@@ -61418,14 +61844,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
61418
61844
  } catch (err) {
61419
61845
  if (attempt < 2) {
61420
61846
  try {
61421
- execSync30(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
61847
+ execSync32(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
61422
61848
  } catch {
61423
61849
  }
61424
61850
  } else {
61425
61851
  writeContent(() => renderWarning(`Could not fully remove ${OA_DIR}/: ${err instanceof Error ? err.message : String(err)}`));
61426
61852
  if (process.platform === "win32") {
61427
61853
  try {
61428
- execSync30(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
61854
+ execSync32(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
61429
61855
  deleted = true;
61430
61856
  } catch {
61431
61857
  }