@linxiraos/pi-tui 1.1.26 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -491
- package/README.md +13 -7
- package/dist/types/active-terminal.d.ts +30 -0
- package/dist/types/app-keybindings.d.ts +7 -2
- package/dist/types/apps/cleanse-board.d.ts +1 -1
- package/dist/types/apps/debug/log-viewer.d.ts +4 -0
- package/dist/types/apps/debug/raw-sse-buffer.d.ts +2 -0
- package/dist/types/apps/git/git-tui.d.ts +5 -4
- package/dist/types/apps/git/help.d.ts +3 -1
- package/dist/types/apps/if-bench-board.d.ts +2 -2
- package/dist/types/apps/setup-model-picker.d.ts +1 -1
- package/dist/types/autocomplete.d.ts +5 -2
- package/dist/types/charts/chart-plan.d.ts +674 -0
- package/dist/types/charts/chart-svg.d.ts +59 -0
- package/dist/types/charts/table-data.d.ts +175 -0
- package/dist/types/chat/assistant-message.d.ts +11 -1
- package/dist/types/chat/chat-transcript-builder.d.ts +3 -0
- package/dist/types/chat/compaction-summary-message.d.ts +1 -0
- package/dist/types/chat/execution-shared.d.ts +6 -5
- package/dist/types/chat/fence-figure.d.ts +42 -0
- package/dist/types/chat/figure-markdown.d.ts +42 -0
- package/dist/types/chat/messages.d.ts +1 -1
- package/dist/types/chat/svg-figure.d.ts +33 -0
- package/dist/types/chat/svg-source.d.ts +49 -0
- package/dist/types/chat/table-chart.d.ts +89 -0
- package/dist/types/chat/tool-execution.d.ts +2 -0
- package/dist/types/chat/user-message.d.ts +17 -4
- package/dist/types/chrome/shared.d.ts +9 -0
- package/dist/types/chrome/status-notice.d.ts +15 -3
- package/dist/types/chrome/transcript-container.d.ts +6 -0
- package/dist/types/components/box.d.ts +1 -0
- package/dist/types/components/disclosure.d.ts +1 -0
- package/dist/types/components/editor.d.ts +23 -5
- package/dist/types/components/form.d.ts +1 -0
- package/dist/types/components/image.d.ts +26 -44
- package/dist/types/components/input.d.ts +2 -1
- package/dist/types/components/key-value-list.d.ts +1 -0
- package/dist/types/components/layout/row.d.ts +1 -0
- package/dist/types/components/layout/stack.d.ts +1 -0
- package/dist/types/components/loader.d.ts +5 -6
- package/dist/types/components/markdown.d.ts +47 -5
- package/dist/types/components/scroll-view.d.ts +1 -0
- package/dist/types/components/section.d.ts +1 -0
- package/dist/types/components/table.d.ts +1 -0
- package/dist/types/components/text.d.ts +1 -0
- package/dist/types/components/tree-view.d.ts +7 -0
- package/dist/types/components/truncated-text.d.ts +1 -0
- package/dist/types/fuzzy.d.ts +29 -1
- package/dist/types/key-hint-format.d.ts +9 -1
- package/dist/types/keybinding-matchers.d.ts +3 -0
- package/dist/types/keybindings.d.ts +1 -1
- package/dist/types/kitty-graphics.d.ts +2 -2
- package/dist/types/loop-watchdog.d.ts +8 -7
- package/dist/types/multiplexers/cmux.d.ts +16 -0
- package/dist/types/multiplexers/herdr.d.ts +26 -0
- package/dist/types/multiplexers/notify.d.ts +13 -0
- package/dist/types/multiplexers/orca.d.ts +12 -0
- package/dist/types/multiplexers/screen.d.ts +9 -0
- package/dist/types/multiplexers/tmux.d.ts +29 -0
- package/dist/types/multiplexers/types.d.ts +100 -0
- package/dist/types/multiplexers/wmux.d.ts +12 -0
- package/dist/types/multiplexers/zellij.d.ts +12 -0
- package/dist/types/native/apply.d.ts +4 -3
- package/dist/types/native/backend.d.ts +5 -4
- package/dist/types/native/blobs.d.ts +7 -3
- package/dist/types/native/encode.d.ts +8 -6
- package/dist/types/native/node.d.ts +36 -5
- package/dist/types/native/overlay.d.ts +8 -3
- package/dist/types/native/settle.d.ts +4 -3
- package/dist/types/overlays/agent-hub-projection.d.ts +6 -5
- package/dist/types/overlays/agent-hub-types.d.ts +9 -0
- package/dist/types/overlays/agent-hub.d.ts +3 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +12 -2
- package/dist/types/overlays/agents-hub.d.ts +9 -0
- package/dist/types/overlays/annotation-overlay.d.ts +19 -2
- package/dist/types/overlays/annotation-types.d.ts +2 -0
- package/dist/types/overlays/ask-dialog.d.ts +5 -2
- package/dist/types/overlays/btw-history-panel.d.ts +13 -1
- package/dist/types/overlays/copy-selector.d.ts +1 -0
- package/dist/types/overlays/history-search.d.ts +10 -0
- package/dist/types/overlays/hook-selector.d.ts +9 -4
- package/dist/types/overlays/hub-frame.d.ts +4 -1
- package/dist/types/overlays/jobs-panel.d.ts +1 -7
- package/dist/types/overlays/model-browser.d.ts +54 -7
- package/dist/types/overlays/model-hub.d.ts +37 -0
- package/dist/types/overlays/oauth-selector.d.ts +0 -1
- package/dist/types/overlays/plan-review-overlay.d.ts +3 -2
- package/dist/types/overlays/report-panel.d.ts +68 -0
- package/dist/types/overlays/rewind-selector.d.ts +1 -0
- package/dist/types/overlays/session-observer-registry.d.ts +2 -0
- package/dist/types/overlays/session-selector.d.ts +6 -2
- package/dist/types/overlays/settings-defs.d.ts +1 -0
- package/dist/types/overlays/thinking-selector.d.ts +2 -2
- package/dist/types/overlays/usage-dashboard.d.ts +12 -8
- package/dist/types/overlays/usage-display.d.ts +3 -1
- package/dist/types/prompt/composer-cache.d.ts +0 -16
- package/dist/types/prompt/composer.d.ts +18 -3
- package/dist/types/prompt/custom-editor.d.ts +25 -13
- package/dist/types/prompt/image-source.d.ts +2 -1
- package/dist/types/prompt/interactive-context-helpers.d.ts +5 -1
- package/dist/types/prompt/model-mention-autocomplete.d.ts +1 -1
- package/dist/types/prompt/welcome.d.ts +7 -2
- package/dist/types/render/composite.d.ts +2 -0
- package/dist/types/render/output-pane.d.ts +1 -0
- package/dist/types/render/render-utils.d.ts +1 -0
- package/dist/types/render/tool-card.d.ts +6 -0
- package/dist/types/render/width-aware-text.d.ts +2 -0
- package/dist/types/setup/scenes/types.d.ts +1 -0
- package/dist/types/space-hold.d.ts +40 -25
- package/dist/types/status-line/component.d.ts +3 -0
- package/dist/types/status-line/context-usage.d.ts +7 -5
- package/dist/types/status-line/host.d.ts +4 -1
- package/dist/types/status-line/segments.d.ts +2 -0
- package/dist/types/status-line/types.d.ts +14 -3
- package/dist/types/terminal-capabilities.d.ts +41 -36
- package/dist/types/terminal-multiplexer.d.ts +127 -14
- package/dist/types/terminal.d.ts +23 -16
- package/dist/types/theme/active-symbols.d.ts +1 -1
- package/dist/types/theme/schema.d.ts +11 -2
- package/dist/types/theme/symbols.d.ts +1 -1
- package/dist/types/theme/theme-class.d.ts +7 -0
- package/dist/types/theme/theme.d.ts +1 -1
- package/dist/types/theme/tui-adapters.d.ts +3 -0
- package/dist/types/thinking.d.ts +1 -1
- package/dist/types/tmux.d.ts +11 -4
- package/dist/types/tools/bash.d.ts +7 -2
- package/dist/types/tools/daemon.d.ts +1 -1
- package/dist/types/tools/eval.d.ts +22 -3
- package/dist/types/tools/glob.d.ts +4 -0
- package/dist/types/tools/native-view.d.ts +47 -0
- package/dist/types/tools/output-meta.d.ts +11 -1
- package/dist/types/tools/renderer.d.ts +37 -2
- package/dist/types/tools/streaming-output.d.ts +20 -1
- package/dist/types/tools/task.d.ts +2 -3
- package/dist/types/tools/write.d.ts +9 -2
- package/dist/types/tools/yield.d.ts +22 -0
- package/dist/types/tui.d.ts +36 -0
- package/dist/types/utils.d.ts +6 -0
- package/dist/types/vim.d.ts +19 -5
- package/dist/types/windows-input-mode.d.ts +33 -1
- package/package.json +13 -9
- package/src/active-terminal.d.ts +30 -0
- package/src/active-terminal.ts +80 -0
- package/src/app-keybindings.d.ts +7 -2
- package/src/app-keybindings.ts +7 -2
- package/src/apps/autoresearch-dashboard.ts +7 -3
- package/src/apps/cleanse-board.ts +2 -2
- package/src/apps/cleanse-picker.ts +1 -1
- package/src/apps/debug/log-viewer.ts +188 -72
- package/src/apps/debug/raw-sse-buffer.ts +8 -0
- package/src/apps/debug/raw-sse.ts +39 -5
- package/src/apps/git/diff-pane.ts +96 -23
- package/src/apps/git/git-tui.ts +23 -16
- package/src/apps/git/help.ts +29 -20
- package/src/apps/git/sidebar.ts +8 -3
- package/src/apps/if-bench-board.ts +2 -2
- package/src/apps/ps-top.ts +2 -2
- package/src/apps/setup-model-picker.ts +1 -1
- package/src/autocomplete.d.ts +5 -2
- package/src/autocomplete.ts +67 -43
- package/src/bracketed-paste.ts +10 -3
- package/src/charts/chart-plan.d.ts +674 -0
- package/src/charts/chart-plan.ts +5081 -0
- package/src/charts/chart-svg.d.ts +59 -0
- package/src/charts/chart-svg.ts +4657 -0
- package/src/charts/table-data.d.ts +175 -0
- package/src/charts/table-data.ts +1478 -0
- package/src/chat/advisor-message.ts +11 -0
- package/src/chat/assistant-message.d.ts +11 -1
- package/src/chat/assistant-message.ts +245 -54
- package/src/chat/chat-transcript-builder.d.ts +3 -0
- package/src/chat/chat-transcript-builder.ts +9 -3
- package/src/chat/compaction-summary-message.d.ts +1 -0
- package/src/chat/compaction-summary-message.ts +8 -0
- package/src/chat/execution-shared.d.ts +6 -5
- package/src/chat/execution-shared.ts +42 -25
- package/src/chat/fence-figure.d.ts +42 -0
- package/src/chat/fence-figure.ts +80 -0
- package/src/chat/figure-markdown.d.ts +42 -0
- package/src/chat/figure-markdown.ts +174 -0
- package/src/chat/messages.d.ts +1 -1
- package/src/chat/messages.ts +1 -1
- package/src/chat/read-tool-group.ts +6 -4
- package/src/chat/skill-message.ts +6 -0
- package/src/chat/svg-figure.d.ts +33 -0
- package/src/chat/svg-figure.ts +399 -0
- package/src/chat/svg-source.d.ts +49 -0
- package/src/chat/svg-source.ts +188 -0
- package/src/chat/table-chart.d.ts +89 -0
- package/src/chat/table-chart.ts +294 -0
- package/src/chat/tool-execution.d.ts +2 -0
- package/src/chat/tool-execution.ts +86 -7
- package/src/chat/user-message.d.ts +17 -4
- package/src/chat/user-message.ts +71 -8
- package/src/chrome/shared.ts +53 -0
- package/src/chrome/status-notice.ts +25 -7
- package/src/chrome/transcript-container.d.ts +6 -0
- package/src/chrome/transcript-container.ts +162 -19
- package/src/components/box.d.ts +1 -0
- package/src/components/box.ts +5 -0
- package/src/components/disclosure.d.ts +1 -0
- package/src/components/disclosure.ts +8 -0
- package/src/components/editor.d.ts +23 -5
- package/src/components/editor.ts +316 -47
- package/src/components/form.d.ts +1 -0
- package/src/components/form.ts +8 -0
- package/src/components/image.d.ts +26 -44
- package/src/components/image.ts +115 -152
- package/src/components/input.d.ts +2 -1
- package/src/components/input.ts +17 -7
- package/src/components/key-value-list.d.ts +1 -0
- package/src/components/key-value-list.ts +4 -0
- package/src/components/layout/row.d.ts +1 -0
- package/src/components/layout/row.ts +7 -0
- package/src/components/layout/stack.d.ts +1 -0
- package/src/components/layout/stack.ts +7 -0
- package/src/components/loader.d.ts +5 -6
- package/src/components/loader.ts +10 -17
- package/src/components/markdown.d.ts +47 -5
- package/src/components/markdown.ts +786 -303
- package/src/components/scroll-view.d.ts +1 -0
- package/src/components/scroll-view.ts +5 -0
- package/src/components/section.d.ts +1 -0
- package/src/components/section.ts +5 -0
- package/src/components/settings-list.ts +2 -0
- package/src/components/table.d.ts +1 -0
- package/src/components/table.ts +4 -0
- package/src/components/text.d.ts +1 -0
- package/src/components/text.ts +7 -0
- package/src/components/tree-view.d.ts +7 -0
- package/src/components/tree-view.ts +38 -8
- package/src/components/truncated-text.d.ts +1 -0
- package/src/components/truncated-text.ts +5 -0
- package/src/desktop-notify.ts +3 -2
- package/src/fuzzy.d.ts +29 -1
- package/src/fuzzy.ts +115 -30
- package/src/hotkeys-markdown.ts +9 -2
- package/src/key-hint-format.d.ts +9 -1
- package/src/key-hint-format.ts +26 -11
- package/src/keybinding-matchers.d.ts +3 -0
- package/src/keybinding-matchers.ts +6 -2
- package/src/keybindings.d.ts +1 -1
- package/src/keybindings.ts +1 -1
- package/src/kitty-graphics.d.ts +2 -2
- package/src/kitty-graphics.ts +11 -5
- package/src/loop-watchdog.d.ts +8 -7
- package/src/loop-watchdog.ts +18 -13
- package/src/multiplexers/cmux.d.ts +16 -0
- package/src/multiplexers/cmux.ts +29 -0
- package/src/multiplexers/herdr.d.ts +26 -0
- package/src/multiplexers/herdr.ts +64 -0
- package/src/multiplexers/notify.d.ts +13 -0
- package/src/multiplexers/notify.ts +24 -0
- package/src/multiplexers/orca.d.ts +12 -0
- package/src/multiplexers/orca.ts +16 -0
- package/src/multiplexers/screen.d.ts +9 -0
- package/src/multiplexers/screen.ts +15 -0
- package/src/multiplexers/tmux.d.ts +29 -0
- package/src/multiplexers/tmux.ts +40 -0
- package/src/multiplexers/types.d.ts +100 -0
- package/src/multiplexers/types.ts +110 -0
- package/src/multiplexers/wmux.d.ts +12 -0
- package/src/multiplexers/wmux.ts +16 -0
- package/src/multiplexers/zellij.d.ts +12 -0
- package/src/multiplexers/zellij.ts +24 -0
- package/src/native/apply.d.ts +4 -3
- package/src/native/apply.ts +4 -3
- package/src/native/backend.d.ts +5 -4
- package/src/native/backend.ts +199 -22
- package/src/native/blobs.d.ts +7 -3
- package/src/native/blobs.ts +47 -12
- package/src/native/encode.d.ts +8 -6
- package/src/native/encode.ts +76 -34
- package/src/native/node.d.ts +36 -5
- package/src/native/node.ts +31 -5
- package/src/native/overlay.d.ts +8 -3
- package/src/native/overlay.ts +17 -4
- package/src/native/reconcile.ts +16 -4
- package/src/native/settle.d.ts +4 -3
- package/src/native/settle.ts +4 -3
- package/src/overlays/agent-hub-projection.d.ts +6 -5
- package/src/overlays/agent-hub-projection.ts +124 -13
- package/src/overlays/agent-hub-types.d.ts +9 -0
- package/src/overlays/agent-hub-types.ts +6 -0
- package/src/overlays/agent-hub.ts +48 -29
- package/src/overlays/agent-transcript-viewer.ts +93 -23
- package/src/overlays/agents-hub.ts +28 -8
- package/src/overlays/annotation-overlay.ts +293 -90
- package/src/overlays/annotation-types.ts +2 -0
- package/src/overlays/ask-dialog.ts +10 -17
- package/src/overlays/btw-history-panel.ts +136 -39
- package/src/overlays/copy-selector.d.ts +1 -0
- package/src/overlays/copy-selector.ts +32 -8
- package/src/overlays/extensions/extension-dashboard.ts +4 -4
- package/src/overlays/extensions/state-manager.ts +52 -12
- package/src/overlays/history-search.ts +100 -7
- package/src/overlays/hook-selector.ts +12 -5
- package/src/overlays/hub-frame.ts +19 -1
- package/src/overlays/jobs-panel.ts +33 -52
- package/src/overlays/model-browser.ts +367 -122
- package/src/overlays/model-hub.ts +435 -59
- package/src/overlays/move-overlay.ts +28 -14
- package/src/overlays/oauth-selector.ts +54 -70
- package/src/overlays/pause-screen.ts +2 -2
- package/src/overlays/plan-review-overlay.ts +208 -70
- package/src/overlays/plugin-settings.ts +3 -3
- package/src/overlays/report-panel.ts +191 -0
- package/src/overlays/rewind-selector.ts +88 -17
- package/src/overlays/session-observer-registry.d.ts +2 -0
- package/src/overlays/session-observer-registry.ts +10 -2
- package/src/overlays/session-selector.ts +64 -26
- package/src/overlays/settings-defs.ts +5 -4
- package/src/overlays/settings-selector.ts +33 -8
- package/src/overlays/snapcompact-shape-preview.ts +2 -3
- package/src/overlays/stats-notice.ts +1 -1
- package/src/overlays/thinking-selector.ts +11 -10
- package/src/overlays/tree-selector.ts +41 -20
- package/src/overlays/usage-dashboard.ts +117 -58
- package/src/overlays/usage-display.ts +10 -4
- package/src/overlays/usage-row.ts +22 -8
- package/src/prompt/attachment-chips.ts +15 -11
- package/src/prompt/composer-attachments.ts +6 -4
- package/src/prompt/composer-cache.ts +7 -86
- package/src/prompt/composer.ts +37 -26
- package/src/prompt/custom-editor.ts +282 -105
- package/src/prompt/image-source.ts +2 -1
- package/src/prompt/interactive-context-helpers.ts +32 -18
- package/src/prompt/macos-spelling.ts +7 -0
- package/src/prompt/magic-keywords.ts +11 -2
- package/src/prompt/model-mention-autocomplete.ts +14 -14
- package/src/prompt/queued-messages.ts +6 -4
- package/src/prompt/tips.txt +13 -9
- package/src/prompt/welcome.ts +64 -46
- package/src/prompt/word-completion.ts +38 -5
- package/src/render/composite.d.ts +2 -0
- package/src/render/composite.ts +64 -0
- package/src/render/output-pane.d.ts +1 -0
- package/src/render/output-pane.ts +6 -0
- package/src/render/render-utils.d.ts +1 -0
- package/src/render/render-utils.ts +16 -1
- package/src/render/tool-card.d.ts +6 -0
- package/src/render/tool-card.ts +15 -0
- package/src/render/width-aware-text.d.ts +2 -0
- package/src/render/width-aware-text.ts +5 -0
- package/src/setup/scenes/model.ts +2 -1
- package/src/setup/scenes/types.ts +1 -0
- package/src/space-hold.d.ts +40 -25
- package/src/space-hold.ts +156 -52
- package/src/status-line/component.ts +292 -78
- package/src/status-line/context-usage.ts +21 -46
- package/src/status-line/host.ts +4 -1
- package/src/status-line/segments.ts +40 -22
- package/src/status-line/types.ts +15 -3
- package/src/terminal-capabilities.d.ts +41 -36
- package/src/terminal-capabilities.ts +137 -213
- package/src/terminal-multiplexer.d.ts +127 -14
- package/src/terminal-multiplexer.ts +112 -33
- package/src/terminal.d.ts +23 -16
- package/src/terminal.ts +203 -99
- package/src/theme/active-symbols.d.ts +1 -1
- package/src/theme/active-symbols.ts +1 -1
- package/src/theme/schema-validation.ts +1 -0
- package/src/theme/schema.d.ts +11 -2
- package/src/theme/schema.ts +14 -1
- package/src/theme/session-color.ts +1 -7
- package/src/theme/symbols.d.ts +1 -1
- package/src/theme/symbols.ts +11 -4
- package/src/theme/theme-class.d.ts +7 -0
- package/src/theme/theme-class.ts +26 -1
- package/src/theme/theme-schema.json +5 -1
- package/src/theme/theme.d.ts +1 -1
- package/src/theme/theme.ts +8 -4
- package/src/theme/tui-adapters.d.ts +3 -0
- package/src/theme/tui-adapters.ts +68 -0
- package/src/thinking.d.ts +1 -1
- package/src/thinking.ts +1 -1
- package/src/tmux.d.ts +11 -4
- package/src/tmux.ts +47 -11
- package/src/tools/ast-edit.ts +59 -35
- package/src/tools/ast-grep.ts +35 -16
- package/src/tools/bash.d.ts +7 -2
- package/src/tools/bash.ts +116 -47
- package/src/tools/daemon.d.ts +1 -1
- package/src/tools/daemon.ts +1 -1
- package/src/tools/default-renderer.ts +35 -19
- package/src/tools/edit.ts +142 -120
- package/src/tools/eval-format/index.ts +28 -2
- package/src/tools/eval-format/javascript.ts +7 -5
- package/src/tools/eval.d.ts +22 -3
- package/src/tools/eval.ts +364 -208
- package/src/tools/fetch.ts +5 -6
- package/src/tools/glob.d.ts +4 -0
- package/src/tools/glob.ts +33 -65
- package/src/tools/grep.ts +81 -48
- package/src/tools/index.ts +2 -0
- package/src/tools/lsp.ts +81 -59
- package/src/tools/mcp.ts +111 -68
- package/src/tools/native-view.d.ts +47 -0
- package/src/tools/native-view.ts +102 -1
- package/src/tools/output-meta.d.ts +11 -1
- package/src/tools/output-meta.ts +23 -3
- package/src/tools/read.ts +7 -5
- package/src/tools/renderer.d.ts +37 -2
- package/src/tools/renderer.ts +42 -2
- package/src/tools/streaming-output.d.ts +20 -1
- package/src/tools/streaming-output.ts +154 -50
- package/src/tools/task.d.ts +2 -3
- package/src/tools/task.ts +115 -62
- package/src/tools/todo.ts +119 -30
- package/src/tools/wait.ts +34 -24
- package/src/tools/web-search.ts +1 -1
- package/src/tools/write.d.ts +9 -2
- package/src/tools/write.ts +147 -95
- package/src/tools/yield.d.ts +22 -0
- package/src/tools/yield.ts +225 -0
- package/src/tui.d.ts +36 -0
- package/src/tui.ts +666 -217
- package/src/utils.d.ts +6 -0
- package/src/utils.ts +19 -0
- package/src/vim.d.ts +19 -5
- package/src/vim.ts +333 -18
- package/src/windows-input-mode.d.ts +33 -1
- package/src/windows-input-mode.ts +212 -6
package/src/tools/mcp.ts
CHANGED
|
@@ -88,30 +88,22 @@ function renderMarkdownMCPResult(
|
|
|
88
88
|
const markdown = new Markdown(trimmedOutput, 0, 0, getMarkdownTheme(), {
|
|
89
89
|
color: text => theme.fg("toolOutput", text),
|
|
90
90
|
});
|
|
91
|
+
// Args tree and output pane rows are spinner-invariant; rebuild only on
|
|
92
|
+
// expansion or width change instead of every animated frame.
|
|
93
|
+
let bodyMemo: { expanded: boolean; width: number; lines: readonly string[] } | undefined;
|
|
91
94
|
return plainToolCard(
|
|
92
95
|
theme,
|
|
93
96
|
({ contentWidth }) => {
|
|
94
97
|
const isError = result.isError ?? result.details?.isError ?? false;
|
|
95
98
|
const title = result.details ? `${result.details.serverName}/${result.details.mcpToolName}` : "MCP";
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
if (bodyMemo === undefined || bodyMemo.expanded !== options.expanded || bodyMemo.width !== contentWidth) {
|
|
100
|
+
bodyMemo = {
|
|
101
|
+
expanded: options.expanded,
|
|
102
|
+
width: contentWidth,
|
|
103
|
+
lines: buildMarkdownMcpBody(markdown, truncationWarning, options.expanded, contentWidth, theme, args),
|
|
104
|
+
};
|
|
99
105
|
}
|
|
100
|
-
|
|
101
|
-
const rendered = markdown.render(Math.max(1, contentWidth));
|
|
102
|
-
body.push(
|
|
103
|
-
...formatOutputPaneLines(
|
|
104
|
-
{
|
|
105
|
-
lines: rendered,
|
|
106
|
-
expanded: options.expanded,
|
|
107
|
-
collapsedMaxLines: 4,
|
|
108
|
-
expandedMaxLines: 12,
|
|
109
|
-
showExpandHintWhenUncapped: true,
|
|
110
|
-
},
|
|
111
|
-
theme,
|
|
112
|
-
).lines,
|
|
113
|
-
);
|
|
114
|
-
if (truncationWarning) body.push(truncationWarning);
|
|
106
|
+
const body = bodyMemo.lines;
|
|
115
107
|
const status: StatusLineOptions = options.isPartial
|
|
116
108
|
? {
|
|
117
109
|
icon: options.spinnerFrame !== undefined ? "running" : "pending",
|
|
@@ -129,10 +121,47 @@ function renderMarkdownMCPResult(
|
|
|
129
121
|
applyBg: false,
|
|
130
122
|
};
|
|
131
123
|
},
|
|
132
|
-
{
|
|
124
|
+
{
|
|
125
|
+
paddingX: 0,
|
|
126
|
+
paddingY: 0,
|
|
127
|
+
onInvalidate: () => (bodyMemo = undefined),
|
|
128
|
+
onReleaseRenderCaches: () => {
|
|
129
|
+
bodyMemo = undefined;
|
|
130
|
+
markdown.releaseRenderCaches();
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
133
|
);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
+
function buildMarkdownMcpBody(
|
|
137
|
+
markdown: Markdown,
|
|
138
|
+
truncationWarning: string | null,
|
|
139
|
+
expanded: boolean,
|
|
140
|
+
contentWidth: number,
|
|
141
|
+
theme: Theme,
|
|
142
|
+
args: Record<string, unknown> | undefined,
|
|
143
|
+
): string[] {
|
|
144
|
+
const body: string[] = [];
|
|
145
|
+
if (expanded && args && Object.keys(args).length > 0) {
|
|
146
|
+
body.push(...buildMcpArgsSection(args, theme));
|
|
147
|
+
}
|
|
148
|
+
const rendered = markdown.render(Math.max(1, contentWidth));
|
|
149
|
+
body.push(
|
|
150
|
+
...formatOutputPaneLines(
|
|
151
|
+
{
|
|
152
|
+
lines: rendered,
|
|
153
|
+
expanded,
|
|
154
|
+
collapsedMaxLines: 4,
|
|
155
|
+
expandedMaxLines: 12,
|
|
156
|
+
showExpandHintWhenUncapped: true,
|
|
157
|
+
},
|
|
158
|
+
theme,
|
|
159
|
+
).lines,
|
|
160
|
+
);
|
|
161
|
+
if (truncationWarning) body.push(truncationWarning);
|
|
162
|
+
return body;
|
|
163
|
+
}
|
|
164
|
+
|
|
136
165
|
/**
|
|
137
166
|
* Render MCP tool result.
|
|
138
167
|
*/
|
|
@@ -165,6 +194,8 @@ export function renderMCPResult(
|
|
|
165
194
|
if (trimmedOutput && renderMarkdownResults && !isJsonOutput) {
|
|
166
195
|
return renderMarkdownMCPResult(result, trimmedOutput, truncationWarning, options, theme, args);
|
|
167
196
|
}
|
|
197
|
+
// `expanded`, args and output are fixed for this card; only width varies the body.
|
|
198
|
+
let bodyMemo: { width: number; lines: readonly string[] } | undefined;
|
|
168
199
|
return plainToolCard(
|
|
169
200
|
theme,
|
|
170
201
|
({ contentWidth }) => {
|
|
@@ -180,61 +211,72 @@ export function renderMCPResult(
|
|
|
180
211
|
? { icon: "error", title }
|
|
181
212
|
: { iconOverride: theme.styledSymbol("tool.mcp", "accent"), title };
|
|
182
213
|
const phase: ToolCardPhase = options.isPartial ? "partial" : isError ? "error" : "success";
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
// Args section (when expanded)
|
|
186
|
-
if (expanded && args && typeof args === "object" && Object.keys(args).length > 0) {
|
|
187
|
-
body.push(...buildMcpArgsSection(args, theme));
|
|
214
|
+
if (bodyMemo === undefined || bodyMemo.width !== contentWidth) {
|
|
215
|
+
bodyMemo = { width: contentWidth, lines: buildMcpResultBody(contentWidth) };
|
|
188
216
|
}
|
|
217
|
+
return { status, phase, body: bodyMemo.lines, applyBg: false };
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
paddingX: 0,
|
|
221
|
+
paddingY: 0,
|
|
222
|
+
onInvalidate: () => (bodyMemo = undefined),
|
|
223
|
+
onReleaseRenderCaches: () => (bodyMemo = undefined),
|
|
224
|
+
},
|
|
225
|
+
);
|
|
189
226
|
|
|
190
|
-
|
|
191
|
-
|
|
227
|
+
function buildMcpResultBody(contentWidth: number): string[] {
|
|
228
|
+
const body: string[] = [];
|
|
229
|
+
// Args section (when expanded)
|
|
230
|
+
if (expanded && args && typeof args === "object" && Object.keys(args).length > 0) {
|
|
231
|
+
body.push(...buildMcpArgsSection(args, theme));
|
|
232
|
+
}
|
|
192
233
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return { status, phase, body, applyBg: false };
|
|
196
|
-
}
|
|
234
|
+
// Output section. The body and spill metadata are normalized before
|
|
235
|
+
// component selection so the opt-in Markdown path can use its own renderer.
|
|
197
236
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
237
|
+
if (!trimmedOutput) {
|
|
238
|
+
body.push(theme.fg("dim", "(no output)"));
|
|
239
|
+
return body;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Preserve the existing structured JSON renderer regardless of the
|
|
243
|
+
// Markdown preference; JSON trees remain more useful than styled source.
|
|
244
|
+
if (isJsonOutput) {
|
|
245
|
+
const maxDepth = expanded ? JSON_TREE_MAX_DEPTH_EXPANDED : JSON_TREE_MAX_DEPTH_COLLAPSED;
|
|
246
|
+
const maxLines = expanded ? JSON_TREE_MAX_LINES_EXPANDED : JSON_TREE_MAX_LINES_COLLAPSED;
|
|
247
|
+
const maxScalarLen = expanded ? JSON_TREE_SCALAR_LEN_EXPANDED : JSON_TREE_SCALAR_LEN_COLLAPSED;
|
|
248
|
+
const tree = renderJsonTreeLines(parsedOutput, theme, maxDepth, maxLines, maxScalarLen);
|
|
249
|
+
|
|
250
|
+
if (tree.lines.length > 0) {
|
|
251
|
+
body.push(...tree.lines);
|
|
252
|
+
if (!expanded) {
|
|
253
|
+
body.push(formatExpandHint(theme, expanded, true));
|
|
254
|
+
} else if (tree.truncated) {
|
|
255
|
+
body.push(theme.fg("dim", "…"));
|
|
215
256
|
}
|
|
257
|
+
if (truncationWarning) body.push(truncationWarning);
|
|
258
|
+
return body;
|
|
216
259
|
}
|
|
260
|
+
}
|
|
217
261
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
{ paddingX: 0, paddingY: 0 },
|
|
237
|
-
);
|
|
262
|
+
// Raw text output, capped to the first rows with an expand hint while collapsed.
|
|
263
|
+
body.push(
|
|
264
|
+
...formatOutputPaneLines(
|
|
265
|
+
{
|
|
266
|
+
lines: trimmedOutput.split("\n"),
|
|
267
|
+
expanded,
|
|
268
|
+
collapsedMaxLines: 4,
|
|
269
|
+
expandedMaxLines: 12,
|
|
270
|
+
styleLine: line => truncateToWidth(styleToolOutputLine(line, theme), contentWidth),
|
|
271
|
+
showExpandHintWhenUncapped: true,
|
|
272
|
+
},
|
|
273
|
+
theme,
|
|
274
|
+
).lines,
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
if (truncationWarning) body.push(truncationWarning);
|
|
278
|
+
return body;
|
|
279
|
+
}
|
|
238
280
|
}
|
|
239
281
|
|
|
240
282
|
/** Visible MCP argument entries (streaming/intent bookkeeping keys dropped). */
|
|
@@ -273,7 +315,8 @@ export function describeMCPResult(
|
|
|
273
315
|
_options: RenderResultOptions,
|
|
274
316
|
args?: Record<string, unknown>,
|
|
275
317
|
): NativeToolView | undefined {
|
|
276
|
-
|
|
318
|
+
// Callers allocate a fresh args object per streamed delta, so identity is a sound dep.
|
|
319
|
+
return mcpResultMemo.get(result, [renderMarkdownResults, args], () => {
|
|
277
320
|
const textContent = (result.content ?? [])
|
|
278
321
|
.filter(block => block.type === "text")
|
|
279
322
|
.map(block => block.text ?? "")
|
|
@@ -72,6 +72,53 @@ export declare function truncationNotice(meta: OutputMeta | undefined): NativeNo
|
|
|
72
72
|
* truncation / artifact-capture notice from `meta`; undefined when empty.
|
|
73
73
|
*/
|
|
74
74
|
export declare function footnoteText(parts: readonly string[], meta?: OutputMeta): NativeNode | undefined;
|
|
75
|
+
/** Drawn lines of a run's input (command, cell code) before its "N more lines" button. */
|
|
76
|
+
export declare const RUN_INPUT_PREVIEW_LINES = 6;
|
|
77
|
+
/**
|
|
78
|
+
* What a run's foot names: `running` (live clock), `background` (an async job
|
|
79
|
+
* outlives the call), and the settled outcomes. A failure with an exit code
|
|
80
|
+
* reads `exit N`; without one, `Failed`.
|
|
81
|
+
*/
|
|
82
|
+
export type RunState = "running" | "background" | "done" | "failed" | "cancelled" | "timed-out";
|
|
83
|
+
/** Inputs of {@link runFoot}. */
|
|
84
|
+
export interface RunFootInput {
|
|
85
|
+
readonly state: RunState;
|
|
86
|
+
/** Exit code of a `failed` run; a non-zero code names the state `exit N`. */
|
|
87
|
+
readonly exitCode?: number;
|
|
88
|
+
/** Milliseconds run so far (`running`) or in total; the time is omitted when undefined. */
|
|
89
|
+
readonly elapsedMs?: number;
|
|
90
|
+
/** Quiet facts (job id, service state, artifact), muted and ` · `-joined. */
|
|
91
|
+
readonly facts?: readonly string[];
|
|
92
|
+
/** Truncation / artifact-capture notices, appended to the facts in `warning`. */
|
|
93
|
+
readonly meta?: OutputMeta;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The foot line of a run box (`zeta.run.foot`): the state word in its tone,
|
|
97
|
+
* the run time (a live clock while running, frozen once settled) and the
|
|
98
|
+
* quiet facts. Glyphs are the terminal's styling, never text.
|
|
99
|
+
*/
|
|
100
|
+
export declare function runFoot(input: RunFootInput): NativeNode;
|
|
101
|
+
/** A run's input section: the command or cell source, clamped to {@link RUN_INPUT_PREVIEW_LINES}. */
|
|
102
|
+
export declare function runInput(source: string, p: {
|
|
103
|
+
role: string;
|
|
104
|
+
lang: string;
|
|
105
|
+
wrap: boolean;
|
|
106
|
+
}): NativeNode;
|
|
107
|
+
/** A run's terminal output: follows its tail, clamped to the last `previewLines` lines while folded. */
|
|
108
|
+
export declare function runOutput(output: string, p: {
|
|
109
|
+
role: string;
|
|
110
|
+
previewLines: number;
|
|
111
|
+
key?: string;
|
|
112
|
+
}): NativeNode;
|
|
113
|
+
/**
|
|
114
|
+
* One run as one box (`zeta.run`): input, output, status lines and foot in
|
|
115
|
+
* order. `tone` tints the box: `error` for a failed run, `warning` for a
|
|
116
|
+
* timed-out one.
|
|
117
|
+
*/
|
|
118
|
+
export declare function runBox(children: readonly (NativeChild | undefined | false)[], p: {
|
|
119
|
+
key: string;
|
|
120
|
+
tone?: TspTone;
|
|
121
|
+
}): NativeNode;
|
|
75
122
|
/** A diagnostic's severity glyph: `x-circle` error, `warn` warning, `info`, `lightbulb` hint, in the severity tone. */
|
|
76
123
|
export declare function diagnosticGlyph(severity: ParsedDiagnostic["severity"]): NativeNode;
|
|
77
124
|
/**
|
package/src/tools/native-view.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
import { pathToFileURL } from "node:url";
|
|
8
8
|
import type { TspSpan, TspText, TspTone } from "@linxiraos/pi-wire";
|
|
9
|
-
import { code, keyed, node, row, span, text } from "../native/describe";
|
|
9
|
+
import { ansi, code, compact, keyed, node, row, span, text } from "../native/describe";
|
|
10
10
|
import type { NativeChild, NativeNode } from "../native/node";
|
|
11
11
|
import { type ParsedDiagnostic, parseDiagnosticMessage, shortenPath } from "../render/render-utils";
|
|
12
12
|
import { plainText } from "../native/spans";
|
|
@@ -192,6 +192,107 @@ export function footnoteText(parts: readonly string[], meta?: OutputMeta): Nativ
|
|
|
192
192
|
};
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
/** Drawn lines of a run's input (command, cell code) before its "N more lines" button. */
|
|
196
|
+
export const RUN_INPUT_PREVIEW_LINES = 6;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* What a run's foot names: `running` (live clock), `background` (an async job
|
|
200
|
+
* outlives the call), and the settled outcomes. A failure with an exit code
|
|
201
|
+
* reads `exit N`; without one, `Failed`.
|
|
202
|
+
*/
|
|
203
|
+
export type RunState = "running" | "background" | "done" | "failed" | "cancelled" | "timed-out";
|
|
204
|
+
|
|
205
|
+
const RUN_STATE: Record<RunState, { readonly word: string; readonly tone: TspTone }> = {
|
|
206
|
+
running: { word: "Running", tone: "pending" },
|
|
207
|
+
background: { word: "In background", tone: "pending" },
|
|
208
|
+
done: { word: "Done", tone: "success" },
|
|
209
|
+
failed: { word: "Failed", tone: "error" },
|
|
210
|
+
cancelled: { word: "Cancelled", tone: "muted" },
|
|
211
|
+
"timed-out": { word: "Timed out", tone: "warning" },
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/** Inputs of {@link runFoot}. */
|
|
215
|
+
export interface RunFootInput {
|
|
216
|
+
readonly state: RunState;
|
|
217
|
+
/** Exit code of a `failed` run; a non-zero code names the state `exit N`. */
|
|
218
|
+
readonly exitCode?: number;
|
|
219
|
+
/** Milliseconds run so far (`running`) or in total; the time is omitted when undefined. */
|
|
220
|
+
readonly elapsedMs?: number;
|
|
221
|
+
/** Quiet facts (job id, service state, artifact), muted and ` · `-joined. */
|
|
222
|
+
readonly facts?: readonly string[];
|
|
223
|
+
/** Truncation / artifact-capture notices, appended to the facts in `warning`. */
|
|
224
|
+
readonly meta?: OutputMeta;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* The foot line of a run box (`zeta.run.foot`): the state word in its tone,
|
|
229
|
+
* the run time (a live clock while running, frozen once settled) and the
|
|
230
|
+
* quiet facts. Glyphs are the terminal's styling, never text.
|
|
231
|
+
*/
|
|
232
|
+
export function runFoot(input: RunFootInput): NativeNode {
|
|
233
|
+
const failedWithCode = input.state === "failed" && input.exitCode !== undefined && input.exitCode !== 0;
|
|
234
|
+
const state = failedWithCode
|
|
235
|
+
? { word: `exit ${input.exitCode}`, tone: RUN_STATE.failed.tone }
|
|
236
|
+
: RUN_STATE[input.state];
|
|
237
|
+
const facts = (input.facts ?? []).map(fact => plainText(fact).trim()).filter(fact => fact.length > 0);
|
|
238
|
+
const notices: string[] = [];
|
|
239
|
+
if (input.meta?.truncation) notices.push(formatTruncationMetaNotice(input.meta.truncation, input.meta.source));
|
|
240
|
+
if (input.meta?.artifactError) notices.push(formatArtifactErrorNotice(input.meta.artifactError));
|
|
241
|
+
const factSpans: TspSpan[] = [];
|
|
242
|
+
if (facts.length > 0) factSpans.push(span(facts.join(" · "), "muted"));
|
|
243
|
+
for (const notice of notices) {
|
|
244
|
+
if (factSpans.length > 0) factSpans.push(span(" · ", "muted"));
|
|
245
|
+
factSpans.push(span(notice, "warning"));
|
|
246
|
+
}
|
|
247
|
+
const ms = input.elapsedMs === undefined ? undefined : Math.max(0, Math.round(input.elapsedMs));
|
|
248
|
+
const time =
|
|
249
|
+
ms === undefined
|
|
250
|
+
? undefined
|
|
251
|
+
: node(
|
|
252
|
+
"elapsed",
|
|
253
|
+
input.state === "running"
|
|
254
|
+
? { role: "zeta.run.time", age: ms, format: "short" }
|
|
255
|
+
: { role: "zeta.run.time", age: ms, stopped: ms, format: "short" },
|
|
256
|
+
undefined,
|
|
257
|
+
"time",
|
|
258
|
+
);
|
|
259
|
+
return node(
|
|
260
|
+
"row",
|
|
261
|
+
{ role: "zeta.run.foot", gap: "sm", align: "center" },
|
|
262
|
+
compact<NativeNode>([
|
|
263
|
+
keyed(text([span(state.word)], { role: "zeta.run.state", tone: state.tone }), "state"),
|
|
264
|
+
time,
|
|
265
|
+
factSpans.length > 0 && keyed(text(factSpans, { role: "zeta.run.facts", wrap: "word" }), "facts"),
|
|
266
|
+
]),
|
|
267
|
+
"foot",
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** A run's input section: the command or cell source, clamped to {@link RUN_INPUT_PREVIEW_LINES}. */
|
|
272
|
+
export function runInput(source: string, p: { role: string; lang: string; wrap: boolean }): NativeNode {
|
|
273
|
+
return keyed(
|
|
274
|
+
code(source.trimEnd(), { role: p.role, lang: p.lang, wrap: p.wrap, preview: { lines: RUN_INPUT_PREVIEW_LINES } }),
|
|
275
|
+
"input",
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** A run's terminal output: follows its tail, clamped to the last `previewLines` lines while folded. */
|
|
280
|
+
export function runOutput(output: string, p: { role: string; previewLines: number; key?: string }): NativeNode {
|
|
281
|
+
return keyed(ansi(output, { role: p.role, follow: true, preview: { lines: p.previewLines } }), p.key ?? "output");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* One run as one box (`zeta.run`): input, output, status lines and foot in
|
|
286
|
+
* order. `tone` tints the box: `error` for a failed run, `warning` for a
|
|
287
|
+
* timed-out one.
|
|
288
|
+
*/
|
|
289
|
+
export function runBox(
|
|
290
|
+
children: readonly (NativeChild | undefined | false)[],
|
|
291
|
+
p: { key: string; tone?: TspTone },
|
|
292
|
+
): NativeNode {
|
|
293
|
+
return node("col", { role: "zeta.run", gap: "none", tone: p.tone }, compact(children), p.key);
|
|
294
|
+
}
|
|
295
|
+
|
|
195
296
|
/** Diagnostic rows shown before `+N more`. */
|
|
196
297
|
const DIAGNOSTIC_ROWS = 5;
|
|
197
298
|
|
|
@@ -84,12 +84,22 @@ export interface LimitsMeta {
|
|
|
84
84
|
reached: number;
|
|
85
85
|
suggestion: number;
|
|
86
86
|
};
|
|
87
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* `unit` may be absent in sessions persisted before it was recorded. `lines` is
|
|
89
|
+
* the first-to-last range of cut lines, and `selectorBase` the target a
|
|
90
|
+
* `:raw:<line>-<line>` selector reads one of them whole from (an artifact's
|
|
91
|
+
* `artifact://<id>` stands in when absent).
|
|
92
|
+
*/
|
|
88
93
|
columnTruncated?: {
|
|
89
94
|
maxColumn: number;
|
|
90
95
|
unit?: "bytes" | "chars";
|
|
91
96
|
artifactId?: string;
|
|
92
97
|
artifactElidedBytes?: number;
|
|
98
|
+
lines?: {
|
|
99
|
+
first: number;
|
|
100
|
+
last: number;
|
|
101
|
+
};
|
|
102
|
+
selectorBase?: string;
|
|
93
103
|
};
|
|
94
104
|
}
|
|
95
105
|
/**
|
package/src/tools/output-meta.ts
CHANGED
|
@@ -63,8 +63,20 @@ export interface LimitsMeta {
|
|
|
63
63
|
/** `suggestion` is omitted when the tool is already at its hard cap, so no larger usable limit exists to advise. */
|
|
64
64
|
resultLimit?: { reached: number; suggestion?: number };
|
|
65
65
|
headLimit?: { reached: number; suggestion: number };
|
|
66
|
-
/**
|
|
67
|
-
|
|
66
|
+
/**
|
|
67
|
+
* `unit` may be absent in sessions persisted before it was recorded. `lines` is
|
|
68
|
+
* the first-to-last range of cut lines, and `selectorBase` the target a
|
|
69
|
+
* `:raw:<line>-<line>` selector reads one of them whole from (an artifact's
|
|
70
|
+
* `artifact://<id>` stands in when absent).
|
|
71
|
+
*/
|
|
72
|
+
columnTruncated?: {
|
|
73
|
+
maxColumn: number;
|
|
74
|
+
unit?: "bytes" | "chars";
|
|
75
|
+
artifactId?: string;
|
|
76
|
+
artifactElidedBytes?: number;
|
|
77
|
+
lines?: { first: number; last: number };
|
|
78
|
+
selectorBase?: string;
|
|
79
|
+
};
|
|
68
80
|
}
|
|
69
81
|
|
|
70
82
|
/**
|
|
@@ -329,7 +341,15 @@ export function formatOutputNotice(meta: OutputMeta | undefined): string {
|
|
|
329
341
|
// a resumed legacy session renders "… 768 undefined" and stripOutputNotice
|
|
330
342
|
// stops matching the persisted "… 768 chars" text.
|
|
331
343
|
let columnNotice = `Some lines truncated to ${c.maxColumn} ${c.unit ?? "chars"}`;
|
|
332
|
-
|
|
344
|
+
// An artifact cut to a head/tail sample renumbers its lines, so only a complete one names a line.
|
|
345
|
+
const selectorBase =
|
|
346
|
+
c.selectorBase ?? (c.artifactId != null && !c.artifactElidedBytes ? `artifact://${c.artifactId}` : undefined);
|
|
347
|
+
if (c.lines && selectorBase !== undefined) {
|
|
348
|
+
// One line per selector: a span of cut lines can exceed what one read returns.
|
|
349
|
+
const { first, last } = c.lines;
|
|
350
|
+
columnNotice += `. Use ${selectorBase}:raw:${first}-${first} to read line ${first} whole`;
|
|
351
|
+
if (last > first) columnNotice += `; cut lines run to line ${last}, each read the same way`;
|
|
352
|
+
} else if (c.artifactId != null) {
|
|
333
353
|
columnNotice += `. ${formatFullOutputReference(c.artifactId, c.artifactElidedBytes)}`;
|
|
334
354
|
}
|
|
335
355
|
parts.push(columnNotice);
|
package/src/tools/read.ts
CHANGED
|
@@ -600,6 +600,11 @@ export const readToolRenderer = {
|
|
|
600
600
|
let cachedWidth: number | undefined;
|
|
601
601
|
let cachedExpanded: boolean | undefined;
|
|
602
602
|
let cachedLines: string[] | undefined;
|
|
603
|
+
const dropCache = () => {
|
|
604
|
+
cachedWidth = undefined;
|
|
605
|
+
cachedExpanded = undefined;
|
|
606
|
+
cachedLines = undefined;
|
|
607
|
+
};
|
|
603
608
|
return markFramedBlockComponent({
|
|
604
609
|
render: (width: number) => {
|
|
605
610
|
const expanded = options.expanded;
|
|
@@ -634,11 +639,8 @@ export const readToolRenderer = {
|
|
|
634
639
|
cachedExpanded = expanded;
|
|
635
640
|
return cachedLines;
|
|
636
641
|
},
|
|
637
|
-
invalidate:
|
|
638
|
-
|
|
639
|
-
cachedExpanded = undefined;
|
|
640
|
-
cachedLines = undefined;
|
|
641
|
-
},
|
|
642
|
+
invalidate: dropCache,
|
|
643
|
+
releaseRenderCaches: dropCache,
|
|
642
644
|
});
|
|
643
645
|
},
|
|
644
646
|
describeCall(args: ReadRenderArgs): NativeToolView {
|
package/src/tools/renderer.d.ts
CHANGED
|
@@ -25,6 +25,14 @@ export interface RenderResultOptions {
|
|
|
25
25
|
* Streamed `xd://` previews stay queued until this is set.
|
|
26
26
|
*/
|
|
27
27
|
executionStarted?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Milliseconds since this call began executing (`tool_execution_start`),
|
|
30
|
+
* or its total once settled; undefined before it starts. Native describe
|
|
31
|
+
* hooks only.
|
|
32
|
+
*/
|
|
33
|
+
elapsedMs?: number;
|
|
34
|
+
/** The call was abandoned without a final result (turn aborted, sealed). Native describe hooks only. */
|
|
35
|
+
cancelled?: boolean;
|
|
28
36
|
}
|
|
29
37
|
/** Render options for a result, plus the tool-specific context the transcript threads through. */
|
|
30
38
|
export type RenderResultContextOptions = RenderResultOptions & {
|
|
@@ -39,6 +47,18 @@ export interface ToolRenderResult<TDetails = unknown> {
|
|
|
39
47
|
details?: TDetails;
|
|
40
48
|
isError?: boolean;
|
|
41
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* A fence a tool call draws under its card, as assistant Markdown draws that
|
|
52
|
+
* fence. Any fence language may be named (`svg`, `mermaid`, `obj`); the
|
|
53
|
+
* transcript draws only those it draws as figures in assistant text.
|
|
54
|
+
*/
|
|
55
|
+
export interface ToolFigure {
|
|
56
|
+
readonly lang: string;
|
|
57
|
+
/** The body so far. */
|
|
58
|
+
readonly source: string;
|
|
59
|
+
/** No more of the body arrives. */
|
|
60
|
+
readonly closed: boolean;
|
|
61
|
+
}
|
|
42
62
|
/**
|
|
43
63
|
* Per-renderer opt-in for a full viewport replay when the first result
|
|
44
64
|
* replaces a painted pending-call render. A predicate receives the painted
|
|
@@ -73,6 +93,8 @@ export interface NativeToolHead {
|
|
|
73
93
|
readonly targetKind?: TspToolProps["targetKind"];
|
|
74
94
|
/** Language for `command` targets. */
|
|
75
95
|
readonly lang?: string;
|
|
96
|
+
/** The raw command line the head's Copy command button copies (set implicitly by a `command` target). */
|
|
97
|
+
readonly command?: string;
|
|
76
98
|
/** `file://` link for path targets. */
|
|
77
99
|
readonly href?: string;
|
|
78
100
|
/** Short facts after the target (`+8 −1`, `5 matches · 2 files`). */
|
|
@@ -99,10 +121,15 @@ export interface NativeToolView {
|
|
|
99
121
|
readonly body?: readonly NativeChild[];
|
|
100
122
|
/** Tone override; the frame otherwise derives it from the call status. */
|
|
101
123
|
readonly tone?: TspTone;
|
|
102
|
-
/**
|
|
124
|
+
/**
|
|
125
|
+
* Body clamp while collapsed; `{tail}` keeps the end (terminal output). Defaults to the transcript's preview size.
|
|
126
|
+
* `children`: the body stays whole while collapsed and its own `ansi`/`code` previews clamp instead.
|
|
127
|
+
*/
|
|
103
128
|
readonly preview?: TspPreview | {
|
|
104
129
|
readonly tail: number;
|
|
105
|
-
} | "none";
|
|
130
|
+
} | "none" | "children";
|
|
131
|
+
/** Starts expanded whatever the transcript's expand state (the todo checklist); the user can still fold it. */
|
|
132
|
+
readonly open?: boolean;
|
|
106
133
|
/** Render frameless (`frame:"inline"`): a head line plus a disclosed body. */
|
|
107
134
|
readonly inline?: boolean;
|
|
108
135
|
/** Head actions offered on hover (`copy`, `retry`). */
|
|
@@ -125,6 +152,14 @@ export interface ToolRenderer<TArgs = unknown, TDetails = unknown> {
|
|
|
125
152
|
/** Semantic result view for TSP terminals; merged with the call view when {@link mergeCallAndResult}. */
|
|
126
153
|
describeResult?(result: ToolRenderResult<TDetails>, options: RenderResultContextOptions, args?: TArgs): NativeToolView | undefined;
|
|
127
154
|
mergeCallAndResult?: boolean;
|
|
155
|
+
/**
|
|
156
|
+
* The fence a call draws under its card (a `.svg` being written, as its
|
|
157
|
+
* image): growing while the args stream, closed once they are final; none
|
|
158
|
+
* after an error. `result` is undefined until the call has one. Rendered
|
|
159
|
+
* TUI only, and only fences the terminal draws as figures; native views put
|
|
160
|
+
* their drawing in their describe hooks.
|
|
161
|
+
*/
|
|
162
|
+
figure?(args: TArgs, result: ToolRenderResult<TDetails> | undefined, options: RenderResultOptions): ToolFigure | undefined;
|
|
128
163
|
/** Describes current activity without coupling a renderer to terminal layout. */
|
|
129
164
|
activitySummary?(args: TArgs, context: ToolActivityContext): ToolActivitySummary;
|
|
130
165
|
/** Render without background box, inline in the response flow */
|
package/src/tools/renderer.ts
CHANGED
|
@@ -26,6 +26,14 @@ export interface RenderResultOptions {
|
|
|
26
26
|
* Streamed `xd://` previews stay queued until this is set.
|
|
27
27
|
*/
|
|
28
28
|
executionStarted?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Milliseconds since this call began executing (`tool_execution_start`),
|
|
31
|
+
* or its total once settled; undefined before it starts. Native describe
|
|
32
|
+
* hooks only.
|
|
33
|
+
*/
|
|
34
|
+
elapsedMs?: number;
|
|
35
|
+
/** The call was abandoned without a final result (turn aborted, sealed). Native describe hooks only. */
|
|
36
|
+
cancelled?: boolean;
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
/** Render options for a result, plus the tool-specific context the transcript threads through. */
|
|
@@ -38,6 +46,19 @@ export interface ToolRenderResult<TDetails = unknown> {
|
|
|
38
46
|
isError?: boolean;
|
|
39
47
|
}
|
|
40
48
|
|
|
49
|
+
/**
|
|
50
|
+
* A fence a tool call draws under its card, as assistant Markdown draws that
|
|
51
|
+
* fence. Any fence language may be named (`svg`, `mermaid`, `obj`); the
|
|
52
|
+
* transcript draws only those it draws as figures in assistant text.
|
|
53
|
+
*/
|
|
54
|
+
export interface ToolFigure {
|
|
55
|
+
readonly lang: string;
|
|
56
|
+
/** The body so far. */
|
|
57
|
+
readonly source: string;
|
|
58
|
+
/** No more of the body arrives. */
|
|
59
|
+
readonly closed: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
41
62
|
/**
|
|
42
63
|
* Per-renderer opt-in for a full viewport replay when the first result
|
|
43
64
|
* replaces a painted pending-call render. A predicate receives the painted
|
|
@@ -77,6 +98,8 @@ export interface NativeToolHead {
|
|
|
77
98
|
readonly targetKind?: TspToolProps["targetKind"];
|
|
78
99
|
/** Language for `command` targets. */
|
|
79
100
|
readonly lang?: string;
|
|
101
|
+
/** The raw command line the head's Copy command button copies (set implicitly by a `command` target). */
|
|
102
|
+
readonly command?: string;
|
|
80
103
|
/** `file://` link for path targets. */
|
|
81
104
|
readonly href?: string;
|
|
82
105
|
/** Short facts after the target (`+8 −1`, `5 matches · 2 files`). */
|
|
@@ -104,8 +127,13 @@ export interface NativeToolView {
|
|
|
104
127
|
readonly body?: readonly NativeChild[];
|
|
105
128
|
/** Tone override; the frame otherwise derives it from the call status. */
|
|
106
129
|
readonly tone?: TspTone;
|
|
107
|
-
/**
|
|
108
|
-
|
|
130
|
+
/**
|
|
131
|
+
* Body clamp while collapsed; `{tail}` keeps the end (terminal output). Defaults to the transcript's preview size.
|
|
132
|
+
* `children`: the body stays whole while collapsed and its own `ansi`/`code` previews clamp instead.
|
|
133
|
+
*/
|
|
134
|
+
readonly preview?: TspPreview | { readonly tail: number } | "none" | "children";
|
|
135
|
+
/** Starts expanded whatever the transcript's expand state (the todo checklist); the user can still fold it. */
|
|
136
|
+
readonly open?: boolean;
|
|
109
137
|
/** Render frameless (`frame:"inline"`): a head line plus a disclosed body. */
|
|
110
138
|
readonly inline?: boolean;
|
|
111
139
|
/** Head actions offered on hover (`copy`, `retry`). */
|
|
@@ -138,6 +166,18 @@ export interface ToolRenderer<TArgs = unknown, TDetails = unknown> {
|
|
|
138
166
|
args?: TArgs,
|
|
139
167
|
): NativeToolView | undefined;
|
|
140
168
|
mergeCallAndResult?: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* The fence a call draws under its card (a `.svg` being written, as its
|
|
171
|
+
* image): growing while the args stream, closed once they are final; none
|
|
172
|
+
* after an error. `result` is undefined until the call has one. Rendered
|
|
173
|
+
* TUI only, and only fences the terminal draws as figures; native views put
|
|
174
|
+
* their drawing in their describe hooks.
|
|
175
|
+
*/
|
|
176
|
+
figure?(
|
|
177
|
+
args: TArgs,
|
|
178
|
+
result: ToolRenderResult<TDetails> | undefined,
|
|
179
|
+
options: RenderResultOptions,
|
|
180
|
+
): ToolFigure | undefined;
|
|
141
181
|
/** Describes current activity without coupling a renderer to terminal layout. */
|
|
142
182
|
activitySummary?(args: TArgs, context: ToolActivityContext): ToolActivitySummary;
|
|
143
183
|
/** Render without background box, inline in the response flow */
|