open-agents-ai 0.20.0 → 0.20.1

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 +159 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -18006,12 +18006,122 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
18006
18006
  }
18007
18007
  });
18008
18008
 
18009
+ // packages/cli/dist/tui/braille-spinner.js
18010
+ var DENSITY, WAVE, COLOR_RAMP, BrailleSpinner;
18011
+ var init_braille_spinner = __esm({
18012
+ "packages/cli/dist/tui/braille-spinner.js"() {
18013
+ "use strict";
18014
+ DENSITY = [
18015
+ "\u2800",
18016
+ // ⠀ empty
18017
+ "\u2840",
18018
+ // ⡀ dot 7
18019
+ "\u28C0",
18020
+ // ⣀ dots 7,8
18021
+ "\u28C4",
18022
+ // ⣄ dots 3,7,8
18023
+ "\u28E4",
18024
+ // ⣤ dots 3,6,7,8
18025
+ "\u28E6",
18026
+ // ⣦ dots 2,3,6,7,8
18027
+ "\u28F6",
18028
+ // ⣶ dots 2,3,5,6,7,8
18029
+ "\u28F7",
18030
+ // ⣷ dots 1,2,3,5,6,7,8
18031
+ "\u28FF"
18032
+ // ⣿ all dots
18033
+ ];
18034
+ WAVE = [...DENSITY, ...DENSITY.slice(1, -1).reverse()];
18035
+ COLOR_RAMP = [
18036
+ 237,
18037
+ // ⠀ very dim gray
18038
+ 60,
18039
+ // ⡀ muted lavender
18040
+ 97,
18041
+ // ⣀ dim purple
18042
+ 97,
18043
+ // ⣄ dim purple
18044
+ 141,
18045
+ // ⣤ medium purple
18046
+ 141,
18047
+ // ⣦ medium purple
18048
+ 183,
18049
+ // ⣶ light lavender
18050
+ 183,
18051
+ // ⣷ light lavender
18052
+ 189,
18053
+ // ⣿ bright lavender
18054
+ 183,
18055
+ // ⣷ (descending)
18056
+ 183,
18057
+ // ⣶
18058
+ 141,
18059
+ // ⣦
18060
+ 141,
18061
+ // ⣤
18062
+ 97,
18063
+ // ⣄
18064
+ 97,
18065
+ // ⣀
18066
+ 60
18067
+ // ⡀
18068
+ ];
18069
+ BrailleSpinner = class {
18070
+ frame = 0;
18071
+ timer = null;
18072
+ /** Start the animation, calling `onFrame` every tick (~80 ms). */
18073
+ start(onFrame) {
18074
+ this.frame = 0;
18075
+ this.timer = setInterval(() => {
18076
+ this.frame++;
18077
+ onFrame();
18078
+ }, 80);
18079
+ }
18080
+ /** Stop the animation and reset. */
18081
+ stop() {
18082
+ if (this.timer) {
18083
+ clearInterval(this.timer);
18084
+ this.timer = null;
18085
+ }
18086
+ this.frame = 0;
18087
+ }
18088
+ /** Whether the animation timer is active. */
18089
+ get isRunning() {
18090
+ return this.timer !== null;
18091
+ }
18092
+ /**
18093
+ * Render the current animation frame as an ANSI-colored string.
18094
+ * Each column gets a braille character whose density and color vary
18095
+ * sinusoidally, shifted by `this.frame` to create movement.
18096
+ */
18097
+ render(width) {
18098
+ const cycleLen = WAVE.length;
18099
+ let buf = "";
18100
+ let lastColor = -1;
18101
+ for (let col = 0; col < width; col++) {
18102
+ const idx = (col * 2 + this.frame) % cycleLen;
18103
+ const ch = WAVE[idx];
18104
+ const color = COLOR_RAMP[idx];
18105
+ if (color !== lastColor) {
18106
+ buf += `\x1B[38;5;${color}m`;
18107
+ lastColor = color;
18108
+ }
18109
+ buf += ch;
18110
+ }
18111
+ buf += "\x1B[0m";
18112
+ return buf;
18113
+ }
18114
+ };
18115
+ }
18116
+ });
18117
+
18009
18118
  // packages/cli/dist/tui/status-bar.js
18010
18119
  var FOOTER_ROWS, StatusBar;
18011
18120
  var init_status_bar = __esm({
18012
18121
  "packages/cli/dist/tui/status-bar.js"() {
18013
18122
  "use strict";
18014
18123
  init_render();
18124
+ init_braille_spinner();
18015
18125
  FOOTER_ROWS = 5;
18016
18126
  StatusBar = class {
18017
18127
  metrics = {
@@ -18050,6 +18160,9 @@ var init_status_bar = __esm({
18050
18160
  _countdown = 0;
18051
18161
  _recBlink = true;
18052
18162
  _recBlinkTimer = null;
18163
+ /** Whether agent is actively processing (braille animation) */
18164
+ _processing = false;
18165
+ _brailleSpinner = new BrailleSpinner();
18053
18166
  /**
18054
18167
  * Provide a callback that returns readline's current input state.
18055
18168
  * StatusBar uses this to render typed text and position the cursor
@@ -18085,6 +18198,22 @@ var init_status_bar = __esm({
18085
18198
  if (this.active)
18086
18199
  this.renderFooterPreserveCursor();
18087
18200
  }
18201
+ /** Start or stop the braille-dot processing animation on the buffer line. */
18202
+ setProcessing(active) {
18203
+ if (active === this._processing)
18204
+ return;
18205
+ this._processing = active;
18206
+ if (active) {
18207
+ this._brailleSpinner.start(() => {
18208
+ if (this.active)
18209
+ this.renderBufferLine();
18210
+ });
18211
+ } else {
18212
+ this._brailleSpinner.stop();
18213
+ if (this.active)
18214
+ this.renderBufferLine();
18215
+ }
18216
+ }
18088
18217
  /** Context window size to display. Can be updated if model changes. */
18089
18218
  setContextWindowSize(size) {
18090
18219
  this.metrics.contextWindowSize = size;
@@ -18162,7 +18291,7 @@ var init_status_bar = __esm({
18162
18291
  const w = getTermWidth();
18163
18292
  const sep = c2.dim("\u2500".repeat(w));
18164
18293
  const inputRow = rows - 2;
18165
- process.stdout.write(`\x1B[${this.scrollRegionTop};${scrollEnd}r\x1B[?25l\x1B[?7l\x1B[${rows - 4};1H\x1B[2K\x1B[${rows - 3};1H\x1B[2K${sep}\x1B[${inputRow};1H\x1B[2K${this.promptText}\x1B[${rows - 1};1H\x1B[2K${sep}\x1B[${rows};1H\x1B[2K${this.buildMetricsLine()}\x1B[?7h\x1B[${scrollEnd};1H`);
18294
+ process.stdout.write(`\x1B[${this.scrollRegionTop};${scrollEnd}r\x1B[?25l\x1B[?7l\x1B[${rows - 4};1H\x1B[2K${this.buildBufferContent(w)}\x1B[${rows - 3};1H\x1B[2K${sep}\x1B[${inputRow};1H\x1B[2K${this.promptText}\x1B[${rows - 1};1H\x1B[2K${sep}\x1B[${rows};1H\x1B[2K${this.buildMetricsLine()}\x1B[?7h\x1B[${scrollEnd};1H`);
18166
18295
  } else {
18167
18296
  this.applyScrollRegion();
18168
18297
  this.renderFooterAndPositionInput();
@@ -18289,7 +18418,7 @@ var init_status_bar = __esm({
18289
18418
  visibleText = fullLine.slice(scrollOffset, scrollOffset + availWidth);
18290
18419
  cursorCol = this.promptWidth + (cursorPos - scrollOffset) + 1;
18291
18420
  }
18292
- const buf = `\x1B[?7l\x1B[${rows - 4};1H\x1B[2K\x1B[${rows - 3};1H\x1B[2K${sep}\x1B[${inputRow};1H\x1B[2K${this.promptText}${visibleText}\x1B[${rows - 1};1H\x1B[2K${sep}\x1B[${rows};1H\x1B[2K${this.buildMetricsLine()}\x1B[?7h\x1B[?25h\x1B[${inputRow};${cursorCol}H`;
18421
+ const buf = `\x1B[?7l\x1B[${rows - 4};1H\x1B[2K${this.buildBufferContent(w)}\x1B[${rows - 3};1H\x1B[2K${sep}\x1B[${inputRow};1H\x1B[2K${this.promptText}${visibleText}\x1B[${rows - 1};1H\x1B[2K${sep}\x1B[${rows};1H\x1B[2K${this.buildMetricsLine()}\x1B[?7h\x1B[?25h\x1B[${inputRow};${cursorCol}H`;
18293
18422
  process.stdout.write(buf);
18294
18423
  }
18295
18424
  /**
@@ -18308,7 +18437,7 @@ var init_status_bar = __esm({
18308
18437
  const rows = process.stdout.rows ?? 24;
18309
18438
  const w = getTermWidth();
18310
18439
  const sep = c2.dim("\u2500".repeat(w));
18311
- const buf = `\x1B7\x1B[?7l\x1B[${rows - 4};1H\x1B[2K\x1B[${rows - 3};1H\x1B[2K${sep}\x1B[${rows - 1};1H\x1B[2K${sep}\x1B[${rows};1H\x1B[2K${this.buildMetricsLine()}\x1B[?7h\x1B8`;
18440
+ const buf = `\x1B7\x1B[?7l\x1B[${rows - 4};1H\x1B[2K${this.buildBufferContent(w)}\x1B[${rows - 3};1H\x1B[2K${sep}\x1B[${rows - 1};1H\x1B[2K${sep}\x1B[${rows};1H\x1B[2K${this.buildMetricsLine()}\x1B[?7h\x1B8`;
18312
18441
  process.stdout.write(buf);
18313
18442
  }
18314
18443
  /**
@@ -18340,6 +18469,29 @@ var init_status_bar = __esm({
18340
18469
  }
18341
18470
  process.stdout.write(`\x1B7\x1B[?7l\x1B[${inputRow};1H\x1B[2K${this.promptText}${visibleText}\x1B[?7h\x1B8`);
18342
18471
  }
18472
+ /**
18473
+ * Build the content for the buffer line (rows − 4).
18474
+ * Returns braille animation when processing, empty string when idle.
18475
+ */
18476
+ buildBufferContent(width) {
18477
+ if (this._processing && this._brailleSpinner.isRunning) {
18478
+ return this._brailleSpinner.render(width);
18479
+ }
18480
+ return "";
18481
+ }
18482
+ /**
18483
+ * Render ONLY the buffer line (rows − 4) using DEC save/restore cursor.
18484
+ * Called by the braille spinner timer without disrupting scroll or input.
18485
+ */
18486
+ renderBufferLine() {
18487
+ if (!this.active)
18488
+ return;
18489
+ const rows = process.stdout.rows ?? 24;
18490
+ const w = getTermWidth();
18491
+ const bufferRow = rows - 4;
18492
+ const content = this.buildBufferContent(w);
18493
+ process.stdout.write(`\x1B7\x1B[?7l\x1B[${bufferRow};1H\x1B[2K${content}\x1B[?7h\x1B8`);
18494
+ }
18343
18495
  /**
18344
18496
  * Hook into process.stdin to redraw footer after every keystroke.
18345
18497
  * Since readline's output is suppressed (redirected to a no-op stream),
@@ -19272,6 +19424,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
19272
19424
  writeContent(() => renderUserMessage(`/${cmdResult.name}${cmdResult.args ? " " + cmdResult.args : ""}`));
19273
19425
  lastSubmittedPrompt = skillPrompt;
19274
19426
  try {
19427
+ statusBar.setProcessing(true);
19275
19428
  const task = startTask(skillPrompt, currentConfig, repoRoot, voiceEngine, {
19276
19429
  enabled: streamEnabled,
19277
19430
  renderer: streamRenderer
@@ -19290,6 +19443,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
19290
19443
  const errMsg = err instanceof Error ? err.message : String(err);
19291
19444
  writeContent(() => renderError(errMsg));
19292
19445
  }
19446
+ statusBar.setProcessing(false);
19293
19447
  activeTask = null;
19294
19448
  showPrompt();
19295
19449
  return;
@@ -19372,6 +19526,7 @@ Summarize or analyze this transcription as appropriate.`;
19372
19526
  writeContent(() => renderUserMessage(displayText));
19373
19527
  lastSubmittedPrompt = fullInput;
19374
19528
  try {
19529
+ statusBar.setProcessing(true);
19375
19530
  const task = startTask(fullInput, currentConfig, repoRoot, voiceEngine, {
19376
19531
  enabled: streamEnabled,
19377
19532
  renderer: streamRenderer
@@ -19409,6 +19564,7 @@ Summarize or analyze this transcription as appropriate.`;
19409
19564
  }
19410
19565
  }
19411
19566
  } finally {
19567
+ statusBar.setProcessing(false);
19412
19568
  if (activeTask) {
19413
19569
  sessionFilesTouched = Array.from(activeTask.filesTouched);
19414
19570
  sessionToolCallCount = activeTask.toolCallCount;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.20.0",
3
+ "version": "0.20.1",
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",