Skip to content

Conversation

@AviPeltz
Copy link
Collaborator

@AviPeltz AviPeltz commented Dec 17, 2025

Description

Related Issues

Type of Change

  • [x ] Bug fix
  • New feature
  • Documentation
  • Refactor
  • Other (please describe):

Testing

Screenshots (if applicable)

Additional Notes

Summary by CodeRabbit

  • Performance

    • Optimized terminal escape sequence filtering for faster processing.
    • Implemented efficient scrollback buffer management.
  • Bug Fixes

    • Improved filtering of terminal control sequences (CPR, DA, OSC responses) from output and scrollback.
    • Enhanced handling of fragmented terminal sequences across data chunks.
  • Tests

    • Added comprehensive test coverage for escape sequence filtering and scrollback behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 17, 2025

Walkthrough

The PR introduces FastEscapeFilter (a state machine–based escape sequence filter) and ScrollbackBuffer (a chunked string accumulator) to replace regex-based filtering and optimize scrollback storage. Both are integrated into session and manager flows, with comprehensive test coverage added for new and modified components.

Changes

Cohort / File(s) Summary
New Fast Escape Filter
fast-escape-filter.ts, fast-escape-filter.test.ts
Implements a high-performance, single-pass state machine escape filter that discards CPR, DA, DECRPM, OSC color responses, and DCS sequences; buffers partial sequences across chunks for reassembly; includes comprehensive test coverage for all pattern types and edge cases.
New Scrollback Buffer
scrollback-buffer.ts
Introduces a chunked string accumulator with O(1) amortized append, lazy concatenation with caching, and O(1) length access; provides static factory and string conversion methods.
Terminal Escape Filter Optimization
terminal-escape-filter.ts, terminal-escape-filter.test.ts
Adds fast-path bypass when no ESC character is present; tightens buffering heuristics to reduce unnecessary buffering of normal output; expands test coverage for TUI scenarios, stateful chunked output, and buffering edge cases.
Terminal Session Integration
terminal/session.ts, terminal/session.test.ts
Replaces TerminalEscapeFilter with FastEscapeFilter; changes scrollback storage from string to ScrollbackBuffer; introduces ESC-based fast path for data handling; updates history recovery to sanitize scrollback; modifies tests to use ScrollbackBuffer instances.
Terminal Manager & Types
terminal/manager.ts, terminal/manager.test.ts, terminal/types.ts
Updates manager methods to stringify scrollback via toString(); changes nullish coalescing for empty scrollback handling; updates session/types to use ScrollbackBuffer for internal storage and FastEscapeFilter for filtering; adjusts test expectations to reflect query-response filtering behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • State machine logic in FastEscapeFilter: Multiple states and transitions with character-level processing require careful verification against specification.
  • ScrollbackBuffer caching and compaction: Lazy string concatenation and chunk management logic should be validated for correctness and memory efficiency.
  • Integration across session/manager/types: Type signature changes and updated data flow through scrollback and history layers need cross-file consistency verification.
  • Nullish coalescing changes: Confirm that ?? null instead of || null correctly preserves empty string scrollback in recovery scenarios.

Possibly related PRs

  • PR #157 — Implements the original regex-based terminal query-response filter that this PR replaces with FastEscapeFilter and integrates into session/manager.
  • PR #154 — Also implements terminal query-response filtering and filtering integration; shares code-level changes in the same filtering domain.
  • PR #120 — Modifies terminal session history handling and TerminalManager.createOrAttach; overlaps with scrollback recovery and history persistence logic.

Poem

🐰 A filter swift, a state machine neat,
Escape sequences—gone in one complete beat!
ScrollbackBuffer chunks the text with care,
Fast paths and caching float through the air,
Performance hops, no regex delays—
Terminal scrollback soars through our days!

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete. While the template structure is present with the 'Bug fix' type selected, all major sections lack substantive content: Description, Related Issues, and Testing are empty or contain only template comments. Add detailed description of the changes, link any related issues, and describe the testing performed to validate the escape sequence filtering behavior.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title refers to fixing escape sequences handling to prevent them from being pushed to input, which aligns with the PR's focus on escape sequence filtering and buffering across multiple files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch electronic-giraffe-8d7a4b

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Dec 17, 2025

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) View Branch
Vercel API (Vercel) Open Preview
Vercel Web (Vercel) Open Preview
Vercel Marketing (Vercel) Open Preview
Vercel Admin (Vercel) Open Preview
Vercel Docs (Vercel) Open Preview

Preview updates automatically with new commits

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/desktop/src/main/lib/terminal/session.ts (1)

157-188: LGTM: Well-designed fast path optimization with correct filtering logic.

The data handler implementation is solid:

  • Fast path for plain text (no ESC) provides excellent performance optimization
  • Slow path correctly handles escape sequences, preserving clear sequences for visual rendering while removing them from history
  • Filter reset on clear sequence is appropriate

The logic is complex but appears correct. Consider extracting the slow path (lines 167-188) into a separate helper function to improve maintainability.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 361067e and fc02219.

📒 Files selected for processing (10)
  • apps/desktop/src/main/lib/fast-escape-filter.test.ts (1 hunks)
  • apps/desktop/src/main/lib/fast-escape-filter.ts (1 hunks)
  • apps/desktop/src/main/lib/scrollback-buffer.ts (1 hunks)
  • apps/desktop/src/main/lib/terminal-escape-filter.test.ts (2 hunks)
  • apps/desktop/src/main/lib/terminal-escape-filter.ts (3 hunks)
  • apps/desktop/src/main/lib/terminal/manager.test.ts (3 hunks)
  • apps/desktop/src/main/lib/terminal/manager.ts (4 hunks)
  • apps/desktop/src/main/lib/terminal/session.test.ts (7 hunks)
  • apps/desktop/src/main/lib/terminal/session.ts (6 hunks)
  • apps/desktop/src/main/lib/terminal/types.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc

Files:

  • apps/desktop/src/main/lib/terminal-escape-filter.ts
  • apps/desktop/src/main/lib/terminal/manager.test.ts
  • apps/desktop/src/main/lib/scrollback-buffer.ts
  • apps/desktop/src/main/lib/fast-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal-escape-filter.test.ts
  • apps/desktop/src/main/lib/fast-escape-filter.ts
  • apps/desktop/src/main/lib/terminal/session.test.ts
  • apps/desktop/src/main/lib/terminal/types.ts
  • apps/desktop/src/main/lib/terminal/session.ts
  • apps/desktop/src/main/lib/terminal/manager.ts
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: Please use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Files:

  • apps/desktop/src/main/lib/terminal-escape-filter.ts
  • apps/desktop/src/main/lib/terminal/manager.test.ts
  • apps/desktop/src/main/lib/scrollback-buffer.ts
  • apps/desktop/src/main/lib/fast-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal-escape-filter.test.ts
  • apps/desktop/src/main/lib/fast-escape-filter.ts
  • apps/desktop/src/main/lib/terminal/session.test.ts
  • apps/desktop/src/main/lib/terminal/types.ts
  • apps/desktop/src/main/lib/terminal/session.ts
  • apps/desktop/src/main/lib/terminal/manager.ts
**/*.{ts,tsx,js,jsx,json}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome for code formatting and linting, running at root level for speed

Files:

  • apps/desktop/src/main/lib/terminal-escape-filter.ts
  • apps/desktop/src/main/lib/terminal/manager.test.ts
  • apps/desktop/src/main/lib/scrollback-buffer.ts
  • apps/desktop/src/main/lib/fast-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal-escape-filter.test.ts
  • apps/desktop/src/main/lib/fast-escape-filter.ts
  • apps/desktop/src/main/lib/terminal/session.test.ts
  • apps/desktop/src/main/lib/terminal/types.ts
  • apps/desktop/src/main/lib/terminal/session.ts
  • apps/desktop/src/main/lib/terminal/manager.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Avoid any type and prioritize type safety in TypeScript code

Files:

  • apps/desktop/src/main/lib/terminal-escape-filter.ts
  • apps/desktop/src/main/lib/terminal/manager.test.ts
  • apps/desktop/src/main/lib/scrollback-buffer.ts
  • apps/desktop/src/main/lib/fast-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal-escape-filter.test.ts
  • apps/desktop/src/main/lib/fast-escape-filter.ts
  • apps/desktop/src/main/lib/terminal/session.test.ts
  • apps/desktop/src/main/lib/terminal/types.ts
  • apps/desktop/src/main/lib/terminal/session.ts
  • apps/desktop/src/main/lib/terminal/manager.ts
apps/desktop/src/main/lib/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Implement IPC handlers accepting object parameters (not positional parameters) in apps/desktop/src/main/lib/*.ts files

Files:

  • apps/desktop/src/main/lib/terminal-escape-filter.ts
  • apps/desktop/src/main/lib/scrollback-buffer.ts
  • apps/desktop/src/main/lib/fast-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal-escape-filter.test.ts
  • apps/desktop/src/main/lib/fast-escape-filter.ts
apps/desktop/**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.test.{ts,tsx,js,jsx}: Tests should have one assert per test
Tests should be readable
Tests should be fast
Tests should be independent
Tests should be repeatable

Files:

  • apps/desktop/src/main/lib/terminal/manager.test.ts
  • apps/desktop/src/main/lib/fast-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal/session.test.ts
🧠 Learnings (5)
📚 Learning: 2025-12-12T05:45:09.686Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-12T05:45:09.686Z
Learning: Applies to apps/desktop/src/main/lib/*.ts : Implement IPC handlers accepting object parameters (not positional parameters) in apps/desktop/src/main/lib/*.ts files

Applied to files:

  • apps/desktop/src/main/lib/terminal/manager.test.ts
  • apps/desktop/src/main/lib/terminal/types.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be readable

Applied to files:

  • apps/desktop/src/main/lib/terminal/manager.test.ts
  • apps/desktop/src/main/lib/terminal-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal/session.test.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be repeatable

Applied to files:

  • apps/desktop/src/main/lib/terminal/manager.test.ts
  • apps/desktop/src/main/lib/terminal-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal/session.test.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be fast

Applied to files:

  • apps/desktop/src/main/lib/fast-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal/session.test.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be independent

Applied to files:

  • apps/desktop/src/main/lib/terminal-escape-filter.test.ts
  • apps/desktop/src/main/lib/terminal/session.test.ts
🧬 Code graph analysis (4)
apps/desktop/src/main/lib/terminal-escape-filter.test.ts (1)
apps/desktop/src/main/lib/terminal-escape-filter.ts (3)
  • filterTerminalQueryResponses (267-269)
  • filter (122-154)
  • TerminalEscapeFilter (115-257)
apps/desktop/src/main/lib/terminal/session.test.ts (3)
apps/desktop/src/main/lib/scrollback-buffer.ts (1)
  • ScrollbackBuffer (11-69)
apps/desktop/src/main/lib/terminal/session.ts (1)
  • recoverScrollback (21-45)
apps/desktop/src/main/lib/terminal/types.ts (1)
  • TerminalSession (7-25)
apps/desktop/src/main/lib/terminal/types.ts (3)
apps/desktop/src/main/lib/scrollback-buffer.ts (1)
  • ScrollbackBuffer (11-69)
apps/desktop/src/main/lib/terminal-history.ts (1)
  • HistoryWriter (32-107)
apps/desktop/src/main/lib/fast-escape-filter.ts (1)
  • FastEscapeFilter (70-333)
apps/desktop/src/main/lib/terminal/session.ts (3)
apps/desktop/src/main/lib/scrollback-buffer.ts (1)
  • ScrollbackBuffer (11-69)
apps/desktop/src/main/lib/fast-escape-filter.ts (1)
  • FastEscapeFilter (70-333)
apps/desktop/src/main/lib/terminal-escape-filter.ts (2)
  • containsClearScrollbackSequence (282-284)
  • extractContentAfterClear (294-308)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Deploy Docs
  • GitHub Check: Deploy Marketing
  • GitHub Check: Deploy Admin
  • GitHub Check: Deploy API
  • GitHub Check: Deploy Web
  • GitHub Check: Build
🔇 Additional comments (25)
apps/desktop/src/main/lib/terminal-escape-filter.ts (2)

127-131: LGTM! Effective fast-path optimization.

The early-exit when no ESC character is present eliminates unnecessary regex work for plain text, delivering a measurable performance boost for common terminal output.


158-206: LGTM! Conservative buffering reduces latency.

The updated buffering logic correctly balances correctness with performance by:

  • Not buffering ESC alone or ESC[ alone (too common in normal output)
  • Buffering only sequences that strongly indicate query responses (ESC[?, ESC[>, ESC[digit, OSC 1x, DCS patterns)
  • Including length checks to prevent array out-of-bounds access

The digit buffering at lines 185-187 is intentional: color codes like ESC[32m will complete quickly and pass through since they don't match filter patterns.

apps/desktop/src/main/lib/fast-escape-filter.ts (4)

20-64: LGTM! Well-structured state machine design.

The use of character codes for fast comparison and a comprehensive state enum covering all target escape sequence patterns (CSI, OSC, DCS variants) is appropriate for high-performance filtering.


77-90: LGTM! Efficient single-pass implementation.

The filter method correctly implements O(n) processing with pre-allocated output, iterating through each character and delegating to the state machine.


92-299: LGTM! Comprehensive state machine logic.

The processChar method correctly handles all target escape sequence patterns:

  • CPR: ESC[row;colR or ESC[rowR
  • DA1/DA2/DA: ESC[?...c, ESC[>...c, ESC[digits...c
  • Mode reports: ESC[...$y
  • OSC color responses: ESC]1x;rgb:... with BEL or ST terminators
  • DCS sequences: DA3 (ESC P ! |) and XTVERSION (ESC P > |)
  • Unknown CSI: ESC[O

State transitions properly emit pending data when sequences don't match patterns, ensuring normal terminal output is preserved.


314-332: LGTM! Proper lifecycle management.

The flush() and reset() methods correctly handle session lifecycle by emitting buffered incomplete sequences and clearing state, respectively.

apps/desktop/src/main/lib/terminal/manager.test.ts (1)

518-542: LGTM! Test expectations align with filtering behavior.

The renamed test now correctly verifies that CPR (ESC[2;1R), DA1 (ESC[?1;0c), and OSC color responses are filtered from the data stream, with only plain text ("helloworld\n") passed to the handler. This aligns with the PR's objective to prevent escape sequences from appearing as garbage in the input.

apps/desktop/src/main/lib/terminal/session.test.ts (1)

4-141: LGTM! Tests correctly updated for ScrollbackBuffer.

All test cases have been appropriately updated to:

  • Use ScrollbackBuffer.fromString() for test data initialization
  • Call .toString() on scrollback results for string assertions
  • Update mock session structures to hold ScrollbackBuffer instances

The changes maintain test coverage while aligning with the new type signature.

apps/desktop/src/main/lib/terminal/types.ts (3)

3-4: LGTM! Imports updated for new implementations.

The imports correctly reflect the migration to FastEscapeFilter (state machine-based filtering) and ScrollbackBuffer (chunked string accumulator).


15-20: LGTM! Type changes deliver performance improvements.

Updating scrollback from string to ScrollbackBuffer eliminates O(n²) string concatenation overhead, providing O(1) amortized appends. Similarly, FastEscapeFilter replaces regex-based filtering with a single-pass state machine for better performance.


60-60: LGTM! Parameter type aligned with TerminalSession.

The existingScrollback parameter type change to ScrollbackBuffer | null correctly reflects the refactored session structure.

apps/desktop/src/main/lib/terminal-escape-filter.test.ts (2)

367-510: LGTM! Comprehensive TUI scenario coverage.

The new test suite thoroughly validates filtering behavior for real-world TUI applications (Claude Code, Codex):

  • CPR burst filtering during redraws
  • Interleaved query responses with UI output
  • Tab switch scenarios with accumulated responses
  • Chunked data handling across state transitions
  • Conservative buffering rules (ESC alone and ESC[ alone not buffered for performance, ESC[digit buffered for correctness)

These tests provide strong evidence that the filtering logic correctly handles the reported bug scenario.


567-580: LGTM! Test descriptions clarify performance rationale.

The updated test descriptions at lines 567 and 575 explicitly mention performance concerns, making it clear why ESC alone and ESC[ alone should pass through immediately rather than being buffered.

apps/desktop/src/main/lib/fast-escape-filter.test.ts (1)

1-182: LGTM! Comprehensive test coverage for FastEscapeFilter.

The test suite thoroughly validates the state machine implementation:

  • All target patterns filtered: CPR, DA1/DA2/DA, Mode Reports, OSC color responses, DCS sequences, Unknown CSI
  • Normal sequences preserved: colors, cursor movements, clear scrollback, reset
  • Chunked sequences handled correctly across chunk boundaries
  • Flush behavior verified for incomplete sequences
  • Plain text passthrough validated including edge cases

The tests are readable, fast, and independent, following project guidelines.

apps/desktop/src/main/lib/scrollback-buffer.ts (1)

1-69: LGTM! Efficient chunked buffer design.

The ScrollbackBuffer class effectively addresses the O(n²) string concatenation problem:

  • Array-based chunk storage provides O(1) amortized appends
  • Lazy toString() with caching avoids redundant joins
  • Memory compaction at lines 34-36 reduces overhead after the first toString() call
  • fromString() factory method enables efficient initialization
  • length getter provides O(1) length tracking

This is a significant performance improvement over repeated string concatenation, especially for large scrollback buffers.

apps/desktop/src/main/lib/terminal/manager.ts (5)

37-42: LGTM: ScrollbackBuffer integration for existing sessions.

The conversion to string via toString() correctly maintains the API contract while leveraging the new ScrollbackBuffer abstraction.


44-48: LGTM: Correct use of nullish coalescing operator.

Using ?? instead of || properly preserves empty-string scrollback values, which is important for accurate recovery logic.


78-83: LGTM: Consistent scrollback serialization.

The toString() conversion maintains consistency with the existing session path (line 39) and properly serializes the ScrollbackBuffer for the API response.


108-114: LGTM: Correct scrollback preservation in crash recovery.

Passing session.scrollback directly is appropriate here since the session definitely exists in this crash recovery path. This preserves the scrollback history when falling back to the fallback shell.


235-249: LGTM: Proper use of ScrollbackBuffer API.

Using scrollback.clear() instead of assignment correctly leverages the ScrollbackBuffer abstraction and maintains proper encapsulation.

apps/desktop/src/main/lib/terminal/session.ts (5)

15-16: LGTM: ESC constant improves readability and performance.

Defining the ESC character as a constant enhances code clarity and enables efficient fast-path checks in the data handler.


21-45: LGTM: ScrollbackBuffer integration in recovery path.

The updated recoverScrollback function correctly:

  • Integrates ScrollbackBuffer throughout the recovery flow
  • Sanitizes recovered history using FastEscapeFilter to remove protocol responses
  • Properly flushes the filter to include any pending data

117-120: LGTM: Efficient scrollback persistence.

Converting the scrollback to string only when non-empty and passing it to the history writer is both correct and efficient.


138-138: LGTM: FastEscapeFilter initialization.

Replacing the previous filter with the new state machine-based FastEscapeFilter aligns with the PR's objective to improve escape sequence handling.


241-249: LGTM: Consistent ScrollbackBuffer usage in flush.

Using scrollback.append() for the remaining filtered data maintains consistency with the ScrollbackBuffer abstraction throughout the session lifecycle.

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.

2 participants