@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/theme/schema.d.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import type { SpinnerFramesOverride } from "./symbols";
|
|
2
2
|
export type ColorValue = string | number;
|
|
3
|
+
/**
|
|
4
|
+
* Tokens a theme is allowed to omit. They resolve to the terminal default
|
|
5
|
+
* foreground, so `Theme.fg()` stays total for callers that paint a token a theme
|
|
6
|
+
* never declared (e.g. a `modelTags.<role>.color` reference) while
|
|
7
|
+
* `Theme.hasColor()` still reports them as unset.
|
|
8
|
+
*/
|
|
9
|
+
export declare const OPTIONAL_THEME_COLOR_RECORD: {
|
|
10
|
+
assistantMessageText: true;
|
|
11
|
+
};
|
|
3
12
|
export interface ThemeJson {
|
|
4
13
|
$schema?: string;
|
|
5
14
|
name: string;
|
|
6
15
|
vars?: Record<string, ColorValue>;
|
|
7
|
-
colors: Omit<Record<ThemeColor | ThemeBg, ColorValue>, "thinkingMax"> & {
|
|
16
|
+
colors: Omit<Record<ThemeColor | ThemeBg, ColorValue>, "thinkingMax" | keyof typeof OPTIONAL_THEME_COLOR_RECORD> & Partial<Record<keyof typeof OPTIONAL_THEME_COLOR_RECORD, ColorValue>> & {
|
|
8
17
|
thinkingMax?: ColorValue;
|
|
9
18
|
};
|
|
10
19
|
export?: {
|
|
@@ -36,7 +45,7 @@ export interface ThemeJson {
|
|
|
36
45
|
spinnerFrames?: SpinnerFramesOverride;
|
|
37
46
|
};
|
|
38
47
|
}
|
|
39
|
-
export type ThemeColor = "accent" | "border" | "borderAccent" | "borderMuted" | "success" | "error" | "warning" | "muted" | "dim" | "text" | "thinkingText" | "userMessageText" | "customMessageText" | "customMessageLabel" | "toolTitle" | "toolOutput" | "mdHeading" | "mdLink" | "mdLinkUrl" | "mdCode" | "mdCodeBlock" | "mdCodeBlockBorder" | "mdQuote" | "mdQuoteBorder" | "mdHr" | "mdListBullet" | "toolDiffAdded" | "toolDiffRemoved" | "toolDiffContext" | "syntaxComment" | "syntaxKeyword" | "syntaxFunction" | "syntaxVariable" | "syntaxString" | "syntaxNumber" | "syntaxType" | "syntaxOperator" | "syntaxPunctuation" | "thinkingOff" | "thinkingMinimal" | "thinkingLow" | "thinkingMedium" | "thinkingHigh" | "thinkingXhigh" | "thinkingMax" | "bashMode" | "pythonMode" | "statusLineSep" | "statusLineModel" | "statusLinePath" | "statusLineGitClean" | "statusLineGitDirty" | "statusLineContext" | "statusLineSpend" | "statusLineStaged" | "statusLineDirty" | "statusLineUntracked" | "statusLineOutput" | "statusLineCost" | "statusLineSubagents";
|
|
48
|
+
export type ThemeColor = "accent" | "border" | "borderAccent" | "borderMuted" | "success" | "error" | "warning" | "muted" | "dim" | "text" | "assistantMessageText" | "thinkingText" | "userMessageText" | "customMessageText" | "customMessageLabel" | "toolTitle" | "toolOutput" | "mdHeading" | "mdLink" | "mdLinkUrl" | "mdCode" | "mdCodeBlock" | "mdCodeBlockBorder" | "mdQuote" | "mdQuoteBorder" | "mdHr" | "mdListBullet" | "toolDiffAdded" | "toolDiffRemoved" | "toolDiffContext" | "syntaxComment" | "syntaxKeyword" | "syntaxFunction" | "syntaxVariable" | "syntaxString" | "syntaxNumber" | "syntaxType" | "syntaxOperator" | "syntaxPunctuation" | "thinkingOff" | "thinkingMinimal" | "thinkingLow" | "thinkingMedium" | "thinkingHigh" | "thinkingXhigh" | "thinkingMax" | "bashMode" | "pythonMode" | "statusLineSep" | "statusLineModel" | "statusLinePath" | "statusLineGitClean" | "statusLineGitDirty" | "statusLineContext" | "statusLineSpend" | "statusLineStaged" | "statusLineDirty" | "statusLineUntracked" | "statusLineOutput" | "statusLineCost" | "statusLineSubagents";
|
|
40
49
|
/** Check if a string is a valid ThemeColor value */
|
|
41
50
|
export declare function isValidThemeColor(color: string): color is ThemeColor;
|
|
42
51
|
export type ThemeBg = "selectedBg" | "userMessageBg" | "customMessageBg" | "toolPendingBg" | "toolSuccessBg" | "toolErrorBg" | "statusLineBg";
|
package/src/theme/schema.ts
CHANGED
|
@@ -6,11 +6,22 @@ import type { SpinnerFramesOverride } from "./symbols";
|
|
|
6
6
|
|
|
7
7
|
export type ColorValue = string | number;
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Tokens a theme is allowed to omit. They resolve to the terminal default
|
|
11
|
+
* foreground, so `Theme.fg()` stays total for callers that paint a token a theme
|
|
12
|
+
* never declared (e.g. a `modelTags.<role>.color` reference) while
|
|
13
|
+
* `Theme.hasColor()` still reports them as unset.
|
|
14
|
+
*/
|
|
15
|
+
export const OPTIONAL_THEME_COLOR_RECORD = {
|
|
16
|
+
assistantMessageText: true,
|
|
17
|
+
} satisfies Partial<Record<ThemeColor, true>>;
|
|
18
|
+
|
|
9
19
|
export interface ThemeJson {
|
|
10
20
|
$schema?: string;
|
|
11
21
|
name: string;
|
|
12
22
|
vars?: Record<string, ColorValue>;
|
|
13
|
-
colors: Omit<Record<ThemeColor | ThemeBg, ColorValue>, "thinkingMax"
|
|
23
|
+
colors: Omit<Record<ThemeColor | ThemeBg, ColorValue>, "thinkingMax" | keyof typeof OPTIONAL_THEME_COLOR_RECORD> &
|
|
24
|
+
Partial<Record<keyof typeof OPTIONAL_THEME_COLOR_RECORD, ColorValue>> & { thinkingMax?: ColorValue };
|
|
14
25
|
export?: {
|
|
15
26
|
pageBg?: ColorValue;
|
|
16
27
|
cardBg?: ColorValue;
|
|
@@ -52,6 +63,7 @@ export type ThemeColor =
|
|
|
52
63
|
| "muted"
|
|
53
64
|
| "dim"
|
|
54
65
|
| "text"
|
|
66
|
+
| "assistantMessageText"
|
|
55
67
|
| "thinkingText"
|
|
56
68
|
| "userMessageText"
|
|
57
69
|
| "customMessageText"
|
|
@@ -115,6 +127,7 @@ const THEME_COLOR_RECORD = {
|
|
|
115
127
|
muted: true,
|
|
116
128
|
dim: true,
|
|
117
129
|
text: true,
|
|
130
|
+
assistantMessageText: true,
|
|
118
131
|
thinkingText: true,
|
|
119
132
|
userMessageText: true,
|
|
120
133
|
customMessageText: true,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TERMINAL } from "../terminal-capabilities";
|
|
2
|
-
import { hexToOklch, oklchCusp, oklchToHex, relativeLuminance } from "@linxiraos/pi-utils";
|
|
2
|
+
import { hexToOklch, hueDistance, oklchCusp, oklchToHex, relativeLuminance } from "@linxiraos/pi-utils";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Derive a stable 32-bit hash from a string using djb2.
|
|
@@ -49,12 +49,6 @@ const MIN_HUE_DISTANCE = 10;
|
|
|
49
49
|
/** OKLCH chroma threshold below which hue is meaningless (near-gray). */
|
|
50
50
|
const MIN_CHROMA_FOR_HUE = 0.03;
|
|
51
51
|
|
|
52
|
-
/** Angular distance between two hue values (0-360). */
|
|
53
|
-
function hueDistance(a: number, b: number): number {
|
|
54
|
-
const d = Math.abs(a - b);
|
|
55
|
-
return Math.min(d, 360 - d);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
52
|
/**
|
|
59
53
|
* Parse OKLCH hue (0-360) from a hex color string.
|
|
60
54
|
* Returns undefined for near-gray colors where hue is not meaningful.
|
package/src/theme/symbols.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export type SymbolPreset = "unicode" | "nerd" | "ascii";
|
|
|
2
2
|
/**
|
|
3
3
|
* All available symbol keys organized by category.
|
|
4
4
|
*/
|
|
5
|
-
export type SymbolKey = "status.success" | "status.error" | "status.warning" | "status.info" | "status.pending" | "status.disabled" | "status.enabled" | "status.running" | "status.shadowed" | "status.aborted" | "status.done" | "nav.cursor" | "nav.selected" | "nav.expand" | "nav.collapse" | "nav.back" | "tree.branch" | "tree.last" | "tree.vertical" | "tree.horizontal" | "tree.hook" | "progress.filled" | "progress.empty" | "context.speculation" | "context.compaction" | "boxRound.topLeft" | "boxRound.topRight" | "boxRound.bottomLeft" | "boxRound.bottomRight" | "boxRound.horizontal" | "boxRound.vertical" | "boxDotted.horizontal" | "boxDotted.vertical" | "boxSharp.topLeft" | "boxSharp.topRight" | "boxSharp.bottomLeft" | "boxSharp.bottomRight" | "boxSharp.horizontal" | "boxSharp.vertical" | "boxSharp.cross" | "boxSharp.teeDown" | "boxSharp.teeUp" | "boxSharp.teeRight" | "boxSharp.teeLeft" | "sep.powerline" | "sep.powerlineThin" | "sep.powerlineLeft" | "sep.powerlineRight" | "sep.powerlineThinLeft" | "sep.powerlineThinRight" | "sep.powerlineCapLeft" | "sep.block" | "sep.space" | "sep.asciiLeft" | "sep.asciiRight" | "sep.dot" | "sep.slash" | "sep.pipe" | "icon.model" | "icon.plan" | "icon.prewalk" | "icon.goal" | "icon.pause" | "icon.loop" | "icon.folder" | "icon.worktree" | "icon.search" | "icon.scratchFolder" | "icon.file" | "icon.git" | "icon.branch" | "icon.pr" | "icon.pin" | "icon.tokens" | "icon.context" | "icon.cost" | "icon.subscription" | "icon.advisor" | "icon.advisorClosed" | "icon.time" | "icon.omp" | "icon.ghost" | "icon.agents" | "icon.job" | "icon.cache" | "icon.cacheMiss" | "icon.input" | "icon.output" | "icon.throughput" | "icon.intelligence" | "icon.host" | "icon.session" | "icon.package" | "icon.warning" | "icon.rewind" | "icon.auto" | "icon.fast" | "icon.extensionSkill" | "icon.extensionTool" | "icon.extensionSlashCommand" | "icon.extensionMcp" | "icon.extensionRule" | "icon.extensionHook" | "icon.extensionPrompt" | "icon.extensionContextFile" | "icon.extensionInstruction" | "icon.vimNormal" | "icon.vimInsert" | "icon.vimVisual" | "icon.vimVisualLine" | "cmd.action" | "cmd.prompt" | "cmd.extension" | "cmd.settings" | "cmd.gear" | "cmd.shield" | "cmd.wave" | "cmd.compass" | "cmd.inbox" | "cmd.swap" | "cmd.expand" | "cmd.computer" | "cmd.eye" | "cmd.todo" | "cmd.stats" | "cmd.news" | "cmd.keyboard" | "cmd.export" | "cmd.clipboard" | "cmd.share" | "cmd.broadcast" | "cmd.globe" | "cmd.copy" | "cmd.plus" | "cmd.restart" | "cmd.eraser" | "cmd.trash" | "cmd.compress" | "cmd.vibrate" | "cmd.handoff" | "cmd.history" | "cmd.question" | "cmd.rocket" | "cmd.stethoscope" | "cmd.redo" | "cmd.bug" | "cmd.memory" | "cmd.pencil" | "cmd.folderMove" | "cmd.folderPlus" | "cmd.folderMinus" | "cmd.hammer" | "cmd.power" | "cmd.cart" | "icon.mic" | "icon.camera" | "thinking.minimal" | "thinking.low" | "thinking.medium" | "thinking.high" | "thinking.xhigh" | "thinking.max" | "thinking.autoPending" | "checkbox.checked" | "checkbox.unchecked" | "radio.selected" | "radio.unselected" | "format.bullet" | "format.dash" | "format.bracketLeft" | "format.bracketRight" | "md.quoteBorder" | "md.hrChar" | "md.bullet" | "md.colorSwatch" | "advisor.rail" | "skill.rail" | "lang.default" | "lang.typescript" | "lang.javascript" | "lang.python" | "lang.rust" | "lang.go" | "lang.java" | "lang.c" | "lang.cpp" | "lang.csharp" | "lang.ruby" | "lang.julia" | "lang.php" | "lang.swift" | "lang.kotlin" | "lang.shell" | "lang.html" | "lang.css" | "lang.json" | "lang.yaml" | "lang.markdown" | "lang.sql" | "lang.docker" | "lang.lua" | "lang.text" | "lang.env" | "lang.toml" | "lang.xml" | "lang.ini" | "lang.conf" | "lang.log" | "lang.csv" | "lang.tsv" | "lang.image" | "lang.pdf" | "lang.archive" | "lang.binary" | "chip.image" | "chip.video" | "chip.paste" | "tab.appearance" | "tab.model" | "tab.interaction" | "tab.context" | "tab.files" | "tab.shell" | "tab.tools" | "tab.memory" | "tab.tasks" | "tab.providers" | "tool.write" | "tool.edit" | "tool.bash" | "tool.ssh" | "tool.lsp" | "tool.gh" | "tool.webSearch" | "tool.exa" | "tool.browser" | "tool.eval" | "tool.debug" | "tool.mcp" | "tool.job" | "tool.launch" | "tool.task" | "tool.todo" | "tool.memory" | "tool.ask" | "tool.resolve" | "tool.review" | "tool.goal" | "tool.irc" | "tool.delete" | "tool.move" | "key.ctrl" | "key.ctrlMac" | "key.shift" | "key.alt" | "key.altMac" | "key.super" | "key.superMac" | "key.joiner" | "key.enter" | "key.esc" | "key.tab" | "key.backspace" | "key.delete" | "key.space" | "key.up" | "key.down" | "key.left" | "key.right";
|
|
5
|
+
export type SymbolKey = "status.success" | "status.error" | "status.warning" | "status.info" | "status.pending" | "status.disabled" | "status.enabled" | "status.running" | "status.shadowed" | "status.aborted" | "status.done" | "nav.cursor" | "nav.selected" | "nav.expand" | "nav.collapse" | "nav.back" | "tree.branch" | "tree.last" | "tree.vertical" | "tree.horizontal" | "tree.hook" | "progress.filled" | "progress.empty" | "context.speculation" | "context.compaction" | "boxRound.topLeft" | "boxRound.topRight" | "boxRound.bottomLeft" | "boxRound.bottomRight" | "boxRound.horizontal" | "boxRound.vertical" | "boxDotted.horizontal" | "boxDotted.vertical" | "boxSharp.topLeft" | "boxSharp.topRight" | "boxSharp.bottomLeft" | "boxSharp.bottomRight" | "boxSharp.horizontal" | "boxSharp.vertical" | "boxSharp.cross" | "boxSharp.teeDown" | "boxSharp.teeUp" | "boxSharp.teeRight" | "boxSharp.teeLeft" | "sep.powerline" | "sep.powerlineThin" | "sep.powerlineLeft" | "sep.powerlineRight" | "sep.powerlineThinLeft" | "sep.powerlineThinRight" | "sep.powerlineCapLeft" | "sep.block" | "sep.space" | "sep.asciiLeft" | "sep.asciiRight" | "sep.dot" | "sep.slash" | "sep.pipe" | "icon.model" | "icon.plan" | "icon.prewalk" | "icon.goal" | "icon.pause" | "icon.loop" | "icon.folder" | "icon.worktree" | "icon.search" | "icon.scratchFolder" | "icon.file" | "icon.git" | "icon.branch" | "icon.pr" | "icon.pin" | "icon.tokens" | "icon.context" | "icon.cost" | "icon.subscription" | "icon.advisor" | "icon.advisorClosed" | "icon.time" | "icon.omp" | "icon.ghost" | "icon.agents" | "icon.job" | "icon.cache" | "icon.cacheMiss" | "icon.input" | "icon.output" | "icon.throughput" | "icon.intelligence" | "icon.host" | "icon.session" | "icon.package" | "icon.warning" | "icon.rewind" | "icon.auto" | "icon.fast" | "icon.extensionSkill" | "icon.extensionTool" | "icon.extensionSlashCommand" | "icon.extensionMcp" | "icon.extensionRule" | "icon.extensionHook" | "icon.extensionPrompt" | "icon.extensionContextFile" | "icon.extensionInstruction" | "icon.vimNormal" | "icon.vimInsert" | "icon.vimVisual" | "icon.vimVisualLine" | "icon.vimReplace" | "cmd.action" | "cmd.prompt" | "cmd.extension" | "cmd.settings" | "cmd.gear" | "cmd.shield" | "cmd.wave" | "cmd.compass" | "cmd.inbox" | "cmd.swap" | "cmd.expand" | "cmd.computer" | "cmd.eye" | "cmd.todo" | "cmd.stats" | "cmd.news" | "cmd.keyboard" | "cmd.export" | "cmd.clipboard" | "cmd.share" | "cmd.broadcast" | "cmd.globe" | "cmd.copy" | "cmd.plus" | "cmd.restart" | "cmd.eraser" | "cmd.trash" | "cmd.compress" | "cmd.vibrate" | "cmd.handoff" | "cmd.history" | "cmd.question" | "cmd.rocket" | "cmd.stethoscope" | "cmd.redo" | "cmd.bug" | "cmd.memory" | "cmd.pencil" | "cmd.folderMove" | "cmd.folderPlus" | "cmd.folderMinus" | "cmd.hammer" | "cmd.power" | "cmd.cart" | "icon.mic" | "icon.camera" | "thinking.minimal" | "thinking.low" | "thinking.medium" | "thinking.high" | "thinking.xhigh" | "thinking.max" | "thinking.autoPending" | "checkbox.checked" | "checkbox.unchecked" | "radio.selected" | "radio.unselected" | "format.bullet" | "format.dash" | "format.bracketLeft" | "format.bracketRight" | "md.quoteBorder" | "md.hrChar" | "md.bullet" | "md.colorSwatch" | "advisor.rail" | "skill.rail" | "lang.default" | "lang.typescript" | "lang.javascript" | "lang.python" | "lang.rust" | "lang.go" | "lang.java" | "lang.c" | "lang.cpp" | "lang.csharp" | "lang.ruby" | "lang.julia" | "lang.php" | "lang.swift" | "lang.kotlin" | "lang.shell" | "lang.html" | "lang.css" | "lang.json" | "lang.yaml" | "lang.markdown" | "lang.sql" | "lang.docker" | "lang.lua" | "lang.text" | "lang.env" | "lang.toml" | "lang.xml" | "lang.ini" | "lang.conf" | "lang.log" | "lang.csv" | "lang.tsv" | "lang.image" | "lang.pdf" | "lang.archive" | "lang.binary" | "chip.image" | "chip.video" | "chip.paste" | "tab.appearance" | "tab.model" | "tab.interaction" | "tab.context" | "tab.files" | "tab.shell" | "tab.tools" | "tab.memory" | "tab.tasks" | "tab.providers" | "tool.write" | "tool.edit" | "tool.bash" | "tool.ssh" | "tool.lsp" | "tool.gh" | "tool.webSearch" | "tool.exa" | "tool.browser" | "tool.eval" | "tool.debug" | "tool.mcp" | "tool.job" | "tool.launch" | "tool.task" | "tool.todo" | "tool.memory" | "tool.ask" | "tool.resolve" | "tool.review" | "tool.goal" | "tool.irc" | "tool.delete" | "tool.move" | "key.ctrl" | "key.ctrlMac" | "key.shift" | "key.alt" | "key.altMac" | "key.super" | "key.superMac" | "key.joiner" | "key.enter" | "key.esc" | "key.tab" | "key.backspace" | "key.delete" | "key.space" | "key.up" | "key.down" | "key.left" | "key.right";
|
|
6
6
|
export type SymbolMap = Record<SymbolKey, string>;
|
|
7
7
|
/**
|
|
8
8
|
* Icon vocabulary for slash-command autocomplete type indicators. Each name
|
package/src/theme/symbols.ts
CHANGED
|
@@ -129,6 +129,7 @@ export type SymbolKey =
|
|
|
129
129
|
| "icon.vimInsert"
|
|
130
130
|
| "icon.vimVisual"
|
|
131
131
|
| "icon.vimVisualLine"
|
|
132
|
+
| "icon.vimReplace"
|
|
132
133
|
// Slash-command type indicators (autocomplete); names without an existing
|
|
133
134
|
// icon.* equivalent — see SlashCommandIconName for the full vocabulary.
|
|
134
135
|
| "cmd.action"
|
|
@@ -511,6 +512,7 @@ const UNICODE_SYMBOLS: SymbolMap = {
|
|
|
511
512
|
"icon.vimInsert": "▎",
|
|
512
513
|
"icon.vimVisual": "◉",
|
|
513
514
|
"icon.vimVisualLine": "≡",
|
|
515
|
+
"icon.vimReplace": "▁",
|
|
514
516
|
// Slash-command type indicators
|
|
515
517
|
"cmd.action": "❯",
|
|
516
518
|
"cmd.prompt": "✎",
|
|
@@ -921,6 +923,8 @@ const NERD_SYMBOLS: SymbolMap = {
|
|
|
921
923
|
"icon.vimVisual": "\uf06e",
|
|
922
924
|
// pick: (nf-fa-bars) | alt: (nf-fa-align_left)
|
|
923
925
|
"icon.vimVisualLine": "\uf0c9",
|
|
926
|
+
// pick: (nf-fa-exchange) | alt: (nf-fa-repeat)
|
|
927
|
+
"icon.vimReplace": "\uf0ec",
|
|
924
928
|
// Slash-command type indicators
|
|
925
929
|
// pick: (nf-cod-terminal) | alt: (nf-fa-terminal)
|
|
926
930
|
"cmd.action": "\uea85",
|
|
@@ -1235,9 +1239,11 @@ const ASCII_SYMBOLS: SymbolMap = {
|
|
|
1235
1239
|
"sep.pipe": " | ",
|
|
1236
1240
|
// Icons
|
|
1237
1241
|
"icon.model": "[M]",
|
|
1238
|
-
"
|
|
1239
|
-
|
|
1240
|
-
"icon.
|
|
1242
|
+
// Mode icons are always followed by their word label ("Plan", "Prewalk", "Goal");
|
|
1243
|
+
// an ASCII word here would just repeat it, so render the label alone.
|
|
1244
|
+
"icon.plan": "",
|
|
1245
|
+
"icon.prewalk": "",
|
|
1246
|
+
"icon.goal": "",
|
|
1241
1247
|
"icon.pause": "||",
|
|
1242
1248
|
"icon.loop": "loop",
|
|
1243
1249
|
"icon.folder": "[D]",
|
|
@@ -1256,7 +1262,7 @@ const ASCII_SYMBOLS: SymbolMap = {
|
|
|
1256
1262
|
"icon.advisor": "(adv)",
|
|
1257
1263
|
"icon.advisorClosed": "(adv)",
|
|
1258
1264
|
"icon.time": "t:",
|
|
1259
|
-
"icon.omp": "
|
|
1265
|
+
"icon.omp": "zeta",
|
|
1260
1266
|
"icon.ghost": "@",
|
|
1261
1267
|
"icon.agents": "AG",
|
|
1262
1268
|
"icon.job": "bg",
|
|
@@ -1287,6 +1293,7 @@ const ASCII_SYMBOLS: SymbolMap = {
|
|
|
1287
1293
|
"icon.vimInsert": "I",
|
|
1288
1294
|
"icon.vimVisual": "V",
|
|
1289
1295
|
"icon.vimVisualLine": "L",
|
|
1296
|
+
"icon.vimReplace": "R",
|
|
1290
1297
|
// Slash-command type indicators — unused; the icon column is disabled in ASCII mode
|
|
1291
1298
|
"cmd.action": "",
|
|
1292
1299
|
"cmd.prompt": "",
|
|
@@ -54,6 +54,13 @@ export declare class Theme {
|
|
|
54
54
|
* against. Built once per instance and frozen; callers share the object.
|
|
55
55
|
*/
|
|
56
56
|
get sessionAccentInputs(): SessionAccentTheme;
|
|
57
|
+
/**
|
|
58
|
+
* True when the theme paints `color` with a real foreground — i.e. the token
|
|
59
|
+
* exists and is not the empty string (terminal default, `\x1b[39m`). Optional
|
|
60
|
+
* tokens absent from the theme JSON are also false. Callers use this to keep
|
|
61
|
+
* terminal-default behavior byte-for-byte when an optional token is unset.
|
|
62
|
+
*/
|
|
63
|
+
hasColor(color: ThemeColor): boolean;
|
|
57
64
|
fg(color: ThemeColor, text: string): string;
|
|
58
65
|
/** Apply a foreground, replacing terminal-default tokens with the theme's contrast-safe fallback. */
|
|
59
66
|
fgResolved(color: ThemeColor, text: string): string;
|
package/src/theme/theme-class.ts
CHANGED
|
@@ -2,7 +2,13 @@ import { colorLuma, relativeLuminance } from "@linxiraos/pi-utils/color";
|
|
|
2
2
|
import * as logger from "@linxiraos/pi-utils/logger";
|
|
3
3
|
import chalk from "@linxiraos/pi-utils/chalk";
|
|
4
4
|
import { bgAnsi, colorToAnsi, fgAnsi, resolveToHex } from "./color";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type ColorMode,
|
|
7
|
+
isValidThemeColor,
|
|
8
|
+
OPTIONAL_THEME_COLOR_RECORD,
|
|
9
|
+
type ThemeBg,
|
|
10
|
+
type ThemeColor,
|
|
11
|
+
} from "./schema";
|
|
6
12
|
import type { SessionAccentTheme } from "./session-color";
|
|
7
13
|
import {
|
|
8
14
|
type SlashCommandIconName,
|
|
@@ -204,6 +210,14 @@ export class Theme {
|
|
|
204
210
|
this.#fgColors[key] = fgAnsi(value, mode);
|
|
205
211
|
this.#hexFgColors[key] = hex;
|
|
206
212
|
}
|
|
213
|
+
// A theme may omit an optional token, but callers can still name it (a
|
|
214
|
+
// `modelTags.<role>.color` reference is validated against the theme color
|
|
215
|
+
// list). Resolve those to the terminal default so `fg()` stays total while
|
|
216
|
+
// `hasColor()` reports them as unset.
|
|
217
|
+
for (const key of Object.keys(OPTIONAL_THEME_COLOR_RECORD) as ThemeColor[]) {
|
|
218
|
+
this.#fgColors[key] ??= "\x1b[39m";
|
|
219
|
+
this.#hexFgColors[key] ??= "";
|
|
220
|
+
}
|
|
207
221
|
this.#bgColors = {} as Record<ThemeBg, string>;
|
|
208
222
|
this.#hexBgColors = {} as Record<ThemeBg, string>;
|
|
209
223
|
for (const [key, value] of Object.entries(bgColors) as [ThemeBg, string | number][]) {
|
|
@@ -322,6 +336,17 @@ export class Theme {
|
|
|
322
336
|
return this.#sessionAccentInputs;
|
|
323
337
|
}
|
|
324
338
|
|
|
339
|
+
/**
|
|
340
|
+
* True when the theme paints `color` with a real foreground — i.e. the token
|
|
341
|
+
* exists and is not the empty string (terminal default, `\x1b[39m`). Optional
|
|
342
|
+
* tokens absent from the theme JSON are also false. Callers use this to keep
|
|
343
|
+
* terminal-default behavior byte-for-byte when an optional token is unset.
|
|
344
|
+
*/
|
|
345
|
+
hasColor(color: ThemeColor): boolean {
|
|
346
|
+
const ansi = this.#fgColors[color];
|
|
347
|
+
return ansi !== undefined && ansi !== "\x1b[39m";
|
|
348
|
+
}
|
|
349
|
+
|
|
325
350
|
fg(color: ThemeColor, text: string): string {
|
|
326
351
|
const ansi = this.#fgColors[color];
|
|
327
352
|
if (!ansi) throw new Error(`Unknown theme color: ${color}`);
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"colors": {
|
|
35
35
|
"type": "object",
|
|
36
|
-
"description": "Theme color definitions (all required except thinkingMax)",
|
|
36
|
+
"description": "Theme color definitions (all required except thinkingMax and assistantMessageText)",
|
|
37
37
|
"required": [
|
|
38
38
|
"accent",
|
|
39
39
|
"border",
|
|
@@ -143,6 +143,10 @@
|
|
|
143
143
|
"$ref": "#/$defs/colorValue",
|
|
144
144
|
"description": "Default text color (usually empty string)"
|
|
145
145
|
},
|
|
146
|
+
"assistantMessageText": {
|
|
147
|
+
"$ref": "#/$defs/colorValue",
|
|
148
|
+
"description": "Assistant paragraph prose color (optional; empty string or omitted keeps the terminal default foreground)"
|
|
149
|
+
},
|
|
146
150
|
"thinkingText": {
|
|
147
151
|
"$ref": "#/$defs/colorValue",
|
|
148
152
|
"description": "Thinking text color"
|
package/src/theme/theme.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { getAvailableThemes, getAvailableThemesWithPaths, getThemeByName, type T
|
|
|
6
6
|
export { isValidThemeColor, type ThemeBg, type ThemeColor } from "./schema";
|
|
7
7
|
export { getAvailableSymbolPresets, isValidSymbolPreset, type SpinnerType, type SymbolKey, type SymbolPreset, } from "./symbols";
|
|
8
8
|
export { Theme } from "./theme-class";
|
|
9
|
-
export { createHighlightStream, getEditorTheme, getMarkdownTheme, getSelectListTheme, getSettingsListTheme, getSymbolTheme, highlightCode, setMarkdownMermaidRendering, warmHighlighter, } from "./tui-adapters";
|
|
9
|
+
export { createHighlightStream, getEditorTheme, getMarkdownTheme, getMarkdownThemeWithLinkTargets, getSelectListTheme, getSettingsListTheme, getSymbolTheme, highlightCode, setMarkdownMermaidRendering, warmHighlighter, } from "./tui-adapters";
|
|
10
10
|
/** Active theme; imports remain live across initialization, previews, and theme switches. */
|
|
11
11
|
export declare var theme: Theme;
|
|
12
12
|
type ThemeBinding = (value: Theme) => void;
|
package/src/theme/theme.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { Terminal, TerminalAppearance } from "../terminal";
|
|
|
5
5
|
import { colorLuma } from "@linxiraos/pi-utils/color";
|
|
6
6
|
import { getCustomThemesDir } from "@linxiraos/pi-utils/dirs";
|
|
7
7
|
import * as logger from "@linxiraos/pi-utils/logger";
|
|
8
|
+
import { terminalMultiplexerSessions } from "../terminal-multiplexer";
|
|
8
9
|
import { setActiveSymbolTheme } from "./active-symbols";
|
|
9
10
|
import { ansi256ToHex, resolveThemeColors, resolveVarRefs } from "./color";
|
|
10
11
|
import {
|
|
@@ -34,6 +35,7 @@ export {
|
|
|
34
35
|
createHighlightStream,
|
|
35
36
|
getEditorTheme,
|
|
36
37
|
getMarkdownTheme,
|
|
38
|
+
getMarkdownThemeWithLinkTargets,
|
|
37
39
|
getSelectListTheme,
|
|
38
40
|
getSettingsListTheme,
|
|
39
41
|
getSymbolTheme,
|
|
@@ -49,10 +51,12 @@ var terminalReportedAppearance: "dark" | "light" | undefined;
|
|
|
49
51
|
var macOSReportedAppearance: "dark" | "light" | undefined;
|
|
50
52
|
|
|
51
53
|
function shouldUseMacOSAppearanceFallback(): boolean {
|
|
52
|
-
//
|
|
53
|
-
// appearance cannot be trusted there. Fall back
|
|
54
|
-
// without letting it override valid terminal
|
|
55
|
-
|
|
54
|
+
// Some multiplexers break OSC 11 passthrough on some platforms (Zellij on
|
|
55
|
+
// macOS), so terminal-derived appearance cannot be trusted there. Fall back
|
|
56
|
+
// to host macOS appearance without letting it override valid terminal
|
|
57
|
+
// signals elsewhere.
|
|
58
|
+
const platform = process.platform;
|
|
59
|
+
return terminalMultiplexerSessions().some(multiplexer => multiplexer.backgroundQueryBrokenOn?.includes(platform));
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
function detectTerminalBackground(): "dark" | "light" {
|
|
@@ -16,6 +16,9 @@ export declare function createHighlightStream(lang?: string, highlightTheme?: Th
|
|
|
16
16
|
/** Warm native syntax grammars off-thread once per process. */
|
|
17
17
|
export declare function warmHighlighter(): Promise<void>;
|
|
18
18
|
export declare function getSymbolTheme(): SymbolTheme;
|
|
19
|
+
/** Only themes assembled here have stable callbacks and private link state. */
|
|
20
|
+
export declare function canCacheMarkdownListItems(candidate: MarkdownTheme): boolean;
|
|
21
|
+
export declare function getMarkdownThemeWithLinkTargets(targets: ReadonlyMap<string, string>): MarkdownTheme;
|
|
19
22
|
export declare function setMarkdownMermaidRendering(enabled: boolean): void;
|
|
20
23
|
export declare function getMarkdownTheme(): MarkdownTheme;
|
|
21
24
|
export declare function getSelectListTheme(): SelectListTheme;
|
|
@@ -183,8 +183,75 @@ export function getSymbolTheme(): SymbolTheme {
|
|
|
183
183
|
|
|
184
184
|
let cachedMarkdownTheme: MarkdownTheme | undefined;
|
|
185
185
|
let cachedMarkdownThemeRef: Theme | undefined;
|
|
186
|
+
const cacheableMarkdownThemes = new WeakMap<
|
|
187
|
+
MarkdownTheme,
|
|
188
|
+
{
|
|
189
|
+
theme: Theme;
|
|
190
|
+
fields: ReadonlyArray<readonly [PropertyKey, unknown]>;
|
|
191
|
+
symbolFields: ReadonlyArray<readonly [PropertyKey, unknown]>;
|
|
192
|
+
symbolValues: string;
|
|
193
|
+
}
|
|
194
|
+
>();
|
|
195
|
+
const linkTargetSnapshots = new WeakMap<ReadonlyMap<string, string>, ReadonlyMap<string, string>>();
|
|
186
196
|
let markdownMermaidRendering = true;
|
|
187
197
|
|
|
198
|
+
function ownFields(object: object): ReadonlyArray<readonly [PropertyKey, unknown]> {
|
|
199
|
+
return Reflect.ownKeys(object).map(key => [key, Object.getOwnPropertyDescriptor(object, key)?.value]);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function hasUnchangedOwnFields(object: object, fields: ReadonlyArray<readonly [PropertyKey, unknown]>): boolean {
|
|
203
|
+
if (Reflect.ownKeys(object).length !== fields.length) return false;
|
|
204
|
+
return fields.every(([key, value]) => {
|
|
205
|
+
const descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
206
|
+
return descriptor !== undefined && "value" in descriptor && descriptor.value === value;
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Only themes assembled here have stable callbacks and private link state. */
|
|
211
|
+
export function canCacheMarkdownListItems(candidate: MarkdownTheme): boolean {
|
|
212
|
+
const registered = cacheableMarkdownThemes.get(candidate);
|
|
213
|
+
if (registered === undefined || registered.theme !== theme || candidate.symbols === undefined) return false;
|
|
214
|
+
if (!hasUnchangedOwnFields(candidate, registered.fields)) return false;
|
|
215
|
+
if (!hasUnchangedOwnFields(candidate.symbols, registered.symbolFields)) return false;
|
|
216
|
+
try {
|
|
217
|
+
return JSON.stringify(candidate.symbols) === registered.symbolValues;
|
|
218
|
+
} catch {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function registerCacheableMarkdownTheme(markdownTheme: MarkdownTheme): void {
|
|
224
|
+
if (markdownTheme.symbols === undefined) return;
|
|
225
|
+
cacheableMarkdownThemes.set(markdownTheme, {
|
|
226
|
+
theme,
|
|
227
|
+
fields: ownFields(markdownTheme),
|
|
228
|
+
symbolFields: ownFields(markdownTheme.symbols),
|
|
229
|
+
symbolValues: JSON.stringify(markdownTheme.symbols),
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function getMarkdownThemeWithLinkTargets(targets: ReadonlyMap<string, string>): MarkdownTheme {
|
|
234
|
+
const base = getMarkdownTheme();
|
|
235
|
+
let snapshot = linkTargetSnapshots.get(targets);
|
|
236
|
+
let matches = snapshot?.size === targets.size;
|
|
237
|
+
if (matches && snapshot !== undefined) {
|
|
238
|
+
for (const [href, target] of targets) {
|
|
239
|
+
if (snapshot.get(href) !== target) {
|
|
240
|
+
matches = false;
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (snapshot === undefined || !matches) {
|
|
246
|
+
snapshot = new Map(targets);
|
|
247
|
+
linkTargetSnapshots.set(targets, snapshot);
|
|
248
|
+
}
|
|
249
|
+
const stableSnapshot = snapshot;
|
|
250
|
+
const linked: MarkdownTheme = { ...base, resolveLink: href => stableSnapshot.get(href) };
|
|
251
|
+
if (canCacheMarkdownListItems(base)) registerCacheableMarkdownTheme(linked);
|
|
252
|
+
return linked;
|
|
253
|
+
}
|
|
254
|
+
|
|
188
255
|
export function setMarkdownMermaidRendering(enabled: boolean): void {
|
|
189
256
|
if (markdownMermaidRendering === enabled) return;
|
|
190
257
|
markdownMermaidRendering = enabled;
|
|
@@ -247,6 +314,7 @@ export function getMarkdownTheme(): MarkdownTheme {
|
|
|
247
314
|
};
|
|
248
315
|
cachedMarkdownTheme = markdownTheme;
|
|
249
316
|
cachedMarkdownThemeRef = theme;
|
|
317
|
+
registerCacheableMarkdownTheme(markdownTheme);
|
|
250
318
|
return markdownTheme;
|
|
251
319
|
}
|
|
252
320
|
|
package/src/thinking.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { ThinkingLevel } from "@linxiraos/pi-agent-core/thinking";
|
|
|
4
4
|
import { Effort } from "@linxiraos/pi-catalog/effort";
|
|
5
5
|
import type { Model } from "@linxiraos/pi-catalog/types";
|
|
6
6
|
/** Thinking selectors accepted by CLI inputs, in display order. */
|
|
7
|
-
export declare const CLI_THINKING_LEVELS: readonly
|
|
7
|
+
export declare const CLI_THINKING_LEVELS: readonly ConfiguredThinkingLevel[];
|
|
8
8
|
/**
|
|
9
9
|
* Metadata used to render thinking selector values in the coding-agent UI.
|
|
10
10
|
*/
|
package/src/thinking.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { clampThinkingLevelForModel, getSupportedEfforts } from "@linxiraos/pi-c
|
|
|
6
6
|
import { modelsAreEqual } from "@linxiraos/pi-catalog/models";
|
|
7
7
|
import type { Model } from "@linxiraos/pi-catalog/types";
|
|
8
8
|
/** Thinking selectors accepted by CLI inputs, in display order. */
|
|
9
|
-
export const CLI_THINKING_LEVELS: readonly
|
|
9
|
+
export const CLI_THINKING_LEVELS: readonly ConfiguredThinkingLevel[] = ["off", ...THINKING_EFFORTS, "auto"];
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Metadata used to render thinking selector values in the coding-agent UI.
|
package/src/tmux.d.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function isInsideTmux(env?: NodeJS.ProcessEnv): boolean;
|
|
3
|
-
/** Wrap a control sequence in tmux's DCS passthrough envelope. */
|
|
4
|
-
export declare function wrapTmuxPassthrough(payload: string): string;
|
|
1
|
+
export { wrapTmuxPassthrough } from "./multiplexers/tmux";
|
|
5
2
|
/** Pass a control sequence through tmux, leaving direct-terminal output unchanged. */
|
|
6
3
|
export declare function wrapTmuxPassthroughIfNeeded(payload: string, env?: NodeJS.ProcessEnv): string;
|
|
4
|
+
/**
|
|
5
|
+
* Whether the terminal hosting this tmux session draws TSP programs natively:
|
|
6
|
+
* it sets the session user option `@tern-tsp` while it watches the session.
|
|
7
|
+
*/
|
|
8
|
+
export declare function tmuxSessionSpeaksTsp(env?: NodeJS.ProcessEnv): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Stop (`on` false) or restore (`on` true) tmux turning this pane's APC
|
|
11
|
+
* strings into its title, which would otherwise swallow every TSP message.
|
|
12
|
+
*/
|
|
13
|
+
export declare function setTmuxPaneApcTitles(on: boolean, env?: NodeJS.ProcessEnv): void;
|
|
7
14
|
/**
|
|
8
15
|
* Resolve the terminal emulator name recorded for this tmux client.
|
|
9
16
|
*
|
package/src/tmux.ts
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import { $which } from "@linxiraos/pi-utils";
|
|
2
2
|
import { isBunTestRuntime } from "@linxiraos/pi-utils/env";
|
|
3
|
+
import { tmuxMultiplexer, wrapTmuxPassthrough } from "./multiplexers/tmux";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
export function isInsideTmux(env: NodeJS.ProcessEnv = Bun.env): boolean {
|
|
6
|
-
return Boolean(env.TMUX);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/** Wrap a control sequence in tmux's DCS passthrough envelope. */
|
|
10
|
-
export function wrapTmuxPassthrough(payload: string): string {
|
|
11
|
-
return `\x1bPtmux;${payload.replaceAll("\x1b", "\x1b\x1b")}\x1b\\`;
|
|
12
|
-
}
|
|
5
|
+
export { wrapTmuxPassthrough } from "./multiplexers/tmux";
|
|
13
6
|
|
|
14
7
|
/** Pass a control sequence through tmux, leaving direct-terminal output unchanged. */
|
|
15
8
|
export function wrapTmuxPassthroughIfNeeded(payload: string, env: NodeJS.ProcessEnv = Bun.env): string {
|
|
16
|
-
return
|
|
9
|
+
return tmuxMultiplexer.isInside(env) ? wrapTmuxPassthrough(payload) : payload;
|
|
17
10
|
}
|
|
18
11
|
|
|
19
12
|
const CLIENT_TERMTYPE_NAME = /^([A-Za-z][A-Za-z0-9._+-]*)(?=\s|\(|$)/u;
|
|
@@ -38,6 +31,49 @@ function queryTmuxClientTerminalName(env: NodeJS.ProcessEnv): string | null {
|
|
|
38
31
|
}
|
|
39
32
|
}
|
|
40
33
|
|
|
34
|
+
const TMUX_COMMAND_TIMEOUT_MS = 500;
|
|
35
|
+
|
|
36
|
+
/** Run a tmux command against the current server; its stdout, or null on failure. */
|
|
37
|
+
function runTmux(args: string[], env: NodeJS.ProcessEnv): string | null {
|
|
38
|
+
const tmux = $which("tmux", { PATH: env.PATH });
|
|
39
|
+
if (!tmux) return null;
|
|
40
|
+
try {
|
|
41
|
+
const result = Bun.spawnSync([tmux, ...args], {
|
|
42
|
+
env,
|
|
43
|
+
stdout: "pipe",
|
|
44
|
+
stderr: "ignore",
|
|
45
|
+
timeout: TMUX_COMMAND_TIMEOUT_MS,
|
|
46
|
+
killSignal: "SIGKILL",
|
|
47
|
+
});
|
|
48
|
+
return result.exitCode === 0 ? result.stdout.toString() : null;
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Whether the terminal hosting this tmux session draws TSP programs natively:
|
|
56
|
+
* it sets the session user option `@tern-tsp` while it watches the session.
|
|
57
|
+
*/
|
|
58
|
+
export function tmuxSessionSpeaksTsp(env: NodeJS.ProcessEnv = Bun.env): boolean {
|
|
59
|
+
return (runTmux(["show-options", "-qv", "@tern-tsp"], env)?.trim() ?? "") !== "";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Stop (`on` false) or restore (`on` true) tmux turning this pane's APC
|
|
64
|
+
* strings into its title, which would otherwise swallow every TSP message.
|
|
65
|
+
*/
|
|
66
|
+
export function setTmuxPaneApcTitles(on: boolean, env: NodeJS.ProcessEnv = Bun.env): void {
|
|
67
|
+
const pane = env.TMUX_PANE;
|
|
68
|
+
if (!pane) return;
|
|
69
|
+
runTmux(
|
|
70
|
+
on
|
|
71
|
+
? ["set-option", "-pu", "-t", pane, "allow-set-title"]
|
|
72
|
+
: ["set-option", "-p", "-t", pane, "allow-set-title", "off"],
|
|
73
|
+
env,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
41
77
|
/**
|
|
42
78
|
* Resolve the terminal emulator name recorded for this tmux client.
|
|
43
79
|
*
|
|
@@ -46,7 +82,7 @@ function queryTmuxClientTerminalName(env: NodeJS.ProcessEnv): string | null {
|
|
|
46
82
|
* query runs once per process and degrades to `null` when unavailable.
|
|
47
83
|
*/
|
|
48
84
|
export function resolveTmuxClientTerminalName(env: NodeJS.ProcessEnv = Bun.env): string | null {
|
|
49
|
-
if (!
|
|
85
|
+
if (!tmuxMultiplexer.isInside(env) || isBunTestRuntime()) return null;
|
|
50
86
|
if (cachedClientTerminalName === undefined) cachedClientTerminalName = queryTmuxClientTerminalName(env);
|
|
51
87
|
return cachedClientTerminalName;
|
|
52
88
|
}
|