open-agents-ai 0.10.6 → 0.10.7

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 +55 -66
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8586,21 +8586,19 @@ var init_project_context = __esm({
8586
8586
  function fg(code, text) {
8587
8587
  return isTTY3 ? `\x1B[38;5;${code}m${text}\x1B[0m` : text;
8588
8588
  }
8589
- function buildRibbon(phrases, repeatWidth) {
8589
+ function buildPlainRibbon(phrases, repeatWidth) {
8590
8590
  const separator = " \xB7 ";
8591
8591
  let plain = "";
8592
- let rendered = "";
8593
8592
  while (plain.length < repeatWidth * 3) {
8594
8593
  for (const p of phrases) {
8595
- rendered += fg(p.color, p.text) + separator;
8596
8594
  plain += p.text + separator;
8597
8595
  }
8598
8596
  }
8599
- return { rendered, plain };
8597
+ return plain;
8600
8598
  }
8601
8599
  function createRow(phraseIndices, speed, direction) {
8602
8600
  const phrases = phraseIndices.map((i) => PHRASES[i % PHRASES.length]);
8603
- return { phrases, offset: 0, speed, direction, rendered: "", renderedPlain: "" };
8601
+ return { phrases, offset: 0, speed, direction, renderedPlain: "" };
8604
8602
  }
8605
8603
  var isTTY3, PHRASES, Carousel;
8606
8604
  var init_carousel = __esm({
@@ -8690,13 +8688,9 @@ var init_carousel = __esm({
8690
8688
  width;
8691
8689
  lineCount = 3;
8692
8690
  started = false;
8693
- rendered = false;
8694
- topRow = 1;
8695
- promptRow = 20;
8696
- // updated after header renders
8691
+ resizeHandler = null;
8697
8692
  constructor() {
8698
8693
  this.width = process.stdout.columns ?? 80;
8699
- const third = Math.ceil(PHRASES.length / 3);
8700
8694
  const indices0 = Array.from({ length: PHRASES.length }, (_, i) => i).sort(() => Math.random() - 0.5);
8701
8695
  const indices1 = Array.from({ length: PHRASES.length }, (_, i) => i).sort(() => Math.random() - 0.5);
8702
8696
  const indices2 = Array.from({ length: PHRASES.length }, (_, i) => i).sort(() => Math.random() - 0.5);
@@ -8712,24 +8706,40 @@ var init_carousel = __esm({
8712
8706
  }
8713
8707
  rebuildRibbons() {
8714
8708
  for (const row of this.rows) {
8715
- const { rendered, plain } = buildRibbon(row.phrases, this.width);
8716
- row.rendered = rendered;
8717
- row.renderedPlain = plain;
8709
+ row.renderedPlain = buildPlainRibbon(row.phrases, this.width);
8718
8710
  }
8719
8711
  }
8720
8712
  /**
8721
- * Start the animation. Writes 3 lines of scrolling text.
8722
- * Returns the number of lines used (for cursor management).
8713
+ * Start the animation.
8714
+ *
8715
+ * 1. Writes 3 empty lines to reserve space
8716
+ * 2. Sets DECSTBM scroll region to row 4+ (everything below carousel)
8717
+ * 3. Moves cursor into the scroll region
8718
+ * 4. Starts animation timer that writes ONLY to rows 1-3
8719
+ *
8720
+ * The cursor never leaves the scroll region, so readline works perfectly.
8723
8721
  */
8724
8722
  start() {
8725
8723
  if (!isTTY3)
8726
8724
  return 0;
8727
8725
  this.started = true;
8728
- process.stdout.on("resize", () => {
8726
+ const termRows = process.stdout.rows ?? 24;
8727
+ process.stdout.write("\x1B[1;1H");
8728
+ for (let i = 0; i < this.lineCount; i++) {
8729
+ process.stdout.write("\x1B[2K\n");
8730
+ }
8731
+ process.stdout.write(`\x1B[${this.lineCount + 1};${termRows}r`);
8732
+ process.stdout.write(`\x1B[${this.lineCount + 1};1H`);
8733
+ this.resizeHandler = () => {
8729
8734
  this.width = process.stdout.columns ?? 80;
8735
+ const newRows = process.stdout.rows ?? 24;
8730
8736
  this.rebuildRibbons();
8731
- });
8732
- this.render();
8737
+ if (this.started) {
8738
+ process.stdout.write(`\x1B[${this.lineCount + 1};${newRows}r`);
8739
+ }
8740
+ };
8741
+ process.stdout.on("resize", this.resizeHandler);
8742
+ this.renderFrame();
8733
8743
  this.timer = setInterval(() => {
8734
8744
  for (const row of this.rows) {
8735
8745
  row.offset += row.speed * row.direction;
@@ -8737,32 +8747,30 @@ var init_carousel = __esm({
8737
8747
  row.offset = 0;
8738
8748
  }
8739
8749
  }
8740
- this.render();
8750
+ this.renderFrame();
8741
8751
  }, 66);
8742
8752
  return this.lineCount;
8743
8753
  }
8744
- render() {
8754
+ /**
8755
+ * Render one animation frame.
8756
+ *
8757
+ * Uses save/restore cursor (DECSC/DECRC) to briefly visit rows 1-3,
8758
+ * then return. Because the scroll region is set to row 4+, the cursor
8759
+ * restore puts it back exactly where readline expects it.
8760
+ */
8761
+ renderFrame() {
8745
8762
  if (!isTTY3)
8746
8763
  return;
8747
- let buf = "\x1B[?25l";
8764
+ let buf = "\x1B7";
8748
8765
  for (let i = 0; i < this.rows.length; i++) {
8749
8766
  const line = this.extractWindow(this.rows[i]);
8750
- const row = this.topRow + i;
8751
- buf += `\x1B[${row};1H\x1B[2K${line}`;
8752
- }
8753
- if (!this.rendered) {
8754
- buf += `\x1B[${this.topRow + this.lineCount};1H`;
8755
- this.rendered = true;
8756
- } else {
8757
- buf += `\x1B[${this.promptRow};1H`;
8767
+ buf += `\x1B[${i + 1};1H\x1B[2K${line}`;
8758
8768
  }
8759
- buf += "\x1B[?25h";
8769
+ buf += "\x1B8";
8760
8770
  process.stdout.write(buf);
8761
8771
  }
8762
8772
  /**
8763
- * Extract a terminal-width window from the scrolling ribbon.
8764
- * We use the plain text for offset calculation, then slice the
8765
- * rendered (colored) string to match.
8773
+ * Extract a terminal-width colored window from a scrolling ribbon.
8766
8774
  */
8767
8775
  extractWindow(row) {
8768
8776
  const w = this.width;
@@ -8772,34 +8780,25 @@ var init_carousel = __esm({
8772
8780
  let start = Math.floor(Math.abs(row.offset)) % plain.length;
8773
8781
  if (start < 0)
8774
8782
  start += plain.length;
8775
- let windowPlain = "";
8776
- let pos = start;
8777
- while (windowPlain.length < w) {
8778
- windowPlain += plain[pos % plain.length];
8779
- pos++;
8780
- }
8781
8783
  const separator = " \xB7 ";
8782
8784
  let coloredLine = "";
8783
8785
  let charCount = 0;
8784
- let phraseIdx = 0;
8785
8786
  let charInPhrase = 0;
8786
8787
  let skipChars = start;
8787
8788
  const phrases = row.phrases;
8788
8789
  let fullIdx = 0;
8789
- outer: while (skipChars > 0) {
8790
+ while (skipChars > 0) {
8790
8791
  const p = phrases[fullIdx % phrases.length];
8791
8792
  const fullText = p.text + separator;
8792
8793
  if (skipChars < fullText.length) {
8793
- phraseIdx = fullIdx;
8794
8794
  charInPhrase = skipChars;
8795
- break outer;
8795
+ break;
8796
8796
  }
8797
8797
  skipChars -= fullText.length;
8798
8798
  fullIdx++;
8799
8799
  }
8800
- phraseIdx = fullIdx;
8801
8800
  while (charCount < w) {
8802
- const p = phrases[phraseIdx % phrases.length];
8801
+ const p = phrases[fullIdx % phrases.length];
8803
8802
  const fullText = p.text + separator;
8804
8803
  const remaining = fullText.slice(charInPhrase);
8805
8804
  for (const ch of remaining) {
@@ -8814,33 +8813,34 @@ var init_carousel = __esm({
8814
8813
  charCount++;
8815
8814
  charInPhrase++;
8816
8815
  }
8817
- phraseIdx++;
8816
+ fullIdx++;
8818
8817
  charInPhrase = 0;
8819
8818
  }
8820
8819
  return coloredLine;
8821
8820
  }
8822
8821
  /**
8823
- * Stop the animation and clear the carousel lines.
8822
+ * Stop the animation, clear the carousel lines, and reset scroll region.
8824
8823
  */
8825
8824
  stop() {
8826
8825
  if (this.timer) {
8827
8826
  clearInterval(this.timer);
8828
8827
  this.timer = null;
8829
8828
  }
8829
+ if (this.resizeHandler) {
8830
+ process.stdout.removeListener("resize", this.resizeHandler);
8831
+ this.resizeHandler = null;
8832
+ }
8830
8833
  if (!isTTY3 || !this.started)
8831
8834
  return;
8832
- let buf = "\x1B[?25l";
8835
+ let buf = "\x1B7";
8833
8836
  for (let i = 0; i < this.lineCount; i++) {
8834
- buf += `\x1B[${this.topRow + i};1H\x1B[2K`;
8837
+ buf += `\x1B[${i + 1};1H\x1B[2K`;
8835
8838
  }
8836
- buf += `\x1B[${this.promptRow};1H\x1B[?25h`;
8839
+ buf += "\x1B[r";
8840
+ buf += "\x1B8";
8837
8841
  process.stdout.write(buf);
8838
8842
  this.started = false;
8839
8843
  }
8840
- /** Tell the carousel where the prompt/content area starts */
8841
- setPromptRow(row) {
8842
- this.promptRow = row;
8843
- }
8844
8844
  /** Check if carousel is running */
8845
8845
  get isRunning() {
8846
8846
  return this.timer !== null;
@@ -9645,13 +9645,12 @@ async function startInteractive(config, repoPath) {
9645
9645
  const carousel = new Carousel();
9646
9646
  const carouselLines = carousel.start();
9647
9647
  const version = getVersion();
9648
- const headerLines = renderRichHeader({
9648
+ renderRichHeader({
9649
9649
  model: config.model,
9650
9650
  version,
9651
9651
  workspace: repoRoot,
9652
9652
  carouselLines
9653
9653
  });
9654
- carousel.setPromptRow(1 + carouselLines + headerLines);
9655
9654
  const voiceEngine = new VoiceEngine();
9656
9655
  let currentConfig = { ...config };
9657
9656
  let activeTask = null;
@@ -9666,16 +9665,6 @@ async function startInteractive(config, repoPath) {
9666
9665
  terminal: true,
9667
9666
  historySize: 100
9668
9667
  });
9669
- if (process.stdin.isTTY) {
9670
- const retireOnKey = () => {
9671
- if (!carouselRetired && carousel.isRunning) {
9672
- carousel.stop();
9673
- carouselRetired = true;
9674
- }
9675
- process.stdin.removeListener("data", retireOnKey);
9676
- };
9677
- process.stdin.on("data", retireOnKey);
9678
- }
9679
9668
  function showPrompt() {
9680
9669
  rl.setPrompt(activeTask ? activePrompt : idlePrompt);
9681
9670
  rl.prompt();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
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",