Measured each animated Loader paint and recursively scheduled the next frame with a 10% duty-cycle target, capped at 200ms to retain responsiveness.
Added a regression covering a slow synchronized-output direct-write path and documented the fix.
Fixes#7290
Cached one stable layout representative per frame display width so same-width animation retains the fast path while width transitions rewrap before painting. Added coverage for wider custom frames remaining within terminal bounds.
(cherry picked from commit 3aa173a574538d754e68f8d10f7b88d437709884)
The Loader baked the advancing braille glyph into the underlying Text
via setText, so Text.render's wrap cache (keyed on text) missed every
80ms tick and re-ran wrapTextWithAnsi plus per-line width measurement
over the whole message even though only a 1-cell glyph changed. On a
single-subagent hub wait the direct-write render loop consumed ~48% of
a saturated core.
The wrapped text now carries a stable sentinel glyph (frames[0]); the
spinner advance only bumps the frame index and requests a repaint, and
render() swaps the visible glyph over the cached layout. wrapTextWithAnsi
and stringWidth now run only when the message actually changes.
Fixes#6940
(cherry picked from commit 6ec38053ebc1e33859358df3b66f71fea27532c7)
Fell back to requestComponentRender when Loader receives a lightweight TUI stub without requestDirectWrite.
Added regression coverage for legacy Loader stubs used by component tests.
Added a direct-write path for quiet visible component segments so Loader animation rewrites only its known rows instead of scheduling the full render pipeline.
Updated Loader scheduling and regression coverage for direct-write fast paths and overlay fallback behavior.
Fixes#5192
Stopped new-session and session-switch UI paths from detaching active loader/render components without running their disposal hooks.
Added container and loader coverage for disposing children before destructive transcript/status replacement.
Fixes#4686
Throttled animated loader message-only repaints when synchronized output is unavailable so unsupported terminals only repaint on spinner frame changes.
Fixes#2771
- Added reconstructed SSE event emission for OpenAI, Azure, and Anthropic streams.
- Added raw SSE text to debug report bundles, including raw-sse.txt output.
- Included dropped-record metadata in raw SSE text when events were trimmed.
- Updated raw SSE and sse-debug tests for observer-based capture and safety checks.
- Built canonical and alias key maps for action/custom handlers and rebuilt them on changes.
- Preserved the first handler when custom key alias collisions occurred during rebuilds.
- Exported canonicalKeyId and addKeyAliases from keybindings for external use.
- Updated settle helpers in repro tests to wait 40ms before terminal flush.
- Raised process-terminal-render-harness SETTLE_MS to 67ms for 30fps timing.
- Updated render-throttle mocks to advance mock time by 40ms per frame.
- Added Loader component cadence test for 30fps animated repaint timing.
- Added render-regressions check that non-force renders are scheduled at ~33ms.
- Added ChatBlock and ChatBlockHost with mount, finish, and dispose lifecycle callbacks.
- Added InteractiveModeContext.present and resetTranscript APIs and used them to mount/repaint blocks.
- Reworked controller rendering paths to emit command, event, extension, and selector outputs via ctx.present.
- Implemented component and container dispose hooks in tui so loaders and child blocks cleanup timers/effects.
- Introduce `deferrable?: boolean` on AgentTool, CustomTool, and ToolDefinition.
AstEditTool sets it to true; resolve is now injected only when at least one
active tool is deferrable (previously unconditional).
- Replace single-slot PendingActionStore (set/get/clear) with a LIFO stack
(push/peek/pop/clear). Multiple deferrable tools can stage independent
preview actions; resolve always consumes the topmost one first.
- Wire pendingActionStore through discoverAndLoadCustomTools / loadCustomTools /
CustomToolLoader so custom tools can call pushPendingAction(action) to
register a resolve-compatible pending action with label, apply callback,
optional details, and optional sourceToolName.
- Export HIDDEN_TOOLS and ResolveTool from the SDK for manual tool composition.
- Add CustomToolPendingAction type and pushPendingAction to CustomToolAPI.
- Update createAgentSession to re-inject or remove resolve after the deferrable
audit, consistent with createTools behavior.
- Add LIFO resolve test, update existing tests (set -> push, get -> peek).
- Add docs/resolve-tool-runtime.md covering PendingActionStore internals,
built-in producer example, and custom tool usage guide.
- Fixed loader component text overflow by truncating lines exceeding terminal width using column-aware slicing.
- Improved terminal clear logic on resize to use hard clear (\x1b[2J) preventing stale wrapped cells.
- Added test coverage for loader component line clamping to verify rendered lines fit within terminal width.
- Refactored terminal clear conditional logic from ternary to multi-line if-else for improved maintainability.