Commit Graph

21 Commits

Author SHA1 Message Date
roboomp e6b3e1acf0 fix(tui): buffered split raw paste bursts before classifying
Raw unbracketed paste data may span adjacent stdin reads. The prior call-local check drained a first chunk such as "line 1\r" before later lines could classify the burst, leaving the original per-line submit bug.

- Held ESC-free break-bearing input in a fixed 10 ms classification window and appended adjacent raw reads before classification.
- Coalesced candidates after two completed logical line breaks; replayed ambiguous candidates unchanged through the normal per-key path on expiry or before escape-bearing input.
- Cleared and exposed pending candidates through the existing flush, clear, getBuffer, and destroy lifecycle.
- Added regressions for split reads, a break-only boundary, and delayed replay of ordinary Enter input.

Fixes #5841
2026-07-17 13:26:38 +00:00
roboomp bacad80b56 fix(tui): require 3+ lines to coalesce a raw paste burst
The single-interior-break heuristic misclassified a single Enter batched with a following keystroke in one stdin read ("a\rb") as a paste, swallowing the submit. Terminal read boundaries are not key boundaries.

- Tightened RAW_MULTILINE_BURST to content-break-content-break-content so only 3+ line bursts (two interior break runs; CRLF counts as one) coalesce; a single Enter can never produce two interior breaks.
- Added regression tests for CRLF three-line bursts, a batched single Enter, and an ambiguous two-line burst staying on the key path.

Fixes #5841
2026-07-17 13:16:39 +00:00
roboomp 838fbca3d1 fix(tui): coalesced raw multiline paste bursts without bracketed markers
- Detected an ESC-free stdin burst with an interior CR/LF in StdinBuffer.process and routed it through the paste channel instead of per-key splitting, so a Cmd+V multiline block whose terminal omitted the \x1b[200~…\x1b[201~ markers no longer fires one submit per line.
- Guarded to ESC-free buffers so real bracketed pastes, CSI keys, and mouse reports keep their path; a lone Enter, a single trailing newline, and a run of bare Enters stay normal keypresses.
- Added regression tests for the raw CR/LF burst, single Enter, trailing Enter, bare-Enter run, single-line burst, and escape-bearing chunk.

Fixes #5841
2026-07-17 13:07:57 +00:00
can1357 dbe232f643 refactor(tui): optimized render pipeline allocations and simplified input parsing
- Bypasses frame array allocation and merging during render except when hosted under ConPTY.
- Reuses the active window array slice for DECCARA calculations to avoid redundant array copies.
- Simplifies the `stdin-buffer` CSI sequence scanner by removing unnecessary resume search logic and redundant SGR mouse validation regexes.
2026-07-02 02:40:08 +02:00
can1357 d4182835dc fix(tui): bounded escape sequence scanning to chunk limits
- Replaced unbounded `String#indexOf` lookups with structured byte loops to enforce `MAX_STRING_SEQ_BYTES` cap.
- Stopped unterminated OSC, DCS, and APC sequences from scanning past their limits and blocking the event loop.
- Maintained a one-byte overlap when checking chunk boundaries to ensure split escape terminators are correctly reassembled.
- Added comprehensive unit tests covering split boundary terminators and oversized payload scenarios.
2026-07-02 01:51:09 +02:00
can1357 5f1ed0fcde chore: reformat 2026-07-01 23:14:36 +02:00
can1357 cfdd369d9b fix(tui): reset stdin escape hint before paste 2026-07-01 21:53:17 +02:00
roboomp 089db21333 fix(tui): bound terminal input parsing so malformed sequences and non-bracketed pastes do not block the event loop
Three failure modes shared the same root cause on the StdinBuffer.process
hot path — unbounded synchronous work in a single call.

- `StdinBuffer.extractCompleteSequences` grew each escape candidate one code
  unit at a time and re-tested every prefix, so a malformed CSI/OSC/DCS/APC
  streamed across chunks re-inspected the accumulated buffer on every
  `process()` call (issue A). Replaced the grow-and-recheck loop with a
  single linear scan bounded by a per-type cap (CSI 4 KiB, OSC/DCS/APC 16
  MiB) and a resume-search offset carried on `StdinBuffer` so a legit
  chunked OSC 5522 image paste stays O(total) instead of O(total²).
- `BracketedPasteHandler` had no cap or timeout: a caller that bypassed
  StdinBuffer (fed the start marker with no end marker) grew `#buffer`
  forever (issue B, defense in depth). Added an optional `byteLimit` option
  (default 64 MiB) that aborts paste mode and delivers accumulated bytes as
  `pasteContent`, mirroring `StdinBuffer#abortPaste`.
- The `ProcessTerminal` data handler ran six always-executed escape-probe
  regex tests per `data` event; a 100 KB non-bracketed paste (terminal
  without DEC 2004 support) turned into ~600K regex executions (issue C).
  Added a fast path that forwards non-ESC sequences straight to the input
  handler when no reassembly buffer is holding state.

Verified with new stdin-buffer + bracketed-paste tests plus empirical
repros: a streamed 1 MiB malformed CSI drops from ~4300 ms to ~50 ms of
synchronous work, and a 1 MiB chunked OSC 5522 payload drops from ~6800 ms
to ~25 ms.

Fixes #4073
2026-07-01 07:19:28 +00:00
roboomp c2d6c8cf18 fix(tui): deliver buffered double-Esc as two events and re-arm loader after task completion
StdinBuffer held a bare `\x1b\x1b` chunk and timer-flushed it as one
sequence. `parseKey("\x1b\x1b")` returns undefined, so CustomEditor
fell through to the base editor and never fired the configured `onEscape` —
the double-escape gesture and the second-press single-Esc handler both went
dead whenever the terminal batched the two presses into one stdin read.

Split an exact bare `\x1b\x1b` into two ESC events only after the
flush window proves no follower arrived. If a follower does arrive, emit the
first ESC and restart parsing at the second ESC so legacy Alt chords
(`\x1bd`, `\x1b\x7f`) remain one downstream keypress. Meta-CSI/SS3
chords (`\x1b\x1b[A`, `\x1b\x1bO…`) still emit as one combined
sequence.

EventController.tool_execution_update re-armed the working loader when a
transient overlay (auto-compaction / auto-retry / handoff) had torn it down
mid-tool; tool_execution_end did not. A subagent (`task`) call only fires
_end, so a task result landing after such an overlay left the UI looking
idle even though the session was still streaming. Mirror the reconciler
call in #handleToolExecutionEnd.

Fixes #3857
2026-06-30 04:30:42 +00:00
roboomp 64734021a7 fix(tui): deliver buffered double-Esc as two events and re-arm loader after task completion
StdinBuffer held a bare `\x1b\x1b` chunk (or emitted it as one when followed by
a non-CSI byte). `parseKey("\x1b\x1b")` returns undefined, so CustomEditor
fell through to the base editor and never fired the configured `onEscape` —
the double-escape gesture and the second-press single-Esc handler both went
dead whenever the terminal batched the two presses into one stdin read.

Split a bare `\x1b\x1b` into two ESC events at the buffer layer, mirroring
the existing split for ESC + SGR mouse report. Meta-CSI/SS3 chords
(`\x1b\x1b[A`, `\x1b\x1bO…`) still emit as one combined sequence.

EventController.tool_execution_update re-armed the working loader when a
transient overlay (auto-compaction / auto-retry / handoff) had torn it down
mid-tool; tool_execution_end did not. A subagent (`task`) call only fires
_end, so a task result landing after such an overlay left the UI looking
idle even though the session was still streaming. Mirror the reconciler
call in #handleToolExecutionEnd.

Fixes #3857
2026-06-30 03:41:24 +00:00
can1357 15a4047785 fix(tui): fixed kitty mode reapply and double-ESC parsing across alt-screen
- Stored the active kitty keyboard enable sequence in the terminal and re-applied it after entering the alternate screen, then emitted `\x1b[<u` before leaving the alternate screen.
- Updated StdinBuffer parsing so `\x1b\x1b` waits for CSI/SS3 followers, splits `\x1b\x1b[` SGR mouse reports into a standalone Esc plus report, and reduced `PARTIAL_HOLD_MAX_MS` to 150ms.
2026-06-12 04:25:14 +02:00
can1357 3fd0dc3b58 feat(tui): added bounded holding for split escape partials in StdinBuffer
- Added `partialHoldTimeout` to `StdinBufferOptions` to configure extra wait for dangling partial escapes.
- Reworked `StdinBuffer` flush scheduling to defer emits and avoid stale partials merging with new escapes.
- Held SGR mouse and kitty partial escapes until cap expiry to prevent tail bytes leaking as typed text.
2026-06-12 03:27:50 +02:00
can1357 2d00ac3e45 fix(tui): restored terminal state on crash and unwedged paste-mode input
emergency restore leaves the alt screen and disables mouse tracking; bracketed paste gets an inactivity watchdog and byte cap so a lost end marker cannot eat input forever; split-escape flush window raised to 50ms; kitty printable dedup expires; resetDisplay repaints on the alt screen; input scanning is index-based instead of O(n^2) slicing; appearance poll no longer clears selection every 2s.
2026-06-10 01:28:23 +02:00
can1357 f6b0a690ab perf(tui): optimized bracketed paste processing for large inputs
- Reworked `StdinBuffer` to collect bracketed-paste chunks incrementally and flush them once the end marker is found, while carrying an overlap tail so split markers are still detected.
- Simplified pasted-text sanitization in `Editor` to use a single regex pass that strips control characters while preserving newlines.
- Added tests covering split-marker boundaries and large chunked pastes to verify the new paste assembly behavior.
2026-06-08 13:11:18 +02:00
can1357 61f11a6ce0 fix(tui): blocked destructive scrollback replay on unknown terminal viewports
- Blocked checkpoint scrollback replay unless native viewport-at-bottom proof succeeded.
- Expanded ED3-risk terminal detection to include SSH, multiplexer, WT-like, and unknown profiles.
- Added sync-output defaults with PI_TUI_SYNC_OUTPUT and PI_FORCE_SYNC_OUTPUT overrides.
- Deferred transcript thawing until native scrollback refresh returned true.
- Adjusted non-escape parsing to emit one Unicode scalar and raised timeout to 75ms.
2026-06-05 17:47:47 +02:00
Nick 7acb6987bf fix(tui): progressive enhancement keyboard negotiation for Zellij 2026-05-26 17:47:31 +04:00
can1357 718ab4e3ae feat(tui): added tui autocomplete awaitable slash cmd returns with hints
- Added promise-based slash command completions with Awaitable returns and argumentHint metadata.
- Added kitty modifier-key decoding with super-mask support and validation of Alt/Ctrl/Super printable events.
- Added kitty printable key deduplication by filtering pending unmodified follow-up codepoints in the stdin buffer.
- Added render throttling with stop-time finalization, output normalization, and OSC 9;4 progress updates.
2026-05-12 10:17:04 +02:00
can1357 acf8ab5225 style: stylistic changes 2026-02-10 07:39:39 +01:00
can1357 779ca4872b style(deps): migrated from Prettier to Biome and updated formatting rules
- Removed Prettier configuration files (.prettierignore and .prettierrc) and migrated formatting to Biome.
- Updated Biome configuration from version 2.3.11 to 2.3.12 and changed arrowParentheses rule from 'always' to 'asNeeded'.
- Pinned @biomejs/biome dependency to exact version 2.3.12 in package.json and bun.lock.
- Applied consistent arrow function formatting across 489 files by removing unnecessary parentheses around single parameters.
- Removed blank lines after comment blocks and reorganized imports for consistency across the codebase.
2026-01-24 04:20:19 +01:00
can1357 741ab06ed2 feat: port upstream improvements from pi-mono (f1b64b9d..6730b4fa)
TUI:
- Add fuzzy matching module (moved from coding-agent)
- Remove Kitty protocol query timeout (fixes shift+enter delays)
- Add bracketed paste check for key release/repeat detection
- Rendering optimizations (only re-render changed lines)
- Add backslash+enter newline fallback, getExpandedText()
- Refactor input.ts to use keybindings manager

Coding-agent:
- Add /skill:name slash commands with enableSkillCommands setting
- Add cwd to SessionInfo for session list display
- Improve tree selector with custom summarization instructions
- Add dequeue (Alt+Up) to restore all queued messages at once
- Add shutdown request handling for extensions
- Component invalidate() fixes for theme changes
2026-01-12 03:18:30 +01:00
can1357 100061accb chore: merged in upstream changes
- Added ExtensionRuntime shared state with async extension factory support
- Introduced pluggable tool operations (BashOperations, FileOperations, etc.) for remote execution
- Added new CLI flags: --no-tools, --no-extensions, --no-skills
- Added login dialog, countdown timer, and component barrel export
- Added blockImages and thinkingBudgets settings
- Refactored stdin handling with StdinBuffer for improved key parsing
- Updated DEVELOPMENT.md with new architecture documentation
2026-01-10 06:32:51 +01:00