Skip to content

release: v0.4.1#16

Merged
code-crusher merged 2 commits into
mainfrom
release/v0.4.1
Jul 8, 2026
Merged

release: v0.4.1#16
code-crusher merged 2 commits into
mainfrom
release/v0.4.1

Conversation

@code-crusher

Copy link
Copy Markdown
Member

Release v0.4.1

Patch release — fixes the CLI viewport scrolling issue.

Fixed

  • Input box now stays pinned to the bottom of the terminal. Removed <Static> (which permanently wrote rows to stdout and caused the whole view to scroll up when a long response completed). Rows are now rendered in the dynamic region with viewport-capped visibility — only the rows that fit above the input box are shown. A spacer fills the gap when content is short so the input box + status bar are always at the bottom. Streaming text is capped with tailForHeight() (accounting for line wrapping) so it never grows tall enough to push the input box off-screen.

Checklist

  • npm run typecheck and npm run build pass
  • Version bumped to 0.4.1 in package.json
  • CHANGELOG.md updated
  • Branch named release/v0.4.1 (matches version)

Remove <Static> which permanently wrote rows to stdout and caused
uncontrolled terminal scrolling when long responses completed.
Render rows in the dynamic region with viewport-capped visibility
so only the rows that fit above the input box are shown. Add a
spacer to pin the input box + status bar at the bottom when
content is short. Cap streaming text with tailForHeight() which
accounts for line wrapping so it never pushes the input box
off-screen.
@matterai-app

matterai-app Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary By MatterAI MatterAI logo

🔄 What Changed

Bumped version to 0.4.1. Implemented a custom viewport management system in the TUI. Replaced the <Static> rendering pattern with a dynamic calculation logic that measures terminal dimensions (useStdout) to determine which chat rows fit on screen, ensuring the input box and status bar remain pinned at the bottom.

🔍 Impact of the Change

Significantly improves the CLI user experience by preventing uncontrolled terminal scrolling. The interface now intelligently truncates long message histories and streaming text based on the current terminal height, maintaining visibility of critical UI elements like the prompt and active tasks.

📁 Total Files Changed

Click to Expand
File ChangeLog
Version Bump package.json Incremented version from 0.4.0 to 0.4.1.
Viewport Logic src/ui/App.tsx Added terminal dimension tracking and row virtualization logic to manage screen real estate.

🧪 Test Added/Recommended

Recommended

  • Unit Tests: Validate wrapHeight and tailForHeight with various string lengths and terminal widths.
  • Edge Case Testing: Verify UI behavior when the terminal window is resized to extremely small dimensions (e.g., < 10 rows).

🔒 Security Vulnerabilities

No security vulnerabilities detected in this PR. 🛡️

@matterai-app matterai-app Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧪 PR Review is completed: Viewport management system is well-structured but has a height estimation gap for tool diffs and a potential regression in reasoning expand functionality.

Skipped files
  • CHANGELOG.md: Skipped file pattern
⬇️ Low Priority Suggestions (2)
src/ui/App.tsx (2 suggestions)

Location: src/ui/App.tsx (Lines 1685-1685)

🟡 Logic Error

Issue: The estimateRowLines function for the "tool" case with row.diff counts raw newline-delimited lines (row.diff.split(" ").length) without accounting for terminal line wrapping. The function's own JSDoc states it "Intentionally slightly conservative (overestimates)" but this case actually underestimates height when diff lines are longer than wrapWidth. Long diff lines (e.g., minified code, long URLs) will wrap to multiple terminal rows, causing more rows to be displayed than availableHeight allows and potentially pushing the input box off-screen.

Fix: Use the already-defined wrapped() helper instead of raw line counting to account for line wrapping, while keeping the 62-line cap.

Impact: Ensures the viewport height estimation remains conservative as documented, preventing the input box from being pushed off-screen by long diff content.

-          h += Math.min(62, row.diff.split("\n").length) + 1;
+          h += Math.min(62, wrapped(row.diff)) + 1;

Location: src/ui/App.tsx (Lines 1376-1378)

🟡 Potential Regression

Issue: The old code displayed streaming reasoning with tail(streamingReasoning, expandReasoningRef.current ? 30 : 3), respecting the user's expand/collapse toggle. The new streamingReasoningDisplay always uses 3 lines via tailForHeight(streamingReasoning, 3, wrapWidth), ignoring expandReasoningRef.current. If the expand toggle is still wired to user input (e.g., a keypress), the user will press it but see no effect — a silent regression. Additionally, middleHeight at line 1344 hardcodes += 4 for reasoning, which would also need to change if expand is restored.

Fix: Restore the expand-aware line count in streamingReasoningDisplay, and update middleHeight at line 1344 to 1 + (expandReasoningRef.current ? 30 : 3) to reserve the correct vertical space.

Impact: Restores the reasoning expand/collapse UX and keeps viewport calculations consistent.

-    const streamingReasoningDisplay = streamingReasoning
-      ? tailForHeight(streamingReasoning, 3, wrapWidth)
-      : "";
+    const streamingReasoningDisplay = streamingReasoning
+      ? tailForHeight(streamingReasoning, expandReasoningRef.current ? 30 : 3, wrapWidth)
+      : "";

@code-crusher code-crusher merged commit ce61a22 into main Jul 8, 2026
1 check passed
@code-crusher code-crusher deleted the release/v0.4.1 branch July 8, 2026 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant