open-agents-ai 0.138.88 → 0.138.90

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 +127 -71
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -37855,7 +37855,8 @@ function tuiSelect(opts) {
37855
37855
  cursor = first >= 0 ? first : 0;
37856
37856
  }
37857
37857
  const reservedTopBottom = 6;
37858
- const selectChrome = 3;
37858
+ const hasCrumbs = opts.breadcrumbs && opts.breadcrumbs.length > 0;
37859
+ const selectChrome = hasCrumbs ? 8 : 7;
37859
37860
  const contentArea = opts.availableRows ?? Math.max(6, (process.stdout.rows ?? 24) - reservedTopBottom);
37860
37861
  const maxVisible = opts.maxVisible ?? Math.max(3, contentArea - selectChrome);
37861
37862
  let scrollOffset = 0;
@@ -43321,7 +43322,8 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
43321
43322
  const modeResult = await tuiSelect({
43322
43323
  items: modeItems,
43323
43324
  activeKey: currentMode,
43324
- title: "Voice \u203A Mode",
43325
+ title: "Mode",
43326
+ breadcrumbs: ["Voice"],
43325
43327
  rl: ctx.rl,
43326
43328
  availableRows: ctx.availableContentRows?.()
43327
43329
  });
@@ -43348,7 +43350,8 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
43348
43350
  const voiceResult = await tuiSelect({
43349
43351
  items: voiceItems,
43350
43352
  activeKey: currentModel,
43351
- title: "Voice \u203A Engine",
43353
+ title: "Engine",
43354
+ breadcrumbs: ["Voice"],
43352
43355
  rl: ctx.rl,
43353
43356
  availableRows: ctx.availableContentRows?.(),
43354
43357
  skipKeys: ["header-onnx", "header-mlx", "header-clone"]
@@ -44127,6 +44130,81 @@ async function handleUpdate(subcommand, ctx) {
44127
44130
  process.stdout.write(text);
44128
44131
  }
44129
44132
  };
44133
+ const particles = [" ", "\u2801", "\u2802", "\u2840", "\u2804", "\u2820", "\u2812", "\u28C0", "\u2824", "\u28C4", "\xB7", "\u2591", "\u28E4", "\u2592", "\u28F6", "\u2593", "\u28FF", "\u2588"];
44134
+ const hash = (r, c3, f) => {
44135
+ const x = r * 7 + c3 * 13 + f * 3 + 37;
44136
+ return (x * x * 31 + x * 17 + 59) % 97 / 97;
44137
+ };
44138
+ function renderInstallFrame(version, frame, statusLine) {
44139
+ const cols = process.stdout.columns ?? 80;
44140
+ const rows = process.stdout.rows ?? 24;
44141
+ const bgDark = 234;
44142
+ const yellow = 178;
44143
+ let buf = `\x1B[48;5;${bgDark}m\x1B[H\x1B[2J`;
44144
+ const centerRow = Math.floor(rows / 2);
44145
+ const centerCol = Math.floor(cols / 2);
44146
+ const boxW = Math.min(44, cols - 4);
44147
+ const boxH = 7;
44148
+ const boxTop = centerRow - Math.floor(boxH / 2);
44149
+ const boxLeft = centerCol - Math.floor(boxW / 2);
44150
+ buf += `\x1B[${boxTop};${boxLeft}H\x1B[38;5;${yellow}m\u250C`;
44151
+ buf += `\x1B[${boxTop};${boxLeft + boxW - 1}H\u2510`;
44152
+ buf += `\x1B[${boxTop + boxH - 1};${boxLeft}H\u2514`;
44153
+ buf += `\x1B[${boxTop + boxH - 1};${boxLeft + boxW - 1}H\u2518`;
44154
+ for (let c3 = 1; c3 < boxW - 1; c3++) {
44155
+ const density = Math.sin(c3 * 0.3 + frame * 0.4) * 0.5 + 0.5;
44156
+ const noise = hash(0, c3, frame);
44157
+ const charIdx = noise < density ? Math.min(particles.length - 1, Math.floor(density * particles.length)) : 0;
44158
+ const ch = particles[charIdx];
44159
+ buf += `\x1B[${boxTop};${boxLeft + c3}H\x1B[38;5;${yellow}m${ch}`;
44160
+ const density2 = Math.sin(c3 * 0.3 + frame * 0.4 + 1.5) * 0.5 + 0.5;
44161
+ const noise2 = hash(boxH, c3, frame);
44162
+ const charIdx2 = noise2 < density2 ? Math.min(particles.length - 1, Math.floor(density2 * particles.length)) : 0;
44163
+ buf += `\x1B[${boxTop + boxH - 1};${boxLeft + c3}H${particles[charIdx2]}`;
44164
+ }
44165
+ for (let r = 1; r < boxH - 1; r++) {
44166
+ const density = Math.sin(r * 0.5 + frame * 0.35) * 0.5 + 0.5;
44167
+ const noise = hash(r, 0, frame);
44168
+ const charIdx = noise < density ? Math.min(particles.length - 1, Math.floor(density * particles.length)) : 0;
44169
+ buf += `\x1B[${boxTop + r};${boxLeft}H\x1B[38;5;${yellow}m${particles[charIdx]}`;
44170
+ const density2 = Math.sin(r * 0.5 + frame * 0.35 + 2) * 0.5 + 0.5;
44171
+ const noise2 = hash(r, boxW, frame);
44172
+ const charIdx2 = noise2 < density2 ? Math.min(particles.length - 1, Math.floor(density2 * particles.length)) : 0;
44173
+ buf += `\x1B[${boxTop + r};${boxLeft + boxW - 1}H${particles[charIdx2]}`;
44174
+ }
44175
+ const label = "INSTALLING";
44176
+ const labelCol = centerCol - Math.floor(label.length / 2);
44177
+ buf += `\x1B[${centerRow - 1};${labelCol}H\x1B[1;38;5;${yellow}m${label}`;
44178
+ const vLabel = `v${version}`;
44179
+ const vCol = centerCol - Math.floor(vLabel.length / 2);
44180
+ buf += `\x1B[${centerRow};${vCol}H\x1B[0;38;5;245m\x1B[48;5;${bgDark}m${vLabel}`;
44181
+ if (statusLine) {
44182
+ const sCol = centerCol - Math.floor(statusLine.length / 2);
44183
+ buf += `\x1B[${centerRow + 2};${Math.max(1, sCol)}H\x1B[38;5;240m\x1B[48;5;${bgDark}m${statusLine.slice(0, cols - 2)}`;
44184
+ }
44185
+ buf += `\x1B[0m`;
44186
+ process.stdout.write(buf);
44187
+ }
44188
+ function startInstallOverlay(version) {
44189
+ process.stdout.write("\x1B[?1049h\x1B[?25l");
44190
+ let frame = 0;
44191
+ let status = "";
44192
+ renderInstallFrame(version, frame, status);
44193
+ const timer = setInterval(() => {
44194
+ frame++;
44195
+ renderInstallFrame(version, frame, status);
44196
+ }, 80);
44197
+ return {
44198
+ setStatus(text) {
44199
+ status = text;
44200
+ },
44201
+ stop(finalText) {
44202
+ clearInterval(timer);
44203
+ status = finalText;
44204
+ renderInstallFrame(version, frame, status);
44205
+ }
44206
+ };
44207
+ }
44130
44208
  function startInlineSpinner(prefix) {
44131
44209
  let frame = 0;
44132
44210
  const nvActive = isNeovimActive();
@@ -44222,12 +44300,8 @@ async function handleUpdate(subcommand, ctx) {
44222
44300
  const doRebuild = menuResult.key === "rebuild" || menuResult.key === "full";
44223
44301
  const doPython = menuResult.key === "python" || menuResult.key === "full";
44224
44302
  const doCloudflared = menuResult.key === "full";
44225
- process.stdout.write("\x1B[?1049h\x1B[H\x1B[2J");
44226
- process.stdout.write(`
44227
- ${c2.bold("Open Agents Update")}
44228
- ${c2.dim("\u2500".repeat(40))}
44229
-
44230
- `);
44303
+ const targetVersion = info?.latestVersion ?? currentVersion;
44304
+ const installOverlay = startInstallOverlay(targetVersion);
44231
44305
  let installError = "";
44232
44306
  const runInstall2 = (cmd) => new Promise((resolve32) => {
44233
44307
  const child = exec4(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
@@ -44238,24 +44312,22 @@ async function handleUpdate(subcommand, ctx) {
44238
44312
  child.stdout?.on("data", (chunk) => {
44239
44313
  const text = String(chunk);
44240
44314
  for (const line of text.split("\n")) {
44241
- if (line.trim()) {
44242
- process.stdout.write(` ${c2.dim("\u2502")} ${line.trim().slice(0, 70)}
44243
- `);
44244
- }
44315
+ if (line.trim())
44316
+ installOverlay.setStatus(line.trim().slice(0, 50));
44245
44317
  }
44246
44318
  });
44247
44319
  child.stderr?.on("data", (chunk) => {
44248
44320
  const text = String(chunk);
44249
44321
  for (const line of text.split("\n")) {
44250
44322
  if (line.trim() && !line.includes("npm warn")) {
44251
- process.stdout.write(` ${c2.dim("\u2502")} ${c2.yellow(line.trim().slice(0, 70))}
44252
- `);
44323
+ installOverlay.setStatus(line.trim().slice(0, 50));
44253
44324
  }
44254
44325
  }
44255
44326
  });
44256
44327
  });
44257
44328
  if (needsSudo) {
44258
- process.stdout.write("\x1B[?1049l");
44329
+ installOverlay.stop("Requesting permissions...");
44330
+ process.stdout.write("\x1B[?1049l\x1B[?25h");
44259
44331
  renderInfo("Global npm directory requires elevated permissions.");
44260
44332
  renderInfo("Enter your password if prompted...");
44261
44333
  safeWrite("\n");
@@ -44268,24 +44340,18 @@ async function handleUpdate(subcommand, ctx) {
44268
44340
  renderWarning("Could not acquire sudo credentials. Try: sudo npm i -g open-agents-ai");
44269
44341
  return;
44270
44342
  }
44271
- process.stdout.write("\x1B[?1049h\x1B[H\x1B[2J");
44272
- process.stdout.write(`
44273
- ${c2.bold("Open Agents Update")}
44274
- ${c2.dim("\u2500".repeat(40))}
44275
-
44276
- `);
44343
+ const installOverlay2 = startInstallOverlay(targetVersion);
44344
+ Object.assign(installOverlay, installOverlay2);
44277
44345
  }
44278
44346
  const sudoPrefix = needsSudo ? "sudo " : "";
44279
44347
  let primaryUpdated = false;
44280
44348
  let depsUpdated = false;
44281
44349
  if (doPackage && info) {
44282
- const installSpinner = startInlineSpinner("Installing update");
44350
+ installOverlay.setStatus("Installing package...");
44283
44351
  const installCmd = `${sudoPrefix}npm install -g open-agents-ai@latest --prefer-online`;
44284
44352
  let installOk = await runInstall2(installCmd);
44285
44353
  if (!installOk && /ENOTEMPTY|errno -39/i.test(installError)) {
44286
- installSpinner.stop("ENOTEMPTY \u2014 cleaning stale npm artifacts...");
44287
- process.stdout.write(` ${c2.dim("\u2502")} Removing stale temp directories and npm cache...
44288
- `);
44354
+ installOverlay.setStatus("Cleaning stale artifacts...");
44289
44355
  try {
44290
44356
  const prefix = await execA("npm prefix -g", { timeout: 5e3 });
44291
44357
  const globalModules = prefix.endsWith("/lib") ? prefix + "/node_modules" : prefix + "/lib/node_modules";
@@ -44294,28 +44360,22 @@ async function handleUpdate(subcommand, ctx) {
44294
44360
  await execA(`${sudoPrefix}npm cache clean --force 2>/dev/null || true`, { timeout: 3e4 });
44295
44361
  } catch {
44296
44362
  }
44297
- process.stdout.write(` ${c2.dim("\u2502")} Retrying with --force...
44298
- `);
44299
- const retrySpinner = startInlineSpinner("Retrying install (force)");
44363
+ installOverlay.setStatus("Retrying install...");
44300
44364
  installError = "";
44301
44365
  installOk = await runInstall2(`${sudoPrefix}npm install -g open-agents-ai@latest --force --prefer-online`);
44302
- if (!installOk) {
44303
- retrySpinner.stop("Retry failed.");
44304
- } else {
44305
- retrySpinner.stop(`Update installed (v${info.latestVersion}).`);
44306
- }
44307
44366
  }
44308
44367
  if (!installOk) {
44309
- installSpinner.stop("Update install failed.");
44368
+ installOverlay.stop("Install failed");
44369
+ await new Promise((r) => setTimeout(r, 1500));
44370
+ process.stdout.write("\x1B[?1049l\x1B[?25h");
44310
44371
  renderWarning(`Try manually: ${sudoPrefix}npm i -g open-agents-ai`);
44311
- process.stdout.write("\x1B[?1049l");
44312
44372
  return;
44313
44373
  }
44314
- installSpinner.stop(`Update installed (v${info.latestVersion}).`);
44374
+ installOverlay.setStatus(`Package installed (v${info.latestVersion})`);
44315
44375
  primaryUpdated = true;
44316
44376
  }
44317
44377
  if (doDeps) {
44318
- const depsSpinner = startInlineSpinner("Updating subordinate dependencies");
44378
+ installOverlay.setStatus("Updating dependencies...");
44319
44379
  try {
44320
44380
  const prefix = await execA("npm prefix -g", { timeout: 5e3 });
44321
44381
  const globalModules = prefix.endsWith("/lib") ? prefix + "/node_modules" : prefix + "/lib/node_modules";
@@ -44334,23 +44394,22 @@ async function handleUpdate(subcommand, ctx) {
44334
44394
  }
44335
44395
  } catch {
44336
44396
  }
44337
- depsSpinner.stop(depsUpdated ? "Dependencies updated." : "Dependencies checked.");
44397
+ installOverlay.setStatus(depsUpdated ? "Dependencies updated" : "Dependencies OK");
44338
44398
  }
44339
44399
  if (!primaryUpdated && !depsUpdated && !doRebuild && !doPython && !doCloudflared) {
44340
- renderInfo("No changes needed.");
44341
- safeWrite("\n");
44342
- await new Promise((r) => setTimeout(r, 1e3));
44343
- process.stdout.write("\x1B[?1049l");
44400
+ installOverlay.stop("No changes needed");
44401
+ await new Promise((r) => setTimeout(r, 1500));
44402
+ process.stdout.write("\x1B[?1049l\x1B[?25h");
44344
44403
  return;
44345
44404
  }
44346
44405
  if (doRebuild) {
44347
- const rebuildSpinner = startInlineSpinner("Rebuilding native modules");
44348
- const rebuildOk = await new Promise((resolve32) => {
44406
+ installOverlay.setStatus("Rebuilding native modules...");
44407
+ await new Promise((resolve32) => {
44349
44408
  const child = exec4(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve32(true));
44350
44409
  child.stdout?.resume();
44351
44410
  child.stderr?.resume();
44352
44411
  });
44353
- rebuildSpinner.stop(rebuildOk ? "Native modules rebuilt." : "Native rebuild skipped.");
44412
+ installOverlay.setStatus("Native modules rebuilt");
44354
44413
  }
44355
44414
  const { existsSync: fsExists } = await import("node:fs");
44356
44415
  const { join: pathJoin } = await import("node:path");
@@ -44358,46 +44417,42 @@ async function handleUpdate(subcommand, ctx) {
44358
44417
  if (doPython) {
44359
44418
  let hasPython = hasCmd("python3") || hasCmd("python");
44360
44419
  if (!hasPython) {
44361
- const pyInstallSpinner = startInlineSpinner("Installing Python3");
44420
+ installOverlay.setStatus("Installing Python3...");
44362
44421
  try {
44363
44422
  ensurePython3();
44364
44423
  hasPython = hasCmd("python3") || hasCmd("python");
44365
- pyInstallSpinner.stop(hasPython ? "Python3 installed." : "Python3 install failed.");
44366
44424
  } catch {
44367
- pyInstallSpinner.stop("Python3 install failed.");
44368
44425
  }
44426
+ installOverlay.setStatus(hasPython ? "Python3 installed" : "Python3 unavailable");
44369
44427
  }
44370
44428
  if (hasPython && !checkPythonVenv()) {
44371
- const venvInstallSpinner = startInlineSpinner("Installing python3-venv");
44429
+ installOverlay.setStatus("Installing python3-venv...");
44372
44430
  try {
44373
44431
  ensurePythonVenv();
44374
- venvInstallSpinner.stop(checkPythonVenv() ? "python3-venv installed." : "python3-venv install failed.");
44375
44432
  } catch {
44376
- venvInstallSpinner.stop("python3-venv install failed.");
44377
44433
  }
44378
44434
  }
44379
44435
  const venvDir = pathJoin(getHome(), ".open-agents", "venv");
44380
44436
  const venvPip = pathJoin(venvDir, "bin", "pip");
44381
44437
  if (fsExists(venvPip)) {
44382
- const pySpinner = startInlineSpinner("Upgrading Python venv packages");
44383
- const pyOk = await new Promise((resolve32) => {
44438
+ installOverlay.setStatus("Upgrading Python packages...");
44439
+ await new Promise((resolve32) => {
44384
44440
  const child = exec4(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve32(!err));
44385
44441
  child.stdout?.resume();
44386
44442
  child.stderr?.resume();
44387
44443
  });
44388
- pySpinner.stop(pyOk ? "Python packages upgraded." : "Python upgrade skipped.");
44444
+ installOverlay.setStatus("Python packages updated");
44389
44445
  } else {
44390
- const pySpinner = startInlineSpinner("Setting up Python venv & deps");
44391
- await ensureVisionDeps((msg) => {
44392
- pySpinner.stop(msg);
44446
+ installOverlay.setStatus("Setting up Python venv...");
44447
+ await ensureVisionDeps(() => {
44393
44448
  }).catch(() => {
44394
44449
  });
44395
- pySpinner.stop("Python deps bootstrapped.");
44450
+ installOverlay.setStatus("Python deps bootstrapped");
44396
44451
  }
44397
44452
  }
44398
44453
  let hasCf = false;
44399
44454
  if (doCloudflared) {
44400
- const cfSpinner = startInlineSpinner("Checking cloudflared");
44455
+ installOverlay.setStatus("Checking cloudflared...");
44401
44456
  try {
44402
44457
  const { execSync: es } = await import("node:child_process");
44403
44458
  es("which cloudflared", { stdio: "pipe", timeout: 3e3 });
@@ -44405,29 +44460,29 @@ async function handleUpdate(subcommand, ctx) {
44405
44460
  } catch {
44406
44461
  }
44407
44462
  if (!hasCf) {
44408
- cfSpinner.stop("Installing cloudflared...");
44409
- ensureCloudflaredBackground((msg) => renderInfo(msg));
44463
+ installOverlay.setStatus("Installing cloudflared...");
44464
+ ensureCloudflaredBackground(() => {
44465
+ });
44410
44466
  await new Promise((r) => setTimeout(r, 1e3));
44411
44467
  } else {
44412
- cfSpinner.stop("cloudflared ready.");
44468
+ installOverlay.setStatus("cloudflared ready");
44413
44469
  }
44414
44470
  ensureTranscribeCliBackground();
44415
44471
  }
44416
44472
  if (!primaryUpdated) {
44417
- safeWrite(`
44418
- ${c2.green("\u2714")} Done.
44419
- `);
44420
- await new Promise((r) => setTimeout(r, 1e3));
44421
- process.stdout.write("\x1B[?1049l");
44473
+ installOverlay.stop("Done");
44474
+ await new Promise((r) => setTimeout(r, 1500));
44475
+ process.stdout.write("\x1B[?1049l\x1B[?25h");
44422
44476
  return;
44423
44477
  }
44424
- const reloadSpinner = startInlineSpinner("Loading");
44478
+ installOverlay.setStatus("Reloading...");
44425
44479
  await new Promise((r) => setTimeout(r, 400));
44426
44480
  ctx.contextSave?.();
44427
44481
  const hadActiveTask = ctx.savePendingTaskState?.() ?? false;
44428
44482
  const resumeFlag = hadActiveTask ? "1" : "update-only";
44429
- reloadSpinner.stop("Reloading\u2026");
44430
- process.stdout.write("\x1B[?1049l");
44483
+ installOverlay.stop("Reloading\u2026");
44484
+ await new Promise((r) => setTimeout(r, 300));
44485
+ process.stdout.write("\x1B[?1049l\x1B[?25h");
44431
44486
  const { execPath, argv } = process;
44432
44487
  try {
44433
44488
  const { execFileSync } = await import("node:child_process");
@@ -56061,6 +56116,7 @@ async function startInteractive(config, repoPath) {
56061
56116
  const { onOverlayLeave: onOverlayLeave2 } = await Promise.resolve().then(() => (init_overlay_lock(), overlay_lock_exports));
56062
56117
  onOverlayLeave2(() => {
56063
56118
  banner.renderCurrentFrame();
56119
+ statusBar.enableMouseTracking();
56064
56120
  if (statusBar.isActive)
56065
56121
  statusBar.handleResize();
56066
56122
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.138.88",
3
+ "version": "0.138.90",
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",