@linxiraos/pi-tui 1.1.27 → 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 +47 -463
- package/README.md +7 -5
- package/dist/types/app-keybindings.d.ts +1 -1
- 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 +2 -2
- 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 +5 -0
- package/dist/types/chat/chat-transcript-builder.d.ts +2 -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 +15 -2
- package/dist/types/chrome/shared.d.ts +9 -0
- 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 +15 -4
- package/dist/types/components/form.d.ts +1 -0
- package/dist/types/components/image.d.ts +12 -44
- 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/markdown.d.ts +36 -3
- 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 +1 -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/backend.d.ts +3 -2
- package/dist/types/native/blobs.d.ts +7 -3
- package/dist/types/native/encode.d.ts +3 -4
- package/dist/types/native/overlay.d.ts +5 -0
- 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 +2 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +11 -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/history-search.d.ts +10 -0
- package/dist/types/overlays/hook-selector.d.ts +9 -4
- 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 +23 -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/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/usage-dashboard.d.ts +8 -4
- package/dist/types/overlays/usage-display.d.ts +3 -1
- package/dist/types/prompt/composer.d.ts +1 -1
- package/dist/types/prompt/custom-editor.d.ts +11 -8
- package/dist/types/prompt/image-source.d.ts +2 -1
- package/dist/types/prompt/interactive-context-helpers.d.ts +4 -1
- package/dist/types/prompt/model-mention-autocomplete.d.ts +1 -1
- package/dist/types/prompt/welcome.d.ts +6 -1
- 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/status-line/component.d.ts +3 -0
- 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 +27 -35
- package/dist/types/terminal-multiplexer.d.ts +127 -14
- package/dist/types/terminal.d.ts +22 -6
- 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/tmux.d.ts +11 -4
- 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 +0 -4
- package/dist/types/tools/write.d.ts +9 -2
- package/dist/types/tools/yield.d.ts +22 -0
- package/dist/types/tui.d.ts +31 -0
- package/dist/types/utils.d.ts +6 -0
- package/dist/types/vim.d.ts +19 -5
- package/package.json +13 -9
- package/src/app-keybindings.d.ts +1 -1
- package/src/app-keybindings.ts +1 -1
- 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 +26 -5
- package/src/apps/git/git-tui.ts +2 -2
- package/src/apps/git/help.ts +29 -20
- 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/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 +5 -0
- package/src/chat/assistant-message.ts +219 -50
- package/src/chat/chat-transcript-builder.d.ts +2 -0
- package/src/chat/chat-transcript-builder.ts +5 -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 +80 -6
- package/src/chat/user-message.d.ts +15 -2
- package/src/chat/user-message.ts +55 -3
- package/src/chrome/shared.ts +53 -0
- package/src/chrome/transcript-container.d.ts +6 -0
- package/src/chrome/transcript-container.ts +93 -13
- 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 +15 -4
- package/src/components/editor.ts +294 -46
- package/src/components/form.d.ts +1 -0
- package/src/components/form.ts +8 -0
- package/src/components/image.d.ts +12 -44
- package/src/components/image.ts +47 -151
- 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/markdown.d.ts +36 -3
- package/src/components/markdown.ts +433 -318
- 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 +1 -1
- package/src/fuzzy.d.ts +29 -1
- package/src/fuzzy.ts +115 -30
- package/src/key-hint-format.d.ts +1 -1
- package/src/key-hint-format.ts +1 -1
- 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 +4 -4
- 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/backend.d.ts +3 -2
- package/src/native/backend.ts +174 -18
- package/src/native/blobs.d.ts +7 -3
- package/src/native/blobs.ts +47 -12
- package/src/native/encode.d.ts +3 -4
- package/src/native/encode.ts +58 -31
- package/src/native/overlay.d.ts +5 -0
- package/src/native/overlay.ts +13 -0
- package/src/native/reconcile.ts +4 -0
- 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 +44 -29
- package/src/overlays/agent-transcript-viewer.ts +91 -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 +7 -10
- package/src/overlays/btw-history-panel.ts +12 -1
- package/src/overlays/copy-selector.ts +30 -8
- 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/jobs-panel.ts +28 -46
- package/src/overlays/model-browser.ts +341 -110
- package/src/overlays/model-hub.ts +300 -49
- package/src/overlays/move-overlay.ts +28 -14
- package/src/overlays/oauth-selector.ts +54 -70
- package/src/overlays/plan-review-overlay.ts +194 -70
- package/src/overlays/plugin-settings.ts +3 -3
- package/src/overlays/report-panel.ts +2 -2
- package/src/overlays/rewind-selector.ts +86 -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 +4 -3
- 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/tree-selector.ts +41 -20
- package/src/overlays/usage-dashboard.ts +100 -50
- package/src/overlays/usage-display.ts +10 -4
- package/src/prompt/attachment-chips.ts +15 -11
- package/src/prompt/composer-attachments.ts +6 -4
- package/src/prompt/composer.ts +4 -15
- package/src/prompt/custom-editor.ts +54 -26
- package/src/prompt/image-source.ts +2 -1
- package/src/prompt/interactive-context-helpers.ts +30 -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/tips.txt +6 -5
- package/src/prompt/welcome.ts +55 -12
- 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 +11 -0
- 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/status-line/component.ts +292 -78
- 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 +27 -35
- package/src/terminal-capabilities.ts +75 -189
- package/src/terminal-multiplexer.d.ts +127 -14
- package/src/terminal-multiplexer.ts +112 -33
- package/src/terminal.d.ts +22 -6
- package/src/terminal.ts +139 -37
- 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 +6 -1
- 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/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.ts +92 -42
- 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 +149 -50
- package/src/tools/task.d.ts +0 -4
- package/src/tools/task.ts +112 -59
- 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 +31 -0
- package/src/tui.ts +309 -160
- 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.ts +8 -0
|
@@ -20,6 +20,7 @@ import { DEFAULT_TERMINAL_PREVIEW_LINES, expandKeyHint } from "../render/render-
|
|
|
20
20
|
import type { TspCardStatus, TspSpan, TspText, TspTone } from "@linxiraos/pi-wire";
|
|
21
21
|
import { card, node, span, text } from "../native/describe";
|
|
22
22
|
import type { NativeChild, NativeNode } from "../native/node";
|
|
23
|
+
import { runBox, runFoot, runInput, runOutput, type RunState } from "../tools/native-view";
|
|
23
24
|
|
|
24
25
|
/** Output rows shown while an execution is collapsed. */
|
|
25
26
|
export const PREVIEW_LINES = 20;
|
|
@@ -190,7 +191,7 @@ export interface ExecutionToolInput {
|
|
|
190
191
|
/** Tool name for the head icon (`bash`, `eval`). */
|
|
191
192
|
readonly name: string;
|
|
192
193
|
readonly title: string;
|
|
193
|
-
/** The command / cell source
|
|
194
|
+
/** The command / cell source: the run box's input and the head's Copy command. */
|
|
194
195
|
readonly command: string;
|
|
195
196
|
readonly lang: string;
|
|
196
197
|
/** Excluded from context (`!!`/`$$`). */
|
|
@@ -208,39 +209,55 @@ export interface ExecutionToolInput {
|
|
|
208
209
|
readonly artifactError?: OutputArtifactError;
|
|
209
210
|
}
|
|
210
211
|
|
|
212
|
+
const EXECUTION_RUN_STATE: Record<ExecutionStatus, RunState> = {
|
|
213
|
+
running: "running",
|
|
214
|
+
complete: "done",
|
|
215
|
+
cancelled: "cancelled",
|
|
216
|
+
error: "failed",
|
|
217
|
+
};
|
|
218
|
+
|
|
211
219
|
/**
|
|
212
|
-
* A user `!`/`$` run as the agent's `tool` frame (§6.6):
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
220
|
+
* A user `!`/`$` run as the agent's `tool` frame (§6.6): a head with a `you`
|
|
221
|
+
* badge (plus `not sent` when excluded from context) and the command for Copy
|
|
222
|
+
* command; the body is one run box — the source, the output as an `ansi` mini
|
|
223
|
+
* terminal following its tail, and the foot (state, time, truncation) — with
|
|
224
|
+
* any images below it. Timer, exit chip and cancelled note stay head data.
|
|
216
225
|
*/
|
|
217
226
|
export function describeExecutionTool(input: ExecutionToolInput): NativeNode {
|
|
218
227
|
const running = input.status === "running";
|
|
219
|
-
const
|
|
220
|
-
if (input.output) body.push(node("ansi", { text: input.output, follow: running }, undefined, "output"));
|
|
221
|
-
if (input.images) body.push(...input.images);
|
|
222
|
-
const notes: string[] = [];
|
|
223
|
-
if (input.truncation) notes.push(formatTruncationMetaNotice(input.truncation));
|
|
224
|
-
if (input.artifactError) notes.push(formatArtifactErrorNotice(input.artifactError));
|
|
225
|
-
if (notes.length > 0) {
|
|
226
|
-
body.push({
|
|
227
|
-
...text([span(notes.join(" · "), "muted")], { wrap: "word", role: "zeta.tool.notice" }),
|
|
228
|
-
key: "foot",
|
|
229
|
-
});
|
|
230
|
-
}
|
|
228
|
+
const shell = input.name === "bash";
|
|
231
229
|
const ms = Math.max(0, Math.round((input.endedAt ?? performance.now()) - input.startedAt));
|
|
230
|
+
const state = EXECUTION_RUN_STATE[input.status];
|
|
231
|
+
const box = runBox(
|
|
232
|
+
[
|
|
233
|
+
runInput(input.command, {
|
|
234
|
+
role: shell ? "zeta.tool.bash.command" : "zeta.tool.eval.input",
|
|
235
|
+
lang: input.lang,
|
|
236
|
+
wrap: shell,
|
|
237
|
+
}),
|
|
238
|
+
input.output.length > 0 &&
|
|
239
|
+
runOutput(input.output, {
|
|
240
|
+
role: shell ? "zeta.tool.bash.output" : "zeta.tool.eval.output",
|
|
241
|
+
previewLines: DEFAULT_TERMINAL_PREVIEW_LINES,
|
|
242
|
+
}),
|
|
243
|
+
runFoot({
|
|
244
|
+
state,
|
|
245
|
+
exitCode: input.exitCode,
|
|
246
|
+
elapsedMs: ms,
|
|
247
|
+
meta: { truncation: input.truncation, artifactError: input.artifactError },
|
|
248
|
+
}),
|
|
249
|
+
],
|
|
250
|
+
{ key: "run", tone: state === "failed" ? "error" : undefined },
|
|
251
|
+
);
|
|
232
252
|
const badges: { text: string; tone?: TspTone; title?: string }[] = [{ text: "you", tone: "user" }];
|
|
233
253
|
if (input.excluded) badges.push({ text: "not sent", title: "Not sent to the model", tone: "muted" });
|
|
234
|
-
const hasBody = body.length > 0;
|
|
235
254
|
return node(
|
|
236
255
|
"tool",
|
|
237
256
|
{
|
|
238
257
|
role: input.role,
|
|
239
258
|
name: input.name,
|
|
240
259
|
title: input.title,
|
|
241
|
-
|
|
242
|
-
targetKind: "command",
|
|
243
|
-
lang: input.lang,
|
|
260
|
+
command: input.command,
|
|
244
261
|
badges,
|
|
245
262
|
status: EXECUTION_CARD_STATUS[input.status],
|
|
246
263
|
age: running ? ms : undefined,
|
|
@@ -248,11 +265,11 @@ export function describeExecutionTool(input: ExecutionToolInput): NativeNode {
|
|
|
248
265
|
exit: input.status === "error" ? input.exitCode : undefined,
|
|
249
266
|
note: input.status === "cancelled" ? "cancelled" : undefined,
|
|
250
267
|
frame: "card",
|
|
251
|
-
collapsible:
|
|
252
|
-
collapsed:
|
|
253
|
-
preview:
|
|
268
|
+
collapsible: true,
|
|
269
|
+
collapsed: !input.expanded,
|
|
270
|
+
preview: "children",
|
|
254
271
|
},
|
|
255
|
-
|
|
272
|
+
[box, ...(input.images ?? [])],
|
|
256
273
|
);
|
|
257
274
|
}
|
|
258
275
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tool call's {@link ToolFigure} drawn under its card, the way assistant
|
|
3
|
+
* Markdown draws that fence: ```svg as an inline image ({@link SvgFigure}),
|
|
4
|
+
* redrawn as the body streams; ```mermaid as ASCII art once the body is
|
|
5
|
+
* final. The card already shows the source, so unlike the assistant's fence
|
|
6
|
+
* it never falls back to code: {@link FenceFigure.draws} turns down fences
|
|
7
|
+
* this terminal shows as code, and an svg that does not rasterize stays blank.
|
|
8
|
+
*/
|
|
9
|
+
import type { ImageBudget } from "../components/image";
|
|
10
|
+
import type { ToolFigure } from "../tools/renderer";
|
|
11
|
+
import type { Component } from "../tui";
|
|
12
|
+
/** Fence languages a {@link FenceFigure} draws. */
|
|
13
|
+
export type FenceFigureLang = "svg" | "mermaid";
|
|
14
|
+
export interface FenceFigureOptions {
|
|
15
|
+
/** Shared inline-image budget for an svg's rasters. */
|
|
16
|
+
budget?: ImageBudget;
|
|
17
|
+
/** The figure's rows changed outside a render: a raster landed. */
|
|
18
|
+
onChange: () => void;
|
|
19
|
+
}
|
|
20
|
+
export declare class FenceFigure implements Component {
|
|
21
|
+
#private;
|
|
22
|
+
/**
|
|
23
|
+
* Whether this terminal draws `figure` now: an svg where inline images show
|
|
24
|
+
* (`showImages` and a graphics protocol), a closed mermaid fence when
|
|
25
|
+
* diagram rendering is on and the source renders.
|
|
26
|
+
*/
|
|
27
|
+
static draws(figure: ToolFigure, options: {
|
|
28
|
+
showImages: boolean;
|
|
29
|
+
}): figure is ToolFigure & {
|
|
30
|
+
readonly lang: FenceFigureLang;
|
|
31
|
+
};
|
|
32
|
+
readonly lang: FenceFigureLang;
|
|
33
|
+
constructor(lang: FenceFigureLang, options: FenceFigureOptions);
|
|
34
|
+
/** Feed the fence as it stands; its `lang` is this figure's. */
|
|
35
|
+
update(figure: ToolFigure): void;
|
|
36
|
+
/** Whether a closed svg's raster is still on its way. */
|
|
37
|
+
get pending(): boolean;
|
|
38
|
+
/** The drawing; no rows while an svg draws, or when it does not. */
|
|
39
|
+
render(width: number): readonly string[];
|
|
40
|
+
invalidate(): void;
|
|
41
|
+
dispose(): void;
|
|
42
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tool call's {@link ToolFigure} drawn under its card, the way assistant
|
|
3
|
+
* Markdown draws that fence: ```svg as an inline image ({@link SvgFigure}),
|
|
4
|
+
* redrawn as the body streams; ```mermaid as ASCII art once the body is
|
|
5
|
+
* final. The card already shows the source, so unlike the assistant's fence
|
|
6
|
+
* it never falls back to code: {@link FenceFigure.draws} turns down fences
|
|
7
|
+
* this terminal shows as code, and an svg that does not rasterize stays blank.
|
|
8
|
+
*/
|
|
9
|
+
import type { ImageBudget } from "../components/image";
|
|
10
|
+
import { fencedCode, Markdown } from "../components/markdown";
|
|
11
|
+
import { TERMINAL } from "../terminal-capabilities";
|
|
12
|
+
import { getMarkdownTheme } from "../theme";
|
|
13
|
+
import type { ToolFigure } from "../tools/renderer";
|
|
14
|
+
import type { Component } from "../tui";
|
|
15
|
+
import { SvgFigure, svgFigureRendering } from "./svg-figure";
|
|
16
|
+
|
|
17
|
+
/** Fence languages a {@link FenceFigure} draws. */
|
|
18
|
+
export type FenceFigureLang = "svg" | "mermaid";
|
|
19
|
+
|
|
20
|
+
export interface FenceFigureOptions {
|
|
21
|
+
/** Shared inline-image budget for an svg's rasters. */
|
|
22
|
+
budget?: ImageBudget;
|
|
23
|
+
/** The figure's rows changed outside a render: a raster landed. */
|
|
24
|
+
onChange: () => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class FenceFigure implements Component {
|
|
28
|
+
/**
|
|
29
|
+
* Whether this terminal draws `figure` now: an svg where inline images show
|
|
30
|
+
* (`showImages` and a graphics protocol), a closed mermaid fence when
|
|
31
|
+
* diagram rendering is on and the source renders.
|
|
32
|
+
*/
|
|
33
|
+
static draws(
|
|
34
|
+
figure: ToolFigure,
|
|
35
|
+
options: { showImages: boolean },
|
|
36
|
+
): figure is ToolFigure & { readonly lang: FenceFigureLang } {
|
|
37
|
+
if (figure.lang === "svg") return options.showImages && TERMINAL.imageProtocol !== null && svgFigureRendering();
|
|
38
|
+
if (figure.lang !== "mermaid" || !figure.closed) return false;
|
|
39
|
+
return getMarkdownTheme().resolveMermaidAscii?.(figure.source.trimEnd()) != null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
readonly lang: FenceFigureLang;
|
|
43
|
+
readonly #svg: SvgFigure | undefined;
|
|
44
|
+
#source = "";
|
|
45
|
+
/** The mermaid fence as assistant Markdown renders it; rebuilt after a theme change. */
|
|
46
|
+
#diagram: Markdown | undefined;
|
|
47
|
+
|
|
48
|
+
constructor(lang: FenceFigureLang, options: FenceFigureOptions) {
|
|
49
|
+
this.lang = lang;
|
|
50
|
+
if (lang === "svg") this.#svg = new SvgFigure({ budget: options.budget, onChange: options.onChange });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Feed the fence as it stands; its `lang` is this figure's. */
|
|
54
|
+
update(figure: ToolFigure): void {
|
|
55
|
+
if (figure.source !== this.#source) this.#diagram = undefined;
|
|
56
|
+
this.#source = figure.source;
|
|
57
|
+
this.#svg?.update(figure.source, figure.closed);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Whether a closed svg's raster is still on its way. */
|
|
61
|
+
get pending(): boolean {
|
|
62
|
+
return this.#svg?.pending === true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The drawing; no rows while an svg draws, or when it does not. */
|
|
66
|
+
render(width: number): readonly string[] {
|
|
67
|
+
if (this.#svg) return this.#svg.render(width);
|
|
68
|
+
this.#diagram ??= new Markdown(fencedCode("mermaid", this.#source), 1, 0, getMarkdownTheme());
|
|
69
|
+
return this.#diagram.render(width);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
invalidate(): void {
|
|
73
|
+
this.#svg?.invalidate();
|
|
74
|
+
this.#diagram = undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
dispose(): void {
|
|
78
|
+
this.#svg?.dispose();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ImageBudget } from "../components/image";
|
|
2
|
+
import type { Markdown } from "../components/markdown";
|
|
3
|
+
import { Container } from "../tui";
|
|
4
|
+
export interface FigureMarkdownOptions {
|
|
5
|
+
/** Markdown for one prose run (and a failed figure's code fallback); FigureMarkdown drives its transience. */
|
|
6
|
+
markdown: (text: string) => Markdown;
|
|
7
|
+
/** Draw charts under numeric tables; off for transcripts that are not the main session's. */
|
|
8
|
+
charts: boolean;
|
|
9
|
+
/** Shared inline-image budget for the figures. */
|
|
10
|
+
budget?: ImageBudget;
|
|
11
|
+
/** A figure's rows changed outside a text update (raster landed, fell back to code). */
|
|
12
|
+
onChange: () => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Assistant Markdown whose top-level ```svg fences are lifted out of the prose
|
|
16
|
+
* and drawn as images ({@link SvgFigure}), and whose numeric tables get a chart
|
|
17
|
+
* drawn under them ({@link TableChartFigure}), with ordinary {@link Markdown}
|
|
18
|
+
* for the prose between them. Stands in for Markdown on an assistant text
|
|
19
|
+
* block that holds an svg fence or a chartable table: {@link setText} streams
|
|
20
|
+
* in place, reusing every part whose kind is unchanged, and
|
|
21
|
+
* {@link transientRenderCache} marks the block's tail as still streaming — the
|
|
22
|
+
* last prose run renders transient, the last figure throttles its rasters
|
|
23
|
+
* until its fence closes, and a table at the tail waits for its last row.
|
|
24
|
+
*/
|
|
25
|
+
export declare class FigureMarkdown extends Container {
|
|
26
|
+
#private;
|
|
27
|
+
constructor(text: string, options: FigureMarkdownOptions);
|
|
28
|
+
/** Replace the source; returns whether it changed. */
|
|
29
|
+
setText(text: string): boolean;
|
|
30
|
+
get transientRenderCache(): boolean;
|
|
31
|
+
set transientRenderCache(value: boolean);
|
|
32
|
+
/**
|
|
33
|
+
* The trimmed prose ahead of the first figure, or "" when the block opens
|
|
34
|
+
* with one. These are the only rows plain Markdown reproduces byte for
|
|
35
|
+
* byte, so they are all a transcript may publish ahead of the figure.
|
|
36
|
+
*/
|
|
37
|
+
get leadingProse(): string;
|
|
38
|
+
/** Whether a figure's final source still waits for its raster, or a chart for its pick or raster. */
|
|
39
|
+
get pending(): boolean;
|
|
40
|
+
/** Rebuild the prose runs through the Markdown factory after its theme changed; figures keep their rasters. */
|
|
41
|
+
restyle(): void;
|
|
42
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { Tokens } from "@linxiraos/pi-utils/marked";
|
|
2
|
+
import type { ImageBudget } from "../components/image";
|
|
3
|
+
import type { Markdown } from "../components/markdown";
|
|
4
|
+
import { Spacer } from "../components/spacer";
|
|
5
|
+
import { Container } from "../tui";
|
|
6
|
+
import { SvgFigure, svgFigureRendering } from "./svg-figure";
|
|
7
|
+
import { type FigureSegment, splitSvgFences } from "./svg-source";
|
|
8
|
+
import { type ChartSegment, hasChartTable, splitTableCharts, TableChartFigure } from "./table-chart";
|
|
9
|
+
|
|
10
|
+
export interface FigureMarkdownOptions {
|
|
11
|
+
/** Markdown for one prose run (and a failed figure's code fallback); FigureMarkdown drives its transience. */
|
|
12
|
+
markdown: (text: string) => Markdown;
|
|
13
|
+
/** Draw charts under numeric tables; off for transcripts that are not the main session's. */
|
|
14
|
+
charts: boolean;
|
|
15
|
+
/** Shared inline-image budget for the figures. */
|
|
16
|
+
budget?: ImageBudget;
|
|
17
|
+
/** A figure's rows changed outside a text update (raster landed, fell back to code). */
|
|
18
|
+
onChange: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type Part =
|
|
22
|
+
| { readonly kind: "markdown"; readonly md: Markdown; text: string }
|
|
23
|
+
| { readonly kind: "svg"; readonly figure: SvgFigure; source: string; closed: boolean }
|
|
24
|
+
| { readonly kind: "chart"; readonly figure: TableChartFigure; table: Tokens.Table };
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Assistant Markdown whose top-level ```svg fences are lifted out of the prose
|
|
28
|
+
* and drawn as images ({@link SvgFigure}), and whose numeric tables get a chart
|
|
29
|
+
* drawn under them ({@link TableChartFigure}), with ordinary {@link Markdown}
|
|
30
|
+
* for the prose between them. Stands in for Markdown on an assistant text
|
|
31
|
+
* block that holds an svg fence or a chartable table: {@link setText} streams
|
|
32
|
+
* in place, reusing every part whose kind is unchanged, and
|
|
33
|
+
* {@link transientRenderCache} marks the block's tail as still streaming — the
|
|
34
|
+
* last prose run renders transient, the last figure throttles its rasters
|
|
35
|
+
* until its fence closes, and a table at the tail waits for its last row.
|
|
36
|
+
*/
|
|
37
|
+
export class FigureMarkdown extends Container {
|
|
38
|
+
readonly #options: FigureMarkdownOptions;
|
|
39
|
+
#text = "";
|
|
40
|
+
#transient = false;
|
|
41
|
+
#parts: Part[] = [];
|
|
42
|
+
|
|
43
|
+
constructor(text: string, options: FigureMarkdownOptions) {
|
|
44
|
+
super();
|
|
45
|
+
this.#options = options;
|
|
46
|
+
this.setText(text);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Replace the source; returns whether it changed. */
|
|
50
|
+
setText(text: string): boolean {
|
|
51
|
+
if (text === this.#text) return false;
|
|
52
|
+
this.#text = text;
|
|
53
|
+
this.#reconcile();
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get transientRenderCache(): boolean {
|
|
58
|
+
return this.#transient;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
set transientRenderCache(value: boolean) {
|
|
62
|
+
if (this.#transient === value) return;
|
|
63
|
+
this.#transient = value;
|
|
64
|
+
// The end of the stream completes a tail table, which may now get its chart.
|
|
65
|
+
this.#reconcile();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The trimmed prose ahead of the first figure, or "" when the block opens
|
|
70
|
+
* with one. These are the only rows plain Markdown reproduces byte for
|
|
71
|
+
* byte, so they are all a transcript may publish ahead of the figure.
|
|
72
|
+
*/
|
|
73
|
+
get leadingProse(): string {
|
|
74
|
+
const first = this.#parts[0];
|
|
75
|
+
return first?.kind === "markdown" ? first.text : "";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Whether a figure's final source still waits for its raster, or a chart for its pick or raster. */
|
|
79
|
+
get pending(): boolean {
|
|
80
|
+
return this.#parts.some(part => part.kind !== "markdown" && part.figure.pending);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Rebuild the prose runs through the Markdown factory after its theme changed; figures keep their rasters. */
|
|
84
|
+
restyle(): void {
|
|
85
|
+
this.#parts = this.#parts.map(part =>
|
|
86
|
+
part.kind === "markdown" ? { kind: "markdown", md: this.#options.markdown(part.text), text: part.text } : part,
|
|
87
|
+
);
|
|
88
|
+
this.#mount();
|
|
89
|
+
this.#syncTails();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#reconcile(): void {
|
|
93
|
+
const previous = this.#parts;
|
|
94
|
+
const segments = this.#segments();
|
|
95
|
+
let reshaped = previous.length !== segments.length;
|
|
96
|
+
this.#parts = segments.map((segment, index): Part => {
|
|
97
|
+
const old = previous[index];
|
|
98
|
+
if (segment.kind === "chart") {
|
|
99
|
+
if (old?.kind === "chart") {
|
|
100
|
+
old.table = segment.table;
|
|
101
|
+
return old;
|
|
102
|
+
}
|
|
103
|
+
reshaped = true;
|
|
104
|
+
const { budget, onChange } = this.#options;
|
|
105
|
+
return { kind: "chart", figure: new TableChartFigure({ budget, onChange }), table: segment.table };
|
|
106
|
+
}
|
|
107
|
+
if (segment.kind === "markdown") {
|
|
108
|
+
const text = segment.text.trim();
|
|
109
|
+
if (old?.kind === "markdown") {
|
|
110
|
+
old.md.setText(text);
|
|
111
|
+
old.text = text;
|
|
112
|
+
return old;
|
|
113
|
+
}
|
|
114
|
+
reshaped = true;
|
|
115
|
+
return { kind: "markdown", md: this.#options.markdown(text), text };
|
|
116
|
+
}
|
|
117
|
+
if (old?.kind === "svg") {
|
|
118
|
+
old.source = segment.source;
|
|
119
|
+
old.closed = segment.closed;
|
|
120
|
+
return old;
|
|
121
|
+
}
|
|
122
|
+
reshaped = true;
|
|
123
|
+
const { markdown, budget, onChange } = this.#options;
|
|
124
|
+
return {
|
|
125
|
+
kind: "svg",
|
|
126
|
+
figure: new SvgFigure({ markdown, budget, onChange }),
|
|
127
|
+
source: segment.source,
|
|
128
|
+
closed: segment.closed,
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
if (reshaped) {
|
|
132
|
+
for (const old of previous) {
|
|
133
|
+
if (old.kind !== "markdown" && !this.#parts.includes(old)) old.figure.dispose();
|
|
134
|
+
}
|
|
135
|
+
this.#mount();
|
|
136
|
+
}
|
|
137
|
+
this.#syncTails();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The block as prose, ```svg fences (when figures are on) and charts after
|
|
142
|
+
* complete tables (when charts are on); only the last run can still stream.
|
|
143
|
+
*/
|
|
144
|
+
#segments(): (FigureSegment | ChartSegment)[] {
|
|
145
|
+
const fences: FigureSegment[] = svgFigureRendering()
|
|
146
|
+
? splitSvgFences(this.#text)
|
|
147
|
+
: [{ kind: "markdown", text: this.#text }];
|
|
148
|
+
if (!this.#options.charts || !hasChartTable(this.#text)) return fences;
|
|
149
|
+
const last = fences.length - 1;
|
|
150
|
+
return fences.flatMap((segment, index): (FigureSegment | ChartSegment)[] =>
|
|
151
|
+
segment.kind === "markdown" ? splitTableCharts(segment.text, this.#transient && index === last) : [segment],
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Mount the parts as children, a blank row between neighbours; a chart draws its own when it has rows. */
|
|
156
|
+
#mount(): void {
|
|
157
|
+
this.clear();
|
|
158
|
+
this.#parts.forEach((part, index) => {
|
|
159
|
+
if (index > 0 && part.kind !== "chart") this.addChild(new Spacer(1));
|
|
160
|
+
this.addChild(part.kind === "markdown" ? part.md : part.figure);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Push sources and streaming state down: only the last part can still be streaming. */
|
|
165
|
+
#syncTails(): void {
|
|
166
|
+
const last = this.#parts.length - 1;
|
|
167
|
+
this.#parts.forEach((part, index) => {
|
|
168
|
+
const streaming = this.#transient && index === last;
|
|
169
|
+
if (part.kind === "markdown") part.md.transientRenderCache = streaming;
|
|
170
|
+
else if (part.kind === "svg") part.figure.update(part.source, part.closed || !streaming);
|
|
171
|
+
else part.figure.update(part.table);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
package/src/chat/messages.d.ts
CHANGED
|
@@ -64,7 +64,7 @@ export interface SkillPromptDetails {
|
|
|
64
64
|
* `ui-helpers.addMessageToChat` (renderers), `AgentHubOverlayComponent
|
|
65
65
|
* #buildTranscriptLines`, `runPrintMode`, and `AcpAgent#replayAssistantMessage`
|
|
66
66
|
* (fallback error emission) read it via `isSilentAbort`. */
|
|
67
|
-
export declare const SILENT_ABORT_MARKER = "
|
|
67
|
+
export declare const SILENT_ABORT_MARKER = "__zeta.silent_abort__";
|
|
68
68
|
/** Type-guard for silent aborts. Renderers MUST call this helper so structured
|
|
69
69
|
* `errorId` and legacy persisted marker messages stay in lockstep. */
|
|
70
70
|
export declare function isSilentAbort(message: Pick<AssistantMessage, "errorId" | "errorMessage">): boolean;
|
package/src/chat/messages.ts
CHANGED
|
@@ -86,7 +86,7 @@ export interface SkillPromptDetails {
|
|
|
86
86
|
* `ui-helpers.addMessageToChat` (renderers), `AgentHubOverlayComponent
|
|
87
87
|
* #buildTranscriptLines`, `runPrintMode`, and `AcpAgent#replayAssistantMessage`
|
|
88
88
|
* (fallback error emission) read it via `isSilentAbort`. */
|
|
89
|
-
export const SILENT_ABORT_MARKER = "
|
|
89
|
+
export const SILENT_ABORT_MARKER = "__zeta.silent_abort__";
|
|
90
90
|
|
|
91
91
|
/** Type-guard for silent aborts. Renderers MUST call this helper so structured
|
|
92
92
|
* `errorId` and legacy persisted marker messages stay in lockstep. */
|
|
@@ -1143,6 +1143,10 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
|
|
|
1143
1143
|
const title = pathDisplay ? `Read ${pathDisplay}` : "Read";
|
|
1144
1144
|
let cachedWidth: number | undefined;
|
|
1145
1145
|
let cachedLines: string[] | undefined;
|
|
1146
|
+
const dropCache = () => {
|
|
1147
|
+
cachedWidth = undefined;
|
|
1148
|
+
cachedLines = undefined;
|
|
1149
|
+
};
|
|
1146
1150
|
const expanded = this.#expanded;
|
|
1147
1151
|
const component: Component = {
|
|
1148
1152
|
render: (width: number) => {
|
|
@@ -1164,10 +1168,8 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
|
|
|
1164
1168
|
cachedWidth = width;
|
|
1165
1169
|
return cachedLines;
|
|
1166
1170
|
},
|
|
1167
|
-
invalidate:
|
|
1168
|
-
|
|
1169
|
-
cachedLines = undefined;
|
|
1170
|
-
},
|
|
1171
|
+
invalidate: dropCache,
|
|
1172
|
+
releaseRenderCaches: dropCache,
|
|
1171
1173
|
};
|
|
1172
1174
|
this.addChild(component);
|
|
1173
1175
|
}
|
|
@@ -286,6 +286,12 @@ class SkillCallout implements Component {
|
|
|
286
286
|
this.#lines = undefined;
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
releaseRenderCaches(): void {
|
|
290
|
+
this.#source = undefined;
|
|
291
|
+
this.#lines = undefined;
|
|
292
|
+
this.#box.releaseRenderCaches();
|
|
293
|
+
}
|
|
294
|
+
|
|
289
295
|
render(width: number): readonly string[] {
|
|
290
296
|
const inner = this.#box.render(Math.max(1, width - 1));
|
|
291
297
|
if (this.#source === inner && this.#lines !== undefined) return this.#lines;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ImageBudget } from "../components/image";
|
|
2
|
+
import { type Markdown } from "../components/markdown";
|
|
3
|
+
import type { Component } from "../tui";
|
|
4
|
+
/** The active theme's color per figure token, for resolving a figure with `prepareSvg`. */
|
|
5
|
+
export declare function svgFigurePalette(): Record<string, string>;
|
|
6
|
+
/** Turn lifting ```svg fences into images on or off (the host's `tui.renderSvg`); the host rebuilds the transcript after. */
|
|
7
|
+
export declare function setSvgFigureRendering(enabled: boolean): void;
|
|
8
|
+
/** Whether assistant ```svg fences render as images where the terminal can show them. */
|
|
9
|
+
export declare function svgFigureRendering(): boolean;
|
|
10
|
+
export interface SvgFigureOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Markdown for the fenced-code fallback shown when the final source does not
|
|
13
|
+
* render. Without it the figure decorates content shown elsewhere (a chart
|
|
14
|
+
* under its table): it stays blank until drawn, and when it cannot be.
|
|
15
|
+
*/
|
|
16
|
+
markdown?: (text: string) => Markdown;
|
|
17
|
+
/** Shared inline-image budget; superseded rasters are released from it. */
|
|
18
|
+
budget?: ImageBudget;
|
|
19
|
+
/** The figure's rows changed outside a text update: a raster landed or rendering fell back to code. */
|
|
20
|
+
onChange: () => void;
|
|
21
|
+
}
|
|
22
|
+
export declare class SvgFigure implements Component {
|
|
23
|
+
#private;
|
|
24
|
+
constructor(options: SvgFigureOptions);
|
|
25
|
+
/** Feed the fence body; `final` once the fence closed or the message stopped streaming. */
|
|
26
|
+
update(source: string, final: boolean): void;
|
|
27
|
+
/** Whether the final source still waits for its raster (or for failing to render). */
|
|
28
|
+
get pending(): boolean;
|
|
29
|
+
render(width: number): readonly string[];
|
|
30
|
+
invalidate(): void;
|
|
31
|
+
dispose(): void;
|
|
32
|
+
debugState(): Record<string, unknown>;
|
|
33
|
+
}
|