open-agents-ai 0.103.10 → 0.103.11

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 +229 -86
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -17464,7 +17464,9 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
17464
17464
  } catch (reqErr) {
17465
17465
  const recovered = await this.retryOnTransient(reqErr, chatRequest, turn);
17466
17466
  if (!recovered) {
17467
- this.emit({ type: "error", content: `Backend error: ${reqErr instanceof Error ? reqErr.message : String(reqErr)}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
17467
+ const errMsg = reqErr instanceof Error ? reqErr.message : String(reqErr);
17468
+ const cause = reqErr instanceof Error && reqErr.cause ? ` (${reqErr.cause.message ?? ""} ${reqErr.cause?.code ?? ""})` : "";
17469
+ this.emit({ type: "error", content: `Backend error: ${errMsg}${cause}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
17468
17470
  messages.push({ role: "user", content: "[System: backend request failed, retrying on next turn. The previous request was lost.]" });
17469
17471
  continue;
17470
17472
  }
@@ -17974,7 +17976,9 @@ Integrate this guidance into your current approach. Continue working on the task
17974
17976
  } catch (reqErr) {
17975
17977
  const recovered = await this.retryOnTransient(reqErr, chatRequest, turn);
17976
17978
  if (!recovered) {
17977
- this.emit({ type: "error", content: `Backend error: ${reqErr instanceof Error ? reqErr.message : String(reqErr)}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
17979
+ const errMsg2 = reqErr instanceof Error ? reqErr.message : String(reqErr);
17980
+ const cause2 = reqErr instanceof Error && reqErr.cause ? ` (${reqErr.cause.message ?? ""} ${reqErr.cause?.code ?? ""})` : "";
17981
+ this.emit({ type: "error", content: `Backend error: ${errMsg2}${cause2}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
17978
17982
  messages.push({ role: "user", content: "[System: backend request failed, retrying on next turn. The previous request was lost.]" });
17979
17983
  continue;
17980
17984
  }
@@ -20358,9 +20362,9 @@ function ensureTranscribeCliBackground() {
20358
20362
  } catch {
20359
20363
  }
20360
20364
  try {
20361
- const { exec } = await import("node:child_process");
20365
+ const { exec: exec2 } = await import("node:child_process");
20362
20366
  return new Promise((resolve31) => {
20363
- exec("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
20367
+ exec2("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
20364
20368
  resolve31(!err);
20365
20369
  });
20366
20370
  });
@@ -26194,12 +26198,30 @@ var init_voice_session = __esm({
26194
26198
 
26195
26199
  // packages/cli/dist/tui/expose.js
26196
26200
  import { createServer as createServer2, request as httpRequest } from "node:http";
26197
- import { spawn as spawn14, execSync as execSync25 } from "node:child_process";
26201
+ import { spawn as spawn14, exec } from "node:child_process";
26198
26202
  import { EventEmitter as EventEmitter3 } from "node:events";
26199
26203
  import { randomBytes as randomBytes7 } from "node:crypto";
26200
26204
  import { URL as URL2 } from "node:url";
26201
26205
  import { loadavg, cpus, totalmem, freemem } from "node:os";
26202
- function collectSystemMetrics() {
26206
+ function cleanForwardHeaders(raw, targetHost) {
26207
+ const out = {};
26208
+ for (const [key, value] of Object.entries(raw)) {
26209
+ if (HOP_BY_HOP_HEADERS.has(key))
26210
+ continue;
26211
+ if (CF_HEADERS_PREFIX.some((p) => key.startsWith(p)))
26212
+ continue;
26213
+ if (key === "authorization")
26214
+ continue;
26215
+ if (key.startsWith("x-forwarded-"))
26216
+ continue;
26217
+ if (key === "sec-fetch-mode")
26218
+ continue;
26219
+ out[key] = value;
26220
+ }
26221
+ out.host = targetHost;
26222
+ return out;
26223
+ }
26224
+ async function collectSystemMetricsAsync() {
26203
26225
  const [l1, l5, l15] = loadavg();
26204
26226
  const cores = cpus().length;
26205
26227
  const totalMem = totalmem();
@@ -26214,7 +26236,9 @@ function collectSystemMetrics() {
26214
26236
  vramUtilization: 0
26215
26237
  };
26216
26238
  try {
26217
- const smi = execSync25("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
26239
+ const smi = await new Promise((resolve31, reject) => {
26240
+ exec("nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 3e3 }, (err, stdout) => err ? reject(err) : resolve31(stdout));
26241
+ });
26218
26242
  const line = smi.trim().split("\n")[0];
26219
26243
  if (line) {
26220
26244
  const parts = line.split(",").map((s) => s.trim());
@@ -26245,11 +26269,22 @@ function collectSystemMetrics() {
26245
26269
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
26246
26270
  };
26247
26271
  }
26248
- var DEFAULT_TARGETS, ExposeGateway;
26272
+ var HOP_BY_HOP_HEADERS, CF_HEADERS_PREFIX, DEFAULT_TARGETS, ExposeGateway;
26249
26273
  var init_expose = __esm({
26250
26274
  "packages/cli/dist/tui/expose.js"() {
26251
26275
  "use strict";
26252
26276
  init_render();
26277
+ HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
26278
+ "connection",
26279
+ "keep-alive",
26280
+ "proxy-authenticate",
26281
+ "proxy-authorization",
26282
+ "te",
26283
+ "trailers",
26284
+ "transfer-encoding",
26285
+ "upgrade"
26286
+ ]);
26287
+ CF_HEADERS_PREFIX = ["cf-", "cdn-"];
26253
26288
  DEFAULT_TARGETS = {
26254
26289
  ollama: "http://127.0.0.1:11434",
26255
26290
  vllm: "http://127.0.0.1:8000",
@@ -26344,15 +26379,19 @@ var init_expose = __esm({
26344
26379
  return;
26345
26380
  }
26346
26381
  if (url.pathname === "/v1/system/metrics" && req.method === "GET") {
26347
- const metrics = collectSystemMetrics();
26348
- const gatewayStats = {
26349
- totalRequests: this._stats.totalRequests,
26350
- activeConnections: this._stats.activeConnections,
26351
- errors: this._stats.errors,
26352
- modelUsage: Object.fromEntries(this._stats.modelUsage)
26353
- };
26354
- res.writeHead(200, { "Content-Type": "application/json" });
26355
- res.end(JSON.stringify({ ...metrics, gateway: gatewayStats }));
26382
+ collectSystemMetricsAsync().then((metrics) => {
26383
+ const gatewayStats = {
26384
+ totalRequests: this._stats.totalRequests,
26385
+ activeConnections: this._stats.activeConnections,
26386
+ errors: this._stats.errors,
26387
+ modelUsage: Object.fromEntries(this._stats.modelUsage)
26388
+ };
26389
+ res.writeHead(200, { "Content-Type": "application/json" });
26390
+ res.end(JSON.stringify({ ...metrics, gateway: gatewayStats }));
26391
+ }).catch(() => {
26392
+ res.writeHead(500);
26393
+ res.end("metrics error");
26394
+ });
26356
26395
  return;
26357
26396
  }
26358
26397
  this._stats.totalRequests++;
@@ -26364,6 +26403,7 @@ var init_expose = __esm({
26364
26403
  req.on("data", (chunk) => bodyChunks.push(chunk));
26365
26404
  req.on("end", () => {
26366
26405
  const body = Buffer.concat(bodyChunks);
26406
+ let isStreaming = false;
26367
26407
  if (req.method === "POST" && body.length > 0) {
26368
26408
  try {
26369
26409
  const text = body.toString("utf8", 0, Math.min(body.length, 1024));
@@ -26373,14 +26413,35 @@ var init_expose = __esm({
26373
26413
  const count = this._stats.modelUsage.get(model) ?? 0;
26374
26414
  this._stats.modelUsage.set(model, count + 1);
26375
26415
  }
26416
+ isStreaming = /"stream"\s*:\s*true/.test(text);
26376
26417
  } catch {
26377
26418
  }
26378
26419
  }
26379
- const forwardHeaders = { ...req.headers, host: target.host };
26380
- delete forwardHeaders.authorization;
26420
+ const forwardHeaders = cleanForwardHeaders(req.headers, target.host);
26381
26421
  if (body.length > 0) {
26382
26422
  forwardHeaders["content-length"] = String(body.length);
26383
26423
  }
26424
+ let heartbeatTimer = null;
26425
+ if (isStreaming) {
26426
+ res.writeHead(200, {
26427
+ "Content-Type": "text/event-stream",
26428
+ "Cache-Control": "no-cache",
26429
+ "X-Accel-Buffering": "no"
26430
+ // tells nginx/CF not to buffer
26431
+ });
26432
+ heartbeatTimer = setInterval(() => {
26433
+ try {
26434
+ res.write(": heartbeat\n\n");
26435
+ } catch {
26436
+ }
26437
+ }, 15e3);
26438
+ }
26439
+ const cleanupHeartbeat = () => {
26440
+ if (heartbeatTimer) {
26441
+ clearInterval(heartbeatTimer);
26442
+ heartbeatTimer = null;
26443
+ }
26444
+ };
26384
26445
  const proxyReq = httpRequest({
26385
26446
  hostname: target.hostname,
26386
26447
  port: target.port || (target.protocol === "https:" ? 443 : 80),
@@ -26388,24 +26449,58 @@ var init_expose = __esm({
26388
26449
  method: req.method,
26389
26450
  headers: forwardHeaders
26390
26451
  }, (proxyRes) => {
26452
+ cleanupHeartbeat();
26391
26453
  proxyRes.on("error", () => {
26392
26454
  this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
26393
26455
  this.emitStats();
26394
26456
  });
26395
- res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);
26396
- proxyRes.pipe(res);
26457
+ if (isStreaming) {
26458
+ if (proxyRes.statusCode !== 200) {
26459
+ let errBody = "";
26460
+ proxyRes.on("data", (chunk) => {
26461
+ errBody += chunk.toString();
26462
+ });
26463
+ proxyRes.on("end", () => {
26464
+ try {
26465
+ res.write(`data: ${JSON.stringify({ error: `Backend ${proxyRes.statusCode}: ${errBody.slice(0, 200)}` })}
26466
+
26467
+ `);
26468
+ } catch {
26469
+ }
26470
+ try {
26471
+ res.end();
26472
+ } catch {
26473
+ }
26474
+ this._stats.errors++;
26475
+ this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
26476
+ this.emitStats();
26477
+ });
26478
+ return;
26479
+ }
26480
+ proxyRes.pipe(res);
26481
+ } else {
26482
+ res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);
26483
+ proxyRes.pipe(res);
26484
+ }
26397
26485
  proxyRes.on("end", () => {
26398
26486
  this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
26399
26487
  this.emitStats();
26400
26488
  });
26401
26489
  });
26402
26490
  proxyReq.on("error", (err) => {
26491
+ cleanupHeartbeat();
26403
26492
  this._stats.errors++;
26404
26493
  this._stats.activeConnections = Math.max(0, this._stats.activeConnections - 1);
26405
26494
  if (!res.headersSent) {
26406
26495
  res.writeHead(502, { "Content-Type": "application/json" });
26407
26496
  res.end(JSON.stringify({ error: `Backend unreachable: ${err.message}` }));
26408
26497
  } else {
26498
+ try {
26499
+ res.write(`data: ${JSON.stringify({ error: err.message })}
26500
+
26501
+ `);
26502
+ } catch {
26503
+ }
26409
26504
  try {
26410
26505
  res.end();
26411
26506
  } catch {
@@ -26429,7 +26524,10 @@ var init_expose = __esm({
26429
26524
  return server;
26430
26525
  }
26431
26526
  // ── Cloudflared ─────────────────────────────────────────────────────────
26527
+ /** Port the proxy is listening on (needed for cloudflared restart) */
26528
+ _proxyPort = 0;
26432
26529
  startCloudflared(port) {
26530
+ this._proxyPort = port;
26433
26531
  return new Promise((resolve31, reject) => {
26434
26532
  const timeout = setTimeout(() => {
26435
26533
  reject(new Error("Cloudflared tunnel start timeout (30s)"));
@@ -26437,7 +26535,9 @@ var init_expose = __esm({
26437
26535
  this.cloudflaredProcess = spawn14("cloudflared", [
26438
26536
  "tunnel",
26439
26537
  "--url",
26440
- `http://127.0.0.1:${port}`
26538
+ `http://127.0.0.1:${port}`,
26539
+ "--proxy-keepalive-timeout",
26540
+ "300s"
26441
26541
  ], {
26442
26542
  stdio: ["ignore", "pipe", "pipe"]
26443
26543
  });
@@ -26463,12 +26563,27 @@ var init_expose = __esm({
26463
26563
  reject(new Error(`Cloudflared exited with code ${code} before providing URL`));
26464
26564
  }
26465
26565
  if (this._stats.status === "active") {
26566
+ this.options.onInfo?.("Cloudflared tunnel died \u2014 restarting...");
26466
26567
  this._stats.status = "error";
26467
26568
  this.emitStats();
26569
+ this.restartCloudflared();
26468
26570
  }
26469
26571
  });
26470
26572
  });
26471
26573
  }
26574
+ /** Auto-restart cloudflared after unexpected exit (new URL assigned) */
26575
+ async restartCloudflared() {
26576
+ if (!this.server || this._proxyPort === 0)
26577
+ return;
26578
+ try {
26579
+ this._tunnelUrl = await this.startCloudflared(this._proxyPort);
26580
+ this._stats.status = "active";
26581
+ this.emitStats();
26582
+ this.options.onInfo?.(`Tunnel restarted: ${this._tunnelUrl}`);
26583
+ } catch (err) {
26584
+ this.options.onError?.(`Tunnel restart failed: ${err instanceof Error ? err.message : String(err)}`);
26585
+ }
26586
+ }
26472
26587
  // ── Helpers ─────────────────────────────────────────────────────────────
26473
26588
  findFreePort() {
26474
26589
  return new Promise((resolve31, reject) => {
@@ -28623,7 +28738,7 @@ var init_oa_directory = __esm({
28623
28738
 
28624
28739
  // packages/cli/dist/tui/setup.js
28625
28740
  import * as readline from "node:readline";
28626
- import { execSync as execSync26, spawn as spawn15 } from "node:child_process";
28741
+ import { execSync as execSync25, spawn as spawn15 } from "node:child_process";
28627
28742
  import { existsSync as existsSync29, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
28628
28743
  import { join as join39 } from "node:path";
28629
28744
  import { homedir as homedir10, platform } from "node:os";
@@ -28633,7 +28748,7 @@ function detectSystemSpecs() {
28633
28748
  let gpuVramGB = 0;
28634
28749
  let gpuName = "";
28635
28750
  try {
28636
- const memInfo = execSync26("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
28751
+ const memInfo = execSync25("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
28637
28752
  encoding: "utf8",
28638
28753
  timeout: 5e3
28639
28754
  });
@@ -28653,7 +28768,7 @@ function detectSystemSpecs() {
28653
28768
  } catch {
28654
28769
  }
28655
28770
  try {
28656
- const nvidiaSmi = execSync26("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
28771
+ const nvidiaSmi = execSync25("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
28657
28772
  const lines = nvidiaSmi.trim().split("\n");
28658
28773
  if (lines.length > 0) {
28659
28774
  for (const line of lines) {
@@ -28778,7 +28893,7 @@ function ensureCurl() {
28778
28893
  for (const s of strategies) {
28779
28894
  if (hasCmd(s.check)) {
28780
28895
  try {
28781
- execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
28896
+ execSync25(s.install, { stdio: "inherit", timeout: 12e4 });
28782
28897
  if (hasCmd("curl")) {
28783
28898
  process.stdout.write(` ${c2.green("\u2714")} curl installed via ${s.label}.
28784
28899
  `);
@@ -28792,7 +28907,7 @@ function ensureCurl() {
28792
28907
  }
28793
28908
  if (plat === "darwin") {
28794
28909
  try {
28795
- execSync26("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
28910
+ execSync25("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
28796
28911
  if (hasCmd("curl"))
28797
28912
  return true;
28798
28913
  } catch {
@@ -28827,7 +28942,7 @@ function installOllamaLinux() {
28827
28942
 
28828
28943
  `);
28829
28944
  try {
28830
- execSync26("curl -fsSL https://ollama.com/install.sh | sh", {
28945
+ execSync25("curl -fsSL https://ollama.com/install.sh | sh", {
28831
28946
  stdio: "inherit",
28832
28947
  timeout: 3e5
28833
28948
  });
@@ -28855,7 +28970,7 @@ async function installOllamaMac(_rl) {
28855
28970
 
28856
28971
  `);
28857
28972
  try {
28858
- execSync26('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
28973
+ execSync25('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
28859
28974
  if (!hasCmd("brew")) {
28860
28975
  try {
28861
28976
  const brewPrefix = existsSync29("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
@@ -28888,7 +29003,7 @@ async function installOllamaMac(_rl) {
28888
29003
 
28889
29004
  `);
28890
29005
  try {
28891
- execSync26("brew install ollama", {
29006
+ execSync25("brew install ollama", {
28892
29007
  stdio: "inherit",
28893
29008
  timeout: 3e5
28894
29009
  });
@@ -28915,7 +29030,7 @@ function installOllamaWindows() {
28915
29030
 
28916
29031
  `);
28917
29032
  try {
28918
- execSync26('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
29033
+ execSync25('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
28919
29034
  stdio: "inherit",
28920
29035
  timeout: 3e5
28921
29036
  });
@@ -28996,7 +29111,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
28996
29111
  }
28997
29112
  function pullModelWithAutoUpdate(tag) {
28998
29113
  try {
28999
- execSync26(`ollama pull ${tag}`, {
29114
+ execSync25(`ollama pull ${tag}`, {
29000
29115
  stdio: "inherit",
29001
29116
  timeout: 36e5
29002
29117
  // 1 hour max
@@ -29016,7 +29131,7 @@ function pullModelWithAutoUpdate(tag) {
29016
29131
 
29017
29132
  `);
29018
29133
  try {
29019
- execSync26("curl -fsSL https://ollama.com/install.sh | sh", {
29134
+ execSync25("curl -fsSL https://ollama.com/install.sh | sh", {
29020
29135
  stdio: "inherit",
29021
29136
  timeout: 3e5
29022
29137
  // 5 min max for install
@@ -29027,7 +29142,7 @@ function pullModelWithAutoUpdate(tag) {
29027
29142
  process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
29028
29143
 
29029
29144
  `);
29030
- execSync26(`ollama pull ${tag}`, {
29145
+ execSync25(`ollama pull ${tag}`, {
29031
29146
  stdio: "inherit",
29032
29147
  timeout: 36e5
29033
29148
  });
@@ -29129,7 +29244,7 @@ function ensurePython3() {
29129
29244
  if (plat === "darwin") {
29130
29245
  if (hasCmd("brew")) {
29131
29246
  try {
29132
- execSync26("brew install python3", { stdio: "inherit", timeout: 3e5 });
29247
+ execSync25("brew install python3", { stdio: "inherit", timeout: 3e5 });
29133
29248
  if (hasCmd("python3")) {
29134
29249
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via Homebrew.
29135
29250
  `);
@@ -29142,7 +29257,7 @@ function ensurePython3() {
29142
29257
  for (const s of strategies) {
29143
29258
  if (hasCmd(s.check)) {
29144
29259
  try {
29145
- execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
29260
+ execSync25(s.install, { stdio: "inherit", timeout: 12e4 });
29146
29261
  if (hasCmd("python3") || hasCmd("python")) {
29147
29262
  process.stdout.write(` ${c2.green("\u2714")} Python3 installed via ${s.label}.
29148
29263
  `);
@@ -29158,11 +29273,11 @@ function ensurePython3() {
29158
29273
  }
29159
29274
  function checkPythonVenv() {
29160
29275
  try {
29161
- execSync26("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
29276
+ execSync25("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
29162
29277
  return true;
29163
29278
  } catch {
29164
29279
  try {
29165
- execSync26("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
29280
+ execSync25("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
29166
29281
  return true;
29167
29282
  } catch {
29168
29283
  return false;
@@ -29181,7 +29296,7 @@ function ensurePythonVenv() {
29181
29296
  for (const s of strategies) {
29182
29297
  if (hasCmd(s.check)) {
29183
29298
  try {
29184
- execSync26(s.install, { stdio: "inherit", timeout: 12e4 });
29299
+ execSync25(s.install, { stdio: "inherit", timeout: 12e4 });
29185
29300
  if (checkPythonVenv()) {
29186
29301
  process.stdout.write(` ${c2.green("\u2714")} python3-venv installed via ${s.label}.
29187
29302
  `);
@@ -29617,7 +29732,7 @@ async function doSetup(config, rl) {
29617
29732
  const modelfilePath = join39(modelDir2, `Modelfile.${customName}`);
29618
29733
  writeFileSync10(modelfilePath, modelfileContent + "\n", "utf8");
29619
29734
  process.stdout.write(` ${c2.dim("Creating model...")} `);
29620
- execSync26(`ollama create ${customName} -f ${modelfilePath}`, {
29735
+ execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
29621
29736
  stdio: "pipe",
29622
29737
  timeout: 12e4
29623
29738
  });
@@ -29668,7 +29783,7 @@ function isFirstRun() {
29668
29783
  function hasCmd(cmd) {
29669
29784
  try {
29670
29785
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
29671
- execSync26(whichCmd, { stdio: "pipe", timeout: 3e3 });
29786
+ execSync25(whichCmd, { stdio: "pipe", timeout: 3e3 });
29672
29787
  return true;
29673
29788
  } catch {
29674
29789
  return false;
@@ -29701,7 +29816,7 @@ function getVenvDir() {
29701
29816
  }
29702
29817
  function hasVenvModule() {
29703
29818
  try {
29704
- execSync26("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
29819
+ execSync25("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
29705
29820
  return true;
29706
29821
  } catch {
29707
29822
  return false;
@@ -29723,8 +29838,8 @@ function ensureVenv(log) {
29723
29838
  }
29724
29839
  try {
29725
29840
  mkdirSync10(join39(homedir10(), ".open-agents"), { recursive: true });
29726
- execSync26(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
29727
- execSync26(`"${join39(venvDir, "bin", "pip")}" install --upgrade pip`, {
29841
+ execSync25(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
29842
+ execSync25(`"${join39(venvDir, "bin", "pip")}" install --upgrade pip`, {
29728
29843
  stdio: "pipe",
29729
29844
  timeout: 6e4
29730
29845
  });
@@ -29737,7 +29852,7 @@ function ensureVenv(log) {
29737
29852
  }
29738
29853
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
29739
29854
  try {
29740
- execSync26(`sudo -n ${cmd}`, {
29855
+ execSync25(`sudo -n ${cmd}`, {
29741
29856
  stdio: "pipe",
29742
29857
  timeout: timeoutMs,
29743
29858
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -29750,7 +29865,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
29750
29865
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
29751
29866
  try {
29752
29867
  const escaped = cmd.replace(/'/g, "'\\''");
29753
- execSync26(`sudo -S bash -c '${escaped}'`, {
29868
+ execSync25(`sudo -S bash -c '${escaped}'`, {
29754
29869
  input: password + "\n",
29755
29870
  stdio: ["pipe", "pipe", "pipe"],
29756
29871
  timeout: timeoutMs,
@@ -29857,7 +29972,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
29857
29972
  ok = await sudoInstall(batchCmd, getPassword, log, cachedPasswordRef, 18e4);
29858
29973
  } else {
29859
29974
  try {
29860
- execSync26(batchCmd, { stdio: "pipe", timeout: 18e4 });
29975
+ execSync25(batchCmd, { stdio: "pipe", timeout: 18e4 });
29861
29976
  ok = true;
29862
29977
  } catch {
29863
29978
  ok = false;
@@ -29894,7 +30009,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
29894
30009
  const venvCmds = {
29895
30010
  apt: () => {
29896
30011
  try {
29897
- const pyVer = execSync26(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
30012
+ const pyVer = execSync25(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
29898
30013
  return `apt-get install -y python3-venv python${pyVer}-venv`;
29899
30014
  } catch {
29900
30015
  return "apt-get install -y python3-venv";
@@ -29922,12 +30037,12 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
29922
30037
  const venvPip = join39(venvBin, "pip");
29923
30038
  log("Installing moondream-station in ~/.open-agents/venv...");
29924
30039
  try {
29925
- execSync26(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
30040
+ execSync25(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
29926
30041
  if (existsSync29(venvMoondream)) {
29927
30042
  log("moondream-station installed successfully.");
29928
30043
  } else {
29929
30044
  try {
29930
- const check = execSync26(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
30045
+ const check = execSync25(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
29931
30046
  if (check.includes("moondream")) {
29932
30047
  log("moondream-station package installed.");
29933
30048
  }
@@ -29944,7 +30059,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
29944
30059
  const venvPip2 = join39(venvBin, "pip");
29945
30060
  let ocrStackInstalled = false;
29946
30061
  try {
29947
- execSync26(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
30062
+ execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
29948
30063
  ocrStackInstalled = true;
29949
30064
  } catch {
29950
30065
  }
@@ -29952,9 +30067,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
29952
30067
  const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
29953
30068
  log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
29954
30069
  try {
29955
- execSync26(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
30070
+ execSync25(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
29956
30071
  try {
29957
- execSync26(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
30072
+ execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
29958
30073
  log("OCR Python stack installed successfully.");
29959
30074
  } catch {
29960
30075
  log("OCR Python stack install completed but import verification failed.");
@@ -29988,7 +30103,7 @@ function ensureCloudflaredBackground(onInfo) {
29988
30103
  const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
29989
30104
  const cfArch = archMap[arch] ?? "amd64";
29990
30105
  try {
29991
- execSync26(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir10()}/.local/bin" && mv /tmp/cloudflared "${homedir10()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
30106
+ execSync25(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir10()}/.local/bin" && mv /tmp/cloudflared "${homedir10()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
29992
30107
  if (!process.env.PATH?.includes(`${homedir10()}/.local/bin`)) {
29993
30108
  process.env.PATH = `${homedir10()}/.local/bin:${process.env.PATH}`;
29994
30109
  }
@@ -29999,7 +30114,7 @@ function ensureCloudflaredBackground(onInfo) {
29999
30114
  } catch {
30000
30115
  }
30001
30116
  try {
30002
- execSync26(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
30117
+ execSync25(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
30003
30118
  if (hasCmd("cloudflared")) {
30004
30119
  log("cloudflared installed.");
30005
30120
  return true;
@@ -30008,7 +30123,7 @@ function ensureCloudflaredBackground(onInfo) {
30008
30123
  }
30009
30124
  } else if (os === "darwin") {
30010
30125
  try {
30011
- execSync26("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
30126
+ execSync25("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
30012
30127
  if (hasCmd("cloudflared")) {
30013
30128
  log("cloudflared installed via Homebrew.");
30014
30129
  return true;
@@ -30058,7 +30173,7 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
30058
30173
  mkdirSync10(modelDir2, { recursive: true });
30059
30174
  const modelfilePath = join39(modelDir2, `Modelfile.${customName}`);
30060
30175
  writeFileSync10(modelfilePath, modelfileContent + "\n", "utf8");
30061
- execSync26(`ollama create ${customName} -f ${modelfilePath}`, {
30176
+ execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
30062
30177
  stdio: "pipe",
30063
30178
  timeout: 12e4
30064
30179
  });
@@ -31808,10 +31923,38 @@ async function handleEndpoint(arg, ctx, local = false) {
31808
31923
  process.stdout.write(` ${c2.dim(" /endpoint https://api.together.xyz --auth ... Together AI")}
31809
31924
  `);
31810
31925
  process.stdout.write(` ${c2.dim(" /endpoint http://localhost:8000 vLLM")}
31926
+ `);
31927
+ process.stdout.write(` ${c2.dim(" /endpoint stop Reset to local Ollama")}
31811
31928
 
31812
31929
  `);
31813
31930
  return;
31814
31931
  }
31932
+ if (arg === "stop" || arg === "off" || arg.startsWith("stop ") || arg.startsWith("off ")) {
31933
+ if (ctx.isExposeActive?.()) {
31934
+ await ctx.exposeStop?.();
31935
+ renderInfo("Expose gateway stopped.");
31936
+ }
31937
+ if (ctx.hasActiveTask?.()) {
31938
+ ctx.abortActiveTask?.();
31939
+ }
31940
+ const defaultUrl = "http://127.0.0.1:11434";
31941
+ ctx.setEndpoint(defaultUrl, "ollama", void 0);
31942
+ const defaultSettings = { backendUrl: defaultUrl, backendType: "ollama", apiKey: void 0 };
31943
+ if (local) {
31944
+ ctx.saveLocalSettings(defaultSettings);
31945
+ } else {
31946
+ setConfigValue("backendUrl", defaultUrl);
31947
+ setConfigValue("backendType", "ollama");
31948
+ ctx.saveSettings(defaultSettings);
31949
+ }
31950
+ process.stdout.write(`
31951
+ ${c2.green("\u2714")} Endpoint reset to local Ollama (${defaultUrl})
31952
+ `);
31953
+ if (ctx.hasActiveTask?.()) {
31954
+ renderWarning("Active task aborted \u2014 send a new prompt to continue.");
31955
+ }
31956
+ return;
31957
+ }
31815
31958
  const parts = arg.split(/\s+/);
31816
31959
  const url = parts[0];
31817
31960
  let apiKey;
@@ -32008,7 +32151,7 @@ async function handleUpdate(subcommand, ctx) {
32008
32151
  return;
32009
32152
  }
32010
32153
  checkSpinner.stop(`Update available: v${info.currentVersion} \u2192 v${c2.bold(c2.green(info.latestVersion))}`);
32011
- const { exec, execSync: es2 } = await import("node:child_process");
32154
+ const { exec: exec2, execSync: es2 } = await import("node:child_process");
32012
32155
  let needsSudo = false;
32013
32156
  try {
32014
32157
  const prefix = es2("npm prefix -g", { encoding: "utf8", timeout: 5e3 }).trim();
@@ -32037,7 +32180,7 @@ async function handleUpdate(subcommand, ctx) {
32037
32180
  let installOk = false;
32038
32181
  let installError = "";
32039
32182
  const runInstall2 = (cmd) => new Promise((resolve31) => {
32040
- const child = exec(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
32183
+ const child = exec2(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
32041
32184
  if (err)
32042
32185
  installError = (stderr || err.message || "").trim();
32043
32186
  resolve31(!err);
@@ -32075,7 +32218,7 @@ async function handleUpdate(subcommand, ctx) {
32075
32218
  installSpinner.stop(`Update installed (v${info.latestVersion}).`);
32076
32219
  const rebuildSpinner = startInlineSpinner("Rebuilding native modules");
32077
32220
  const rebuildOk = await new Promise((resolve31) => {
32078
- const child = exec(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve31(true));
32221
+ const child = exec2(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve31(true));
32079
32222
  child.stdout?.resume();
32080
32223
  child.stderr?.resume();
32081
32224
  });
@@ -32108,7 +32251,7 @@ async function handleUpdate(subcommand, ctx) {
32108
32251
  if (fsExists(venvPip)) {
32109
32252
  const pySpinner = startInlineSpinner("Upgrading Python venv packages");
32110
32253
  const pyOk = await new Promise((resolve31) => {
32111
- const child = exec(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve31(!err));
32254
+ const child = exec2(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve31(!err));
32112
32255
  child.stdout?.resume();
32113
32256
  child.stderr?.resume();
32114
32257
  });
@@ -32259,7 +32402,7 @@ var init_commands = __esm({
32259
32402
  // packages/cli/dist/tui/project-context.js
32260
32403
  import { existsSync as existsSync30, readFileSync as readFileSync21, readdirSync as readdirSync8 } from "node:fs";
32261
32404
  import { join as join40, basename as basename10 } from "node:path";
32262
- import { execSync as execSync27 } from "node:child_process";
32405
+ import { execSync as execSync26 } from "node:child_process";
32263
32406
  import { homedir as homedir11, platform as platform2, release } from "node:os";
32264
32407
  function getModelTier(modelName) {
32265
32408
  const m = modelName.toLowerCase();
@@ -32305,19 +32448,19 @@ function loadProjectMap(repoRoot) {
32305
32448
  }
32306
32449
  function getGitInfo(repoRoot) {
32307
32450
  try {
32308
- execSync27("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
32451
+ execSync26("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
32309
32452
  } catch {
32310
32453
  return "";
32311
32454
  }
32312
32455
  const lines = [];
32313
32456
  try {
32314
- const branch = execSync27("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
32457
+ const branch = execSync26("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
32315
32458
  if (branch)
32316
32459
  lines.push(`Branch: ${branch}`);
32317
32460
  } catch {
32318
32461
  }
32319
32462
  try {
32320
- const status = execSync27("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
32463
+ const status = execSync26("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
32321
32464
  if (status) {
32322
32465
  const changed = status.split("\n").length;
32323
32466
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -32327,7 +32470,7 @@ function getGitInfo(repoRoot) {
32327
32470
  } catch {
32328
32471
  }
32329
32472
  try {
32330
- const log = execSync27("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
32473
+ const log = execSync26("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
32331
32474
  if (log)
32332
32475
  lines.push(`Recent commits:
32333
32476
  ${log}`);
@@ -33744,7 +33887,7 @@ var init_carousel_descriptors = __esm({
33744
33887
  import { existsSync as existsSync32, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12, readFileSync as readFileSync23, unlinkSync as unlinkSync4 } from "node:fs";
33745
33888
  import { join as join42 } from "node:path";
33746
33889
  import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
33747
- import { execSync as execSync28, spawn as nodeSpawn } from "node:child_process";
33890
+ import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
33748
33891
  import { createRequire } from "node:module";
33749
33892
  function voiceDir() {
33750
33893
  return join42(homedir12(), ".open-agents", "voice");
@@ -34801,7 +34944,7 @@ var init_voice = __esm({
34801
34944
  }
34802
34945
  for (const player of ["paplay", "pw-play", "aplay"]) {
34803
34946
  try {
34804
- execSync28(`which ${player}`, { stdio: "pipe" });
34947
+ execSync27(`which ${player}`, { stdio: "pipe" });
34805
34948
  return [player, path];
34806
34949
  } catch {
34807
34950
  }
@@ -34830,7 +34973,7 @@ var init_voice = __esm({
34830
34973
  return this.python3Path;
34831
34974
  for (const bin of ["python3", "python"]) {
34832
34975
  try {
34833
- const path = execSync28(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
34976
+ const path = execSync27(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
34834
34977
  if (path) {
34835
34978
  this.python3Path = path;
34836
34979
  return path;
@@ -34850,7 +34993,7 @@ var init_voice = __esm({
34850
34993
  return false;
34851
34994
  }
34852
34995
  try {
34853
- execSync28(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
34996
+ execSync27(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
34854
34997
  this.mlxInstalled = true;
34855
34998
  return true;
34856
34999
  } catch {
@@ -34874,7 +35017,7 @@ var init_voice = __esm({
34874
35017
  return;
34875
35018
  renderInfo("Installing MLX Audio for voice synthesis (first time setup)...");
34876
35019
  try {
34877
- execSync28(`${py} -m pip install mlx-audio --quiet`, {
35020
+ execSync27(`${py} -m pip install mlx-audio --quiet`, {
34878
35021
  stdio: "pipe",
34879
35022
  timeout: 3e5
34880
35023
  // 5 min — may need to compile
@@ -34882,7 +35025,7 @@ var init_voice = __esm({
34882
35025
  this.mlxInstalled = true;
34883
35026
  } catch (err) {
34884
35027
  try {
34885
- execSync28(`${py} -m pip install mlx-audio --user --quiet`, {
35028
+ execSync27(`${py} -m pip install mlx-audio --user --quiet`, {
34886
35029
  stdio: "pipe",
34887
35030
  timeout: 3e5
34888
35031
  });
@@ -34918,11 +35061,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
34918
35061
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
34919
35062
  ].join("; ");
34920
35063
  try {
34921
- execSync28(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
35064
+ execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
34922
35065
  } catch (err) {
34923
35066
  try {
34924
35067
  const safeText = cleaned.replace(/'/g, "'\\''");
34925
- execSync28(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
35068
+ execSync27(`${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: tmpdir6() });
34926
35069
  } catch (err2) {
34927
35070
  return;
34928
35071
  }
@@ -34986,11 +35129,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
34986
35129
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
34987
35130
  ].join("; ");
34988
35131
  try {
34989
- execSync28(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
35132
+ execSync27(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
34990
35133
  } catch {
34991
35134
  try {
34992
35135
  const safeText = cleaned.replace(/'/g, "'\\''");
34993
- execSync28(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir6() });
35136
+ execSync27(`${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: tmpdir6() });
34994
35137
  } catch {
34995
35138
  return null;
34996
35139
  }
@@ -35038,7 +35181,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
35038
35181
  const voiceRequire = createRequire(join42(voiceDir(), "index.js"));
35039
35182
  const probeOnnx = () => {
35040
35183
  try {
35041
- const result = execSync28(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join42(voiceDir(), "node_modules") } });
35184
+ const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join42(voiceDir(), "node_modules") } });
35042
35185
  const output = result.toString().trim();
35043
35186
  return output === "OK";
35044
35187
  } catch {
@@ -35055,7 +35198,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
35055
35198
  } catch {
35056
35199
  renderInfo("Installing ONNX runtime for voice synthesis...");
35057
35200
  try {
35058
- execSync28("npm install --no-audit --no-fund", {
35201
+ execSync27("npm install --no-audit --no-fund", {
35059
35202
  cwd: voiceDir(),
35060
35203
  stdio: "pipe",
35061
35204
  timeout: 12e4
@@ -35080,7 +35223,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
35080
35223
  } catch {
35081
35224
  renderInfo("Installing phonemizer for voice synthesis...");
35082
35225
  try {
35083
- execSync28("npm install --no-audit --no-fund", {
35226
+ execSync27("npm install --no-audit --no-fund", {
35084
35227
  cwd: voiceDir(),
35085
35228
  stdio: "pipe",
35086
35229
  timeout: 12e4
@@ -36164,7 +36307,7 @@ var init_promptLoader3 = __esm({
36164
36307
  // packages/cli/dist/tui/dream-engine.js
36165
36308
  import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync13, readFileSync as readFileSync25, existsSync as existsSync34, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
36166
36309
  import { join as join45, basename as basename12 } from "node:path";
36167
- import { execSync as execSync29 } from "node:child_process";
36310
+ import { execSync as execSync28 } from "node:child_process";
36168
36311
  function loadAutoresearchMemory(repoRoot) {
36169
36312
  const memoryPath = join45(repoRoot, ".oa", "memory", "autoresearch.json");
36170
36313
  if (!existsSync34(memoryPath))
@@ -36528,7 +36671,7 @@ var init_dream_engine = __esm({
36528
36671
  }
36529
36672
  }
36530
36673
  try {
36531
- const output = execSync29(cmd, {
36674
+ const output = execSync28(cmd, {
36532
36675
  cwd: this.repoRoot,
36533
36676
  timeout: 3e4,
36534
36677
  encoding: "utf-8",
@@ -37305,17 +37448,17 @@ ${summaryResult}
37305
37448
  try {
37306
37449
  mkdirSync14(checkpointDir, { recursive: true });
37307
37450
  try {
37308
- const gitStatus = execSync29("git status --porcelain", {
37451
+ const gitStatus = execSync28("git status --porcelain", {
37309
37452
  cwd: this.repoRoot,
37310
37453
  encoding: "utf-8",
37311
37454
  timeout: 1e4
37312
37455
  });
37313
- const gitDiff = execSync29("git diff", {
37456
+ const gitDiff = execSync28("git diff", {
37314
37457
  cwd: this.repoRoot,
37315
37458
  encoding: "utf-8",
37316
37459
  timeout: 1e4
37317
37460
  });
37318
- const gitHash = execSync29("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
37461
+ const gitHash = execSync28("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
37319
37462
  cwd: this.repoRoot,
37320
37463
  encoding: "utf-8",
37321
37464
  timeout: 5e3
@@ -44650,8 +44793,8 @@ NEW TASK: ${fullInput}`;
44650
44793
  try {
44651
44794
  const updateInfo = await checkForUpdate(version);
44652
44795
  if (updateInfo) {
44653
- const { exec } = await import("node:child_process");
44654
- exec(`npm install -g open-agents-ai@latest --prefer-online`, { timeout: 18e4 }, (err) => {
44796
+ const { exec: exec2 } = await import("node:child_process");
44797
+ exec2(`npm install -g open-agents-ai@latest --prefer-online`, { timeout: 18e4 }, (err) => {
44655
44798
  if (!err) {
44656
44799
  writeContent(() => renderInfo(`Updated to v${updateInfo.latestVersion} in background. Takes effect next session.`));
44657
44800
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.10",
3
+ "version": "0.103.11",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",