open-agents-ai 0.187.373 → 0.187.375

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 +84 -37
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -534479,7 +534479,14 @@ ${CONTENT_BG_SEQ}`);
534479
534479
  this.termWrite(`\x1B[${this.scrollRegionTop};${pos.scrollEnd}r`);
534480
534480
  } else {
534481
534481
  const absD = Math.abs(heightDelta);
534482
- this.termWrite(`\x1B[${this.scrollRegionTop};${pos.scrollEnd}r`);
534482
+ const oldScrollEnd = Math.max(rows - oldFooterHeight, this.scrollRegionTop);
534483
+ const newScrollEnd = pos.scrollEnd;
534484
+ this.termWrite(`\x1B[${this.scrollRegionTop};${newScrollEnd}r`);
534485
+ let wipeTransition = "";
534486
+ for (let r2 = oldScrollEnd + 1; r2 <= newScrollEnd; r2++) {
534487
+ wipeTransition += `\x1B[${r2};1H${CONTENT_BG_SEQ}\x1B[2K`;
534488
+ }
534489
+ if (wipeTransition) this.termWrite(wipeTransition);
534483
534490
  let scrollDown = `\x1B[${this.scrollRegionTop};1H`;
534484
534491
  for (let i2 = 0; i2 < absD; i2++) scrollDown += "\x1BM";
534485
534492
  this.termWrite(scrollDown);
@@ -558432,6 +558439,7 @@ var init_stream_renderer = __esm({
558432
558439
  "packages/cli/src/tui/stream-renderer.ts"() {
558433
558440
  "use strict";
558434
558441
  init_layout2();
558442
+ init_text_selection();
558435
558443
  isTTY8 = process.stdout.isTTY ?? false;
558436
558444
  PASTEL = {
558437
558445
  key: 222,
@@ -558512,6 +558520,16 @@ var init_stream_renderer = __esm({
558512
558520
  */
558513
558521
  jsonBlobSize = 0;
558514
558522
  jsonBlobSuppressed = false;
558523
+ /**
558524
+ * Track cursor's current column on the bottom-of-scroll row during partial
558525
+ * flushes so we can wrap when cumulative partials would exceed terminal
558526
+ * width. Reset to 0 on \n, 5 when a new " ⎿ " prefix line starts.
558527
+ * Essential for the typing-effect: without this, successive partial
558528
+ * writes pile up on the bottom row past the right edge and the user
558529
+ * only sees proper placement once the stream ends and a full repaint
558530
+ * runs. Tracked in VISIBLE chars (ANSI escapes stripped).
558531
+ */
558532
+ _cursorCol = 0;
558515
558533
  /** Called when a new model response starts streaming */
558516
558534
  onStreamStart() {
558517
558535
  this.lineBuffer = "";
@@ -558522,6 +558540,7 @@ var init_stream_renderer = __esm({
558522
558540
  this.inToolArgs = false;
558523
558541
  this.jsonBlobSize = 0;
558524
558542
  this.jsonBlobSuppressed = false;
558543
+ this._cursorCol = 0;
558525
558544
  this.enabled = true;
558526
558545
  this.tokenCount = 0;
558527
558546
  this.startTime = Date.now();
@@ -558680,51 +558699,70 @@ var init_stream_renderer = __esm({
558680
558699
  }
558681
558700
  }
558682
558701
  const prefix = this.lineStarted ? "" : " ⎿ ";
558702
+ const maxW = Math.max(10, termCols() - 6);
558683
558703
  let rendered;
558704
+ const emitWrapped = (text2, highlight, trailingNewline) => {
558705
+ if (!text2) return;
558706
+ if (this.lineStarted && this._cursorCol > 0) {
558707
+ const remaining = maxW - this._cursorCol;
558708
+ const firstChunkLen = Math.min(text2.length, Math.max(1, remaining));
558709
+ if (remaining < 8 && text2.length > remaining) {
558710
+ this.writeRaw("\n");
558711
+ this.lineStarted = false;
558712
+ } else if (text2.length > remaining) {
558713
+ const head = text2.slice(0, firstChunkLen).replace(/\s+$/, "");
558714
+ const tail = text2.slice(firstChunkLen).replace(/^\s+/, "");
558715
+ this.writeRaw(highlight(head) + "\n");
558716
+ this.lineStarted = false;
558717
+ text2 = tail;
558718
+ if (!text2) return;
558719
+ }
558720
+ }
558721
+ const usePrefix = this.lineStarted ? "" : prefix;
558722
+ const usableW = this.lineStarted ? maxW : Math.max(1, maxW - usePrefix.length);
558723
+ const lines = text2.length > usableW ? this.wordWrap(text2, usableW) : [text2];
558724
+ for (let i2 = 0; i2 < lines.length; i2++) {
558725
+ const isFirst = i2 === 0;
558726
+ const isLast = i2 === lines.length - 1;
558727
+ const lp = isFirst ? usePrefix : " ";
558728
+ const needsNewline = !isLast || trailingNewline;
558729
+ this.writeRaw(dimText(lp) + highlight(lines[i2]) + (needsNewline ? "\n" : ""));
558730
+ }
558731
+ this.lineStarted = !trailingNewline;
558732
+ };
558684
558733
  switch (kind) {
558685
558734
  case "thinking":
558686
- rendered = dimItalic(raw);
558687
- break;
558735
+ emitWrapped(raw, dimItalic, hasNewline);
558736
+ return;
558688
558737
  case "tool_args":
558689
558738
  rendered = this.highlightJson(raw, true);
558690
558739
  break;
558691
- case "content":
558692
- {
558693
- const maxW = termCols() - 6;
558694
- if (this.inCodeBlock) {
558695
- const cropped = raw.length > maxW ? raw.slice(0, maxW - 3) + "..." : raw;
558696
- if (this.codeLang === "diff" || this.codeLang === "patch") {
558697
- rendered = this.highlightDiff(cropped);
558698
- } else if (this.codeLang === "bash" || this.codeLang === "sh" || this.codeLang === "shell" || this.codeLang === "zsh") {
558699
- rendered = this.highlightShell(cropped);
558700
- } else {
558701
- rendered = this.highlightCode(cropped);
558702
- }
558703
- } else if (this.looksLikeJson(raw)) {
558704
- const cropped = raw.length > maxW ? raw.slice(0, maxW - 3) + "..." : raw;
558705
- rendered = this.highlightJson(cropped, false);
558740
+ case "content": {
558741
+ if (this.inCodeBlock) {
558742
+ const cropped = raw.length > maxW ? raw.slice(0, maxW - 3) + "..." : raw;
558743
+ if (this.codeLang === "diff" || this.codeLang === "patch") {
558744
+ rendered = this.highlightDiff(cropped);
558745
+ } else if (this.codeLang === "bash" || this.codeLang === "sh" || this.codeLang === "shell" || this.codeLang === "zsh") {
558746
+ rendered = this.highlightShell(cropped);
558706
558747
  } else {
558707
- if (hasNewline && raw.length > maxW) {
558708
- const wrapped = this.wordWrap(raw, maxW);
558709
- for (let i2 = 0; i2 < wrapped.length; i2++) {
558710
- const lp = i2 === 0 ? prefix : " ";
558711
- const isLast = i2 === wrapped.length - 1;
558712
- this.writeRaw(
558713
- dimText(lp) + this.highlightMarkdown(wrapped[i2]) + (isLast ? "\n" : "\n")
558714
- );
558715
- }
558716
- this.lineStarted = false;
558717
- return;
558718
- }
558719
- const cropped = raw.length > maxW ? raw.slice(0, maxW) : raw;
558720
- rendered = this.highlightMarkdown(cropped);
558748
+ rendered = this.highlightCode(cropped);
558721
558749
  }
558722
- break;
558750
+ } else if (this.looksLikeJson(raw)) {
558751
+ const cropped = raw.length > maxW ? raw.slice(0, maxW - 3) + "..." : raw;
558752
+ rendered = this.highlightJson(cropped, false);
558753
+ } else {
558754
+ if (raw.length > maxW || this.lineStarted && this._cursorCol + raw.length > maxW) {
558755
+ emitWrapped(raw, (s2) => this.highlightMarkdown(s2), hasNewline);
558756
+ return;
558757
+ }
558758
+ rendered = this.highlightMarkdown(raw);
558723
558759
  }
558724
558760
  break;
558725
- case "thinking":
558726
- rendered = dimItalic(raw);
558727
- break;
558761
+ }
558762
+ }
558763
+ if (kind === "content" && this.lineStarted && this._cursorCol + raw.length > maxW) {
558764
+ emitWrapped(raw, (s2) => this.highlightMarkdown(s2), hasNewline);
558765
+ return;
558728
558766
  }
558729
558767
  this.writeRaw(dimText(prefix) + rendered + (hasNewline ? "\n" : ""));
558730
558768
  this.lineStarted = !hasNewline;
@@ -558738,13 +558776,22 @@ var init_stream_renderer = __esm({
558738
558776
  }
558739
558777
  /** Write raw ANSI text to stdout and capture for scrollback.
558740
558778
  * Wraps each write in autowrap-disable (DECAWM off) to prevent the terminal
558741
- * from injecting line breaks when a token fragment reaches the right edge. */
558779
+ * from injecting line breaks when a token fragment reaches the right edge.
558780
+ * Also maintains _cursorCol so emitWrapped can decide when to force a
558781
+ * wrap on the NEXT partial flush (avoiding bottom-row token pile-up). */
558742
558782
  writeRaw(text) {
558743
558783
  if (isTTY8) {
558744
558784
  process.stdout.write(`\x1B[?7l${text}\x1B[?7h`);
558745
558785
  } else {
558746
558786
  process.stdout.write(text);
558747
558787
  }
558788
+ const lastNl = text.lastIndexOf("\n");
558789
+ if (lastNl >= 0) {
558790
+ const after = text.slice(lastNl + 1);
558791
+ this._cursorCol = stripAnsi(after).length;
558792
+ } else {
558793
+ this._cursorCol += stripAnsi(text).length;
558794
+ }
558748
558795
  if (this.onRenderedLine) {
558749
558796
  const parts = text.split("\n");
558750
558797
  for (let i2 = 0; i2 < parts.length - 1; i2++) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.373",
3
+ "version": "0.187.375",
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",