open-agents-ai 0.185.49 → 0.185.50

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 +389 -366
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1289,12 +1289,69 @@ var init_tool_executor = __esm({
1289
1289
  }
1290
1290
  });
1291
1291
 
1292
+ // packages/execution/dist/process-kill.js
1293
+ import { execSync } from "node:child_process";
1294
+ function killProcessTree(pid, signal = "SIGKILL") {
1295
+ if (!pid || pid <= 0)
1296
+ return;
1297
+ if (IS_WINDOWS) {
1298
+ const forceFlag = signal === "SIGKILL" ? " /F" : "";
1299
+ try {
1300
+ execSync(`taskkill /PID ${pid} /T${forceFlag}`, { stdio: "pipe", timeout: 5e3 });
1301
+ } catch {
1302
+ }
1303
+ } else {
1304
+ try {
1305
+ process.kill(-pid, signal);
1306
+ } catch {
1307
+ }
1308
+ try {
1309
+ process.kill(pid, signal);
1310
+ } catch {
1311
+ }
1312
+ }
1313
+ }
1314
+ function killProcess(pid, signal = "SIGKILL") {
1315
+ if (!pid || pid <= 0)
1316
+ return;
1317
+ if (IS_WINDOWS) {
1318
+ const forceFlag = signal === "SIGKILL" ? " /F" : "";
1319
+ try {
1320
+ execSync(`taskkill /PID ${pid}${forceFlag}`, { stdio: "pipe", timeout: 5e3 });
1321
+ } catch {
1322
+ }
1323
+ } else {
1324
+ try {
1325
+ process.kill(pid, signal);
1326
+ } catch {
1327
+ }
1328
+ }
1329
+ }
1330
+ function isProcessAlive(pid) {
1331
+ if (!pid || pid <= 0)
1332
+ return false;
1333
+ try {
1334
+ process.kill(pid, 0);
1335
+ return true;
1336
+ } catch {
1337
+ return false;
1338
+ }
1339
+ }
1340
+ var IS_WINDOWS;
1341
+ var init_process_kill = __esm({
1342
+ "packages/execution/dist/process-kill.js"() {
1343
+ "use strict";
1344
+ IS_WINDOWS = process.platform === "win32";
1345
+ }
1346
+ });
1347
+
1292
1348
  // packages/execution/dist/tools/shell.js
1293
1349
  import { spawn } from "node:child_process";
1294
1350
  var PERMISSION_ERROR_RE, ShellTool;
1295
1351
  var init_shell = __esm({
1296
1352
  "packages/execution/dist/tools/shell.js"() {
1297
1353
  "use strict";
1354
+ init_process_kill();
1298
1355
  PERMISSION_ERROR_RE = /Permission denied|Operation not permitted|EACCES|EPERM|PermissionError|sudo:|not permitted|password is required|authentication failure/i;
1299
1356
  ShellTool = class {
1300
1357
  name = "shell";
@@ -1329,10 +1386,8 @@ var init_shell = __esm({
1329
1386
  /** Kill all active child processes and their entire process groups (called by /stop) */
1330
1387
  killAll() {
1331
1388
  for (const child of this._activeChildren) {
1332
- try {
1333
- process.kill(-child.pid, "SIGKILL");
1334
- } catch {
1335
- }
1389
+ if (child.pid)
1390
+ killProcessTree(child.pid, "SIGKILL");
1336
1391
  try {
1337
1392
  child.kill("SIGKILL");
1338
1393
  } catch {
@@ -1420,23 +1475,11 @@ ${stdinInput ?? ""}`);
1420
1475
  };
1421
1476
  const timer = setTimeout(() => {
1422
1477
  killed = true;
1423
- try {
1424
- process.kill(-child.pid, "SIGTERM");
1425
- } catch {
1426
- try {
1427
- child.kill("SIGTERM");
1428
- } catch {
1429
- }
1430
- }
1478
+ if (child.pid)
1479
+ killProcessTree(child.pid, "SIGTERM");
1431
1480
  setTimeout(() => {
1432
- try {
1433
- process.kill(-child.pid, "SIGKILL");
1434
- } catch {
1435
- try {
1436
- child.kill("SIGKILL");
1437
- } catch {
1438
- }
1439
- }
1481
+ if (child.pid)
1482
+ killProcessTree(child.pid, "SIGKILL");
1440
1483
  }, 5e3);
1441
1484
  }, timeout);
1442
1485
  let exitFlushTimer = null;
@@ -4019,7 +4062,7 @@ var init_list_directory = __esm({
4019
4062
  });
4020
4063
 
4021
4064
  // packages/execution/dist/tools/aiwg-setup.js
4022
- import { execSync } from "node:child_process";
4065
+ import { execSync as execSync2 } from "node:child_process";
4023
4066
  var AiwgSetupTool;
4024
4067
  var init_aiwg_setup = __esm({
4025
4068
  "packages/execution/dist/tools/aiwg-setup.js"() {
@@ -4058,7 +4101,7 @@ var init_aiwg_setup = __esm({
4058
4101
  };
4059
4102
  }
4060
4103
  try {
4061
- const output = execSync(`aiwg use ${framework}`, {
4104
+ const output = execSync2(`aiwg use ${framework}`, {
4062
4105
  cwd: projectDir,
4063
4106
  encoding: "utf8",
4064
4107
  timeout: 6e4,
@@ -4082,7 +4125,7 @@ ${output}`,
4082
4125
  }
4083
4126
  isAiwgInstalled() {
4084
4127
  try {
4085
- execSync("aiwg --version", {
4128
+ execSync2("aiwg --version", {
4086
4129
  encoding: "utf8",
4087
4130
  timeout: 5e3,
4088
4131
  stdio: ["pipe", "pipe", "pipe"]
@@ -4097,7 +4140,7 @@ ${output}`,
4097
4140
  });
4098
4141
 
4099
4142
  // packages/execution/dist/tools/aiwg-health.js
4100
- import { execSync as execSync2 } from "node:child_process";
4143
+ import { execSync as execSync3 } from "node:child_process";
4101
4144
  import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync5, statSync as statSync2 } from "node:fs";
4102
4145
  import { join as join10 } from "node:path";
4103
4146
  var AiwgHealthTool;
@@ -4177,7 +4220,7 @@ var init_aiwg_health = __esm({
4177
4220
  }
4178
4221
  if (this.isAiwgInstalled()) {
4179
4222
  try {
4180
- const runtimeInfo = execSync2("aiwg runtime-info 2>/dev/null", {
4223
+ const runtimeInfo = execSync3("aiwg runtime-info 2>/dev/null", {
4181
4224
  cwd: projectDir,
4182
4225
  encoding: "utf8",
4183
4226
  timeout: 15e3
@@ -4298,7 +4341,7 @@ var init_aiwg_health = __esm({
4298
4341
  }
4299
4342
  isAiwgInstalled() {
4300
4343
  try {
4301
- execSync2("aiwg --version", { encoding: "utf8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] });
4344
+ execSync3("aiwg --version", { encoding: "utf8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] });
4302
4345
  return true;
4303
4346
  } catch {
4304
4347
  return false;
@@ -4309,7 +4352,7 @@ var init_aiwg_health = __esm({
4309
4352
  });
4310
4353
 
4311
4354
  // packages/execution/dist/tools/aiwg-workflow.js
4312
- import { execSync as execSync3 } from "node:child_process";
4355
+ import { execSync as execSync4 } from "node:child_process";
4313
4356
  var AiwgWorkflowTool;
4314
4357
  var init_aiwg_workflow = __esm({
4315
4358
  "packages/execution/dist/tools/aiwg-workflow.js"() {
@@ -4357,7 +4400,7 @@ var init_aiwg_workflow = __esm({
4357
4400
  }
4358
4401
  const sanitized = command.replace(/[;&|`$()]/g, "");
4359
4402
  try {
4360
- const output = execSync3(`aiwg ${sanitized}`, {
4403
+ const output = execSync4(`aiwg ${sanitized}`, {
4361
4404
  cwd: projectDir,
4362
4405
  encoding: "utf8",
4363
4406
  timeout: 12e4,
@@ -4383,7 +4426,7 @@ var init_aiwg_workflow = __esm({
4383
4426
  }
4384
4427
  isAiwgInstalled() {
4385
4428
  try {
4386
- execSync3("aiwg --version", { encoding: "utf8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] });
4429
+ execSync4("aiwg --version", { encoding: "utf8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] });
4387
4430
  return true;
4388
4431
  } catch {
4389
4432
  return false;
@@ -4994,7 +5037,7 @@ var init_codebase_map = __esm({
4994
5037
  });
4995
5038
 
4996
5039
  // packages/execution/dist/tools/diagnostic.js
4997
- import { execSync as execSync4 } from "node:child_process";
5040
+ import { execSync as execSync5 } from "node:child_process";
4998
5041
  import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
4999
5042
  import { join as join12 } from "node:path";
5000
5043
  var DiagnosticTool;
@@ -5109,7 +5152,7 @@ var init_diagnostic = __esm({
5109
5152
  runStep(step, command, cwd4) {
5110
5153
  const start = performance.now();
5111
5154
  try {
5112
- const output = execSync4(command, {
5155
+ const output = execSync5(command, {
5113
5156
  cwd: cwd4,
5114
5157
  encoding: "utf8",
5115
5158
  timeout: 12e4,
@@ -5139,7 +5182,7 @@ ${err.stderr ?? ""}`.trim(),
5139
5182
  });
5140
5183
 
5141
5184
  // packages/execution/dist/tools/git-info.js
5142
- import { execSync as execSync5 } from "node:child_process";
5185
+ import { execSync as execSync6 } from "node:child_process";
5143
5186
  import { existsSync as existsSync10 } from "node:fs";
5144
5187
  import { join as join13 } from "node:path";
5145
5188
  var GitInfoTool;
@@ -5255,7 +5298,7 @@ var init_git_info = __esm({
5255
5298
  }
5256
5299
  git(cwd4, cmd) {
5257
5300
  try {
5258
- return execSync5(`git ${cmd}`, {
5301
+ return execSync6(`git ${cmd}`, {
5259
5302
  cwd: cwd4,
5260
5303
  encoding: "utf8",
5261
5304
  timeout: 1e4,
@@ -5278,7 +5321,7 @@ import { readFile as readFile8, writeFile as writeFile6, mkdir as mkdir3, chmod,
5278
5321
  import { existsSync as existsSync11, readFileSync as readFileSync8, watch as fsWatchLocal } from "node:fs";
5279
5322
  import { resolve as resolve13, join as join14 } from "node:path";
5280
5323
  import { randomBytes as randomBytes4, createCipheriv, createDecipheriv, scryptSync, createHash } from "node:crypto";
5281
- import { execSync as execSync6, spawn as spawn2 } from "node:child_process";
5324
+ import { execSync as execSync7, spawn as spawn2 } from "node:child_process";
5282
5325
  import { hostname, userInfo, homedir as homedir4 } from "node:os";
5283
5326
  function containsKeyMaterial(input) {
5284
5327
  for (const pattern of KEY_PATTERNS) {
@@ -9618,7 +9661,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
9618
9661
  }
9619
9662
  async doInferenceProof() {
9620
9663
  try {
9621
- const psRaw = execSync6("ollama ps 2>/dev/null", { timeout: 1e4, encoding: "utf8" });
9664
+ const psRaw = execSync7("ollama ps 2>/dev/null", { timeout: 1e4, encoding: "utf8" });
9622
9665
  const lines = psRaw.trim().split("\n").filter((l) => l.trim());
9623
9666
  if (lines.length < 2)
9624
9667
  return "No model loaded. Run 'ollama ps' to check.";
@@ -9626,7 +9669,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
9626
9669
  const modelName = parts[0] || "unknown";
9627
9670
  let gpuName = "none", vramMb = 0;
9628
9671
  try {
9629
- const smi = execSync6("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null", {
9672
+ const smi = execSync7("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null", {
9630
9673
  timeout: 5e3,
9631
9674
  encoding: "utf8"
9632
9675
  });
@@ -9635,7 +9678,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
9635
9678
  vramMb = parseInt(gp[1]?.trim() || "0", 10);
9636
9679
  } catch {
9637
9680
  try {
9638
- execSync6("rocm-smi 2>/dev/null", { timeout: 5e3 });
9681
+ execSync7("rocm-smi 2>/dev/null", { timeout: 5e3 });
9639
9682
  gpuName = "AMD GPU";
9640
9683
  } catch {
9641
9684
  }
@@ -10071,7 +10114,7 @@ Exit code: ${task.exitCode ?? "N/A"}`,
10071
10114
  });
10072
10115
 
10073
10116
  // packages/execution/dist/system-deps.js
10074
- import { execSync as execSync7 } from "node:child_process";
10117
+ import { execSync as execSync8 } from "node:child_process";
10075
10118
  function detectPackageManager() {
10076
10119
  if (_detectedPkgManager !== void 0)
10077
10120
  return _detectedPkgManager;
@@ -10104,7 +10147,7 @@ function detectPackageManager() {
10104
10147
  function hasCommand(cmd) {
10105
10148
  try {
10106
10149
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
10107
- execSync7(whichCmd, { stdio: "pipe", timeout: 3e3 });
10150
+ execSync8(whichCmd, { stdio: "pipe", timeout: 3e3 });
10108
10151
  return true;
10109
10152
  } catch {
10110
10153
  return false;
@@ -10123,7 +10166,7 @@ function runInstall(installCmd) {
10123
10166
  cmd = `sudo -n ${installCmd}`;
10124
10167
  }
10125
10168
  }
10126
- execSync7(cmd, {
10169
+ execSync8(cmd, {
10127
10170
  stdio: "pipe",
10128
10171
  timeout: 12e4,
10129
10172
  // 2 min for package install
@@ -10316,7 +10359,7 @@ var init_system_deps = __esm({
10316
10359
  // packages/execution/dist/tools/image.js
10317
10360
  import { existsSync as existsSync12, readFileSync as readFileSync9, statSync as statSync4 } from "node:fs";
10318
10361
  import { resolve as resolve14, extname as extname2, basename as basename2 } from "node:path";
10319
- import { execSync as execSync8 } from "node:child_process";
10362
+ import { execSync as execSync9 } from "node:child_process";
10320
10363
  import { tmpdir } from "node:os";
10321
10364
  import { join as join15 } from "node:path";
10322
10365
  function isImagePath(path) {
@@ -10343,7 +10386,7 @@ function getMimeType(filePath) {
10343
10386
  }
10344
10387
  function getImageDimensions(filePath) {
10345
10388
  try {
10346
- const out = execSync8(`identify -format "%w %h" ${JSON.stringify(filePath)}`, {
10389
+ const out = execSync9(`identify -format "%w %h" ${JSON.stringify(filePath)}`, {
10347
10390
  encoding: "utf8",
10348
10391
  stdio: ["pipe", "pipe", "pipe"],
10349
10392
  timeout: 5e3
@@ -10355,7 +10398,7 @@ function getImageDimensions(filePath) {
10355
10398
  const dep = ensureCommand("identify");
10356
10399
  if (dep.installed) {
10357
10400
  try {
10358
- const out = execSync8(`identify -format "%w %h" ${JSON.stringify(filePath)}`, {
10401
+ const out = execSync9(`identify -format "%w %h" ${JSON.stringify(filePath)}`, {
10359
10402
  encoding: "utf8",
10360
10403
  stdio: ["pipe", "pipe", "pipe"],
10361
10404
  timeout: 5e3
@@ -10368,7 +10411,7 @@ function getImageDimensions(filePath) {
10368
10411
  }
10369
10412
  }
10370
10413
  try {
10371
- const out = execSync8(`file ${JSON.stringify(filePath)}`, {
10414
+ const out = execSync9(`file ${JSON.stringify(filePath)}`, {
10372
10415
  encoding: "utf8",
10373
10416
  stdio: ["pipe", "pipe", "pipe"],
10374
10417
  timeout: 5e3
@@ -10382,7 +10425,7 @@ function getImageDimensions(filePath) {
10382
10425
  }
10383
10426
  function hasTesseract() {
10384
10427
  try {
10385
- execSync8("tesseract --version", { stdio: "pipe", timeout: 5e3 });
10428
+ execSync9("tesseract --version", { stdio: "pipe", timeout: 5e3 });
10386
10429
  return true;
10387
10430
  } catch {
10388
10431
  const dep = ensureCommand("tesseract");
@@ -10391,7 +10434,7 @@ function hasTesseract() {
10391
10434
  }
10392
10435
  function runOCR(filePath) {
10393
10436
  try {
10394
- return execSync8(`tesseract ${JSON.stringify(filePath)} stdout 2>/dev/null`, {
10437
+ return execSync9(`tesseract ${JSON.stringify(filePath)} stdout 2>/dev/null`, {
10395
10438
  encoding: "utf8",
10396
10439
  stdio: ["pipe", "pipe", "pipe"],
10397
10440
  timeout: 3e4
@@ -10525,7 +10568,7 @@ ${ocrText}`);
10525
10568
  };
10526
10569
  }
10527
10570
  try {
10528
- execSync8(cmd, { stdio: "pipe", timeout: 1e4 });
10571
+ execSync9(cmd, { stdio: "pipe", timeout: 1e4 });
10529
10572
  } catch (err) {
10530
10573
  return {
10531
10574
  success: false,
@@ -10573,7 +10616,7 @@ ${ocrText}`);
10573
10616
  if (plat === "linux") {
10574
10617
  for (const tool of ["scrot", "gnome-screenshot", "import"]) {
10575
10618
  try {
10576
- execSync8(`which ${tool}`, { stdio: "pipe" });
10619
+ execSync9(`which ${tool}`, { stdio: "pipe" });
10577
10620
  if (tool === "scrot") {
10578
10621
  if (region === "active")
10579
10622
  return `scrot -u ${out}`;
@@ -10660,14 +10703,14 @@ ${ocrText}`);
10660
10703
  if (x != null && y != null && w != null && h != null) {
10661
10704
  const croppedPath = join15(tmpdir(), `oa-ocr-crop-${Date.now()}.png`);
10662
10705
  try {
10663
- execSync8(`convert ${JSON.stringify(fullPath)} -crop ${w}x${h}+${x}+${y} +repage ${JSON.stringify(croppedPath)}`, { stdio: "pipe", timeout: 1e4 });
10706
+ execSync9(`convert ${JSON.stringify(fullPath)} -crop ${w}x${h}+${x}+${y} +repage ${JSON.stringify(croppedPath)}`, { stdio: "pipe", timeout: 1e4 });
10664
10707
  inputPath = croppedPath;
10665
10708
  } catch {
10666
10709
  }
10667
10710
  }
10668
10711
  }
10669
10712
  try {
10670
- const text = execSync8(`tesseract ${JSON.stringify(inputPath)} stdout -l ${language} --psm ${psm} 2>/dev/null`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e4 }).trim();
10713
+ const text = execSync9(`tesseract ${JSON.stringify(inputPath)} stdout -l ${language} --psm ${psm} 2>/dev/null`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e4 }).trim();
10671
10714
  if (!text) {
10672
10715
  return { success: true, output: "(no text detected in image)", durationMs: Date.now() - start };
10673
10716
  }
@@ -11202,7 +11245,7 @@ var init_tool_creator = __esm({
11202
11245
  import { existsSync as existsSync14, readdirSync as readdirSync5, readFileSync as readFileSync11 } from "node:fs";
11203
11246
  import { join as join17, basename as basename3, dirname as dirname3 } from "node:path";
11204
11247
  import { homedir as homedir6 } from "node:os";
11205
- import { execSync as execSync9 } from "node:child_process";
11248
+ import { execSync as execSync10 } from "node:child_process";
11206
11249
  function getAiwgPaths() {
11207
11250
  const dataDir = join17(homedir6(), ".local", "share", "ai-writing-guide");
11208
11251
  return {
@@ -11215,7 +11258,7 @@ function findAiwgPackageRoot() {
11215
11258
  if (_cachedAiwgPkgRoot !== void 0)
11216
11259
  return _cachedAiwgPkgRoot;
11217
11260
  try {
11218
- const globalRoot = execSync9("npm root -g", {
11261
+ const globalRoot = execSync10("npm root -g", {
11219
11262
  encoding: "utf-8",
11220
11263
  timeout: 5e3,
11221
11264
  stdio: ["pipe", "pipe", "pipe"]
@@ -11887,7 +11930,7 @@ ${content}`
11887
11930
  import { existsSync as existsSync16, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7, readFileSync as readFileSync13, unlinkSync } from "node:fs";
11888
11931
  import { join as join19, basename as basename4, extname as extname3, resolve as resolve15 } from "node:path";
11889
11932
  import { homedir as homedir7 } from "node:os";
11890
- import { execSync as execSync10, spawn as spawn5 } from "node:child_process";
11933
+ import { execSync as execSync11, spawn as spawn5 } from "node:child_process";
11891
11934
  function isTranscribable(path) {
11892
11935
  const ext = extname3(path).toLowerCase();
11893
11936
  return AUDIO_EXTS.has(ext) || VIDEO_EXTS.has(ext);
@@ -11897,7 +11940,7 @@ async function loadTranscribeCli() {
11897
11940
  return _tcModule;
11898
11941
  _tcChecked = true;
11899
11942
  try {
11900
- const globalRoot = execSync10("npm root -g", {
11943
+ const globalRoot = execSync11("npm root -g", {
11901
11944
  encoding: "utf-8",
11902
11945
  timeout: 5e3,
11903
11946
  stdio: ["pipe", "pipe", "pipe"]
@@ -11934,11 +11977,11 @@ function isYouTubeUrl(url) {
11934
11977
  }
11935
11978
  function ensureYtDlp() {
11936
11979
  try {
11937
- execSync10("yt-dlp --version", { timeout: 5e3, stdio: "pipe" });
11980
+ execSync11("yt-dlp --version", { timeout: 5e3, stdio: "pipe" });
11938
11981
  return true;
11939
11982
  } catch {
11940
11983
  try {
11941
- execSync10("pip3 install --user yt-dlp 2>/dev/null || pip install --user yt-dlp 2>/dev/null", {
11984
+ execSync11("pip3 install --user yt-dlp 2>/dev/null || pip install --user yt-dlp 2>/dev/null", {
11942
11985
  timeout: 6e4,
11943
11986
  stdio: "pipe"
11944
11987
  });
@@ -12127,7 +12170,7 @@ var init_transcribe_tool = __esm({
12127
12170
  const args = [filePath, "-m", model, "-f", "txt"];
12128
12171
  if (diarize)
12129
12172
  args.push("--diarize");
12130
- const output = execSync10(`transcribe-cli ${args.join(" ")}`, {
12173
+ const output = execSync11(`transcribe-cli ${args.join(" ")}`, {
12131
12174
  encoding: "utf-8",
12132
12175
  timeout: 3e5,
12133
12176
  // 5 min max
@@ -12200,7 +12243,7 @@ var init_transcribe_tool = __esm({
12200
12243
  }
12201
12244
  tmpFile = `${tmpBase}.mp3`;
12202
12245
  try {
12203
- execSync10(`yt-dlp -x --audio-format mp3 --audio-quality 5 -o "${tmpBase}.%(ext)s" "${url}" 2>&1`, { timeout: 3e5, stdio: ["pipe", "pipe", "pipe"] });
12246
+ execSync11(`yt-dlp -x --audio-format mp3 --audio-quality 5 -o "${tmpBase}.%(ext)s" "${url}" 2>&1`, { timeout: 3e5, stdio: ["pipe", "pipe", "pipe"] });
12204
12247
  if (!existsSync16(tmpFile)) {
12205
12248
  const { readdirSync: rd } = __require("node:fs");
12206
12249
  const files = rd(tmpDir).filter((f) => f.startsWith(`download-`) && f !== ".gitkeep");
@@ -12225,12 +12268,12 @@ var init_transcribe_tool = __esm({
12225
12268
  }
12226
12269
  tmpFile = `${tmpBase}${ext}`;
12227
12270
  try {
12228
- execSync10(`curl -sL -o "${tmpFile}" "${url}"`, {
12271
+ execSync11(`curl -sL -o "${tmpFile}" "${url}"`, {
12229
12272
  timeout: 12e4,
12230
12273
  stdio: ["pipe", "pipe", "pipe"]
12231
12274
  });
12232
12275
  } catch {
12233
- execSync10(`wget -q -O "${tmpFile}" "${url}"`, {
12276
+ execSync11(`wget -q -O "${tmpFile}" "${url}"`, {
12234
12277
  timeout: 12e4,
12235
12278
  stdio: ["pipe", "pipe", "pipe"]
12236
12279
  });
@@ -12315,13 +12358,13 @@ ${result.output}`,
12315
12358
  try {
12316
12359
  let title = "download";
12317
12360
  try {
12318
- title = execSync10(`yt-dlp --get-title "${url}"`, { timeout: 15e3, stdio: "pipe" }).toString().trim().replace(/[<>:"/\\|?*]/g, "_").slice(0, 100);
12361
+ title = execSync11(`yt-dlp --get-title "${url}"`, { timeout: 15e3, stdio: "pipe" }).toString().trim().replace(/[<>:"/\\|?*]/g, "_").slice(0, 100);
12319
12362
  } catch {
12320
12363
  }
12321
12364
  if (format === "mp4") {
12322
12365
  const outPath = join19(outputDir, `${title}.mp4`);
12323
12366
  const outTemplate = join19(outputDir, `${title}.%(ext)s`);
12324
- execSync10(`yt-dlp -f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" --merge-output-format mp4 -o "${outTemplate}" "${url}"`, { timeout: 6e5, stdio: "pipe", cwd: outputDir });
12367
+ execSync11(`yt-dlp -f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" --merge-output-format mp4 -o "${outTemplate}" "${url}"`, { timeout: 6e5, stdio: "pipe", cwd: outputDir });
12325
12368
  const actualPath = existsSync16(outPath) ? outPath : outTemplate.replace("%(ext)s", "mp4");
12326
12369
  return {
12327
12370
  success: true,
@@ -12333,7 +12376,7 @@ Format: mp4`,
12333
12376
  } else {
12334
12377
  const outPath = join19(outputDir, `${title}.mp3`);
12335
12378
  const outTemplate = join19(outputDir, `${title}.%(ext)s`);
12336
- execSync10(`yt-dlp -x --audio-format mp3 --audio-quality 0 -o "${outTemplate}" "${url}"`, { timeout: 6e5, stdio: "pipe", cwd: outputDir });
12379
+ execSync11(`yt-dlp -x --audio-format mp3 --audio-quality 0 -o "${outTemplate}" "${url}"`, { timeout: 6e5, stdio: "pipe", cwd: outputDir });
12337
12380
  const actualPath = existsSync16(outPath) ? outPath : outTemplate.replace("%(ext)s", "mp3");
12338
12381
  return {
12339
12382
  success: true,
@@ -13253,6 +13296,7 @@ var ReplTool;
13253
13296
  var init_repl = __esm({
13254
13297
  "packages/execution/dist/tools/repl.js"() {
13255
13298
  "use strict";
13299
+ init_process_kill();
13256
13300
  ReplTool = class {
13257
13301
  name = "repl_exec";
13258
13302
  description = "Execute Python code in a persistent REPL environment. Variables, imports, and functions persist between calls within the same task. Use for data processing, analysis, and building up results across multiple steps. A special function llm_query(prompt, context='') is available to invoke the language model from within Python code for semantic analysis of text chunks. Write results to files or print them to see output.";
@@ -13685,11 +13729,8 @@ print("${sentinel}")
13685
13729
  if (this.proc && !this.proc.killed) {
13686
13730
  try {
13687
13731
  this.proc.stdin?.end();
13688
- try {
13689
- process.kill(-this.proc.pid, "SIGTERM");
13690
- } catch {
13691
- }
13692
- this.proc.kill("SIGTERM");
13732
+ if (this.proc.pid)
13733
+ killProcessTree(this.proc.pid, "SIGTERM");
13693
13734
  } catch {
13694
13735
  }
13695
13736
  this.proc = null;
@@ -15600,7 +15641,7 @@ ${parts.join("\n\n")}`,
15600
15641
 
15601
15642
  // packages/execution/dist/tools/vision.js
15602
15643
  import { readFileSync as readFileSync14, existsSync as existsSync17, statSync as statSync5 } from "node:fs";
15603
- import { execSync as execSync11, spawn as spawn8 } from "node:child_process";
15644
+ import { execSync as execSync12, spawn as spawn8 } from "node:child_process";
15604
15645
  import { resolve as resolve18, extname as extname6, basename as basename5, dirname as dirname6, join as join28 } from "node:path";
15605
15646
  import { fileURLToPath as fileURLToPath2 } from "node:url";
15606
15647
  async function probeStation(endpoint) {
@@ -15622,7 +15663,7 @@ function findStationBinary() {
15622
15663
  const oaVenvPython = isWin2 ? join28(venvBase, "Scripts", "python.exe") : join28(venvBase, "bin", "python");
15623
15664
  if (existsSync17(oaVenvPython)) {
15624
15665
  try {
15625
- execSync11(`${JSON.stringify(oaVenvPython)} -c "import moondream_station"`, { stdio: "pipe", timeout: 5e3 });
15666
+ execSync12(`${JSON.stringify(oaVenvPython)} -c "import moondream_station"`, { stdio: "pipe", timeout: 5e3 });
15626
15667
  return oaVenvPython;
15627
15668
  } catch {
15628
15669
  }
@@ -15639,14 +15680,14 @@ function findStationBinary() {
15639
15680
  for (const p of localVenvPaths) {
15640
15681
  if (existsSync17(p)) {
15641
15682
  try {
15642
- execSync11(`${JSON.stringify(p)} -c "import moondream_station"`, { stdio: "pipe", timeout: 5e3 });
15683
+ execSync12(`${JSON.stringify(p)} -c "import moondream_station"`, { stdio: "pipe", timeout: 5e3 });
15643
15684
  return p;
15644
15685
  } catch {
15645
15686
  }
15646
15687
  }
15647
15688
  }
15648
15689
  try {
15649
- const path = execSync11("which moondream-station", { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e3 }).trim();
15690
+ const path = execSync12("which moondream-station", { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e3 }).trim();
15650
15691
  if (path)
15651
15692
  return path;
15652
15693
  } catch {
@@ -15840,9 +15881,9 @@ var init_vision = __esm({
15840
15881
  if (ollamaResult)
15841
15882
  return ollamaResult;
15842
15883
  try {
15843
- const { execSync: execSync35 } = await import("node:child_process");
15884
+ const { execSync: execSync36 } = await import("node:child_process");
15844
15885
  try {
15845
- execSync35("pip3 install --user moondream 2>/dev/null || pip install --user moondream 2>/dev/null", {
15886
+ execSync36("pip3 install --user moondream 2>/dev/null || pip install --user moondream 2>/dev/null", {
15846
15887
  timeout: 12e4,
15847
15888
  stdio: "pipe"
15848
15889
  });
@@ -15855,7 +15896,7 @@ var init_vision = __esm({
15855
15896
  } catch {
15856
15897
  }
15857
15898
  try {
15858
- execSync35("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
15899
+ execSync36("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
15859
15900
  const retryOllama = await this.tryOllamaVision(buffer, filename, action, prompt, length, start);
15860
15901
  if (retryOllama)
15861
15902
  return retryOllama;
@@ -15963,8 +16004,8 @@ Coordinates are normalized (0-1). Multiply by image width/height for pixel value
15963
16004
  const errText = await res.text().catch(() => "");
15964
16005
  if (res.status === 404 || /not found|does not exist/i.test(errText)) {
15965
16006
  try {
15966
- const { execSync: execSync35 } = await import("node:child_process");
15967
- execSync35("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
16007
+ const { execSync: execSync36 } = await import("node:child_process");
16008
+ execSync36("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
15968
16009
  res = await fetch(`${ollamaHost}/api/generate`, {
15969
16010
  method: "POST",
15970
16011
  headers: { "Content-Type": "application/json" },
@@ -16047,13 +16088,13 @@ ${response}`, durationMs: performance.now() - start };
16047
16088
 
16048
16089
  // packages/execution/dist/tools/desktop-click.js
16049
16090
  import { readFileSync as readFileSync15, existsSync as existsSync18 } from "node:fs";
16050
- import { execSync as execSync12 } from "node:child_process";
16091
+ import { execSync as execSync13 } from "node:child_process";
16051
16092
  import { tmpdir as tmpdir4 } from "node:os";
16052
16093
  import { join as join29, dirname as dirname7 } from "node:path";
16053
16094
  import { fileURLToPath as fileURLToPath3 } from "node:url";
16054
16095
  function hasCommand2(cmd) {
16055
16096
  try {
16056
- execSync12(`which ${cmd}`, { stdio: "pipe", timeout: 3e3 });
16097
+ execSync13(`which ${cmd}`, { stdio: "pipe", timeout: 3e3 });
16057
16098
  return true;
16058
16099
  } catch {
16059
16100
  return false;
@@ -16061,7 +16102,7 @@ function hasCommand2(cmd) {
16061
16102
  }
16062
16103
  function getImageDimensions2(filePath) {
16063
16104
  try {
16064
- const out = execSync12(`identify -format "%w %h" ${JSON.stringify(filePath)}`, {
16105
+ const out = execSync13(`identify -format "%w %h" ${JSON.stringify(filePath)}`, {
16065
16106
  encoding: "utf8",
16066
16107
  stdio: ["pipe", "pipe", "pipe"],
16067
16108
  timeout: 5e3
@@ -16072,14 +16113,14 @@ function getImageDimensions2(filePath) {
16072
16113
  } catch {
16073
16114
  }
16074
16115
  try {
16075
- const out = execSync12(`python3 -c "from PIL import Image; i=Image.open(${JSON.stringify(filePath)}); print(i.size[0], i.size[1])"`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 }).trim();
16116
+ const out = execSync13(`python3 -c "from PIL import Image; i=Image.open(${JSON.stringify(filePath)}); print(i.size[0], i.size[1])"`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 }).trim();
16076
16117
  const [w, h] = out.split(" ").map(Number);
16077
16118
  if (w && h)
16078
16119
  return { width: w, height: h };
16079
16120
  } catch {
16080
16121
  }
16081
16122
  try {
16082
- const out = execSync12(`file ${JSON.stringify(filePath)}`, {
16123
+ const out = execSync13(`file ${JSON.stringify(filePath)}`, {
16083
16124
  encoding: "utf8",
16084
16125
  stdio: ["pipe", "pipe", "pipe"],
16085
16126
  timeout: 5e3
@@ -16110,7 +16151,7 @@ function captureScreenshot(outputPath) {
16110
16151
  cmd = `scrot ${out}`;
16111
16152
  } else {
16112
16153
  try {
16113
- execSync12(`DISPLAY=:0 python3 -c "from PIL import ImageGrab; ImageGrab.grab().save(${JSON.stringify(outputPath)})"`, { stdio: "pipe", timeout: 1e4 });
16154
+ execSync13(`DISPLAY=:0 python3 -c "from PIL import ImageGrab; ImageGrab.grab().save(${JSON.stringify(outputPath)})"`, { stdio: "pipe", timeout: 1e4 });
16114
16155
  if (existsSync18(outputPath))
16115
16156
  return;
16116
16157
  } catch {
@@ -16121,7 +16162,7 @@ function captureScreenshot(outputPath) {
16121
16162
  if (!cmd) {
16122
16163
  throw new Error("No screenshot tool found. Auto-install failed. Try manually: sudo apt install scrot");
16123
16164
  }
16124
- execSync12(cmd, { stdio: "pipe", timeout: 1e4 });
16165
+ execSync13(cmd, { stdio: "pipe", timeout: 1e4 });
16125
16166
  if (!existsSync18(outputPath)) {
16126
16167
  throw new Error("Screenshot file was not created");
16127
16168
  }
@@ -16139,11 +16180,11 @@ function clickAt(x, y, button, clickType) {
16139
16180
  hasXdotool = dep.available;
16140
16181
  }
16141
16182
  if (hasXdotool) {
16142
- execSync12(`xdotool mousemove --sync ${rx} ${ry}`, { stdio: "pipe", timeout: 5e3 });
16183
+ execSync13(`xdotool mousemove --sync ${rx} ${ry}`, { stdio: "pipe", timeout: 5e3 });
16143
16184
  if (clickType === "double") {
16144
- execSync12(`xdotool click --repeat 2 --delay 50 ${buttonNum}`, { stdio: "pipe", timeout: 5e3 });
16185
+ execSync13(`xdotool click --repeat 2 --delay 50 ${buttonNum}`, { stdio: "pipe", timeout: 5e3 });
16145
16186
  } else {
16146
- execSync12(`xdotool click ${buttonNum}`, { stdio: "pipe", timeout: 5e3 });
16187
+ execSync13(`xdotool click ${buttonNum}`, { stdio: "pipe", timeout: 5e3 });
16147
16188
  }
16148
16189
  return;
16149
16190
  }
@@ -16168,14 +16209,14 @@ for i in range(${clicks}):
16168
16209
  time.sleep(0.05)
16169
16210
  `.trim().replace(/\n/g, "; ");
16170
16211
  try {
16171
- execSync12(`DISPLAY=:0 python3 -c "${pyScript}"`, { stdio: "pipe", timeout: 5e3 });
16212
+ execSync13(`DISPLAY=:0 python3 -c "${pyScript}"`, { stdio: "pipe", timeout: 5e3 });
16172
16213
  return;
16173
16214
  } catch {
16174
16215
  }
16175
16216
  try {
16176
16217
  const pyBin = process.platform === "win32" ? "Scripts/python.exe" : "bin/python";
16177
16218
  const venvPy = join29(__dirname2, `../../../../.moondream-venv/${pyBin}`);
16178
- execSync12(`DISPLAY=:0 ${JSON.stringify(venvPy)} -c "${pyScript}"`, { stdio: "pipe", timeout: 5e3 });
16219
+ execSync13(`DISPLAY=:0 ${JSON.stringify(venvPy)} -c "${pyScript}"`, { stdio: "pipe", timeout: 5e3 });
16179
16220
  return;
16180
16221
  } catch {
16181
16222
  }
@@ -16187,11 +16228,11 @@ for i in range(${clicks}):
16187
16228
  const rx2 = Math.round(x);
16188
16229
  const ry2 = Math.round(y);
16189
16230
  if (clickType === "double") {
16190
- execSync12(`cliclick dc:${rx2},${ry2}`, { stdio: "pipe", timeout: 5e3 });
16231
+ execSync13(`cliclick dc:${rx2},${ry2}`, { stdio: "pipe", timeout: 5e3 });
16191
16232
  } else if (button === "right") {
16192
- execSync12(`cliclick rc:${rx2},${ry2}`, { stdio: "pipe", timeout: 5e3 });
16233
+ execSync13(`cliclick rc:${rx2},${ry2}`, { stdio: "pipe", timeout: 5e3 });
16193
16234
  } else {
16194
- execSync12(`cliclick c:${rx2},${ry2}`, { stdio: "pipe", timeout: 5e3 });
16235
+ execSync13(`cliclick c:${rx2},${ry2}`, { stdio: "pipe", timeout: 5e3 });
16195
16236
  }
16196
16237
  } else {
16197
16238
  throw new Error(`Desktop click not supported on platform: ${plat}`);
@@ -16554,7 +16595,7 @@ ${data.response}`);
16554
16595
  const tess = ensureCommand("tesseract");
16555
16596
  if (tess.available) {
16556
16597
  try {
16557
- ocrText = execSync12(`tesseract ${JSON.stringify(screenshotPath)} stdout 2>/dev/null`, {
16598
+ ocrText = execSync13(`tesseract ${JSON.stringify(screenshotPath)} stdout 2>/dev/null`, {
16558
16599
  encoding: "utf8",
16559
16600
  timeout: 15e3
16560
16601
  }).trim();
@@ -16605,7 +16646,7 @@ Screen: ${dims.width}x${dims.height}`);
16605
16646
  // packages/execution/dist/tools/ocr-pdf.js
16606
16647
  import { existsSync as existsSync19, statSync as statSync6 } from "node:fs";
16607
16648
  import { resolve as resolve19, basename as basename6 } from "node:path";
16608
- import { execSync as execSync13 } from "node:child_process";
16649
+ import { execSync as execSync14 } from "node:child_process";
16609
16650
  var OcrPdfTool;
16610
16651
  var init_ocr_pdf = __esm({
16611
16652
  "packages/execution/dist/tools/ocr-pdf.js"() {
@@ -16692,7 +16733,7 @@ var init_ocr_pdf = __esm({
16692
16733
  cmdParts.push(JSON.stringify(inputPath));
16693
16734
  cmdParts.push(JSON.stringify(outputPath));
16694
16735
  try {
16695
- const stdout = execSync13(cmdParts.join(" "), {
16736
+ const stdout = execSync14(cmdParts.join(" "), {
16696
16737
  encoding: "utf8",
16697
16738
  stdio: ["pipe", "pipe", "pipe"],
16698
16739
  timeout: 6e5,
@@ -16728,7 +16769,7 @@ Language: ${language}
16728
16769
  // packages/execution/dist/tools/pdf-to-text.js
16729
16770
  import { existsSync as existsSync20, statSync as statSync7, readFileSync as readFileSync16, unlinkSync as unlinkSync3 } from "node:fs";
16730
16771
  import { resolve as resolve20, basename as basename7, join as join30 } from "node:path";
16731
- import { execSync as execSync14 } from "node:child_process";
16772
+ import { execSync as execSync15 } from "node:child_process";
16732
16773
  import { tmpdir as tmpdir5 } from "node:os";
16733
16774
  var PdfToTextTool;
16734
16775
  var init_pdf_to_text = __esm({
@@ -16824,7 +16865,7 @@ var init_pdf_to_text = __esm({
16824
16865
  cmdParts.push("-l", String(lastPage));
16825
16866
  cmdParts.push(JSON.stringify(fullPath), "-");
16826
16867
  try {
16827
- let text = execSync14(cmdParts.join(" "), {
16868
+ let text = execSync15(cmdParts.join(" "), {
16828
16869
  encoding: "utf8",
16829
16870
  stdio: ["pipe", "pipe", "pipe"],
16830
16871
  timeout: 12e4
@@ -16884,14 +16925,14 @@ ${text}`,
16884
16925
  const tmpPdf = join30(tmpdir5(), `oa-ocr-${Date.now()}.pdf`);
16885
16926
  try {
16886
16927
  const ocrCmd = `ocrmypdf -l ${language} --skip-text ${JSON.stringify(inputPath)} ${JSON.stringify(tmpPdf)}`;
16887
- execSync14(ocrCmd, { stdio: "pipe", timeout: 6e5 });
16928
+ execSync15(ocrCmd, { stdio: "pipe", timeout: 6e5 });
16888
16929
  const textCmdParts = ["pdftotext"];
16889
16930
  if (firstPage)
16890
16931
  textCmdParts.push("-f", String(firstPage));
16891
16932
  if (lastPage)
16892
16933
  textCmdParts.push("-l", String(lastPage));
16893
16934
  textCmdParts.push(JSON.stringify(tmpPdf), "-");
16894
- const text = execSync14(textCmdParts.join(" "), {
16935
+ const text = execSync15(textCmdParts.join(" "), {
16895
16936
  encoding: "utf8",
16896
16937
  stdio: ["pipe", "pipe", "pipe"],
16897
16938
  timeout: 12e4
@@ -16913,7 +16954,7 @@ ${text}`,
16913
16954
  // packages/execution/dist/tools/ocr-image-advanced.js
16914
16955
  import { existsSync as existsSync21, statSync as statSync8 } from "node:fs";
16915
16956
  import { resolve as resolve21, basename as basename8, dirname as dirname8, join as join31 } from "node:path";
16916
- import { execSync as execSync15 } from "node:child_process";
16957
+ import { execSync as execSync16 } from "node:child_process";
16917
16958
  import { fileURLToPath as fileURLToPath4 } from "node:url";
16918
16959
  import { homedir as homedir8, tmpdir as tmpdir6 } from "node:os";
16919
16960
  function findOcrScript() {
@@ -16934,7 +16975,7 @@ function findPython() {
16934
16975
  const venvPython2 = isWin2 ? join31(homedir8(), ".open-agents", "venv", "Scripts", "python.exe") : join31(homedir8(), ".open-agents", "venv", "bin", "python");
16935
16976
  if (existsSync21(venvPython2)) {
16936
16977
  try {
16937
- execSync15(`${JSON.stringify(venvPython2)} -c "import cv2, pytesseract, numpy, PIL"`, {
16978
+ execSync16(`${JSON.stringify(venvPython2)} -c "import cv2, pytesseract, numpy, PIL"`, {
16938
16979
  stdio: "pipe",
16939
16980
  timeout: 5e3
16940
16981
  });
@@ -16943,7 +16984,7 @@ function findPython() {
16943
16984
  }
16944
16985
  }
16945
16986
  try {
16946
- execSync15(`python3 -c "import cv2, pytesseract, numpy, PIL"`, {
16987
+ execSync16(`python3 -c "import cv2, pytesseract, numpy, PIL"`, {
16947
16988
  stdio: "pipe",
16948
16989
  timeout: 5e3
16949
16990
  });
@@ -17081,7 +17122,7 @@ var init_ocr_image_advanced = __esm({
17081
17122
  cmdParts.push("--debug-dir", debugDir);
17082
17123
  }
17083
17124
  try {
17084
- const stdout = execSync15(cmdParts.join(" "), {
17125
+ const stdout = execSync16(cmdParts.join(" "), {
17085
17126
  encoding: "utf8",
17086
17127
  stdio: ["pipe", "pipe", "pipe"],
17087
17128
  timeout: 3e5,
@@ -17177,14 +17218,14 @@ var init_ocr_image_advanced = __esm({
17177
17218
  try {
17178
17219
  const [x, y, w, h] = region.split(",").map(Number);
17179
17220
  const croppedPath = join31(tmpdir6(), `oa-ocr-crop-${Date.now()}.png`);
17180
- execSync15(`convert ${JSON.stringify(imagePath)} -crop ${w}x${h}+${x}+${y} +repage ${JSON.stringify(croppedPath)}`, { stdio: "pipe", timeout: 1e4 });
17221
+ execSync16(`convert ${JSON.stringify(imagePath)} -crop ${w}x${h}+${x}+${y} +repage ${JSON.stringify(croppedPath)}`, { stdio: "pipe", timeout: 1e4 });
17181
17222
  inputPath = croppedPath;
17182
17223
  } catch {
17183
17224
  }
17184
17225
  }
17185
17226
  const psmArg = psm ?? 6;
17186
17227
  try {
17187
- const text = execSync15(`tesseract ${JSON.stringify(inputPath)} stdout -l ${language} --psm ${psmArg} 2>/dev/null`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 6e4 }).trim();
17228
+ const text = execSync16(`tesseract ${JSON.stringify(inputPath)} stdout -l ${language} --psm ${psmArg} 2>/dev/null`, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 6e4 }).trim();
17188
17229
  if (!text) {
17189
17230
  return {
17190
17231
  success: true,
@@ -17215,7 +17256,7 @@ Note: Advanced Python pipeline not available \u2014 install pytesseract, opencv-
17215
17256
  });
17216
17257
 
17217
17258
  // packages/execution/dist/tools/browser-action.js
17218
- import { execSync as execSync16, spawn as spawn9 } from "node:child_process";
17259
+ import { execSync as execSync17, spawn as spawn9 } from "node:child_process";
17219
17260
  import { existsSync as existsSync22, readFileSync as readFileSync17 } from "node:fs";
17220
17261
  import { join as join32, dirname as dirname9 } from "node:path";
17221
17262
  import { fileURLToPath as fileURLToPath5 } from "node:url";
@@ -17246,7 +17287,7 @@ async function probeService() {
17246
17287
  function findPython2() {
17247
17288
  for (const cmd of ["python3", "python"]) {
17248
17289
  try {
17249
- const ver = execSync16(`${cmd} --version 2>&1`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
17290
+ const ver = execSync17(`${cmd} --version 2>&1`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
17250
17291
  if (ver.includes("Python 3"))
17251
17292
  return cmd;
17252
17293
  } catch {
@@ -17481,7 +17522,7 @@ var init_browser_action = __esm({
17481
17522
  });
17482
17523
 
17483
17524
  // packages/execution/dist/tools/autoresearch.js
17484
- import { execSync as execSync17, spawn as spawn10 } from "node:child_process";
17525
+ import { execSync as execSync18, spawn as spawn10 } from "node:child_process";
17485
17526
  import { existsSync as existsSync23, readFileSync as readFileSync18, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, appendFileSync, copyFileSync } from "node:fs";
17486
17527
  import { join as join33, resolve as resolve22, dirname as dirname10 } from "node:path";
17487
17528
  import { fileURLToPath as fileURLToPath6 } from "node:url";
@@ -17611,13 +17652,13 @@ Requires: NVIDIA GPU, Python 3.10+, uv (astral.sh package manager).`;
17611
17652
  async setup(workspace, args, start) {
17612
17653
  const output = [];
17613
17654
  try {
17614
- execSync17("which uv", { encoding: "utf-8", timeout: 5e3 });
17655
+ execSync18("which uv", { encoding: "utf-8", timeout: 5e3 });
17615
17656
  output.push("uv: found");
17616
17657
  } catch {
17617
17658
  return { success: false, output: "", error: "uv not found. Install with: curl -LsSf https://astral.sh/uv/install.sh | sh", durationMs: Date.now() - start };
17618
17659
  }
17619
17660
  try {
17620
- const gpuInfo = execSync17("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null || echo 'no GPU'", { encoding: "utf-8", timeout: 1e4 }).trim();
17661
+ const gpuInfo = execSync18("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null || echo 'no GPU'", { encoding: "utf-8", timeout: 1e4 }).trim();
17621
17662
  output.push(`GPU: ${gpuInfo}`);
17622
17663
  } catch {
17623
17664
  output.push("GPU: detection failed (nvidia-smi not available)");
@@ -17667,10 +17708,10 @@ explicit = true
17667
17708
  writeFileSync8(join33(workspace, "pyproject.toml"), pyprojectContent, "utf-8");
17668
17709
  output.push("Created pyproject.toml");
17669
17710
  try {
17670
- execSync17("git rev-parse --git-dir", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
17711
+ execSync18("git rev-parse --git-dir", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
17671
17712
  output.push("Git: already initialized");
17672
17713
  } catch {
17673
- execSync17("git init && git add -A && git commit -m 'autoresearch: initial setup'", {
17714
+ execSync18("git init && git add -A && git commit -m 'autoresearch: initial setup'", {
17674
17715
  cwd: workspace,
17675
17716
  encoding: "utf-8",
17676
17717
  timeout: 1e4
@@ -17680,14 +17721,14 @@ explicit = true
17680
17721
  const tag = String(args["tag"] ?? (/* @__PURE__ */ new Date()).toISOString().slice(5, 10).replace("-", ""));
17681
17722
  const branchName = `autoresearch/${tag}`;
17682
17723
  try {
17683
- execSync17(`git checkout -b ${branchName}`, { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
17724
+ execSync18(`git checkout -b ${branchName}`, { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
17684
17725
  output.push(`Branch: created ${branchName}`);
17685
17726
  } catch {
17686
17727
  output.push(`Branch: ${branchName} may already exist, staying on current branch`);
17687
17728
  }
17688
17729
  output.push("Installing dependencies with uv sync (this may take a while)...");
17689
17730
  try {
17690
- const uvOut = execSync17("uv sync 2>&1", { cwd: workspace, encoding: "utf-8", timeout: 3e5 });
17731
+ const uvOut = execSync18("uv sync 2>&1", { cwd: workspace, encoding: "utf-8", timeout: 3e5 });
17691
17732
  output.push(`uv sync: ${uvOut.trim().split("\n").slice(-3).join(" | ")}`);
17692
17733
  } catch (err) {
17693
17734
  const e = err;
@@ -17696,7 +17737,7 @@ explicit = true
17696
17737
  const numShards = Number(args["num_shards"] ?? 10);
17697
17738
  output.push(`Preparing data (${numShards} shards)...`);
17698
17739
  try {
17699
- const prepOut = execSync17(`uv run prepare.py --num-shards ${numShards} 2>&1`, {
17740
+ const prepOut = execSync18(`uv run prepare.py --num-shards ${numShards} 2>&1`, {
17700
17741
  cwd: workspace,
17701
17742
  encoding: "utf-8",
17702
17743
  timeout: 6e5
@@ -17733,7 +17774,7 @@ Next steps:
17733
17774
  }
17734
17775
  if (!existsSync23(join33(workspace, ".venv")) && existsSync23(join33(workspace, "pyproject.toml"))) {
17735
17776
  try {
17736
- execSync17("uv sync 2>&1", { cwd: workspace, encoding: "utf-8", timeout: 3e5 });
17777
+ execSync18("uv sync 2>&1", { cwd: workspace, encoding: "utf-8", timeout: 3e5 });
17737
17778
  } catch {
17738
17779
  }
17739
17780
  }
@@ -17883,15 +17924,15 @@ Run autoresearch(action="setup") to begin.`,
17883
17924
  }
17884
17925
  output.push(`Workspace: ${workspace}`);
17885
17926
  try {
17886
- const branch = execSync17("git branch --show-current", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
17927
+ const branch = execSync18("git branch --show-current", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
17887
17928
  output.push(`Branch: ${branch}`);
17888
- const lastCommit = execSync17("git log --oneline -1", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
17929
+ const lastCommit = execSync18("git log --oneline -1", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
17889
17930
  output.push(`Last commit: ${lastCommit}`);
17890
17931
  } catch {
17891
17932
  output.push("Git: not initialized");
17892
17933
  }
17893
17934
  try {
17894
- const gpuInfo = execSync17("nvidia-smi --query-gpu=name,memory.total,memory.used --format=csv,noheader 2>/dev/null", { encoding: "utf-8", timeout: 1e4 }).trim();
17935
+ const gpuInfo = execSync18("nvidia-smi --query-gpu=name,memory.total,memory.used --format=csv,noheader 2>/dev/null", { encoding: "utf-8", timeout: 1e4 }).trim();
17895
17936
  output.push(`GPU: ${gpuInfo}`);
17896
17937
  } catch {
17897
17938
  output.push("GPU: not detected");
@@ -17934,12 +17975,12 @@ Run autoresearch(action="setup") to begin.`,
17934
17975
  memGb = memGb ?? 0;
17935
17976
  let commitHash = "0000000";
17936
17977
  try {
17937
- execSync17("git add train.py", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
17938
- execSync17(`git commit -m "autoresearch: ${desc}"`, { cwd: workspace, encoding: "utf-8", timeout: 1e4 });
17939
- commitHash = execSync17("git rev-parse --short HEAD", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
17978
+ execSync18("git add train.py", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
17979
+ execSync18(`git commit -m "autoresearch: ${desc}"`, { cwd: workspace, encoding: "utf-8", timeout: 1e4 });
17980
+ commitHash = execSync18("git rev-parse --short HEAD", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
17940
17981
  } catch {
17941
17982
  try {
17942
- commitHash = execSync17("git rev-parse --short HEAD", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
17983
+ commitHash = execSync18("git rev-parse --short HEAD", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
17943
17984
  } catch {
17944
17985
  }
17945
17986
  }
@@ -17973,14 +18014,14 @@ Branch advanced. Ready for next experiment.`,
17973
18014
  memGb = memGb ?? 0;
17974
18015
  let commitHash = "0000000";
17975
18016
  try {
17976
- commitHash = execSync17("git rev-parse --short HEAD", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
18017
+ commitHash = execSync18("git rev-parse --short HEAD", { cwd: workspace, encoding: "utf-8", timeout: 5e3 }).trim();
17977
18018
  } catch {
17978
18019
  }
17979
18020
  const row = `${commitHash} ${valBpb.toFixed(6)} ${memGb.toFixed(1)} discard ${desc}
17980
18021
  `;
17981
18022
  appendFileSync(tsvPath, row, "utf-8");
17982
18023
  try {
17983
- execSync17("git checkout -- train.py", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
18024
+ execSync18("git checkout -- train.py", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
17984
18025
  } catch {
17985
18026
  return {
17986
18027
  success: false,
@@ -18001,7 +18042,7 @@ train.py reverted to last kept state. Ready for next experiment.`,
18001
18042
  });
18002
18043
 
18003
18044
  // packages/execution/dist/tools/scheduler.js
18004
- import { execSync as execSync18, exec as execCb } from "node:child_process";
18045
+ import { execSync as execSync19, exec as execCb } from "node:child_process";
18005
18046
  import { readFile as readFile15, writeFile as writeFile15, mkdir as mkdir11 } from "node:fs/promises";
18006
18047
  import { resolve as resolve23, join as join34 } from "node:path";
18007
18048
  import { homedir as homedir9 } from "node:os";
@@ -18064,19 +18105,19 @@ function describeCron(expr) {
18064
18105
  }
18065
18106
  function getCurrentCrontab() {
18066
18107
  try {
18067
- return execSync18("crontab -l 2>/dev/null", { stdio: "pipe" }).toString().split("\n");
18108
+ return execSync19("crontab -l 2>/dev/null", { stdio: "pipe" }).toString().split("\n");
18068
18109
  } catch {
18069
18110
  return [];
18070
18111
  }
18071
18112
  }
18072
18113
  function writeCrontab(lines) {
18073
18114
  const content = lines.join("\n") + "\n";
18074
- execSync18(`echo ${JSON.stringify(content)} | crontab -`, { stdio: "pipe" });
18115
+ execSync19(`echo ${JSON.stringify(content)} | crontab -`, { stdio: "pipe" });
18075
18116
  }
18076
18117
  function findOaBinary() {
18077
18118
  for (const cmd of ["oa", "open-agents"]) {
18078
18119
  try {
18079
- const path = execSync18(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
18120
+ const path = execSync19(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
18080
18121
  if (path)
18081
18122
  return path;
18082
18123
  } catch {
@@ -19067,13 +19108,13 @@ ${sections.join("\n")}`,
19067
19108
  });
19068
19109
 
19069
19110
  // packages/execution/dist/tools/opencode.js
19070
- import { execSync as execSync19, spawn as spawn11 } from "node:child_process";
19111
+ import { execSync as execSync20, spawn as spawn11 } from "node:child_process";
19071
19112
  import { existsSync as existsSync24 } from "node:fs";
19072
19113
  import { join as join37, resolve as resolve26 } from "node:path";
19073
19114
  function findOpencode() {
19074
19115
  for (const cmd of ["opencode"]) {
19075
19116
  try {
19076
- const path = execSync19(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
19117
+ const path = execSync20(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
19077
19118
  if (path)
19078
19119
  return path;
19079
19120
  } catch {
@@ -19093,7 +19134,7 @@ function findOpencode() {
19093
19134
  }
19094
19135
  function getVersion(binary) {
19095
19136
  try {
19096
- return execSync19(`${binary} --version 2>/dev/null`, { stdio: "pipe", timeout: 1e4 }).toString().trim();
19137
+ return execSync20(`${binary} --version 2>/dev/null`, { stdio: "pipe", timeout: 1e4 }).toString().trim();
19097
19138
  } catch {
19098
19139
  return "unknown";
19099
19140
  }
@@ -19102,12 +19143,12 @@ function installOpencode() {
19102
19143
  const platform6 = process.platform;
19103
19144
  try {
19104
19145
  if (platform6 === "win32") {
19105
- execSync19('powershell -Command "irm https://opencode.ai/install | iex"', {
19146
+ execSync20('powershell -Command "irm https://opencode.ai/install | iex"', {
19106
19147
  stdio: "pipe",
19107
19148
  timeout: 12e4
19108
19149
  });
19109
19150
  } else {
19110
- execSync19("curl -fsSL https://opencode.ai/install | bash", {
19151
+ execSync20("curl -fsSL https://opencode.ai/install | bash", {
19111
19152
  stdio: "pipe",
19112
19153
  timeout: 12e4
19113
19154
  });
@@ -19341,13 +19382,13 @@ var init_opencode = __esm({
19341
19382
  });
19342
19383
 
19343
19384
  // packages/execution/dist/tools/factory.js
19344
- import { execSync as execSync20, spawn as spawn12 } from "node:child_process";
19385
+ import { execSync as execSync21, spawn as spawn12 } from "node:child_process";
19345
19386
  import { existsSync as existsSync25 } from "node:fs";
19346
19387
  import { join as join38 } from "node:path";
19347
19388
  function findDroid() {
19348
19389
  for (const cmd of ["droid"]) {
19349
19390
  try {
19350
- const path = execSync20(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
19391
+ const path = execSync21(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
19351
19392
  if (path)
19352
19393
  return path;
19353
19394
  } catch {
@@ -19367,7 +19408,7 @@ function findDroid() {
19367
19408
  }
19368
19409
  function getVersion2(binary) {
19369
19410
  try {
19370
- return execSync20(`${binary} --version 2>/dev/null`, { stdio: "pipe", timeout: 1e4 }).toString().trim();
19411
+ return execSync21(`${binary} --version 2>/dev/null`, { stdio: "pipe", timeout: 1e4 }).toString().trim();
19371
19412
  } catch {
19372
19413
  return "unknown";
19373
19414
  }
@@ -19376,12 +19417,12 @@ function installDroid() {
19376
19417
  const platform6 = process.platform;
19377
19418
  try {
19378
19419
  if (platform6 === "win32") {
19379
- execSync20('powershell -Command "irm https://app.factory.ai/cli/windows | iex"', {
19420
+ execSync21('powershell -Command "irm https://app.factory.ai/cli/windows | iex"', {
19380
19421
  stdio: "pipe",
19381
19422
  timeout: 12e4
19382
19423
  });
19383
19424
  } else {
19384
- execSync20("curl -fsSL https://app.factory.ai/cli | sh", {
19425
+ execSync21("curl -fsSL https://app.factory.ai/cli | sh", {
19385
19426
  stdio: "pipe",
19386
19427
  timeout: 12e4
19387
19428
  });
@@ -19650,7 +19691,7 @@ var init_factory = __esm({
19650
19691
  });
19651
19692
 
19652
19693
  // packages/execution/dist/tools/cron-agent.js
19653
- import { execSync as execSync21 } from "node:child_process";
19694
+ import { execSync as execSync22 } from "node:child_process";
19654
19695
  import { readFile as readFile18, writeFile as writeFile18, mkdir as mkdir14 } from "node:fs/promises";
19655
19696
  import { resolve as resolve27, join as join39 } from "node:path";
19656
19697
  import { homedir as homedir10 } from "node:os";
@@ -19715,19 +19756,19 @@ function resolveSchedule2(schedule) {
19715
19756
  }
19716
19757
  function getCurrentCrontab2() {
19717
19758
  try {
19718
- return execSync21("crontab -l 2>/dev/null", { stdio: "pipe" }).toString().split("\n");
19759
+ return execSync22("crontab -l 2>/dev/null", { stdio: "pipe" }).toString().split("\n");
19719
19760
  } catch {
19720
19761
  return [];
19721
19762
  }
19722
19763
  }
19723
19764
  function writeCrontab2(lines) {
19724
19765
  const content = lines.join("\n") + "\n";
19725
- execSync21(`echo ${JSON.stringify(content)} | crontab -`, { stdio: "pipe" });
19766
+ execSync22(`echo ${JSON.stringify(content)} | crontab -`, { stdio: "pipe" });
19726
19767
  }
19727
19768
  function findOaBinary2() {
19728
19769
  for (const cmd of ["oa", "open-agents"]) {
19729
19770
  try {
19730
- const path = execSync21(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
19771
+ const path = execSync22(`which ${cmd} 2>/dev/null`, { stdio: "pipe" }).toString().trim();
19731
19772
  if (path)
19732
19773
  return path;
19733
19774
  } catch {
@@ -20127,7 +20168,7 @@ ${truncated}`, durationMs: performance.now() - start };
20127
20168
  ];
20128
20169
  if (job.verifyCommand) {
20129
20170
  try {
20130
- const result = execSync21(job.verifyCommand, {
20171
+ const result = execSync22(job.verifyCommand, {
20131
20172
  cwd: this.workingDir,
20132
20173
  stdio: "pipe",
20133
20174
  timeout: 3e4
@@ -21083,11 +21124,11 @@ var init_repo_map = __esm({
21083
21124
  });
21084
21125
 
21085
21126
  // packages/execution/dist/tools/process-health.js
21086
- import { execSync as execSync22 } from "node:child_process";
21127
+ import { execSync as execSync23 } from "node:child_process";
21087
21128
  function getSystemStatus() {
21088
21129
  const lines = ["# System Health\n"];
21089
21130
  try {
21090
- const uptime2 = execSync22("uptime", { encoding: "utf-8", timeout: 3e3 }).trim();
21131
+ const uptime2 = execSync23("uptime", { encoding: "utf-8", timeout: 3e3 }).trim();
21091
21132
  const loadMatch = uptime2.match(/load average:\s*([\d.]+),\s*([\d.]+),\s*([\d.]+)/);
21092
21133
  if (loadMatch) {
21093
21134
  lines.push(`CPU Load: ${loadMatch[1]} (1m) ${loadMatch[2]} (5m) ${loadMatch[3]} (15m)`);
@@ -21100,20 +21141,20 @@ function getSystemStatus() {
21100
21141
  } catch {
21101
21142
  }
21102
21143
  try {
21103
- const mem = execSync22("free -h | head -2", { encoding: "utf-8", timeout: 3e3 }).trim();
21144
+ const mem = execSync23("free -h | head -2", { encoding: "utf-8", timeout: 3e3 }).trim();
21104
21145
  lines.push(`
21105
21146
  ${mem}`);
21106
21147
  } catch {
21107
21148
  }
21108
21149
  try {
21109
- const top = execSync22("ps aux --sort=-%cpu | head -8", { encoding: "utf-8", timeout: 3e3 }).trim();
21150
+ const top = execSync23("ps aux --sort=-%cpu | head -8", { encoding: "utf-8", timeout: 3e3 }).trim();
21110
21151
  lines.push(`
21111
21152
  Top processes by CPU:
21112
21153
  ${top}`);
21113
21154
  } catch {
21114
21155
  }
21115
21156
  try {
21116
- const nodeCount = execSync22("ps aux | grep 'node ' | grep -v grep | wc -l", { encoding: "utf-8", timeout: 3e3 }).trim();
21157
+ const nodeCount = execSync23("ps aux | grep 'node ' | grep -v grep | wc -l", { encoding: "utf-8", timeout: 3e3 }).trim();
21117
21158
  lines.push(`
21118
21159
  Node.js processes: ${nodeCount}`);
21119
21160
  } catch {
@@ -21122,7 +21163,7 @@ Node.js processes: ${nodeCount}`);
21122
21163
  }
21123
21164
  function findOrphans() {
21124
21165
  try {
21125
- 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();
21166
+ const psOutput = execSync23(`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();
21126
21167
  if (!psOutput)
21127
21168
  return "No OA-related orphan processes found.";
21128
21169
  const myPid = process.pid;
@@ -21152,7 +21193,7 @@ To kill a process: process_health(action='kill', pid=PID)`);
21152
21193
  return "Could not scan for orphan processes.";
21153
21194
  }
21154
21195
  }
21155
- function killProcess(pid) {
21196
+ function killProcess2(pid) {
21156
21197
  try {
21157
21198
  try {
21158
21199
  process.kill(-pid, "SIGTERM");
@@ -21160,7 +21201,7 @@ function killProcess(pid) {
21160
21201
  }
21161
21202
  process.kill(pid, "SIGTERM");
21162
21203
  try {
21163
- execSync22(`sleep 1 && kill -0 ${pid} 2>/dev/null && kill -9 ${pid} 2>/dev/null`, {
21204
+ execSync23(`sleep 1 && kill -0 ${pid} 2>/dev/null && kill -9 ${pid} 2>/dev/null`, {
21164
21205
  timeout: 3e3,
21165
21206
  stdio: "pipe"
21166
21207
  });
@@ -21223,7 +21264,7 @@ var init_process_health = __esm({
21223
21264
  if (pid === process.pid || pid === process.ppid) {
21224
21265
  return { success: false, output: "", error: "Cannot kill self or parent process", durationMs: performance.now() - start };
21225
21266
  }
21226
- return { success: true, output: killProcess(pid), durationMs: performance.now() - start };
21267
+ return { success: true, output: killProcess2(pid), durationMs: performance.now() - start };
21227
21268
  }
21228
21269
  default:
21229
21270
  return { success: false, output: "", error: `Unknown action: ${action}`, durationMs: performance.now() - start };
@@ -21343,21 +21384,10 @@ function stopFullSubAgent(id) {
21343
21384
  if (!entry || entry.status !== "running")
21344
21385
  return false;
21345
21386
  try {
21346
- try {
21347
- process.kill(-entry.pid, "SIGTERM");
21348
- } catch {
21349
- }
21350
- entry.process.kill("SIGTERM");
21387
+ killProcessTree(entry.pid, "SIGTERM");
21351
21388
  entry.status = "stopped";
21352
21389
  setTimeout(() => {
21353
- try {
21354
- process.kill(-entry.pid, "SIGKILL");
21355
- } catch {
21356
- }
21357
- try {
21358
- entry.process.kill("SIGKILL");
21359
- } catch {
21360
- }
21390
+ killProcessTree(entry.pid, "SIGKILL");
21361
21391
  }, 5e3);
21362
21392
  return true;
21363
21393
  } catch {
@@ -21365,16 +21395,9 @@ function stopFullSubAgent(id) {
21365
21395
  }
21366
21396
  }
21367
21397
  function killAllFullSubAgents() {
21368
- for (const [id, entry] of _activeSubProcesses) {
21398
+ for (const [, entry] of _activeSubProcesses) {
21369
21399
  if (entry.status === "running") {
21370
- try {
21371
- process.kill(-entry.pid, "SIGKILL");
21372
- } catch {
21373
- }
21374
- try {
21375
- entry.process.kill("SIGKILL");
21376
- } catch {
21377
- }
21400
+ killProcessTree(entry.pid, "SIGKILL");
21378
21401
  entry.status = "stopped";
21379
21402
  }
21380
21403
  }
@@ -21386,6 +21409,7 @@ var _activeSubProcesses, FullSubAgentTool;
21386
21409
  var init_full_sub_agent = __esm({
21387
21410
  "packages/execution/dist/tools/full-sub-agent.js"() {
21388
21411
  "use strict";
21412
+ init_process_kill();
21389
21413
  _activeSubProcesses = /* @__PURE__ */ new Map();
21390
21414
  FullSubAgentTool = class {
21391
21415
  name = "full_sub_agent";
@@ -21516,7 +21540,7 @@ ${tail}`, durationMs: performance.now() - start };
21516
21540
  });
21517
21541
 
21518
21542
  // packages/execution/dist/tools/environment-snapshot.js
21519
- import { execSync as execSync23 } from "node:child_process";
21543
+ import { execSync as execSync24 } from "node:child_process";
21520
21544
  import { cpus, totalmem, freemem, hostname as hostname2, platform, arch, uptime } from "node:os";
21521
21545
  import { statfsSync } from "node:fs";
21522
21546
  function collectSnapshot(workingDir) {
@@ -21534,7 +21558,7 @@ function collectSnapshot(workingDir) {
21534
21558
  }
21535
21559
  let gpu = void 0;
21536
21560
  try {
21537
- 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());
21561
+ const nvOut = execSync24("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());
21538
21562
  if (nvOut.length >= 3) {
21539
21563
  gpu = {
21540
21564
  name: nvOut[0],
@@ -21549,12 +21573,12 @@ function collectSnapshot(workingDir) {
21549
21573
  let battery = void 0;
21550
21574
  try {
21551
21575
  if (platform() === "linux") {
21552
- const cap = execSync23("cat /sys/class/power_supply/BAT0/capacity 2>/dev/null", { encoding: "utf-8", timeout: 1e3 }).trim();
21553
- const status = execSync23("cat /sys/class/power_supply/BAT0/status 2>/dev/null", { encoding: "utf-8", timeout: 1e3 }).trim();
21576
+ const cap = execSync24("cat /sys/class/power_supply/BAT0/capacity 2>/dev/null", { encoding: "utf-8", timeout: 1e3 }).trim();
21577
+ const status = execSync24("cat /sys/class/power_supply/BAT0/status 2>/dev/null", { encoding: "utf-8", timeout: 1e3 }).trim();
21554
21578
  if (cap)
21555
21579
  battery = { percent: parseInt(cap, 10), charging: status === "Charging" || status === "Full" };
21556
21580
  } else if (platform() === "darwin") {
21557
- const pmOut = execSync23("pmset -g batt", { encoding: "utf-8", timeout: 2e3 });
21581
+ const pmOut = execSync24("pmset -g batt", { encoding: "utf-8", timeout: 2e3 });
21558
21582
  const match = pmOut.match(/(\d+)%;\s*(charging|discharging|charged)/i);
21559
21583
  if (match)
21560
21584
  battery = { percent: parseInt(match[1], 10), charging: match[2].toLowerCase() !== "discharging" };
@@ -21575,8 +21599,8 @@ function collectSnapshot(workingDir) {
21575
21599
  }
21576
21600
  let processInfo = { total: 0, nodeCount: 0, oaSpawned: 0, topCpu: [] };
21577
21601
  try {
21578
- 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");
21579
- const total = parseInt(execSync23("ps aux | wc -l", { encoding: "utf-8", timeout: 2e3 }).trim(), 10);
21602
+ const psLines = execSync24("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");
21603
+ const total = parseInt(execSync24("ps aux | wc -l", { encoding: "utf-8", timeout: 2e3 }).trim(), 10);
21580
21604
  let nodeCount = 0;
21581
21605
  let oaSpawned = 0;
21582
21606
  const topCpu = [];
@@ -21657,7 +21681,7 @@ var init_environment_snapshot = __esm({
21657
21681
  });
21658
21682
 
21659
21683
  // packages/execution/dist/tools/video-understand.js
21660
- import { execSync as execSync24 } from "node:child_process";
21684
+ import { execSync as execSync25 } from "node:child_process";
21661
21685
  import { existsSync as existsSync27, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync20, readdirSync as readdirSync7, unlinkSync as unlinkSync4 } from "node:fs";
21662
21686
  import { join as join41, basename as basename10 } from "node:path";
21663
21687
  import { createHash as createHash2 } from "node:crypto";
@@ -21666,11 +21690,11 @@ function isYouTubeUrl2(url) {
21666
21690
  }
21667
21691
  function ensureYtDlp2() {
21668
21692
  try {
21669
- execSync24("yt-dlp --version", { timeout: 5e3, stdio: "pipe" });
21693
+ execSync25("yt-dlp --version", { timeout: 5e3, stdio: "pipe" });
21670
21694
  return true;
21671
21695
  } catch {
21672
21696
  try {
21673
- execSync24("pip3 install --break-system-packages yt-dlp 2>/dev/null || pip3 install --user yt-dlp 2>/dev/null", { timeout: 6e4, stdio: "pipe" });
21697
+ execSync25("pip3 install --break-system-packages yt-dlp 2>/dev/null || pip3 install --user yt-dlp 2>/dev/null", { timeout: 6e4, stdio: "pipe" });
21674
21698
  return true;
21675
21699
  } catch {
21676
21700
  return false;
@@ -21679,7 +21703,7 @@ function ensureYtDlp2() {
21679
21703
  }
21680
21704
  function ensureFfmpeg() {
21681
21705
  try {
21682
- execSync24("ffmpeg -version", { timeout: 3e3, stdio: "pipe" });
21706
+ execSync25("ffmpeg -version", { timeout: 3e3, stdio: "pipe" });
21683
21707
  return true;
21684
21708
  } catch {
21685
21709
  return false;
@@ -21759,32 +21783,32 @@ var init_video_understand = __esm({
21759
21783
  return { success: false, output: "", error: "yt-dlp required but not available. Install: pip3 install yt-dlp", durationMs: performance.now() - start };
21760
21784
  }
21761
21785
  try {
21762
- execSync24(`yt-dlp -f "worst[ext=mp4]" -o "${join41(tmpDir, "video.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
21786
+ execSync25(`yt-dlp -f "worst[ext=mp4]" -o "${join41(tmpDir, "video.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
21763
21787
  } catch {
21764
- execSync24(`yt-dlp -f worst -o "${join41(tmpDir, "video.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
21788
+ execSync25(`yt-dlp -f worst -o "${join41(tmpDir, "video.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
21765
21789
  }
21766
- execSync24(`yt-dlp -x --audio-format mp3 --audio-quality 5 -o "${join41(tmpDir, "audio.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
21790
+ execSync25(`yt-dlp -x --audio-format mp3 --audio-quality 5 -o "${join41(tmpDir, "audio.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
21767
21791
  try {
21768
- title = execSync24(`yt-dlp --get-title "${url}"`, { encoding: "utf-8", timeout: 15e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
21792
+ title = execSync25(`yt-dlp --get-title "${url}"`, { encoding: "utf-8", timeout: 15e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
21769
21793
  } catch {
21770
21794
  }
21771
21795
  } else {
21772
- execSync24(`curl -sL -o "${join41(tmpDir, "video.mp4")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
21773
- execSync24(`ffmpeg -i "${join41(tmpDir, "video.mp4")}" -vn -acodec libmp3lame -q:a 5 "${join41(tmpDir, "audio.mp3")}" -y`, { timeout: 12e4, stdio: "pipe" });
21796
+ execSync25(`curl -sL -o "${join41(tmpDir, "video.mp4")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
21797
+ execSync25(`ffmpeg -i "${join41(tmpDir, "video.mp4")}" -vn -acodec libmp3lame -q:a 5 "${join41(tmpDir, "audio.mp3")}" -y`, { timeout: 12e4, stdio: "pipe" });
21774
21798
  }
21775
21799
  videoPath = readdirSync7(tmpDir).find((f) => f.startsWith("video")) ? join41(tmpDir, readdirSync7(tmpDir).find((f) => f.startsWith("video"))) : join41(tmpDir, "video.mp4");
21776
21800
  audioPath = readdirSync7(tmpDir).find((f) => f.startsWith("audio")) ? join41(tmpDir, readdirSync7(tmpDir).find((f) => f.startsWith("audio"))) : join41(tmpDir, "audio.mp3");
21777
21801
  } else {
21778
21802
  videoPath = localPath;
21779
21803
  audioPath = join41(tmpDir, "audio.mp3");
21780
- execSync24(`ffmpeg -i "${videoPath}" -vn -acodec libmp3lame -q:a 5 "${audioPath}" -y`, { timeout: 12e4, stdio: "pipe" });
21804
+ execSync25(`ffmpeg -i "${videoPath}" -vn -acodec libmp3lame -q:a 5 "${audioPath}" -y`, { timeout: 12e4, stdio: "pipe" });
21781
21805
  }
21782
21806
  let segments = [];
21783
21807
  let language = "en";
21784
21808
  let duration = 0;
21785
21809
  try {
21786
21810
  const jsonOut = join41(tmpDir, "transcript.json");
21787
- execSync24(`transcribe-cli transcribe "${audioPath}" --model ${whisperModel} --format json -o "${tmpDir}"`, { timeout: 6e5, stdio: "pipe" });
21811
+ execSync25(`transcribe-cli transcribe "${audioPath}" --model ${whisperModel} --format json -o "${tmpDir}"`, { timeout: 6e5, stdio: "pipe" });
21788
21812
  const jsonFile = readdirSync7(tmpDir).find((f) => f.endsWith(".json") && f !== "result.json");
21789
21813
  if (jsonFile) {
21790
21814
  const data = JSON.parse(readFileSync20(join41(tmpDir, jsonFile), "utf-8"));
@@ -21807,7 +21831,7 @@ var init_video_understand = __esm({
21807
21831
  const fps = 25;
21808
21832
  const intervalFrames = Math.max(1, frameInterval * fps);
21809
21833
  try {
21810
- execSync24(`ffmpeg -i "${videoPath}" -vf "select='gt(scene\\,${sceneThreshold})+not(mod(n\\,${intervalFrames}))',showinfo" -vsync vfr "${join41(framesDir, "frame_%04d.jpg")}" -y`, { timeout: 3e5, stdio: "pipe" });
21834
+ execSync25(`ffmpeg -i "${videoPath}" -vf "select='gt(scene\\,${sceneThreshold})+not(mod(n\\,${intervalFrames}))',showinfo" -vsync vfr "${join41(framesDir, "frame_%04d.jpg")}" -y`, { timeout: 3e5, stdio: "pipe" });
21811
21835
  } catch {
21812
21836
  }
21813
21837
  const frameFiles = readdirSync7(framesDir).filter((f) => f.endsWith(".jpg")).sort();
@@ -21940,7 +21964,7 @@ Topic: ${segments.slice(0, 5).map((s) => s.text).join(" ").slice(0, 300)}`,
21940
21964
  }
21941
21965
  }
21942
21966
  try {
21943
- execSync24(`rm -rf "${tmpDir}"`, { timeout: 1e4, stdio: "pipe" });
21967
+ execSync25(`rm -rf "${tmpDir}"`, { timeout: 1e4, stdio: "pipe" });
21944
21968
  } catch {
21945
21969
  }
21946
21970
  return {
@@ -22839,7 +22863,10 @@ __export(dist_exports, {
22839
22863
  getWorkingNotesSummary: () => getWorkingNotesSummary,
22840
22864
  isFortemiAvailable: () => isFortemiAvailable,
22841
22865
  isImagePath: () => isImagePath,
22866
+ isProcessAlive: () => isProcessAlive,
22842
22867
  killAllFullSubAgents: () => killAllFullSubAgents,
22868
+ killProcess: () => killProcess,
22869
+ killProcessTree: () => killProcessTree,
22843
22870
  listCustomToolFiles: () => listCustomToolFiles,
22844
22871
  loadCustomTools: () => loadCustomTools,
22845
22872
  loadReminderStore: () => loadReminderStore,
@@ -22950,6 +22977,7 @@ var init_dist2 = __esm({
22950
22977
  init_typecheckRunner();
22951
22978
  init_testRunner();
22952
22979
  init_buildRunner();
22980
+ init_process_kill();
22953
22981
  init_validationPipeline();
22954
22982
  }
22955
22983
  });
@@ -28541,14 +28569,14 @@ ${transcript}`
28541
28569
  const buffer = Buffer.from(rawBase64, "base64");
28542
28570
  let resizedBase64 = null;
28543
28571
  try {
28544
- const { execSync: execSync35 } = await import("node:child_process");
28572
+ const { execSync: execSync36 } = await import("node:child_process");
28545
28573
  const { writeFileSync: writeFileSync30, readFileSync: readFileSync45, unlinkSync: unlinkSync13 } = await import("node:fs");
28546
28574
  const { join: join77 } = await import("node:path");
28547
28575
  const { tmpdir: tmpdir11 } = await import("node:os");
28548
28576
  const tmpIn = join77(tmpdir11(), `oa_img_in_${Date.now()}.png`);
28549
28577
  const tmpOut = join77(tmpdir11(), `oa_img_out_${Date.now()}.jpg`);
28550
28578
  writeFileSync30(tmpIn, buffer);
28551
- execSync35(`python3 -c "
28579
+ execSync36(`python3 -c "
28552
28580
  from PIL import Image
28553
28581
  img = Image.open('${tmpIn}')
28554
28582
  img.thumbnail((512, 512), Image.LANCZOS)
@@ -28608,8 +28636,8 @@ img.save('${tmpOut}', 'JPEG', quality=75)
28608
28636
  if (!res.ok && model === "moondream" && res.status === 404) {
28609
28637
  this.emit({ type: "status", content: `Pulling moondream vision model...`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
28610
28638
  try {
28611
- const { execSync: execSync35 } = await import("node:child_process");
28612
- execSync35("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
28639
+ const { execSync: execSync36 } = await import("node:child_process");
28640
+ execSync36("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
28613
28641
  res = await fetch(`${ollamaHost}/api/generate`, {
28614
28642
  method: "POST",
28615
28643
  headers: { "Content-Type": "application/json" },
@@ -30314,7 +30342,7 @@ __export(listen_exports, {
30314
30342
  isVideoPath: () => isVideoPath,
30315
30343
  waitForTranscribeCli: () => waitForTranscribeCli
30316
30344
  });
30317
- import { spawn as spawn16, execSync as execSync25 } from "node:child_process";
30345
+ import { spawn as spawn16, execSync as execSync26 } from "node:child_process";
30318
30346
  import { existsSync as existsSync32, mkdirSync as mkdirSync11, writeFileSync as writeFileSync12, readdirSync as readdirSync8 } from "node:fs";
30319
30347
  import { join as join48, dirname as dirname14 } from "node:path";
30320
30348
  import { homedir as homedir11 } from "node:os";
@@ -30336,7 +30364,7 @@ function findMicCaptureCommand() {
30336
30364
  const platform6 = process.platform;
30337
30365
  if (platform6 === "linux") {
30338
30366
  try {
30339
- execSync25("which arecord", { stdio: "pipe" });
30367
+ execSync26("which arecord", { stdio: "pipe" });
30340
30368
  return {
30341
30369
  cmd: "arecord",
30342
30370
  args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
@@ -30346,7 +30374,7 @@ function findMicCaptureCommand() {
30346
30374
  }
30347
30375
  if (platform6 === "darwin") {
30348
30376
  try {
30349
- execSync25("which sox", { stdio: "pipe" });
30377
+ execSync26("which sox", { stdio: "pipe" });
30350
30378
  return {
30351
30379
  cmd: "sox",
30352
30380
  args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
@@ -30355,7 +30383,7 @@ function findMicCaptureCommand() {
30355
30383
  }
30356
30384
  }
30357
30385
  try {
30358
- execSync25("which ffmpeg", { stdio: "pipe" });
30386
+ execSync26("which ffmpeg", { stdio: "pipe" });
30359
30387
  if (platform6 === "linux") {
30360
30388
  return {
30361
30389
  cmd: "ffmpeg",
@@ -30414,7 +30442,7 @@ function findLiveWhisperScript() {
30414
30442
  return p;
30415
30443
  }
30416
30444
  try {
30417
- const globalRoot = execSync25("npm root -g", {
30445
+ const globalRoot = execSync26("npm root -g", {
30418
30446
  encoding: "utf-8",
30419
30447
  timeout: 5e3,
30420
30448
  stdio: ["pipe", "pipe", "pipe"]
@@ -30447,7 +30475,7 @@ function ensureTranscribeCliBackground() {
30447
30475
  return;
30448
30476
  _bgInstallPromise = (async () => {
30449
30477
  try {
30450
- const globalRoot = execSync25("npm root -g", {
30478
+ const globalRoot = execSync26("npm root -g", {
30451
30479
  encoding: "utf-8",
30452
30480
  timeout: 5e3,
30453
30481
  stdio: ["pipe", "pipe", "pipe"]
@@ -30653,7 +30681,7 @@ var init_listen = __esm({
30653
30681
  }
30654
30682
  if (!this.transcribeCliAvailable) {
30655
30683
  try {
30656
- execSync25("which transcribe-cli", { stdio: "pipe" });
30684
+ execSync26("which transcribe-cli", { stdio: "pipe" });
30657
30685
  this.transcribeCliAvailable = true;
30658
30686
  } catch {
30659
30687
  this.transcribeCliAvailable = false;
@@ -30670,7 +30698,7 @@ var init_listen = __esm({
30670
30698
  } catch {
30671
30699
  }
30672
30700
  try {
30673
- const globalRoot = execSync25("npm root -g", {
30701
+ const globalRoot = execSync26("npm root -g", {
30674
30702
  encoding: "utf-8",
30675
30703
  timeout: 5e3,
30676
30704
  stdio: ["pipe", "pipe", "pipe"]
@@ -30720,7 +30748,7 @@ var init_listen = __esm({
30720
30748
  }
30721
30749
  if (!tc) {
30722
30750
  try {
30723
- execSync25("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
30751
+ execSync26("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
30724
30752
  this.transcribeCliAvailable = null;
30725
30753
  tc = await this.loadTranscribeCli();
30726
30754
  } catch {
@@ -30903,7 +30931,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
30903
30931
  }
30904
30932
  if (!tc) {
30905
30933
  try {
30906
- execSync25("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
30934
+ execSync26("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
30907
30935
  this.transcribeCliAvailable = null;
30908
30936
  tc = await this.loadTranscribeCli();
30909
30937
  } catch {
@@ -30957,7 +30985,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
30957
30985
  }
30958
30986
  if (!tc) {
30959
30987
  try {
30960
- execSync25("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
30988
+ execSync26("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
30961
30989
  this.transcribeCliAvailable = null;
30962
30990
  tc = await this.loadTranscribeCli();
30963
30991
  } catch {
@@ -35471,7 +35499,7 @@ var init_render = __esm({
35471
35499
 
35472
35500
  // packages/cli/dist/tui/voice-session.js
35473
35501
  import { createServer as createServer2 } from "node:http";
35474
- import { spawn as spawn17, execSync as execSync26 } from "node:child_process";
35502
+ import { spawn as spawn17, execSync as execSync27 } from "node:child_process";
35475
35503
  import { EventEmitter as EventEmitter2 } from "node:events";
35476
35504
  function generateFrontendHTML() {
35477
35505
  return `<!DOCTYPE html>
@@ -36657,7 +36685,7 @@ function removeExposeState(stateDir) {
36657
36685
  } catch {
36658
36686
  }
36659
36687
  }
36660
- function isProcessAlive(pid) {
36688
+ function isProcessAlive2(pid) {
36661
36689
  try {
36662
36690
  process.kill(pid, 0);
36663
36691
  return true;
@@ -36963,7 +36991,7 @@ var init_expose = __esm({
36963
36991
  async reconnect(state) {
36964
36992
  if (this.server)
36965
36993
  throw new Error("Gateway already running");
36966
- if (!isProcessAlive(state.pid)) {
36994
+ if (!isProcessAlive2(state.pid)) {
36967
36995
  if (this._stateDir)
36968
36996
  removeExposeState(this._stateDir);
36969
36997
  throw new Error("Cloudflared process is no longer running");
@@ -36986,7 +37014,7 @@ var init_expose = __esm({
36986
37014
  }
36987
37015
  async stop() {
36988
37016
  this.stopPidWatchdog();
36989
- if (this._cloudflaredPid && isProcessAlive(this._cloudflaredPid)) {
37017
+ if (this._cloudflaredPid && isProcessAlive2(this._cloudflaredPid)) {
36990
37018
  try {
36991
37019
  process.kill(this._cloudflaredPid, "SIGTERM");
36992
37020
  } catch {
@@ -37021,7 +37049,7 @@ var init_expose = __esm({
37021
37049
  const state = readExposeState(stateDir);
37022
37050
  if (!state)
37023
37051
  return null;
37024
- if (!isProcessAlive(state.pid)) {
37052
+ if (!isProcessAlive2(state.pid)) {
37025
37053
  removeExposeState(stateDir);
37026
37054
  return null;
37027
37055
  }
@@ -37505,7 +37533,7 @@ ${this.formatConnectionInfo()}`);
37505
37533
  startPidWatchdog() {
37506
37534
  this.stopPidWatchdog();
37507
37535
  this._pidWatchdog = setInterval(() => {
37508
- if (!this._cloudflaredPid || !isProcessAlive(this._cloudflaredPid)) {
37536
+ if (!this._cloudflaredPid || !isProcessAlive2(this._cloudflaredPid)) {
37509
37537
  this.stopPidWatchdog();
37510
37538
  if (this._stats.status === "active") {
37511
37539
  this.options.onInfo?.("Cloudflared tunnel died (detected by watchdog) \u2014 restarting...");
@@ -41350,6 +41378,7 @@ var DaemonRegistry, registry;
41350
41378
  var init_daemon_registry = __esm({
41351
41379
  "packages/cli/dist/tui/daemon-registry.js"() {
41352
41380
  "use strict";
41381
+ init_dist2();
41353
41382
  DaemonRegistry = class {
41354
41383
  daemons = /* @__PURE__ */ new Map();
41355
41384
  subAgents = /* @__PURE__ */ new Map();
@@ -41370,34 +41399,23 @@ var init_daemon_registry = __esm({
41370
41399
  for (const [, d] of this.daemons) {
41371
41400
  if (d.status === "stopped" || d.status === "error")
41372
41401
  continue;
41373
- try {
41374
- process.kill(d.pid, 0);
41402
+ if (isProcessAlive(d.pid)) {
41375
41403
  if (d.status === "starting")
41376
41404
  d.status = "running";
41377
- } catch {
41405
+ } else {
41378
41406
  d.status = "stopped";
41379
41407
  }
41380
41408
  }
41381
41409
  }
41382
- /** Kill all tracked daemons (called on exit/update) */
41410
+ /**
41411
+ * Kill all tracked daemons immediately (called on exit/update).
41412
+ * Uses cross-platform killProcessTree — taskkill /T /F on Windows,
41413
+ * process group kill on Unix. Synchronous, no setTimeout.
41414
+ */
41383
41415
  killAll() {
41384
- const pids = [];
41385
41416
  for (const [, d] of this.daemons) {
41386
- try {
41387
- process.kill(d.pid, "SIGTERM");
41388
- pids.push(d.pid);
41389
- } catch {
41390
- }
41391
- }
41392
- if (pids.length > 0) {
41393
- setTimeout(() => {
41394
- for (const pid of pids) {
41395
- try {
41396
- process.kill(pid, "SIGKILL");
41397
- } catch {
41398
- }
41399
- }
41400
- }, 3e3);
41417
+ killProcessTree(d.pid, "SIGKILL");
41418
+ d.status = "stopped";
41401
41419
  }
41402
41420
  }
41403
41421
  /** Render the monitoring bar as an ANSI string */
@@ -41451,7 +41469,7 @@ __export(personaplex_exports, {
41451
41469
  import { existsSync as existsSync37, writeFileSync as writeFileSync16, readFileSync as readFileSync28, mkdirSync as mkdirSync15, copyFileSync as copyFileSync2, readdirSync as readdirSync11, statSync as statSync13 } from "node:fs";
41452
41470
  import { join as join54, dirname as dirname18 } from "node:path";
41453
41471
  import { homedir as homedir13 } from "node:os";
41454
- import { execSync as execSync27, spawn as spawn19, execFile as execFile7 } from "node:child_process";
41472
+ import { execSync as execSync28, spawn as spawn19, execFile as execFile7 } from "node:child_process";
41455
41473
  import { fileURLToPath as fileURLToPath11 } from "node:url";
41456
41474
  function execAsync(cmd, opts = {}) {
41457
41475
  return new Promise((resolve36, reject) => {
@@ -41488,7 +41506,7 @@ function detectJetson() {
41488
41506
  try {
41489
41507
  const model = readFileSync28("/proc/device-tree/model", "utf8").replace(/\0/g, "").trim();
41490
41508
  if (/jetson|orin|tegra/i.test(model)) {
41491
- const memInfo = execSync27("grep MemTotal /proc/meminfo", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
41509
+ const memInfo = execSync28("grep MemTotal /proc/meminfo", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
41492
41510
  const memKB = parseInt(memInfo.match(/(\d+)/)?.[1] ?? "0", 10);
41493
41511
  return { isJetson: true, model, totalMemGB: memKB / 1024 / 1024 };
41494
41512
  }
@@ -41523,7 +41541,7 @@ function detectPersonaPlexCapability() {
41523
41541
  };
41524
41542
  }
41525
41543
  try {
41526
- const nvsmi = execSync27("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits", {
41544
+ const nvsmi = execSync28("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits", {
41527
41545
  encoding: "utf8",
41528
41546
  timeout: 5e3,
41529
41547
  stdio: "pipe"
@@ -41536,7 +41554,7 @@ function detectPersonaPlexCapability() {
41536
41554
  return { ...fail(`GPU has ${vramGB.toFixed(1)}GB VRAM (need \u22658GB)`), gpuName: gpuName ?? "", vramGB };
41537
41555
  }
41538
41556
  try {
41539
- execSync27('python3 -c "import torch; assert torch.cuda.is_available()"', {
41557
+ execSync28('python3 -c "import torch; assert torch.cuda.is_available()"', {
41540
41558
  timeout: 1e4,
41541
41559
  stdio: "pipe"
41542
41560
  });
@@ -41613,7 +41631,7 @@ async function installPersonaPlex(onInfo, weightTier) {
41613
41631
  mkdirSync15(PERSONAPLEX_DIR, { recursive: true });
41614
41632
  let arch2 = "";
41615
41633
  try {
41616
- arch2 = execSync27("uname -m", { encoding: "utf8", timeout: 3e3, stdio: "pipe" }).trim();
41634
+ arch2 = execSync28("uname -m", { encoding: "utf8", timeout: 3e3, stdio: "pipe" }).trim();
41617
41635
  } catch {
41618
41636
  }
41619
41637
  const isAarch64 = arch2 === "aarch64" || arch2 === "arm64";
@@ -41635,16 +41653,16 @@ async function installPersonaPlex(onInfo, weightTier) {
41635
41653
  log("Checking system dependencies (libopus)...");
41636
41654
  try {
41637
41655
  if (process.platform === "linux") {
41638
- execSync27("dpkg -l libopus-dev 2>/dev/null || sudo apt-get install -y libopus-dev", { timeout: 3e4, stdio: "pipe" });
41656
+ execSync28("dpkg -l libopus-dev 2>/dev/null || sudo apt-get install -y libopus-dev", { timeout: 3e4, stdio: "pipe" });
41639
41657
  } else if (process.platform === "darwin") {
41640
- execSync27("brew list opus 2>/dev/null || brew install opus", { timeout: 6e4, stdio: "pipe" });
41658
+ execSync28("brew list opus 2>/dev/null || brew install opus", { timeout: 6e4, stdio: "pipe" });
41641
41659
  }
41642
41660
  } catch {
41643
41661
  }
41644
41662
  if (isAarch64) {
41645
41663
  log("ARM64: Checking Rust toolchain for sphn build...");
41646
41664
  try {
41647
- execSync27("rustc --version", { timeout: 5e3, stdio: "pipe" });
41665
+ execSync28("rustc --version", { timeout: 5e3, stdio: "pipe" });
41648
41666
  } catch {
41649
41667
  log("ARM64: Installing Rust toolchain (needed for sphn audio codec)...");
41650
41668
  try {
@@ -41701,7 +41719,7 @@ async function installPersonaPlex(onInfo, weightTier) {
41701
41719
  }
41702
41720
  const serverPy = join54(venvDir, "lib", `python3.${process.versions.node ? "12" : "10"}`, "site-packages", "moshi", "server.py");
41703
41721
  try {
41704
- const sitePackages = execSync27(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
41722
+ const sitePackages = execSync28(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
41705
41723
  encoding: "utf8",
41706
41724
  timeout: 5e3,
41707
41725
  stdio: "pipe"
@@ -41718,7 +41736,7 @@ async function installPersonaPlex(onInfo, weightTier) {
41718
41736
  } catch {
41719
41737
  }
41720
41738
  try {
41721
- const sitePackages = execSync27(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
41739
+ const sitePackages = execSync28(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
41722
41740
  encoding: "utf8",
41723
41741
  timeout: 5e3,
41724
41742
  stdio: "pipe"
@@ -41816,7 +41834,7 @@ $2if filename.endswith(".safetensors"):`);
41816
41834
  } catch {
41817
41835
  }
41818
41836
  try {
41819
- const sitePackages2 = execSync27(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
41837
+ const sitePackages2 = execSync28(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
41820
41838
  encoding: "utf8",
41821
41839
  timeout: 5e3,
41822
41840
  stdio: "pipe"
@@ -41945,11 +41963,11 @@ async function startPersonaPlexDaemon(onInfo) {
41945
41963
  if (tier === "nf4-distilled") {
41946
41964
  log(`Weight tier: ${tier} \u2014 distilled NF4 (90% token match, ${repoInfo.sizeGB}GB)...`);
41947
41965
  try {
41948
- const weightPath = execSync27(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}', token=False))"`, { encoding: "utf8", timeout: 6e4, stdio: "pipe" }).trim();
41966
+ const weightPath = execSync28(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}', token=False))"`, { encoding: "utf8", timeout: 6e4, stdio: "pipe" }).trim();
41949
41967
  if (existsSync37(weightPath)) {
41950
41968
  if (!existsSync37(cachedBf16)) {
41951
41969
  log("Converting .pt checkpoint to safetensors (one-time)...");
41952
- execSync27(`"${venvPython2}" -c "
41970
+ execSync28(`"${venvPython2}" -c "
41953
41971
  import torch; from safetensors.torch import save_file
41954
41972
  state = torch.load('${weightPath}', map_location='cpu', weights_only=True)
41955
41973
  state = {k: v.to(torch.bfloat16) if v.is_floating_point() else v for k, v in state.items()}
@@ -41979,10 +41997,10 @@ print('Converted')
41979
41997
  }
41980
41998
  }
41981
41999
  try {
41982
- const weightPath = execSync27(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}'${repoInfo.needsToken ? "" : ", token=False"}))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
42000
+ const weightPath = execSync28(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}'${repoInfo.needsToken ? "" : ", token=False"}))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
41983
42001
  if (existsSync37(dequantScript) && existsSync37(weightPath)) {
41984
42002
  try {
41985
- execSync27(`"${venvPython2}" "${dequantScript}" --input "${weightPath}" --output "${cachedBf16}"`, { timeout: 3e5, stdio: "pipe" });
42003
+ execSync28(`"${venvPython2}" "${dequantScript}" --input "${weightPath}" --output "${cachedBf16}"`, { timeout: 3e5, stdio: "pipe" });
41986
42004
  if (existsSync37(cachedBf16)) {
41987
42005
  extraArgs.push("--moshi-weight", cachedBf16);
41988
42006
  log(`Using dequantized cache: ${(statSync13(cachedBf16).size / 1024 ** 3).toFixed(1)}GB`);
@@ -41992,13 +42010,13 @@ print('Converted')
41992
42010
  }
41993
42011
  }
41994
42012
  try {
41995
- const mimiPath = execSync27(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer-e351c8d8-checkpoint125.safetensors', token=False))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
42013
+ const mimiPath = execSync28(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer-e351c8d8-checkpoint125.safetensors', token=False))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
41996
42014
  if (existsSync37(mimiPath))
41997
42015
  extraArgs.push("--mimi-weight", mimiPath);
41998
42016
  } catch {
41999
42017
  }
42000
42018
  try {
42001
- const tokPath = execSync27(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer_spm_32k_3.model', token=False))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
42019
+ const tokPath = execSync28(`"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer_spm_32k_3.model', token=False))"`, { encoding: "utf8", timeout: 3e4, stdio: "pipe" }).trim();
42002
42020
  if (existsSync37(tokPath))
42003
42021
  extraArgs.push("--tokenizer", tokPath);
42004
42022
  } catch {
@@ -42022,7 +42040,7 @@ print('Converted')
42022
42040
  if (!ollamaModel)
42023
42041
  ollamaModel = "qwen3.5:4b";
42024
42042
  try {
42025
- const ollamaCheck = execSync27("curl -s http://localhost:11434/api/tags", {
42043
+ const ollamaCheck = execSync28("curl -s http://localhost:11434/api/tags", {
42026
42044
  timeout: 3e3,
42027
42045
  stdio: "pipe",
42028
42046
  encoding: "utf8"
@@ -42099,7 +42117,7 @@ print('Converted')
42099
42117
  return null;
42100
42118
  }
42101
42119
  try {
42102
- execSync27(`curl -sk -o /dev/null -w "%{http_code}" https://127.0.0.1:${PORT}/`, {
42120
+ execSync28(`curl -sk -o /dev/null -w "%{http_code}" https://127.0.0.1:${PORT}/`, {
42103
42121
  timeout: 3e3,
42104
42122
  stdio: "pipe",
42105
42123
  encoding: "utf8"
@@ -42125,7 +42143,7 @@ function stopPersonaPlex() {
42125
42143
  return;
42126
42144
  try {
42127
42145
  if (process.platform === "win32") {
42128
- execSync27(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
42146
+ execSync28(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
42129
42147
  } else {
42130
42148
  process.kill(pid, "SIGTERM");
42131
42149
  }
@@ -42406,7 +42424,7 @@ var init_personaplex = __esm({
42406
42424
 
42407
42425
  // packages/cli/dist/tui/setup.js
42408
42426
  import * as readline from "node:readline";
42409
- import { execSync as execSync28, spawn as spawn20, exec as exec2 } from "node:child_process";
42427
+ import { execSync as execSync29, spawn as spawn20, exec as exec2 } from "node:child_process";
42410
42428
  import { promisify as promisify6 } from "node:util";
42411
42429
  import { existsSync as existsSync38, writeFileSync as writeFileSync17, readFileSync as readFileSync29, appendFileSync as appendFileSync2, mkdirSync as mkdirSync16 } from "node:fs";
42412
42430
  import { join as join55 } from "node:path";
@@ -42441,7 +42459,7 @@ function detectSystemSpecs() {
42441
42459
  let gpuVramGB = 0;
42442
42460
  let gpuName = "";
42443
42461
  try {
42444
- const memInfo = execSync28("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
42462
+ const memInfo = execSync29("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
42445
42463
  encoding: "utf8",
42446
42464
  timeout: 5e3
42447
42465
  });
@@ -42461,7 +42479,7 @@ function detectSystemSpecs() {
42461
42479
  } catch {
42462
42480
  }
42463
42481
  try {
42464
- const nvidiaSmi = execSync28("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
42482
+ const nvidiaSmi = execSync29("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
42465
42483
  const lines = nvidiaSmi.trim().split("\n");
42466
42484
  if (lines.length > 0) {
42467
42485
  for (const line of lines) {
@@ -42632,7 +42650,7 @@ function ensureCurl() {
42632
42650
  for (const s of strategies) {
42633
42651
  if (hasCmd(s.check)) {
42634
42652
  try {
42635
- execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
42653
+ execSync29(s.install, { stdio: "inherit", timeout: 12e4 });
42636
42654
  if (hasCmd("curl")) {
42637
42655
  process.stdout.write(` ${c2.green("\u2714")} curl installed via ${s.label}.
42638
42656
  `);
@@ -42646,7 +42664,7 @@ function ensureCurl() {
42646
42664
  }
42647
42665
  if (plat === "darwin") {
42648
42666
  try {
42649
- execSync28("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
42667
+ execSync29("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
42650
42668
  if (hasCmd("curl"))
42651
42669
  return true;
42652
42670
  } catch {
@@ -42681,7 +42699,7 @@ function installOllamaLinux() {
42681
42699
 
42682
42700
  `);
42683
42701
  try {
42684
- execSync28("curl -fsSL https://ollama.com/install.sh | sh", {
42702
+ execSync29("curl -fsSL https://ollama.com/install.sh | sh", {
42685
42703
  stdio: "inherit",
42686
42704
  timeout: 3e5
42687
42705
  });
@@ -42709,7 +42727,7 @@ async function installOllamaMac(_rl) {
42709
42727
 
42710
42728
  `);
42711
42729
  try {
42712
- execSync28('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
42730
+ execSync29('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
42713
42731
  if (!hasCmd("brew")) {
42714
42732
  try {
42715
42733
  const brewPrefix = existsSync38("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
@@ -42742,7 +42760,7 @@ async function installOllamaMac(_rl) {
42742
42760
 
42743
42761
  `);
42744
42762
  try {
42745
- execSync28("brew install ollama", {
42763
+ execSync29("brew install ollama", {
42746
42764
  stdio: "inherit",
42747
42765
  timeout: 3e5
42748
42766
  });
@@ -42769,7 +42787,7 @@ function installOllamaWindows() {
42769
42787
 
42770
42788
  `);
42771
42789
  try {
42772
- execSync28('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
42790
+ execSync29('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
42773
42791
  stdio: "inherit",
42774
42792
  timeout: 3e5
42775
42793
  });
@@ -42850,7 +42868,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
42850
42868
  }
42851
42869
  function pullModelWithAutoUpdate(tag) {
42852
42870
  try {
42853
- execSync28(`ollama pull ${tag}`, {
42871
+ execSync29(`ollama pull ${tag}`, {
42854
42872
  stdio: "inherit",
42855
42873
  timeout: 36e5
42856
42874
  // 1 hour max
@@ -42870,7 +42888,7 @@ function pullModelWithAutoUpdate(tag) {
42870
42888
 
42871
42889
  `);
42872
42890
  try {
42873
- execSync28("curl -fsSL https://ollama.com/install.sh | sh", {
42891
+ execSync29("curl -fsSL https://ollama.com/install.sh | sh", {
42874
42892
  stdio: "inherit",
42875
42893
  timeout: 3e5
42876
42894
  // 5 min max for install
@@ -42881,7 +42899,7 @@ function pullModelWithAutoUpdate(tag) {
42881
42899
  process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
42882
42900
 
42883
42901
  `);
42884
- execSync28(`ollama pull ${tag}`, {
42902
+ execSync29(`ollama pull ${tag}`, {
42885
42903
  stdio: "inherit",
42886
42904
  timeout: 36e5
42887
42905
  });
@@ -42983,7 +43001,7 @@ function ensurePython3() {
42983
43001
  if (plat === "darwin") {
42984
43002
  if (hasCmd("brew")) {
42985
43003
  try {
42986
- execSync28("brew install python3", { stdio: "inherit", timeout: 3e5 });
43004
+ execSync29("brew install python3", { stdio: "inherit", timeout: 3e5 });
42987
43005
  if (hasCmd("python3")) {
42988
43006
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via Homebrew.
42989
43007
  `);
@@ -42996,7 +43014,7 @@ function ensurePython3() {
42996
43014
  for (const s of strategies) {
42997
43015
  if (hasCmd(s.check)) {
42998
43016
  try {
42999
- execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
43017
+ execSync29(s.install, { stdio: "inherit", timeout: 12e4 });
43000
43018
  if (hasCmd("python3") || hasCmd("python")) {
43001
43019
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via ${s.label}.
43002
43020
  `);
@@ -43012,11 +43030,11 @@ function ensurePython3() {
43012
43030
  }
43013
43031
  function checkPythonVenv() {
43014
43032
  try {
43015
- execSync28("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
43033
+ execSync29("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
43016
43034
  return true;
43017
43035
  } catch {
43018
43036
  try {
43019
- execSync28("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
43037
+ execSync29("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
43020
43038
  return true;
43021
43039
  } catch {
43022
43040
  return false;
@@ -43035,7 +43053,7 @@ function ensurePythonVenv() {
43035
43053
  for (const s of strategies) {
43036
43054
  if (hasCmd(s.check)) {
43037
43055
  try {
43038
- execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
43056
+ execSync29(s.install, { stdio: "inherit", timeout: 12e4 });
43039
43057
  if (checkPythonVenv()) {
43040
43058
  process.stdout.write(` ${c2.green("\u2714")} python3-venv installed via ${s.label}.
43041
43059
  `);
@@ -43462,7 +43480,7 @@ async function doSetup(config, rl) {
43462
43480
  const modelfilePath = join55(modelDir2, `Modelfile.${customName}`);
43463
43481
  writeFileSync17(modelfilePath, modelfileContent + "\n", "utf8");
43464
43482
  process.stdout.write(` ${c2.dim("Creating model...")} `);
43465
- execSync28(`ollama create ${customName} -f ${modelfilePath}`, {
43483
+ execSync29(`ollama create ${customName} -f ${modelfilePath}`, {
43466
43484
  stdio: "pipe",
43467
43485
  timeout: 12e4
43468
43486
  });
@@ -43513,7 +43531,7 @@ function isFirstRun() {
43513
43531
  function hasCmd(cmd) {
43514
43532
  try {
43515
43533
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
43516
- execSync28(whichCmd, { stdio: "pipe", timeout: 3e3 });
43534
+ execSync29(whichCmd, { stdio: "pipe", timeout: 3e3 });
43517
43535
  return true;
43518
43536
  } catch {
43519
43537
  return false;
@@ -43527,7 +43545,7 @@ function detectPkgManager() {
43527
43545
  if (hasCmd("winget"))
43528
43546
  return "winget";
43529
43547
  try {
43530
- execSync28(`powershell -NoProfile -Command "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))"`, { stdio: "pipe", timeout: 12e4 });
43548
+ execSync29(`powershell -NoProfile -Command "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))"`, { stdio: "pipe", timeout: 12e4 });
43531
43549
  if (hasCmd("choco"))
43532
43550
  return "choco";
43533
43551
  } catch {
@@ -43538,7 +43556,7 @@ function detectPkgManager() {
43538
43556
  if (hasCmd("brew"))
43539
43557
  return "brew";
43540
43558
  try {
43541
- execSync28('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "pipe", timeout: 3e5, env: { ...process.env, NONINTERACTIVE: "1" } });
43559
+ execSync29('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "pipe", timeout: 3e5, env: { ...process.env, NONINTERACTIVE: "1" } });
43542
43560
  if (hasCmd("brew"))
43543
43561
  return "brew";
43544
43562
  } catch {
@@ -43560,7 +43578,7 @@ function getVenvDir() {
43560
43578
  }
43561
43579
  function hasVenvModule() {
43562
43580
  try {
43563
- execSync28("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
43581
+ execSync29("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
43564
43582
  return true;
43565
43583
  } catch {
43566
43584
  return false;
@@ -43585,8 +43603,8 @@ function ensureVenv(log) {
43585
43603
  try {
43586
43604
  mkdirSync16(join55(homedir14(), ".open-agents"), { recursive: true });
43587
43605
  const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
43588
- execSync28(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
43589
- execSync28(`"${pipPath}" install --upgrade pip`, {
43606
+ execSync29(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
43607
+ execSync29(`"${pipPath}" install --upgrade pip`, {
43590
43608
  stdio: "pipe",
43591
43609
  timeout: 6e4
43592
43610
  });
@@ -43599,7 +43617,7 @@ function ensureVenv(log) {
43599
43617
  }
43600
43618
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
43601
43619
  try {
43602
- execSync28(`sudo -n ${cmd}`, {
43620
+ execSync29(`sudo -n ${cmd}`, {
43603
43621
  stdio: "pipe",
43604
43622
  timeout: timeoutMs,
43605
43623
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -43612,7 +43630,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
43612
43630
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
43613
43631
  try {
43614
43632
  const escaped = cmd.replace(/'/g, "'\\''");
43615
- execSync28(`sudo -S bash -c '${escaped}'`, {
43633
+ execSync29(`sudo -S bash -c '${escaped}'`, {
43616
43634
  input: password + "\n",
43617
43635
  stdio: ["pipe", "pipe", "pipe"],
43618
43636
  timeout: timeoutMs,
@@ -43732,7 +43750,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
43732
43750
  ok = await sudoInstall(batchCmd, getPassword, log, cachedPasswordRef, 18e4);
43733
43751
  } else {
43734
43752
  try {
43735
- execSync28(batchCmd, { stdio: "pipe", timeout: 18e4 });
43753
+ execSync29(batchCmd, { stdio: "pipe", timeout: 18e4 });
43736
43754
  ok = true;
43737
43755
  } catch {
43738
43756
  ok = false;
@@ -43769,7 +43787,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
43769
43787
  const venvCmds = {
43770
43788
  apt: () => {
43771
43789
  try {
43772
- const pyVer = execSync28(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
43790
+ const pyVer = execSync29(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
43773
43791
  return `apt-get install -y python3-venv python${pyVer}-venv`;
43774
43792
  } catch {
43775
43793
  return "apt-get install -y python3-venv";
@@ -43798,12 +43816,12 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
43798
43816
  const venvPip2 = join55(venvBin, "pip");
43799
43817
  log("Installing moondream-station in ~/.open-agents/venv...");
43800
43818
  try {
43801
- execSync28(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
43819
+ execSync29(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
43802
43820
  if (existsSync38(venvMoondream)) {
43803
43821
  log("moondream-station installed successfully.");
43804
43822
  } else {
43805
43823
  try {
43806
- const check = execSync28(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
43824
+ const check = execSync29(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
43807
43825
  if (check.includes("moondream")) {
43808
43826
  log("moondream-station package installed.");
43809
43827
  }
@@ -43820,7 +43838,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
43820
43838
  const venvPip2 = join55(venvBin, isWin2 ? "pip.exe" : "pip");
43821
43839
  let ocrStackInstalled = false;
43822
43840
  try {
43823
- execSync28(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
43841
+ execSync29(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
43824
43842
  ocrStackInstalled = true;
43825
43843
  } catch {
43826
43844
  }
@@ -43828,9 +43846,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
43828
43846
  const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
43829
43847
  log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
43830
43848
  try {
43831
- execSync28(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
43849
+ execSync29(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
43832
43850
  try {
43833
- execSync28(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
43851
+ execSync29(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
43834
43852
  log("OCR Python stack installed successfully.");
43835
43853
  } catch {
43836
43854
  log("OCR Python stack install completed but import verification failed.");
@@ -43864,7 +43882,7 @@ function ensureCloudflaredBackground(onInfo) {
43864
43882
  const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
43865
43883
  const cfArch = archMap[arch2] ?? "amd64";
43866
43884
  try {
43867
- execSync28(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir14()}/.local/bin" && mv /tmp/cloudflared "${homedir14()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
43885
+ execSync29(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir14()}/.local/bin" && mv /tmp/cloudflared "${homedir14()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
43868
43886
  if (!process.env.PATH?.includes(`${homedir14()}/.local/bin`)) {
43869
43887
  process.env.PATH = `${homedir14()}/.local/bin:${process.env.PATH}`;
43870
43888
  }
@@ -43875,7 +43893,7 @@ function ensureCloudflaredBackground(onInfo) {
43875
43893
  } catch {
43876
43894
  }
43877
43895
  try {
43878
- execSync28(`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 });
43896
+ execSync29(`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 });
43879
43897
  if (hasCmd("cloudflared")) {
43880
43898
  log("cloudflared installed.");
43881
43899
  return true;
@@ -43884,7 +43902,7 @@ function ensureCloudflaredBackground(onInfo) {
43884
43902
  }
43885
43903
  } else if (os === "darwin") {
43886
43904
  try {
43887
- execSync28("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
43905
+ execSync29("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
43888
43906
  if (hasCmd("cloudflared")) {
43889
43907
  log("cloudflared installed via Homebrew.");
43890
43908
  return true;
@@ -44026,7 +44044,7 @@ async function ensureExpandedContext(modelName, backendUrl) {
44026
44044
  }
44027
44045
  async function ensureNeovim() {
44028
44046
  try {
44029
- const nvimPath = execSync28("which nvim 2>/dev/null || where nvim 2>nul", {
44047
+ const nvimPath = execSync29("which nvim 2>/dev/null || where nvim 2>nul", {
44030
44048
  encoding: "utf8",
44031
44049
  stdio: "pipe",
44032
44050
  timeout: 5e3
@@ -44048,14 +44066,14 @@ async function ensureNeovim() {
44048
44066
  const url = `https://github.com/neovim/neovim/releases/latest/download/${appImageName}`;
44049
44067
  console.log(` Downloading Neovim (${appImageName})...`);
44050
44068
  try {
44051
- execSync28(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
44052
- execSync28(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
44069
+ execSync29(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
44070
+ execSync29(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
44053
44071
  } catch (err) {
44054
44072
  console.log(` Failed to download Neovim: ${err instanceof Error ? err.message : String(err)}`);
44055
44073
  return null;
44056
44074
  }
44057
44075
  try {
44058
- const ver = execSync28(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
44076
+ const ver = execSync29(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
44059
44077
  console.log(` Installed: ${ver}`);
44060
44078
  } catch {
44061
44079
  console.log(" Warning: nvim binary downloaded but may not work (missing FUSE? Try: nvim --appimage-extract)");
@@ -44070,8 +44088,8 @@ async function ensureNeovim() {
44070
44088
  if (hasCmd("brew")) {
44071
44089
  console.log(" Installing Neovim via Homebrew...");
44072
44090
  try {
44073
- execSync28("brew install neovim", { stdio: "inherit", timeout: 12e4 });
44074
- const nvimPath = execSync28("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
44091
+ execSync29("brew install neovim", { stdio: "inherit", timeout: 12e4 });
44092
+ const nvimPath = execSync29("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
44075
44093
  return nvimPath || null;
44076
44094
  } catch {
44077
44095
  console.log(" brew install neovim failed.");
@@ -44085,7 +44103,7 @@ async function ensureNeovim() {
44085
44103
  if (hasCmd("choco")) {
44086
44104
  console.log(" Installing Neovim via Chocolatey...");
44087
44105
  try {
44088
- execSync28("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
44106
+ execSync29("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
44089
44107
  return "nvim";
44090
44108
  } catch {
44091
44109
  console.log(" choco install neovim failed.");
@@ -44094,7 +44112,7 @@ async function ensureNeovim() {
44094
44112
  if (hasCmd("winget")) {
44095
44113
  console.log(" Installing Neovim via winget...");
44096
44114
  try {
44097
- execSync28("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
44115
+ execSync29("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
44098
44116
  stdio: "inherit",
44099
44117
  timeout: 12e4
44100
44118
  });
@@ -44340,7 +44358,7 @@ var init_drop_panel = __esm({
44340
44358
  import { existsSync as existsSync40, unlinkSync as unlinkSync8 } from "node:fs";
44341
44359
  import { tmpdir as tmpdir8 } from "node:os";
44342
44360
  import { join as join56 } from "node:path";
44343
- import { execSync as execSync29 } from "node:child_process";
44361
+ import { execSync as execSync30 } from "node:child_process";
44344
44362
  function isNeovimActive() {
44345
44363
  return _state !== null && !_state.cleanedUp;
44346
44364
  }
@@ -44358,7 +44376,7 @@ async function startNeovimMode(opts) {
44358
44376
  }
44359
44377
  let nvimPath;
44360
44378
  try {
44361
- nvimPath = execSync29("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
44379
+ nvimPath = execSync30("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
44362
44380
  if (!nvimPath)
44363
44381
  throw new Error();
44364
44382
  } catch {
@@ -45933,7 +45951,7 @@ __export(voice_exports, {
45933
45951
  import { existsSync as existsSync42, mkdirSync as mkdirSync18, writeFileSync as writeFileSync19, readFileSync as readFileSync31, unlinkSync as unlinkSync9, readdirSync as readdirSync12, renameSync, statSync as statSync14 } from "node:fs";
45934
45952
  import { join as join58, dirname as dirname19 } from "node:path";
45935
45953
  import { homedir as homedir15, tmpdir as tmpdir9, platform as platform3 } from "node:os";
45936
- import { execSync as execSync30, spawn as nodeSpawn } from "node:child_process";
45954
+ import { execSync as execSync31, spawn as nodeSpawn } from "node:child_process";
45937
45955
  import { createRequire } from "node:module";
45938
45956
  function sanitizeForTTS(text) {
45939
45957
  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();
@@ -47675,7 +47693,7 @@ var init_voice = __esm({
47675
47693
  }
47676
47694
  for (const player of ["paplay", "pw-play", "aplay"]) {
47677
47695
  try {
47678
- execSync30(`which ${player}`, { stdio: "pipe" });
47696
+ execSync31(`which ${player}`, { stdio: "pipe" });
47679
47697
  return [player, path];
47680
47698
  } catch {
47681
47699
  }
@@ -47704,7 +47722,7 @@ var init_voice = __esm({
47704
47722
  return this.python3Path;
47705
47723
  for (const bin of ["python3", "python"]) {
47706
47724
  try {
47707
- const path = execSync30(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
47725
+ const path = execSync31(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
47708
47726
  if (path) {
47709
47727
  this.python3Path = path;
47710
47728
  return path;
@@ -47770,7 +47788,7 @@ var init_voice = __esm({
47770
47788
  return false;
47771
47789
  }
47772
47790
  try {
47773
- execSync30(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
47791
+ execSync31(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
47774
47792
  this.mlxInstalled = true;
47775
47793
  return true;
47776
47794
  } catch {
@@ -47831,11 +47849,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
47831
47849
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
47832
47850
  ].join("; ");
47833
47851
  try {
47834
- execSync30(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
47852
+ execSync31(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
47835
47853
  } catch (err) {
47836
47854
  try {
47837
47855
  const safeText = cleaned.replace(/'/g, "'\\''");
47838
- execSync30(`${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() });
47856
+ execSync31(`${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() });
47839
47857
  } catch (err2) {
47840
47858
  return;
47841
47859
  }
@@ -47899,11 +47917,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
47899
47917
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
47900
47918
  ].join("; ");
47901
47919
  try {
47902
- execSync30(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
47920
+ execSync31(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
47903
47921
  } catch {
47904
47922
  try {
47905
47923
  const safeText = cleaned.replace(/'/g, "'\\''");
47906
- execSync30(`${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() });
47924
+ execSync31(`${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() });
47907
47925
  } catch {
47908
47926
  return null;
47909
47927
  }
@@ -48850,19 +48868,13 @@ async function destroyOrphanProcesses(ctx, global) {
48850
48868
  `);
48851
48869
  }
48852
48870
  for (const c3 of candidates) {
48853
- if (!isWin2) {
48854
- try {
48855
- process.kill(-c3.pid, "SIGTERM");
48856
- } catch {
48857
- }
48858
- }
48859
- if (killPid(c3.pid, "SIGTERM"))
48860
- killed++;
48871
+ killProcessTree(c3.pid, "SIGTERM");
48872
+ killed++;
48861
48873
  }
48862
48874
  if (killed > 0) {
48863
48875
  await new Promise((r) => setTimeout(r, 2e3));
48864
48876
  for (const c3 of candidates) {
48865
- killPid(c3.pid, "SIGKILL");
48877
+ killProcessTree(c3.pid, "SIGKILL");
48866
48878
  }
48867
48879
  }
48868
48880
  } catch {
@@ -49148,16 +49160,9 @@ async function handleSlashCommand(input, ctx) {
49148
49160
  try {
49149
49161
  const pid = parseInt(rf(pidFile, "utf8").trim(), 10);
49150
49162
  if (pid > 0) {
49151
- try {
49152
- process.kill(pid, "SIGTERM");
49153
- } catch {
49154
- }
49163
+ killProcessTree(pid, "SIGTERM");
49155
49164
  await new Promise((r) => setTimeout(r, 1200));
49156
- try {
49157
- process.kill(pid, 0);
49158
- process.kill(pid, "SIGKILL");
49159
- } catch {
49160
- }
49165
+ killProcessTree(pid, "SIGKILL");
49161
49166
  killed = true;
49162
49167
  process.stdout.write(` ${c2.yellow("\u25CF")} Killed daemon (pid ${pid})
49163
49168
  `);
@@ -52943,7 +52948,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
52943
52948
  }
52944
52949
  }
52945
52950
  async function handleParallel(arg, ctx) {
52946
- const { execSync: execSync35 } = await import("node:child_process");
52951
+ const { execSync: execSync36 } = await import("node:child_process");
52947
52952
  const baseUrl = ctx.config.backendUrl || "http://localhost:11434";
52948
52953
  const isRemote = ctx.config.backendType === "nexus";
52949
52954
  if (isRemote) {
@@ -52967,7 +52972,7 @@ async function handleParallel(arg, ctx) {
52967
52972
  }
52968
52973
  let systemdVal = "";
52969
52974
  try {
52970
- const out = execSync35("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
52975
+ const out = execSync36("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
52971
52976
  const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
52972
52977
  if (match)
52973
52978
  systemdVal = match[1];
@@ -52996,7 +53001,7 @@ async function handleParallel(arg, ctx) {
52996
53001
  }
52997
53002
  const isSystemd = (() => {
52998
53003
  try {
52999
- const out = execSync35("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
53004
+ const out = execSync36("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
53000
53005
  return out === "active" || out === "inactive";
53001
53006
  } catch {
53002
53007
  return false;
@@ -53010,10 +53015,10 @@ async function handleParallel(arg, ctx) {
53010
53015
  const overrideContent = `[Service]
53011
53016
  Environment="OLLAMA_NUM_PARALLEL=${n}"
53012
53017
  `;
53013
- execSync35(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
53014
- execSync35(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
53015
- execSync35("sudo systemctl daemon-reload", { stdio: "pipe" });
53016
- execSync35("sudo systemctl restart ollama.service", { stdio: "pipe" });
53018
+ execSync36(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
53019
+ execSync36(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
53020
+ execSync36("sudo systemctl daemon-reload", { stdio: "pipe" });
53021
+ execSync36("sudo systemctl restart ollama.service", { stdio: "pipe" });
53017
53022
  let ready = false;
53018
53023
  for (let i = 0; i < 30 && !ready; i++) {
53019
53024
  await new Promise((r) => setTimeout(r, 500));
@@ -53040,7 +53045,7 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
53040
53045
  renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n}...`);
53041
53046
  try {
53042
53047
  try {
53043
- execSync35("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
53048
+ execSync36("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
53044
53049
  } catch {
53045
53050
  }
53046
53051
  await new Promise((r) => setTimeout(r, 1e3));
@@ -53860,18 +53865,18 @@ async function showExposeDashboard(gateway, rl, ctx) {
53860
53865
  const cmd = `/endpoint ${id} --auth ${gateway.authKey ?? ""}`;
53861
53866
  let copied = false;
53862
53867
  try {
53863
- const { execSync: execSync35 } = __require("node:child_process");
53868
+ const { execSync: execSync36 } = __require("node:child_process");
53864
53869
  const platform6 = process.platform;
53865
53870
  if (platform6 === "darwin") {
53866
- execSync35("pbcopy", { input: cmd, timeout: 3e3 });
53871
+ execSync36("pbcopy", { input: cmd, timeout: 3e3 });
53867
53872
  copied = true;
53868
53873
  } else if (platform6 === "win32") {
53869
- execSync35("clip", { input: cmd, timeout: 3e3 });
53874
+ execSync36("clip", { input: cmd, timeout: 3e3 });
53870
53875
  copied = true;
53871
53876
  } else {
53872
53877
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
53873
53878
  try {
53874
- execSync35(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
53879
+ execSync36(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
53875
53880
  copied = true;
53876
53881
  break;
53877
53882
  } catch {
@@ -53961,7 +53966,7 @@ var init_commands = __esm({
53961
53966
  // packages/cli/dist/tui/project-context.js
53962
53967
  import { existsSync as existsSync44, readFileSync as readFileSync33, readdirSync as readdirSync14 } from "node:fs";
53963
53968
  import { join as join60, basename as basename12 } from "node:path";
53964
- import { execSync as execSync31 } from "node:child_process";
53969
+ import { execSync as execSync32 } from "node:child_process";
53965
53970
  import { homedir as homedir17, platform as platform4, release } from "node:os";
53966
53971
  function getModelTier(modelName) {
53967
53972
  const m = modelName.toLowerCase();
@@ -54007,19 +54012,19 @@ function loadProjectMap(repoRoot) {
54007
54012
  }
54008
54013
  function getGitInfo(repoRoot) {
54009
54014
  try {
54010
- execSync31("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
54015
+ execSync32("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
54011
54016
  } catch {
54012
54017
  return "";
54013
54018
  }
54014
54019
  const lines = [];
54015
54020
  try {
54016
- const branch = execSync31("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
54021
+ const branch = execSync32("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
54017
54022
  if (branch)
54018
54023
  lines.push(`Branch: ${branch}`);
54019
54024
  } catch {
54020
54025
  }
54021
54026
  try {
54022
- const status = execSync31("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
54027
+ const status = execSync32("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
54023
54028
  if (status) {
54024
54029
  const changed = status.split("\n").length;
54025
54030
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -54029,7 +54034,7 @@ function getGitInfo(repoRoot) {
54029
54034
  } catch {
54030
54035
  }
54031
54036
  try {
54032
- const log = execSync31("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
54037
+ const log = execSync32("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
54033
54038
  if (log)
54034
54039
  lines.push(`Recent commits:
54035
54040
  ${log}`);
@@ -56810,7 +56815,7 @@ var init_promptLoader3 = __esm({
56810
56815
  // packages/cli/dist/tui/dream-engine.js
56811
56816
  import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync23, readFileSync as readFileSync37, existsSync as existsSync48, cpSync, rmSync as rmSync2, readdirSync as readdirSync16 } from "node:fs";
56812
56817
  import { join as join65, basename as basename14 } from "node:path";
56813
- import { execSync as execSync32 } from "node:child_process";
56818
+ import { execSync as execSync33 } from "node:child_process";
56814
56819
  function loadAutoresearchMemory(repoRoot) {
56815
56820
  const memoryPath = join65(repoRoot, ".oa", "memory", "autoresearch.json");
56816
56821
  if (!existsSync48(memoryPath))
@@ -57174,7 +57179,7 @@ var init_dream_engine = __esm({
57174
57179
  }
57175
57180
  }
57176
57181
  try {
57177
- const output = execSync32(cmd, {
57182
+ const output = execSync33(cmd, {
57178
57183
  cwd: this.repoRoot,
57179
57184
  timeout: 3e4,
57180
57185
  encoding: "utf-8",
@@ -57951,17 +57956,17 @@ ${summaryResult}
57951
57956
  try {
57952
57957
  mkdirSync23(checkpointDir, { recursive: true });
57953
57958
  try {
57954
- const gitStatus = execSync32("git status --porcelain", {
57959
+ const gitStatus = execSync33("git status --porcelain", {
57955
57960
  cwd: this.repoRoot,
57956
57961
  encoding: "utf-8",
57957
57962
  timeout: 1e4
57958
57963
  });
57959
- const gitDiff = execSync32("git diff", {
57964
+ const gitDiff = execSync33("git diff", {
57960
57965
  cwd: this.repoRoot,
57961
57966
  encoding: "utf-8",
57962
57967
  timeout: 1e4
57963
57968
  });
57964
- const gitHash = execSync32("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
57969
+ const gitHash = execSync33("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
57965
57970
  cwd: this.repoRoot,
57966
57971
  encoding: "utf-8",
57967
57972
  timeout: 5e3
@@ -61786,7 +61791,7 @@ __export(text_selection_exports, {
61786
61791
  stripAnsi: () => stripAnsi3,
61787
61792
  visibleLength: () => visibleLength
61788
61793
  });
61789
- import { execSync as execSync33 } from "node:child_process";
61794
+ import { execSync as execSync34 } from "node:child_process";
61790
61795
  function stripAnsi3(s) {
61791
61796
  return s.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\)/g, "");
61792
61797
  }
@@ -61797,16 +61802,16 @@ function copyText(text) {
61797
61802
  try {
61798
61803
  const platform6 = process.platform;
61799
61804
  if (platform6 === "darwin") {
61800
- execSync33("pbcopy", { input: text, timeout: 3e3 });
61805
+ execSync34("pbcopy", { input: text, timeout: 3e3 });
61801
61806
  return true;
61802
61807
  }
61803
61808
  if (platform6 === "win32") {
61804
- execSync33("clip", { input: text, timeout: 3e3 });
61809
+ execSync34("clip", { input: text, timeout: 3e3 });
61805
61810
  return true;
61806
61811
  }
61807
61812
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
61808
61813
  try {
61809
- execSync33(tool, { input: text, timeout: 3e3 });
61814
+ execSync34(tool, { input: text, timeout: 3e3 });
61810
61815
  return true;
61811
61816
  } catch {
61812
61817
  continue;
@@ -61815,10 +61820,10 @@ function copyText(text) {
61815
61820
  if (!_clipboardAutoInstallAttempted) {
61816
61821
  _clipboardAutoInstallAttempted = true;
61817
61822
  try {
61818
- execSync33("which apt-get", { timeout: 2e3, stdio: "pipe" });
61823
+ execSync34("which apt-get", { timeout: 2e3, stdio: "pipe" });
61819
61824
  try {
61820
- execSync33("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
61821
- execSync33("xclip -selection clipboard", { input: text, timeout: 3e3 });
61825
+ execSync34("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
61826
+ execSync34("xclip -selection clipboard", { input: text, timeout: 3e3 });
61822
61827
  return true;
61823
61828
  } catch {
61824
61829
  }
@@ -66727,7 +66732,7 @@ import { createRequire as createRequire4 } from "node:module";
66727
66732
  import { fileURLToPath as fileURLToPath14 } from "node:url";
66728
66733
  import { readFileSync as readFileSync43, writeFileSync as writeFileSync27, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync22, mkdirSync as mkdirSync28 } from "node:fs";
66729
66734
  import { existsSync as existsSync54 } from "node:fs";
66730
- import { execSync as execSync34 } from "node:child_process";
66735
+ import { execSync as execSync35 } from "node:child_process";
66731
66736
  import { homedir as homedir19 } from "node:os";
66732
66737
  function formatTimeAgo(date) {
66733
66738
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -66793,6 +66798,8 @@ function createTaskCompleteTool() {
66793
66798
  function buildTools(repoRoot, config, contextWindowSize) {
66794
66799
  const shellTool = new ShellTool(repoRoot);
66795
66800
  _shellToolRef = shellTool;
66801
+ const replTool = new ReplTool(repoRoot);
66802
+ _replToolRef = replTool;
66796
66803
  const executionTools = [
66797
66804
  new FileReadTool(repoRoot),
66798
66805
  new FileWriteTool(repoRoot),
@@ -66844,7 +66851,7 @@ function buildTools(repoRoot, config, contextWindowSize) {
66844
66851
  // Code sandbox (isolated code execution)
66845
66852
  new CodeSandboxTool(repoRoot),
66846
66853
  // Persistent Python REPL — RLM (arxiv:2512.24601)
66847
- new ReplTool(repoRoot),
66854
+ replTool,
66848
66855
  // Memory Metabolism — COHERE Layer 5 (arxiv:2512.13564)
66849
66856
  new MemoryMetabolismTool(repoRoot),
66850
66857
  // Identity Kernel — COHERE Layer 6
@@ -68150,7 +68157,14 @@ async function startInteractive(config, repoPath) {
68150
68157
  if (_shellToolRef)
68151
68158
  _shellToolRef.killAll();
68152
68159
  killAllFullSubAgents();
68160
+ taskManager.stopAll();
68153
68161
  registry.killAll();
68162
+ if (_replToolRef) {
68163
+ try {
68164
+ _replToolRef.dispose();
68165
+ } catch {
68166
+ }
68167
+ }
68154
68168
  restoreScreen();
68155
68169
  process.exit(code);
68156
68170
  };
@@ -69334,6 +69348,14 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
69334
69348
  if (_shellToolRef)
69335
69349
  _shellToolRef.killAll();
69336
69350
  killAllFullSubAgents();
69351
+ taskManager.stopAll();
69352
+ registry.killAll();
69353
+ if (_replToolRef) {
69354
+ try {
69355
+ _replToolRef.dispose();
69356
+ } catch {
69357
+ }
69358
+ }
69337
69359
  },
69338
69360
  async voiceToggle() {
69339
69361
  const msg = await voiceEngine.toggle();
@@ -70350,7 +70372,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
70350
70372
  try {
70351
70373
  if (process.platform === "win32") {
70352
70374
  try {
70353
- execSync34(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
70375
+ execSync35(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
70354
70376
  } catch {
70355
70377
  }
70356
70378
  } else {
@@ -70377,7 +70399,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
70377
70399
  if (pid > 0) {
70378
70400
  if (process.platform === "win32") {
70379
70401
  try {
70380
- execSync34(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
70402
+ execSync35(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
70381
70403
  } catch {
70382
70404
  }
70383
70405
  } else {
@@ -70394,7 +70416,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
70394
70416
  } catch {
70395
70417
  }
70396
70418
  try {
70397
- execSync34(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
70419
+ execSync35(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
70398
70420
  } catch {
70399
70421
  }
70400
70422
  const oaPath = join71(repoRoot, OA_DIR);
@@ -70408,14 +70430,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
70408
70430
  } catch (err) {
70409
70431
  if (attempt < 2) {
70410
70432
  try {
70411
- execSync34(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
70433
+ execSync35(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
70412
70434
  } catch {
70413
70435
  }
70414
70436
  } else {
70415
70437
  writeContent(() => renderWarning(`Could not fully remove ${OA_DIR}/: ${err instanceof Error ? err.message : String(err)}`));
70416
70438
  if (process.platform === "win32") {
70417
70439
  try {
70418
- execSync34(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
70440
+ execSync35(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
70419
70441
  deleted = true;
70420
70442
  } catch {
70421
70443
  }
@@ -71609,7 +71631,7 @@ Rules:
71609
71631
  process.exit(1);
71610
71632
  }
71611
71633
  }
71612
- var taskManager, _shellToolRef, _fullSubAgentToolRef, _activeRunnerRef, _autoUpdatedThisSession, SELF_IMPROVE_INTERVAL, _tasksSinceImprove;
71634
+ var taskManager, _shellToolRef, _replToolRef, _fullSubAgentToolRef, _activeRunnerRef, _autoUpdatedThisSession, SELF_IMPROVE_INTERVAL, _tasksSinceImprove;
71613
71635
  var init_interactive = __esm({
71614
71636
  "packages/cli/dist/tui/interactive.js"() {
71615
71637
  "use strict";
@@ -71651,6 +71673,7 @@ var init_interactive = __esm({
71651
71673
  init_neovim_mode();
71652
71674
  taskManager = new BackgroundTaskManager();
71653
71675
  _shellToolRef = null;
71676
+ _replToolRef = null;
71654
71677
  _fullSubAgentToolRef = null;
71655
71678
  _activeRunnerRef = null;
71656
71679
  _autoUpdatedThisSession = false;