|
tui: throttle streaming markdown rebuild + cache height (Etap 2)
The assistant bubble re-parsed rich Markdown on every stream_delta and rich-rendered it twice per delta (once to paint, once to measure height) — O(N^2) over the answer length. Fix the cost while keeping live markdown formatting: - _ChatItemView.maybe_update now throttles assistant_message rebuilds to ~one per 150 ms (coalesced via set_timer). The ChatItem content still updates per delta; only the Markdown parse + rich render is deferred. Plain renderables (thinking/planning are Text) bypass the throttle — they are cheap. The first mutating delta rebuilds immediately for a snappy start; rapid bursts coalesce. - get_content_height is cached by (renderable identity, width) so the layout pass no longer re-renders the rich renderable to measure it between throttled rebuilds. - stream_end flushes any pending throttled rebuild so the final chunk of streamed text appears immediately instead of after the throttle window. - A deferred rebuild re-anchors scroll to the bottom (via ChatPanel._stick_to_bottom) so the freshly rendered streaming text stays in view after its height grows. - ThemedMarkdownRenderable.__rich_console__ now streams segments straight through instead of materializing them into a list first (no per-paint O(N) allocation + double walk); the link rewrite is inline in the loop. Tests: adapted test_per_token_refresh_renders_only_the_streaming_item to the throttled semantics (a burst yields a couple of rebuilds, not one per token, all for the assistant item); added throttle-coalesces and stream_end-flushes tests. Full suite: 939 passed, 1 skipped. |
|---|
|
|
| clients/terminal/tui/renderers/markdown_content.py |
|---|
| clients/terminal/tui/widgets/chat_panel.py |
|---|
| tests/clients/test_chat_panel.py |
|---|