From 9b53b89bd5c0b2be420336f86ac9491f8a76c1db Mon Sep 17 00:00:00 2001 From: Helmut Januschka Date: Sat, 3 Jan 2026 21:43:35 +0100 Subject: [PATCH] fix(widgets): add max line limit and document multi-hook behavior - Limit total widget lines to 10 to prevent viewport overflow/flicker - Show '... (widget truncated)' when limit exceeded - Document that multiple hooks stack widgets vertically - Add caution about keeping widgets small --- packages/coding-agent/docs/hooks.md | 3 ++- .../src/modes/interactive/interactive-mode.ts | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/coding-agent/docs/hooks.md b/packages/coding-agent/docs/hooks.md index bc302b3e..9343fdeb 100644 --- a/packages/coding-agent/docs/hooks.md +++ b/packages/coding-agent/docs/hooks.md @@ -445,9 +445,10 @@ const currentText = ctx.ui.getEditorText(); **Widget notes:** - Widgets are multi-line displays shown above the editor (below "Working..." indicator) -- Multiple hooks can set widgets using unique keys +- Multiple hooks can set widgets using unique keys (all widgets are displayed, stacked vertically) - Use for progress lists, todo tracking, or any multi-line status - Supports ANSI styling via `ctx.ui.theme` (including `strikethrough`) +- **Caution:** Keep widgets small (a few lines). Large widgets from multiple hooks can cause viewport overflow and TUI flicker. **Styling with theme colors:** diff --git a/packages/coding-agent/src/modes/interactive/interactive-mode.ts b/packages/coding-agent/src/modes/interactive/interactive-mode.ts index 2e13e854..8c175950 100644 --- a/packages/coding-agent/src/modes/interactive/interactive-mode.ts +++ b/packages/coding-agent/src/modes/interactive/interactive-mode.ts @@ -633,6 +633,9 @@ export class InteractiveMode { this.renderWidgets(); } + // Maximum total widget lines to prevent viewport overflow + private static readonly MAX_WIDGET_LINES = 10; + /** * Render all hook widgets to the widget container. */ @@ -645,10 +648,18 @@ export class InteractiveMode { return; } - // Render each widget + // Render each widget, respecting max lines to prevent viewport overflow + let totalLines = 0; for (const [_key, lines] of this.hookWidgets) { for (const line of lines) { + if (totalLines >= InteractiveMode.MAX_WIDGET_LINES) { + // Add truncation indicator and stop + this.widgetContainer.addChild(new Text(theme.fg("muted", "... (widget truncated)"), 1, 0)); + this.ui.requestRender(); + return; + } this.widgetContainer.addChild(new Text(line, 1, 0)); + totalLines++; } }