@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/ast-edit.ts
CHANGED
|
@@ -53,13 +53,19 @@ interface AstEditRenderArgs {
|
|
|
53
53
|
const COLLAPSED_CHANGE_LIMIT = PREVIEW_LIMITS.COLLAPSED_LINES * 2;
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
* Flatten
|
|
57
|
-
* by a blank line and carry no tree guides — the
|
|
58
|
-
* so nested `├─ │` gutters would just be
|
|
59
|
-
* least the first group, then fills up
|
|
60
|
-
* rest as `… N more changes`.
|
|
56
|
+
* Flatten change groups (line indices, styled on demand) into frame body
|
|
57
|
+
* lines. Groups are separated by a blank line and carry no tree guides — the
|
|
58
|
+
* frame border is the container, so nested `├─ │` gutters would just be
|
|
59
|
+
* noise. Collapsed mode always shows at least the first group, then fills up
|
|
60
|
+
* to `budget` lines before summarizing the rest as `… N more changes`.
|
|
61
61
|
*/
|
|
62
|
-
function buildChangeBody(
|
|
62
|
+
function buildChangeBody(
|
|
63
|
+
groups: readonly (readonly number[])[],
|
|
64
|
+
styleLine: (index: number) => string,
|
|
65
|
+
expanded: boolean,
|
|
66
|
+
budget: number,
|
|
67
|
+
theme: Theme,
|
|
68
|
+
): string[] {
|
|
63
69
|
const lines: string[] = [];
|
|
64
70
|
let shown = 0;
|
|
65
71
|
for (let i = 0; i < groups.length; i++) {
|
|
@@ -70,7 +76,7 @@ function buildChangeBody(groups: string[][], expanded: boolean, budget: number,
|
|
|
70
76
|
// Always emit the first group; budget only gates subsequent ones.
|
|
71
77
|
if (!expanded && shown > 0 && lines.length + separator + group.length + reserved > budget) break;
|
|
72
78
|
if (separator) lines.push("");
|
|
73
|
-
lines.push(
|
|
79
|
+
for (const index of group) lines.push(styleLine(index));
|
|
74
80
|
shown++;
|
|
75
81
|
}
|
|
76
82
|
const remaining = groups.length - shown;
|
|
@@ -239,29 +245,36 @@ export const astEditToolRenderer = {
|
|
|
239
245
|
// Resolve hyperlinks over the whole output so nested directory headers
|
|
240
246
|
// reconstruct across the blank-line groups the tree list collapses by.
|
|
241
247
|
const contexts = classifyGroupedLines(allLines, details?.cwd ?? details?.searchPath, details?.searchPath);
|
|
242
|
-
|
|
248
|
+
// Style lazily: collapsed bodies show only the first groups.
|
|
249
|
+
const styledLines: (string | undefined)[] = Array.from({ length: allLines.length }, () => undefined);
|
|
250
|
+
const styleLine = (index: number): string => {
|
|
251
|
+
const cached = styledLines[index];
|
|
252
|
+
if (cached !== undefined) return cached;
|
|
243
253
|
const ctx = contexts[index]!;
|
|
244
254
|
// Swap the inner code-frame gutter `│` for a space so it does not nest a
|
|
245
255
|
// second vertical bar inside the frame border.
|
|
246
|
-
const display = replaceTabs(
|
|
256
|
+
const display = replaceTabs(allLines[index]!.replace("│", " "));
|
|
257
|
+
let styled: string;
|
|
247
258
|
if (ctx.kind === "dir") {
|
|
248
|
-
const
|
|
249
|
-
|
|
259
|
+
const accent = uiTheme.fg("accent", display);
|
|
260
|
+
styled = ctx.headerPath ? fileHyperlink(ctx.headerPath, accent) : accent;
|
|
261
|
+
} else if (ctx.kind === "file") {
|
|
262
|
+
const tinted = uiTheme.fg(ctx.depth === 1 ? "accent" : "dim", display);
|
|
263
|
+
styled = ctx.headerPath ? fileHyperlink(ctx.headerPath, tinted) : tinted;
|
|
264
|
+
} else if (display.startsWith("+")) {
|
|
265
|
+
styled = uiTheme.fg("toolDiffAdded", display);
|
|
266
|
+
} else if (display.startsWith("-")) {
|
|
267
|
+
styled = uiTheme.fg("toolDiffRemoved", display);
|
|
268
|
+
} else {
|
|
269
|
+
styled = uiTheme.fg("toolOutput", display);
|
|
250
270
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
return uiTheme.fg("toolOutput", display);
|
|
271
|
+
styledLines[index] = styled;
|
|
272
|
+
return styled;
|
|
273
|
+
};
|
|
274
|
+
const changeGroups = groupLineIndicesByBlank(allLines).filter(indices => {
|
|
275
|
+
const first = allLines[indices[0]!]!;
|
|
276
|
+
return !first.startsWith("Safety cap reached") && !first.startsWith("Parse issues:");
|
|
258
277
|
});
|
|
259
|
-
const changeGroups = groupLineIndicesByBlank(allLines)
|
|
260
|
-
.filter(indices => {
|
|
261
|
-
const first = allLines[indices[0]!]!;
|
|
262
|
-
return !first.startsWith("Safety cap reached") && !first.startsWith("Parse issues:");
|
|
263
|
-
})
|
|
264
|
-
.map(indices => indices.map(index => styledLines[index]!));
|
|
265
278
|
|
|
266
279
|
const badge = { label: "proposed", color: "warning" as const };
|
|
267
280
|
const header = renderStatusLine(
|
|
@@ -278,17 +291,28 @@ export const astEditToolRenderer = {
|
|
|
278
291
|
uiTheme.fg("warning", formatParseErrorsCountLabel(details.parseErrors, details.parseErrorsTotal)),
|
|
279
292
|
);
|
|
280
293
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
294
|
+
// The body is spinner-invariant: rebuild it only on expansion/width change.
|
|
295
|
+
let bodyMemo: { expanded: boolean; width: number; lines: readonly string[] } | undefined;
|
|
296
|
+
return framedToolCard(
|
|
297
|
+
uiTheme,
|
|
298
|
+
({ contentWidth }) => {
|
|
299
|
+
const expanded = Boolean(options.expanded);
|
|
300
|
+
if (bodyMemo === undefined || bodyMemo.expanded !== expanded || bodyMemo.width !== contentWidth) {
|
|
301
|
+
const changeLines = buildChangeBody(changeGroups, styleLine, expanded, COLLAPSED_CHANGE_LIMIT, uiTheme);
|
|
302
|
+
const lines = [...changeLines, ...extraLines].map(l => truncateToWidth(l, contentWidth, Ellipsis.Omit));
|
|
303
|
+
while (lines.length > 0 && lines[0].trim() === "") lines.shift();
|
|
304
|
+
bodyMemo = { expanded, width: contentWidth, lines };
|
|
305
|
+
}
|
|
306
|
+
const bodyLines = bodyMemo.lines;
|
|
307
|
+
return {
|
|
308
|
+
header,
|
|
309
|
+
sections: bodyLines.length > 0 ? [{ content: bodyLines }] : [],
|
|
310
|
+
phase: options.isPartial ? "partial" : "success",
|
|
311
|
+
borderColor: "borderMuted",
|
|
312
|
+
};
|
|
313
|
+
},
|
|
314
|
+
{ onInvalidate: () => (bodyMemo = undefined) },
|
|
315
|
+
);
|
|
292
316
|
},
|
|
293
317
|
describeCall(args: AstEditRenderArgs): NativeToolView {
|
|
294
318
|
return {
|
package/src/tools/ast-grep.ts
CHANGED
|
@@ -136,25 +136,41 @@ export const astGrepToolRenderer = {
|
|
|
136
136
|
// Resolve hyperlinks over the whole output so nested directory headers
|
|
137
137
|
// reconstruct across the blank-line groups the tree list collapses by.
|
|
138
138
|
const contexts = classifyGroupedLines(allLines, details?.cwd ?? details?.searchPath, details?.searchPath);
|
|
139
|
-
|
|
139
|
+
// Style lazily: the collapsed tree list only renders the first few groups,
|
|
140
|
+
// so a large result never styles/hyperlinks rows nobody sees.
|
|
141
|
+
const styledLines: (string | undefined)[] = Array.from({ length: allLines.length }, () => undefined);
|
|
142
|
+
const styleLine = (index: number): string => {
|
|
143
|
+
const cached = styledLines[index];
|
|
144
|
+
if (cached !== undefined) return cached;
|
|
145
|
+
const line = allLines[index]!;
|
|
140
146
|
const ctx = contexts[index]!;
|
|
147
|
+
let styled: string;
|
|
141
148
|
if (ctx.kind === "dir") {
|
|
142
|
-
const
|
|
143
|
-
|
|
149
|
+
const accent = uiTheme.fg("accent", line);
|
|
150
|
+
styled = ctx.headerPath ? fileHyperlink(ctx.headerPath, accent) : accent;
|
|
151
|
+
} else if (ctx.kind === "file") {
|
|
152
|
+
const tinted = uiTheme.fg(ctx.depth === 1 ? "accent" : "dim", line);
|
|
153
|
+
styled = ctx.headerPath ? fileHyperlink(ctx.headerPath, tinted) : tinted;
|
|
154
|
+
} else {
|
|
155
|
+
styled = uiTheme.fg(line.startsWith(" meta:") ? "dim" : "toolOutput", line);
|
|
144
156
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return
|
|
157
|
+
styledLines[index] = styled;
|
|
158
|
+
return styled;
|
|
159
|
+
};
|
|
160
|
+
const matchGroups = groupLineIndicesByBlank(allLines).filter(indices => {
|
|
161
|
+
const first = allLines[indices[0]!]!;
|
|
162
|
+
return !first.startsWith("Result limit reached") && !first.startsWith("Parse issues:");
|
|
151
163
|
});
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
164
|
+
// Line offset at which each group starts. A collapsed tree list stops at the
|
|
165
|
+
// first group that overflows its line budget, so groups starting at or past
|
|
166
|
+
// the budget are never shown — hand it same-length placeholders instead of
|
|
167
|
+
// styling them (renderTreeList only needs their line counts).
|
|
168
|
+
const groupStarts: number[] = [];
|
|
169
|
+
let groupStart = 0;
|
|
170
|
+
for (const group of matchGroups) {
|
|
171
|
+
groupStarts.push(groupStart);
|
|
172
|
+
groupStart += group.length;
|
|
173
|
+
}
|
|
158
174
|
|
|
159
175
|
const extraLines: string[] = [];
|
|
160
176
|
if (limitReached) {
|
|
@@ -178,7 +194,10 @@ export const astGrepToolRenderer = {
|
|
|
178
194
|
maxCollapsed: matchGroups.length,
|
|
179
195
|
maxCollapsedLines: COLLAPSED_MATCH_LIMIT,
|
|
180
196
|
itemType: "match",
|
|
181
|
-
renderItem: group =>
|
|
197
|
+
renderItem: (group, context) =>
|
|
198
|
+
!options.expanded && groupStarts[context.index]! >= COLLAPSED_MATCH_LIMIT
|
|
199
|
+
? Array.from({ length: group.length }, () => "")
|
|
200
|
+
: group.map(styleLine),
|
|
182
201
|
},
|
|
183
202
|
uiTheme,
|
|
184
203
|
);
|
package/src/tools/bash.d.ts
CHANGED
|
@@ -4,8 +4,13 @@ import { type OutputMeta } from "./output-meta";
|
|
|
4
4
|
import type { NativeToolView, RenderResultContextOptions, RenderResultOptions } from "./renderer";
|
|
5
5
|
/** Default collapsed shell output preview height. */
|
|
6
6
|
export declare const BASH_DEFAULT_PREVIEW_LINES = 10;
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* LLM-facing footer appended when a tool call becomes a background job. It states the job's kill
|
|
9
|
+
* deadline (`timeoutSec`, `undefined` when disabled) so the model knows the job will die at it before
|
|
10
|
+
* it waits on the result. The deadline counts the job's whole run time, not time left from now: an
|
|
11
|
+
* auto-backgrounded call has already spent its foreground wait.
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatBackgroundNotice(jobId: string, timeoutSec: number | undefined): string;
|
|
9
14
|
/** Shell execution metadata used by transcript rendering. */
|
|
10
15
|
export interface BashToolDetails {
|
|
11
16
|
meta?: OutputMeta;
|
package/src/tools/bash.ts
CHANGED
|
@@ -25,16 +25,34 @@ import type {
|
|
|
25
25
|
RenderResultOptions,
|
|
26
26
|
ToolRenderer,
|
|
27
27
|
} from "./renderer";
|
|
28
|
-
import {
|
|
29
|
-
import
|
|
30
|
-
import {
|
|
28
|
+
import { INTENT_FIELD, type TspTone } from "@linxiraos/pi-wire";
|
|
29
|
+
import { plainText } from "../native/spans";
|
|
30
|
+
import { resultText, runBox, runFoot, runInput, runOutput, type RunState } from "./native-view";
|
|
31
31
|
|
|
32
32
|
/** Default collapsed shell output preview height. */
|
|
33
33
|
export const BASH_DEFAULT_PREVIEW_LINES = DEFAULT_TERMINAL_PREVIEW_LINES;
|
|
34
34
|
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
/**
|
|
36
|
+
* LLM-facing footer appended when a tool call becomes a background job. It states the job's kill
|
|
37
|
+
* deadline (`timeoutSec`, `undefined` when disabled) so the model knows the job will die at it before
|
|
38
|
+
* it waits on the result. The deadline counts the job's whole run time, not time left from now: an
|
|
39
|
+
* auto-backgrounded call has already spent its foreground wait.
|
|
40
|
+
*/
|
|
41
|
+
export function formatBackgroundNotice(jobId: string, timeoutSec: number | undefined): string {
|
|
42
|
+
const deadline =
|
|
43
|
+
timeoutSec === undefined
|
|
44
|
+
? " (no deadline)"
|
|
45
|
+
: ` (killed once it has run ${timeoutSec}s in total; \`timeout: 0\` disables the deadline)`;
|
|
46
|
+
return `Backgrounded as job ${jobId}${deadline}; its output is injected into the conversation as a follow-up the moment it finishes. Do NOT poll for it (no \`sleep\`, \`ps\`, \`pgrep\`, \`top\`, \`pidwait\`, log tailing): every poll is a wasted turn. Do other work, or end your reply and wait to be woken.`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Whether `line` is `formatBackgroundNotice(jobId, …)` for any deadline, including the deadline-less
|
|
51
|
+
* `Backgrounded as job <id>; …` form persisted in older transcripts.
|
|
52
|
+
*/
|
|
53
|
+
function isBackgroundNotice(line: string, jobId: string): boolean {
|
|
54
|
+
const prefix = `Backgrounded as job ${jobId}`;
|
|
55
|
+
return line.startsWith(prefix) && (line[prefix.length] === ";" || line[prefix.length] === " ");
|
|
38
56
|
}
|
|
39
57
|
|
|
40
58
|
/** Shell execution metadata used by transcript rendering. */
|
|
@@ -289,9 +307,10 @@ function stripBashNotices(
|
|
|
289
307
|
rawOutput: string,
|
|
290
308
|
details: BashToolDetails | undefined,
|
|
291
309
|
): { text: string; artifactId?: string } {
|
|
310
|
+
const job = details?.async;
|
|
292
311
|
const withoutBackground =
|
|
293
|
-
|
|
294
|
-
? stripTrailingNotice(rawOutput,
|
|
312
|
+
job?.state === "running"
|
|
313
|
+
? stripTrailingNotice(rawOutput, line => isBackgroundNotice(line, job.jobId))
|
|
295
314
|
: rawOutput;
|
|
296
315
|
const strippedOutput = stripOutputNotice(withoutBackground, details?.meta);
|
|
297
316
|
const withoutExit =
|
|
@@ -348,34 +367,41 @@ function bashStatsParts(
|
|
|
348
367
|
}
|
|
349
368
|
|
|
350
369
|
/**
|
|
351
|
-
* Native head facts of a shell call: title, the
|
|
352
|
-
*
|
|
353
|
-
*
|
|
370
|
+
* Native head facts of a shell call: title, the model's intent as the target
|
|
371
|
+
* (none without one), the command line for Copy command, the `exit N` chip
|
|
372
|
+
* and a `timed out` note only when the deadline hit. The command itself and a
|
|
373
|
+
* backgrounded job's state draw in the run box.
|
|
354
374
|
*/
|
|
355
375
|
function shellToolHead(
|
|
356
376
|
title: string,
|
|
357
377
|
command: string,
|
|
378
|
+
intent: string | undefined,
|
|
358
379
|
details: BashToolDetails | undefined,
|
|
359
380
|
settled: boolean,
|
|
360
381
|
): NativeToolHead {
|
|
361
382
|
const exit = settled && details?.exitCode !== undefined && details.exitCode !== 0 ? details.exitCode : undefined;
|
|
362
383
|
return {
|
|
363
384
|
title,
|
|
364
|
-
target:
|
|
365
|
-
targetKind: "
|
|
366
|
-
|
|
367
|
-
badges:
|
|
368
|
-
details?.async?.state === "running"
|
|
369
|
-
? [{ text: "background", title: `Backgrounded as job ${details.async.jobId}` }]
|
|
370
|
-
: undefined,
|
|
385
|
+
target: intent,
|
|
386
|
+
targetKind: intent ? "text" : undefined,
|
|
387
|
+
command,
|
|
371
388
|
exit,
|
|
372
389
|
note: settled && details?.timedOut === true ? "timed out" : undefined,
|
|
373
390
|
};
|
|
374
391
|
}
|
|
375
392
|
|
|
376
|
-
/** The
|
|
393
|
+
/** The model's intent line (`i` arg) as plain head text, or undefined when absent. */
|
|
394
|
+
function callIntent(args: unknown): string | undefined {
|
|
395
|
+
if (!args || typeof args !== "object" || !(INTENT_FIELD in args)) return undefined;
|
|
396
|
+
const value = args[INTENT_FIELD];
|
|
397
|
+
if (typeof value !== "string") return undefined;
|
|
398
|
+
return plainText(value).trim() || undefined;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/** The run foot's facts under shell output: background job, service state and the full-output artifact. */
|
|
377
402
|
function shellFootParts(details: BashToolDetails | undefined, artifactId: string | undefined): string[] {
|
|
378
403
|
const parts: string[] = [];
|
|
404
|
+
if (details?.async?.state === "running") parts.push(`Job ${details.async.jobId}`);
|
|
379
405
|
const service = details?.service;
|
|
380
406
|
if (service) {
|
|
381
407
|
parts.push(`Service ${service.name}`, service.state);
|
|
@@ -386,6 +412,27 @@ function shellFootParts(details: BashToolDetails | undefined, artifactId: string
|
|
|
386
412
|
return parts;
|
|
387
413
|
}
|
|
388
414
|
|
|
415
|
+
/** The command line as a run's input: wrapped shell source. */
|
|
416
|
+
const SHELL_INPUT = { role: "zeta.tool.bash.command", lang: "bash", wrap: true } as const;
|
|
417
|
+
|
|
418
|
+
/** Box tint per run state: failed runs read as errors, timed-out ones as warnings. */
|
|
419
|
+
const RUN_BOX_TONE: Partial<Record<RunState, TspTone>> = { failed: "error", "timed-out": "warning" };
|
|
420
|
+
|
|
421
|
+
/** The foot state of a shell call from its result. */
|
|
422
|
+
function shellRunState(
|
|
423
|
+
details: BashToolDetails | undefined,
|
|
424
|
+
isError: boolean,
|
|
425
|
+
isPartial: boolean,
|
|
426
|
+
cancelled: boolean,
|
|
427
|
+
): RunState {
|
|
428
|
+
if (cancelled) return "cancelled";
|
|
429
|
+
if (isPartial) return "running";
|
|
430
|
+
if (details?.timedOut === true) return "timed-out";
|
|
431
|
+
if (details?.async?.state === "running") return "background";
|
|
432
|
+
if (isError || (details?.exitCode !== undefined && details.exitCode !== 0)) return "failed";
|
|
433
|
+
return "done";
|
|
434
|
+
}
|
|
435
|
+
|
|
389
436
|
function toBashRenderArgs<TArgs>(args: TArgs | undefined, config: ShellRendererConfig<TArgs>): BashRenderArgs {
|
|
390
437
|
return {
|
|
391
438
|
command: config.resolveCommand?.(args),
|
|
@@ -475,6 +522,15 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
475
522
|
let cachedIsPartial: boolean | undefined;
|
|
476
523
|
let cachedPreviewWindow: number | undefined;
|
|
477
524
|
let cachedSnapshot: ToolCardSnapshot | undefined;
|
|
525
|
+
const dropSnapshot = () => {
|
|
526
|
+
cachedSnapshot = undefined;
|
|
527
|
+
cachedWidth = undefined;
|
|
528
|
+
cachedPreviewLines = undefined;
|
|
529
|
+
cachedExpanded = undefined;
|
|
530
|
+
cachedRawOutput = undefined;
|
|
531
|
+
cachedIsPartial = undefined;
|
|
532
|
+
cachedPreviewWindow = undefined;
|
|
533
|
+
};
|
|
478
534
|
|
|
479
535
|
return framedToolCard(
|
|
480
536
|
uiTheme,
|
|
@@ -577,25 +633,26 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
577
633
|
cachedSnapshot = snapshot;
|
|
578
634
|
return snapshot;
|
|
579
635
|
},
|
|
580
|
-
{
|
|
581
|
-
onInvalidate: () => {
|
|
582
|
-
cachedSnapshot = undefined;
|
|
583
|
-
cachedWidth = undefined;
|
|
584
|
-
cachedPreviewLines = undefined;
|
|
585
|
-
cachedExpanded = undefined;
|
|
586
|
-
cachedRawOutput = undefined;
|
|
587
|
-
cachedIsPartial = undefined;
|
|
588
|
-
cachedPreviewWindow = undefined;
|
|
589
|
-
},
|
|
590
|
-
},
|
|
636
|
+
{ onInvalidate: dropSnapshot, onReleaseRenderCaches: dropSnapshot },
|
|
591
637
|
);
|
|
592
638
|
},
|
|
593
639
|
describeCall(args: TArgs, options: RenderResultOptions): NativeToolView {
|
|
594
640
|
const command = formatBashCommandText(toBashRenderArgs(args, config));
|
|
595
|
-
//
|
|
641
|
+
// No foot until the command starts; once it runs (before any output) the clock shows.
|
|
642
|
+
const started = options.executionStarted === true;
|
|
596
643
|
return {
|
|
597
|
-
tool: shellToolHead(config.resolveTitle(args, options), command, undefined, false),
|
|
598
|
-
|
|
644
|
+
tool: shellToolHead(config.resolveTitle(args, options), command, callIntent(args), undefined, false),
|
|
645
|
+
body: [
|
|
646
|
+
runBox(
|
|
647
|
+
[
|
|
648
|
+
runInput(command, SHELL_INPUT),
|
|
649
|
+
started &&
|
|
650
|
+
runFoot({ state: options.cancelled ? "cancelled" : "running", elapsedMs: options.elapsedMs }),
|
|
651
|
+
],
|
|
652
|
+
{ key: "run" },
|
|
653
|
+
),
|
|
654
|
+
],
|
|
655
|
+
preview: "children",
|
|
599
656
|
};
|
|
600
657
|
},
|
|
601
658
|
|
|
@@ -619,22 +676,34 @@ export function createShellRenderer<TArgs>(config: ShellRendererConfig<TArgs>) {
|
|
|
619
676
|
const showingFullOutput = expanded && renderContext?.isFullOutput === true;
|
|
620
677
|
const command = formatBashCommandText(toBashRenderArgs(args, config));
|
|
621
678
|
const previewLines = renderContext?.previewLines ?? BASH_DEFAULT_PREVIEW_LINES;
|
|
622
|
-
|
|
623
|
-
//
|
|
679
|
+
const state = shellRunState(details, isError, isPartial, options.cancelled === true);
|
|
680
|
+
// Settled: the measured wall time wins. A background job outlives the call: its run time is unknown here.
|
|
681
|
+
const elapsedMs =
|
|
682
|
+
state === "background"
|
|
683
|
+
? undefined
|
|
684
|
+
: isPartial
|
|
685
|
+
? options.elapsedMs
|
|
686
|
+
: (details?.wallTimeMs ?? options.elapsedMs);
|
|
624
687
|
const meta = details?.meta;
|
|
625
|
-
const
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
688
|
+
const box = runBox(
|
|
689
|
+
[
|
|
690
|
+
runInput(command, SHELL_INPUT),
|
|
691
|
+
output.trim().length > 0 && runOutput(output, { role: "zeta.tool.bash.output", previewLines }),
|
|
692
|
+
runFoot({
|
|
693
|
+
state,
|
|
694
|
+
exitCode: details?.exitCode,
|
|
695
|
+
elapsedMs,
|
|
696
|
+
facts: shellFootParts(details, stripped.artifactId),
|
|
697
|
+
meta: { ...meta, truncation: showingFullOutput ? undefined : meta?.truncation },
|
|
698
|
+
}),
|
|
699
|
+
],
|
|
700
|
+
{ key: "run", tone: RUN_BOX_TONE[state] },
|
|
701
|
+
);
|
|
633
702
|
return {
|
|
634
|
-
tool: shellToolHead(config.resolveTitle(args, options), command, details, !isPartial),
|
|
635
|
-
body,
|
|
636
|
-
tone:
|
|
637
|
-
preview:
|
|
703
|
+
tool: shellToolHead(config.resolveTitle(args, options), command, callIntent(args), details, !isPartial),
|
|
704
|
+
body: [box],
|
|
705
|
+
tone: state === "timed-out" ? "warning" : undefined,
|
|
706
|
+
preview: "children",
|
|
638
707
|
};
|
|
639
708
|
},
|
|
640
709
|
mergeCallAndResult: true,
|
package/src/tools/daemon.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Launch-broker daemon types shared by services, `proc://`, and `
|
|
1
|
+
/** Launch-broker daemon types shared by services, `proc://`, and `zetacode ps`. */
|
|
2
2
|
/** Stable lifecycle states exposed by the launch broker. */
|
|
3
3
|
export type DaemonState = "starting" | "running" | "ready" | "restarting" | "stopping" | "exited" | "failed";
|
|
4
4
|
/** Restart behavior applied after an unexpected daemon exit. */
|
package/src/tools/daemon.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Launch-broker daemon types shared by services, `proc://`, and `
|
|
1
|
+
/** Launch-broker daemon types shared by services, `proc://`, and `zetacode ps`. */
|
|
2
2
|
|
|
3
3
|
/** Stable lifecycle states exposed by the launch broker. */
|
|
4
4
|
export type DaemonState = "starting" | "running" | "ready" | "restarting" | "stopping" | "exited" | "failed";
|
|
@@ -39,19 +39,8 @@ export interface DefaultToolRenderInput {
|
|
|
39
39
|
options: RenderResultOptions;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
status: StatusLineOptions;
|
|
45
|
-
phase: ToolCardPhase;
|
|
46
|
-
body: readonly string[];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Compute the single header/body assembly behind both default-tool entry points. */
|
|
50
|
-
function buildDefaultToolSnapshot(
|
|
51
|
-
input: DefaultToolRenderInput,
|
|
52
|
-
uiTheme: Theme,
|
|
53
|
-
contentWidth: number,
|
|
54
|
-
): DefaultToolSnapshot {
|
|
42
|
+
/** Spinner-dependent header state; cheap, recomputed every frame. */
|
|
43
|
+
function buildDefaultToolStatus(input: DefaultToolRenderInput): { status: StatusLineOptions; phase: ToolCardPhase } {
|
|
55
44
|
const { options, result } = input;
|
|
56
45
|
const status: StatusLineOptions = {
|
|
57
46
|
icon: options.isPartial
|
|
@@ -76,7 +65,12 @@ function buildDefaultToolSnapshot(
|
|
|
76
65
|
: result?.isError
|
|
77
66
|
? "error"
|
|
78
67
|
: "success";
|
|
68
|
+
return { status, phase };
|
|
69
|
+
}
|
|
79
70
|
|
|
71
|
+
/** Args preview plus JSON-tree/raw output body; depends only on args, output, expansion and width. */
|
|
72
|
+
function buildDefaultToolBody(input: DefaultToolRenderInput, uiTheme: Theme, contentWidth: number): string[] {
|
|
73
|
+
const { options, result } = input;
|
|
80
74
|
const body: string[] = [];
|
|
81
75
|
const args = isRecord(input.args) ? input.args : undefined;
|
|
82
76
|
if (!options.expanded && args && Object.keys(args).length > 0) {
|
|
@@ -149,7 +143,7 @@ function buildDefaultToolSnapshot(
|
|
|
149
143
|
}
|
|
150
144
|
}
|
|
151
145
|
|
|
152
|
-
return
|
|
146
|
+
return body;
|
|
153
147
|
}
|
|
154
148
|
|
|
155
149
|
/** Format one generic tool call/result card at the available content width. */
|
|
@@ -158,8 +152,8 @@ export function formatDefaultToolExecution(
|
|
|
158
152
|
contentWidth: number,
|
|
159
153
|
uiTheme: Theme,
|
|
160
154
|
): string {
|
|
161
|
-
const
|
|
162
|
-
return [renderStatusLine(
|
|
155
|
+
const { status } = buildDefaultToolStatus(input);
|
|
156
|
+
return [renderStatusLine(status, uiTheme), ...buildDefaultToolBody(input, uiTheme, contentWidth)].join("\n");
|
|
163
157
|
}
|
|
164
158
|
|
|
165
159
|
/** Inline args summary budget in characters (a data cap, not a width). */
|
|
@@ -195,12 +189,34 @@ export function describeDefaultToolExecution(input: DefaultToolRenderInput): Nat
|
|
|
195
189
|
|
|
196
190
|
/** Render the generic fallback as the state-tinted card used by direct custom tools. */
|
|
197
191
|
export function renderDefaultToolExecution(input: DefaultToolRenderInput, uiTheme: Theme): Component {
|
|
192
|
+
// The body (JSON parse + tree walk or output styling) is spinner-invariant;
|
|
193
|
+
// rebuild it only when its inputs change instead of on every animated frame.
|
|
194
|
+
let memo:
|
|
195
|
+
| { args: unknown; output: string | undefined; expanded: boolean; contentWidth: number; body: readonly string[] }
|
|
196
|
+
| undefined;
|
|
198
197
|
return plainToolCard(
|
|
199
198
|
uiTheme,
|
|
200
199
|
({ contentWidth }) => {
|
|
201
|
-
const
|
|
202
|
-
|
|
200
|
+
const { status, phase } = buildDefaultToolStatus(input);
|
|
201
|
+
const output = input.result?.output;
|
|
202
|
+
const expanded = input.options.expanded;
|
|
203
|
+
if (
|
|
204
|
+
memo === undefined ||
|
|
205
|
+
memo.args !== input.args ||
|
|
206
|
+
memo.output !== output ||
|
|
207
|
+
memo.expanded !== expanded ||
|
|
208
|
+
memo.contentWidth !== contentWidth
|
|
209
|
+
) {
|
|
210
|
+
memo = {
|
|
211
|
+
args: input.args,
|
|
212
|
+
output,
|
|
213
|
+
expanded,
|
|
214
|
+
contentWidth,
|
|
215
|
+
body: buildDefaultToolBody(input, uiTheme, contentWidth),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return { status, phase, body: memo.body };
|
|
203
219
|
},
|
|
204
|
-
{ paddingX: 1, paddingY: 1, ignoreTight: true },
|
|
220
|
+
{ paddingX: 1, paddingY: 1, ignoreTight: true, onInvalidate: () => (memo = undefined) },
|
|
205
221
|
);
|
|
206
222
|
}
|