@deepseek-harness-tui/dsh-tui 0.11.1 → 0.11.2
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/README.md +50 -20
- package/assets/whale-girl/whale-girl-dark.png +0 -0
- package/assets/whale-girl/whale-girl-happy.png +0 -0
- package/assets/whale-girl/whale-girl.png +0 -0
- package/bin/dsh-tui.js +63 -3
- package/cordis.patch.yml +39 -17
- package/cordis.yml +3 -2
- package/lib/settings.json +1272 -0
- package/lib/types/adapter/channel/ui-policy.d.ts +9 -2
- package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
- package/lib/types/adapter/channel/ui-policy.js +13 -0
- package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
- package/lib/types/adapter/kernel/replay.js +2 -0
- package/lib/types/adapter/ports/channel-display.d.ts +12 -0
- package/lib/types/adapter/ports/channel-display.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-session.d.ts +38 -0
- package/lib/types/adapter/ports/channel-session.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-settings.d.ts +12 -0
- package/lib/types/adapter/ports/channel-settings.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-ui.d.ts +46 -4
- package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-view.d.ts +43 -0
- package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +2 -0
- package/lib/types/components/BalanceReportRow.d.ts +10 -2
- package/lib/types/components/BalanceReportRow.d.ts.map +1 -1
- package/lib/types/components/BalanceReportRow.js +18 -4
- package/lib/types/components/CompactionStatusRow.d.ts +24 -0
- package/lib/types/components/CompactionStatusRow.d.ts.map +1 -0
- package/lib/types/components/CompactionStatusRow.js +72 -0
- package/lib/types/components/GoalTodoPanel.js +2 -2
- package/lib/types/components/HelpMenu.d.ts +2 -2
- package/lib/types/components/HelpMenu.d.ts.map +1 -1
- package/lib/types/components/HelpMenu.js +5 -4
- package/lib/types/components/InlineMathParagraph.d.ts +22 -0
- package/lib/types/components/InlineMathParagraph.d.ts.map +1 -0
- package/lib/types/components/InlineMathParagraph.js +178 -0
- package/lib/types/components/LogoV2.d.ts +41 -3
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +148 -24
- package/lib/types/components/Markdown.d.ts +10 -3
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +47 -14
- package/lib/types/components/MathBlock.d.ts +13 -0
- package/lib/types/components/MathBlock.d.ts.map +1 -0
- package/lib/types/components/MathBlock.js +136 -0
- package/lib/types/components/MessageList.d.ts +10 -1
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +13 -4
- package/lib/types/components/MigratePicker.d.ts +30 -0
- package/lib/types/components/MigratePicker.d.ts.map +1 -0
- package/lib/types/components/MigratePicker.js +38 -0
- package/lib/types/components/PromptInput.d.ts +17 -0
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +48 -7
- package/lib/types/components/SplitDiffView.d.ts.map +1 -1
- package/lib/types/components/SplitDiffView.js +2 -1
- package/lib/types/components/StarPrompt.d.ts +53 -0
- package/lib/types/components/StarPrompt.d.ts.map +1 -0
- package/lib/types/components/StarPrompt.js +281 -0
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
- package/lib/types/components/StreamingMarkdown.js +20 -3
- package/lib/types/components/TimelineRail.d.ts.map +1 -1
- package/lib/types/components/TimelineRail.js +9 -1
- package/lib/types/components/Whale.d.ts +17 -8
- package/lib/types/components/Whale.d.ts.map +1 -1
- package/lib/types/components/Whale.js +25 -15
- package/lib/types/components/WhaleGirl.d.ts +29 -0
- package/lib/types/components/WhaleGirl.d.ts.map +1 -0
- package/lib/types/components/WhaleGirl.js +32 -0
- package/lib/types/components/WorkingSpinner.d.ts +4 -1
- package/lib/types/components/WorkingSpinner.d.ts.map +1 -1
- package/lib/types/components/WorkingSpinner.js +2 -2
- package/lib/types/components/bigfont.d.ts +47 -18
- package/lib/types/components/bigfont.d.ts.map +1 -1
- package/lib/types/components/bigfont.js +55 -40
- package/lib/types/components/design-system/ThemeProvider.d.ts +6 -0
- package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
- package/lib/types/components/design-system/ThemeProvider.js +40 -1
- package/lib/types/components/maidPortrait.d.ts +44 -0
- package/lib/types/components/maidPortrait.d.ts.map +1 -0
- package/lib/types/components/maidPortrait.js +178 -0
- package/lib/types/components/mathPreview.d.ts +25 -0
- package/lib/types/components/mathPreview.d.ts.map +1 -0
- package/lib/types/components/mathPreview.js +48 -0
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +2 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +3 -2
- package/lib/types/components/messages/TranscriptImages.d.ts.map +1 -1
- package/lib/types/components/messages/TranscriptImages.js +11 -1
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts +14 -2
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +80 -38
- package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
- package/lib/types/components/questions/PlanReviewPanel.js +3 -3
- package/lib/types/components/sessions/ForeignSessionRow.d.ts +34 -0
- package/lib/types/components/sessions/ForeignSessionRow.d.ts.map +1 -0
- package/lib/types/components/sessions/ForeignSessionRow.js +43 -0
- package/lib/types/components/sessions/SourceTabs.d.ts +52 -0
- package/lib/types/components/sessions/SourceTabs.d.ts.map +1 -0
- package/lib/types/components/sessions/SourceTabs.js +70 -0
- package/lib/types/components/splashEggs.d.ts +56 -0
- package/lib/types/components/splashEggs.d.ts.map +1 -0
- package/lib/types/components/splashEggs.js +67 -0
- package/lib/types/components/splashFonts.d.ts +119 -0
- package/lib/types/components/splashFonts.d.ts.map +1 -0
- package/lib/types/components/splashFonts.js +267 -0
- package/lib/types/components/splashLayout.d.ts +41 -0
- package/lib/types/components/splashLayout.d.ts.map +1 -0
- package/lib/types/components/splashLayout.js +40 -0
- package/lib/types/components/whaleGirlSprite.d.ts +17 -0
- package/lib/types/components/whaleGirlSprite.d.ts.map +1 -0
- package/lib/types/components/whaleGirlSprite.js +47 -0
- package/lib/types/deepseekPricing.d.ts +74 -0
- package/lib/types/deepseekPricing.d.ts.map +1 -1
- package/lib/types/deepseekPricing.js +110 -11
- package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/action-readiness.js +6 -1
- package/lib/types/dsh-adapter/channel/background-action.d.ts +1 -0
- package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/background-action.js +1 -0
- package/lib/types/dsh-adapter/channel/binding-events.d.ts +8 -9
- package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding-events.js +69 -21
- package/lib/types/dsh-adapter/channel/compaction.d.ts +2 -1
- package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/compaction.js +35 -2
- package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/local-actions.js +6 -1
- package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/model-switch.js +5 -1
- package/lib/types/dsh-adapter/channel/paths.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/paths.js +7 -1
- package/lib/types/dsh-adapter/channel/preferences.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/preferences.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/preferences.js +16 -0
- package/lib/types/dsh-adapter/channel/projection.d.ts +1 -2
- package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/projection.js +127 -17
- package/lib/types/dsh-adapter/channel/question-record.d.ts +76 -0
- package/lib/types/dsh-adapter/channel/question-record.d.ts.map +1 -0
- package/lib/types/dsh-adapter/channel/question-record.js +107 -0
- package/lib/types/dsh-adapter/channel/session-lineage.d.ts +42 -0
- package/lib/types/dsh-adapter/channel/session-lineage.d.ts.map +1 -0
- package/lib/types/dsh-adapter/channel/session-lineage.js +51 -0
- package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +2 -0
- package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-live-adoption.js +9 -3
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts +2 -1
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-metadata.js +39 -7
- package/lib/types/dsh-adapter/channel/session-reset.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/session-reset.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-reset.js +7 -0
- package/lib/types/dsh-adapter/channel/session-resume.d.ts +1 -0
- package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-resume.js +4 -2
- package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/settings-host.js +8 -0
- package/lib/types/dsh-adapter/channel/state.d.ts +14 -1
- package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/state.js +6 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts +30 -35
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.js +138 -4
- package/lib/types/dsh-adapter/channel/types.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +19 -4
- package/lib/types/dsh-adapter/compat/messages.d.ts +6 -0
- package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/messages.js +9 -0
- package/lib/types/dsh-adapter/contract.d.ts +5 -5
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +8 -6
- package/lib/types/dsh-adapter/index.d.ts +36 -1
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +22 -6
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts +3 -0
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.js +131 -0
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts +17 -0
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.js +329 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts +3 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.js +102 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts +16 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.parse.js +289 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts +3 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.js +117 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts +13 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.js +178 -0
- package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts +3 -0
- package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/omp.js +133 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts +60 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan-fs.js +178 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts +8 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan.js +40 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts +3 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.js +93 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts +9 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.js +89 -0
- package/lib/types/dsh-adapter/migrate/bin-path.d.ts +6 -0
- package/lib/types/dsh-adapter/migrate/bin-path.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/bin-path.js +30 -0
- package/lib/types/dsh-adapter/migrate/browse.d.ts +42 -0
- package/lib/types/dsh-adapter/migrate/browse.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/browse.js +90 -0
- package/lib/types/dsh-adapter/migrate/cli.d.ts +9 -0
- package/lib/types/dsh-adapter/migrate/cli.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/cli.js +106 -0
- package/lib/types/dsh-adapter/migrate/import-one.d.ts +89 -0
- package/lib/types/dsh-adapter/migrate/import-one.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/import-one.js +133 -0
- package/lib/types/dsh-adapter/migrate/index.d.ts +35 -0
- package/lib/types/dsh-adapter/migrate/index.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/index.js +107 -0
- package/lib/types/dsh-adapter/migrate/parse/injection.d.ts +40 -0
- package/lib/types/dsh-adapter/migrate/parse/injection.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/parse/injection.js +127 -0
- package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts +28 -0
- package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/parse/jsonl.js +40 -0
- package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts +28 -0
- package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/parse/role-turns.js +50 -0
- package/lib/types/dsh-adapter/migrate/parse/title.d.ts +18 -0
- package/lib/types/dsh-adapter/migrate/parse/title.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/parse/title.js +29 -0
- package/lib/types/dsh-adapter/migrate/parse/tools.d.ts +62 -0
- package/lib/types/dsh-adapter/migrate/parse/tools.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/parse/tools.js +110 -0
- package/lib/types/dsh-adapter/migrate/picker.d.ts +64 -0
- package/lib/types/dsh-adapter/migrate/picker.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/picker.js +86 -0
- package/lib/types/dsh-adapter/migrate/recent-agents.d.ts +40 -0
- package/lib/types/dsh-adapter/migrate/recent-agents.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/recent-agents.js +100 -0
- package/lib/types/dsh-adapter/migrate/sessionize.d.ts +39 -0
- package/lib/types/dsh-adapter/migrate/sessionize.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/sessionize.js +271 -0
- package/lib/types/dsh-adapter/migrate/types.d.ts +176 -0
- package/lib/types/dsh-adapter/migrate/types.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/types.js +11 -0
- package/lib/types/dsh-adapter/migrate/uuid.d.ts +7 -0
- package/lib/types/dsh-adapter/migrate/uuid.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/uuid.js +25 -0
- package/lib/types/dsh-adapter/plugin.d.ts +4 -2
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +143 -364
- package/lib/types/dsh-adapter/providerWizard.d.ts +17 -0
- package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
- package/lib/types/dsh-adapter/providerWizard.js +254 -66
- package/lib/types/dsh-adapter/questions.d.ts +22 -15
- package/lib/types/dsh-adapter/questions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/questions.js +47 -45
- package/lib/types/dsh-adapter/sessions/digest.d.ts +11 -6
- package/lib/types/dsh-adapter/sessions/digest.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/digest.js +20 -13
- package/lib/types/dsh-adapter/sessions/frames.d.ts +3 -1
- package/lib/types/dsh-adapter/sessions/frames.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/frames.js +5 -4
- package/lib/types/dsh-adapter/sessions/list.d.ts +6 -1
- package/lib/types/dsh-adapter/sessions/list.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/list.js +188 -164
- package/lib/types/dsh-adapter/sessions/recovery.d.ts +16 -0
- package/lib/types/dsh-adapter/sessions/recovery.d.ts.map +1 -0
- package/lib/types/dsh-adapter/sessions/recovery.js +108 -0
- package/lib/types/dsh-adapter/sessions/snapshot.d.ts +7 -0
- package/lib/types/dsh-adapter/sessions/snapshot.d.ts.map +1 -0
- package/lib/types/dsh-adapter/sessions/snapshot.js +90 -0
- package/lib/types/dsh-adapter/sessions/store.d.ts +10 -4
- package/lib/types/dsh-adapter/sessions/store.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/store.js +62 -25
- package/lib/types/dsh-adapter/sideQuestion.d.ts +41 -2
- package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sideQuestion.js +98 -2
- package/lib/types/dsh-adapter/subagents.d.ts +28 -3
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
- package/lib/types/dsh-adapter/subagents.js +77 -2
- package/lib/types/herdr.d.ts +2 -0
- package/lib/types/herdr.d.ts.map +1 -1
- package/lib/types/herdr.js +9 -3
- package/lib/types/i18n.d.ts +424 -42
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +145 -20
- package/lib/types/ink/components/App.d.ts +2 -2
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +5 -1
- package/lib/types/ink/components/Image.d.ts +14 -1
- package/lib/types/ink/components/Image.d.ts.map +1 -1
- package/lib/types/ink/components/Image.js +2 -2
- package/lib/types/ink/events/input-event.js +3 -3
- package/lib/types/ink/hooks/use-terminal-images.d.ts +12 -0
- package/lib/types/ink/hooks/use-terminal-images.d.ts.map +1 -1
- package/lib/types/ink/hooks/use-terminal-images.js +13 -0
- package/lib/types/ink/ink.d.ts +6 -0
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +16 -1
- package/lib/types/ink/kitty-graphics.d.ts +44 -3
- package/lib/types/ink/kitty-graphics.d.ts.map +1 -1
- package/lib/types/ink/kitty-graphics.js +184 -23
- package/lib/types/ink/output.d.ts +24 -2
- package/lib/types/ink/output.d.ts.map +1 -1
- package/lib/types/ink/output.js +83 -5
- package/lib/types/ink/parse-keypress.d.ts +26 -1
- package/lib/types/ink/parse-keypress.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.js +156 -13
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
- package/lib/types/ink/render-node-to-output.js +8 -1
- package/lib/types/ink/screen.d.ts +24 -0
- package/lib/types/ink/screen.d.ts.map +1 -1
- package/lib/types/ink/screen.js +89 -0
- package/lib/types/ink/selection.d.ts +40 -18
- package/lib/types/ink/selection.d.ts.map +1 -1
- package/lib/types/ink/selection.js +142 -30
- package/lib/types/ink/sixel-codec.d.ts +12 -1
- package/lib/types/ink/sixel-codec.d.ts.map +1 -1
- package/lib/types/ink/sixel-codec.js +29 -5
- package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
- package/lib/types/ink/sixel-graphics.js +5 -3
- package/lib/types/ink/styles.d.ts +9 -0
- package/lib/types/ink/styles.d.ts.map +1 -1
- package/lib/types/ink/terminal-image.d.ts +8 -0
- package/lib/types/ink/terminal-image.d.ts.map +1 -1
- package/lib/types/ink/terminal-querier.d.ts +7 -1
- package/lib/types/ink/terminal-querier.d.ts.map +1 -1
- package/lib/types/ink/terminal-querier.js +12 -2
- package/lib/types/ink/timeline-rail.d.ts +5 -0
- package/lib/types/ink/timeline-rail.d.ts.map +1 -1
- package/lib/types/math/inline-layout.d.ts +29 -0
- package/lib/types/math/inline-layout.d.ts.map +1 -0
- package/lib/types/math/inline-layout.js +106 -0
- package/lib/types/math/layout.d.ts +58 -0
- package/lib/types/math/layout.d.ts.map +1 -0
- package/lib/types/math/layout.js +59 -0
- package/lib/types/math/renderer.d.ts +64 -0
- package/lib/types/math/renderer.d.ts.map +1 -0
- package/lib/types/math/renderer.js +256 -0
- package/lib/types/screens/Chat.d.ts +14 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +606 -53
- package/lib/types/screens/SessionSupervisor.d.ts +2 -1
- package/lib/types/screens/SessionSupervisor.d.ts.map +1 -1
- package/lib/types/screens/SessionSupervisor.js +156 -19
- package/lib/types/screens/Settings.d.ts.map +1 -1
- package/lib/types/screens/Settings.js +49 -11
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +45 -15
- package/lib/types/screens/chatOverlay.d.ts +5 -0
- package/lib/types/screens/chatOverlay.d.ts.map +1 -1
- package/lib/types/screens/chatOverlay.js +1 -0
- package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts +47 -0
- package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts.map +1 -0
- package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.js +65 -0
- package/lib/types/screens/sessionSupervisor/model.d.ts +12 -0
- package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -1
- package/lib/types/screens/sessionSupervisor/model.js +26 -0
- package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts +107 -0
- package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts.map +1 -0
- package/lib/types/screens/sessionSupervisor/useForeignSessions.js +312 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +4 -1
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -1
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +97 -14
- package/lib/types/sessionHistory.d.ts +2 -2
- package/lib/types/sessionHistory.d.ts.map +1 -1
- package/lib/types/sessionHistory.js +31 -5
- package/lib/types/settings/definitions.d.ts +681 -0
- package/lib/types/settings/definitions.d.ts.map +1 -0
- package/lib/types/settings/definitions.js +511 -0
- package/lib/types/starAction.d.ts +44 -0
- package/lib/types/starAction.d.ts.map +1 -0
- package/lib/types/starAction.js +52 -0
- package/lib/types/terminal-utils/latex.d.ts +10 -0
- package/lib/types/terminal-utils/latex.d.ts.map +1 -0
- package/lib/types/terminal-utils/latex.js +1417 -0
- package/lib/types/terminal-utils/markdown.d.ts +3 -1
- package/lib/types/terminal-utils/markdown.d.ts.map +1 -1
- package/lib/types/terminal-utils/markdown.js +26 -1
- package/lib/types/terminal-utils/math.d.ts +66 -0
- package/lib/types/terminal-utils/math.d.ts.map +1 -0
- package/lib/types/terminal-utils/math.js +337 -0
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +6 -0
- package/lib/types/tuiDisplayPrefs.d.ts +67 -0
- package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
- package/lib/types/tuiDisplayPrefs.js +59 -0
- package/lib/types/ui.d.ts +1 -1
- package/lib/types/ui.d.ts.map +1 -1
- package/lib/types/ui.js +1 -1
- package/lib/types/usageStats.d.ts +98 -0
- package/lib/types/usageStats.d.ts.map +1 -0
- package/lib/types/usageStats.js +169 -0
- package/lib/types/utils/bmp.d.ts +17 -0
- package/lib/types/utils/bmp.d.ts.map +1 -0
- package/lib/types/utils/bmp.js +154 -0
- package/lib/types/utils/clipboard.d.ts +14 -2
- package/lib/types/utils/clipboard.d.ts.map +1 -1
- package/lib/types/utils/clipboard.js +143 -8
- package/lib/types/utils/fold-long-lines.d.ts.map +1 -1
- package/lib/types/utils/fold-long-lines.js +2 -1
- package/lib/types/utils/keymap.d.ts +4 -1
- package/lib/types/utils/keymap.d.ts.map +1 -1
- package/lib/types/utils/keymap.js +8 -0
- package/lib/types/utils/modifiers.d.ts +4 -3
- package/lib/types/utils/modifiers.d.ts.map +1 -1
- package/lib/types/utils/modifiers.js +4 -3
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/LICENSE +202 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/NOTICE +20 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/index.d.ts +16 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/bundled-packages.json +4 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs +20 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs.LEGAL.txt +35 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/package.json +29 -0
- package/package.json +111 -97
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { getLang, t as tr, tOr } from '../i18n.js';
|
|
4
4
|
import { pickRandomTip } from '../tips.js';
|
|
@@ -6,14 +6,21 @@ import { upstreamDriftSummary, UPSTREAM_VALIDATED_VERSION } from '../dsh-adapter
|
|
|
6
6
|
import { readFileSync } from 'node:fs';
|
|
7
7
|
import { dirname, join } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
|
-
import { Box, Text, useAnimationFrame, useTerminalSize } from '../ui.js';
|
|
9
|
+
import { Box, Text, useAnimationFrame, useTerminalImages, useTerminalSize } from '../ui.js';
|
|
10
10
|
import { getTheme } from '../theme.js';
|
|
11
11
|
import { useTheme } from './design-system/ThemeProvider.js';
|
|
12
12
|
import { parseRGB } from './Spinner/spinnerUtils.js';
|
|
13
13
|
import { renderBigText } from './bigfont.js';
|
|
14
|
+
import { COLUMN_GAP, WHALE_BOX_WIDTH, resolveSplashLayout } from './splashLayout.js';
|
|
15
|
+
import { withTagline, pickSplashFont, splashFontById } from './splashFonts.js';
|
|
16
|
+
import { pickSplashEgg, splashStarLine } from './splashEggs.js';
|
|
17
|
+
import { isHistoricMilestone, markStarAsked, pendingStarMilestone, recordLaunch, STAR_MILESTONES, usageSnapshot } from '../usageStats.js';
|
|
18
|
+
import { effectiveComboDisplay } from '../utils/keymap.js';
|
|
14
19
|
import { stringWidth } from '../ink/stringWidth.js';
|
|
15
20
|
import { BRAND, FLASH, ICE, PALE, sweep } from './shimmer.js';
|
|
16
21
|
import { STANDARD_FRAME_INDEX, WhaleArt } from './Whale.js';
|
|
22
|
+
import { WhaleGirlArt } from './WhaleGirl.js';
|
|
23
|
+
import { MAID_BOX_CENTER, MaidPortrait, useMaidPortraits } from './maidPortrait.js';
|
|
17
24
|
import { OPENING_SEQUENCES, pickOpeningSequence, WHALE_FRAME_INDEX } from './whaleFrames.js';
|
|
18
25
|
import { RESTING_POSE } from './whaleLayers.js';
|
|
19
26
|
import { initialWhaleIdleState, nextWhaleIdleStep, } from './whaleIdle.js';
|
|
@@ -35,14 +42,6 @@ const VERSION = (() => {
|
|
|
35
42
|
return '0.1.0';
|
|
36
43
|
}
|
|
37
44
|
})();
|
|
38
|
-
/** Below this width the whale hides and the header goes text-only. */
|
|
39
|
-
const WHALE_MIN_COLUMNS = 64;
|
|
40
|
-
/**
|
|
41
|
-
* Fixed whale box width: the tail-wag frames reach 4 columns further right
|
|
42
|
-
* than the standard pose, and a pinned width keeps the text column from
|
|
43
|
-
* shifting sideways during the opening animation.
|
|
44
|
-
*/
|
|
45
|
-
const FULL_WHALE_WIDTH = 40;
|
|
46
45
|
/**
|
|
47
46
|
* Center of the whale art's bounding box: sprite columns 3..34 (center
|
|
48
47
|
* 18.5) of the 40-wide box. The welcome tagline is indented so its own
|
|
@@ -54,6 +53,8 @@ const FULL_WHALE_WIDTH = 40;
|
|
|
54
53
|
* centered under the art too.
|
|
55
54
|
*/
|
|
56
55
|
const WHALE_CENTER = 18.5;
|
|
56
|
+
/** 「高兴鲸娘」停留时长(点她之后自动回安静版)。 */
|
|
57
|
+
const MAID_HAPPY_MS = 3000;
|
|
57
58
|
/** `max` → `Max` (effort levels arrive lower-case from the adapter). */
|
|
58
59
|
function capitalize(text) {
|
|
59
60
|
return text.length === 0 ? text : text[0].toUpperCase() + text.slice(1);
|
|
@@ -70,12 +71,23 @@ function capitalize(text) {
|
|
|
70
71
|
*
|
|
71
72
|
* Layout: the 13-row pixel whale beside a text column of matching height —
|
|
72
73
|
* the `✦ dsh-TUI` wordmark with version, the `DEEPSEEK`/`HARNESS` tagline in
|
|
73
|
-
* the 5-row block font (brand-blue → ice gradient
|
|
74
|
+
* the 5-row block font (brand-blue → ice gradient, a blank row between the
|
|
75
|
+
* two words, both stretched to the same width — see `splashFonts.ts` for the
|
|
76
|
+
* eight faces and the per-face kerning), the model/effort and
|
|
74
77
|
* cwd in plain text (no brand-color highlight), the startup tip, and below
|
|
75
78
|
* the whale the welcome tagline, centered under the art, in ice
|
|
76
|
-
* blue. Narrow terminals
|
|
79
|
+
* blue. Narrow terminals climb down the `resolveSplashLayout` ladder —
|
|
80
|
+
* whale + big text, then the big text alone, then the whale alone, then one
|
|
81
|
+
* plain title line. The face rotates by local date (`pickSplashFont`), so a
|
|
82
|
+
* given day always shows the same one.
|
|
83
|
+
*
|
|
84
|
+
* Two easter eggs sit on top of that layout without changing it (both live in
|
|
85
|
+
* `splashEggs.ts`): the holiday word pair swaps the two big-text words on its
|
|
86
|
+
* date (`MERRY` on 12/25, …), and a 1-in-20 roll replaces the welcome tagline
|
|
87
|
+
* with a clickable "star us on GitHub" line whose indent is recomputed from
|
|
88
|
+
* its own width.
|
|
77
89
|
*/
|
|
78
|
-
export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whale = true, whaleIdle = true, working = false, drift, }) {
|
|
90
|
+
export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, fontId, whale = true, whaleIdle = true, whaleGirl = false, starred = false, starReveal, onStarClick, working = false, drift, egg, starChance, }) {
|
|
79
91
|
// One intro per logo mount: the production path rolls (startup splash
|
|
80
92
|
// and each /deepseek replay roll independently), the `intro` seam pins
|
|
81
93
|
// a specific animation for probes.
|
|
@@ -134,13 +146,52 @@ export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whal
|
|
|
134
146
|
clearTimeout(timer);
|
|
135
147
|
};
|
|
136
148
|
}, [heartSeq, heartKey, settled, whaleIdle, whaleFrozen]);
|
|
149
|
+
/** 预览缝:`DSH_TUI_STAR_LINE=1` 时开屏就显示求 star 标语行(不记账)。 */
|
|
150
|
+
const starLinePreview = process.env.DSH_TUI_STAR_LINE === '1';
|
|
137
151
|
const [themeName] = useTheme();
|
|
152
|
+
/** 终端真底色(Sixel 不透明衬底;见渲染处的注释)。 */
|
|
138
153
|
const theme = getTheme(themeName);
|
|
139
154
|
const { columns } = useTerminalSize();
|
|
140
155
|
const wordmarkRGB = parseRGB(theme.accent) ?? BRAND;
|
|
141
156
|
const wordmarkShimmerRGB = parseRGB(theme.accentShimmer) ?? ICE;
|
|
142
157
|
const taglineRGB = parseRGB(theme.activity) ?? ICE;
|
|
143
|
-
|
|
158
|
+
// 按天轮换的大字字体:同一天内恒定、隔天换一款;`fontId`(设置项)可 pin 住一款。
|
|
159
|
+
const [dailyFont] = React.useState(() => pickSplashFont());
|
|
160
|
+
const font = fontId === undefined ? dailyFont : splashFontById(fontId);
|
|
161
|
+
// 节日彩蛋:本地日期整天恒定,每次 mount 只判一次(照 pickSplashFont 的写法)。
|
|
162
|
+
// 只换词——字身宽度不变、字距按新词重解,所以阶梯阈值也跟着当天真实标题宽度走。
|
|
163
|
+
const [dailyEgg] = React.useState(() => (egg === undefined ? pickSplashEgg() : egg));
|
|
164
|
+
const titleFont = dailyEgg === null ? font : withTagline(font, dailyEgg.top, dailyEgg.bottom);
|
|
165
|
+
// 窄终端阶梯:鲸鱼 + 大字 → 纯大字 → 纯鲸鱼 → 一行纯文字(阈值随字体字身宽度变)。
|
|
166
|
+
const { showWhale, showBigTitle, showPlainTitle } = resolveSplashLayout(columns, { whale, font: titleFont });
|
|
167
|
+
// 女仆娘档优先走**真图**(Kitty/Sixel 终端图像协议,见 `maidPortrait.tsx`);
|
|
168
|
+
// 协议不可用(内联模式、终端不支持)或资产解码失败时,回落到字符画版
|
|
169
|
+
// 女仆娘(`WhaleGirl.tsx` 半块精灵——作者占位,之后会换更好看的)。
|
|
170
|
+
// 两种形态都是静态立绘:闲置动画与点击爱心仍是鲸鱼专属。
|
|
171
|
+
// `maidImageActive` 只在「真图画出来了」时为真。
|
|
172
|
+
const imagesAvailable = useTerminalImages(whaleGirl);
|
|
173
|
+
const portraits = useMaidPortraits(whaleGirl && imagesAvailable);
|
|
174
|
+
const maidSource = portraits?.normal;
|
|
175
|
+
const maidImageActive = whaleGirl && imagesAvailable && maidSource !== undefined;
|
|
176
|
+
// 点一下她 → 换成「高兴鲸娘」几秒(自动回安静版;第一个任务后定格、
|
|
177
|
+
// 不再响应,与鲸鱼的规则一致)。定时器在卸载/重挂时清掉。
|
|
178
|
+
const [maidHappy, setMaidHappy] = React.useState(false);
|
|
179
|
+
const maidHappyTimerRef = React.useRef(null);
|
|
180
|
+
const reactMaid = React.useCallback(() => {
|
|
181
|
+
setMaidHappy(true);
|
|
182
|
+
if (maidHappyTimerRef.current !== null)
|
|
183
|
+
clearTimeout(maidHappyTimerRef.current);
|
|
184
|
+
const timer = setTimeout(() => {
|
|
185
|
+
maidHappyTimerRef.current = null;
|
|
186
|
+
setMaidHappy(false);
|
|
187
|
+
}, MAID_HAPPY_MS);
|
|
188
|
+
timer.unref?.();
|
|
189
|
+
maidHappyTimerRef.current = timer;
|
|
190
|
+
}, []);
|
|
191
|
+
React.useEffect(() => () => {
|
|
192
|
+
if (maidHappyTimerRef.current !== null)
|
|
193
|
+
clearTimeout(maidHappyTimerRef.current);
|
|
194
|
+
}, []);
|
|
144
195
|
// Welcome-phase idle behaviors (settings `dsh-tui.whaleIdle`): fin
|
|
145
196
|
// flutters, tail thumps and blinks while idle, and a sleep-Z loop after
|
|
146
197
|
// sustained inactivity — all as INDEPENDENT layers composed per tick
|
|
@@ -156,7 +207,9 @@ export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whal
|
|
|
156
207
|
const pendingHeartRef = React.useRef(false);
|
|
157
208
|
const tickRef = React.useRef(null);
|
|
158
209
|
React.useEffect(() => {
|
|
159
|
-
|
|
210
|
+
// 女仆娘档(真图或字符画)没有闲置规划器:立绘是静态的,开屏定格
|
|
211
|
+
// 后不给她留任何定时器。
|
|
212
|
+
if (!settled || !whaleIdle || !showWhale || whaleFrozen || whaleGirl) {
|
|
160
213
|
setIdlePose(null);
|
|
161
214
|
tickRef.current = null;
|
|
162
215
|
return;
|
|
@@ -187,7 +240,7 @@ export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whal
|
|
|
187
240
|
if (timer !== undefined)
|
|
188
241
|
clearTimeout(timer);
|
|
189
242
|
};
|
|
190
|
-
}, [settled, whaleIdle, showWhale, working, whaleFrozen]);
|
|
243
|
+
}, [settled, whaleIdle, showWhale, working, whaleFrozen, whaleGirl]);
|
|
191
244
|
// Render priority: the layered planner pose owns the settled header while
|
|
192
245
|
// it runs (hearts and blinks compose over the body planes). Otherwise a
|
|
193
246
|
// click heart plays as whole heart frames over the intro — or over the
|
|
@@ -201,6 +254,55 @@ export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whal
|
|
|
201
254
|
// off-screen, leaving the static gradient behind.
|
|
202
255
|
const t = settled ? 0 : time;
|
|
203
256
|
const tagline = tr('logo-tagline');
|
|
257
|
+
// 求 star 改由**本机用量里程碑**触发(累计启动次数 / 累计在线时长),不再每次随机:
|
|
258
|
+
// 跨档时只报最高那一档、每档只报一次(`usageStats` 记账)。`starChance` 退化成测试缝
|
|
259
|
+
// ——0 关掉、非 0 强开(强开时用最高那档的文案)。`DSH_TUI_STAR_LINE=1`
|
|
260
|
+
// 是给人看效果的预览缝:强开标语行且**不记账**(生产不设这个变量)。
|
|
261
|
+
const [starMilestone] = React.useState(() => {
|
|
262
|
+
const usage = recordLaunch();
|
|
263
|
+
if (starLinePreview)
|
|
264
|
+
return STAR_MILESTONES.length - 1;
|
|
265
|
+
if (starChance === 0)
|
|
266
|
+
return null;
|
|
267
|
+
if (starChance !== undefined)
|
|
268
|
+
return STAR_MILESTONES.length - 1;
|
|
269
|
+
const pending = pendingStarMilestone(usage);
|
|
270
|
+
// 历史性时刻(99h / 999 次)不走标语行——那两档归 Chat 的开屏弹窗
|
|
271
|
+
//(弹窗自己 markStarAsked)。这里既不画也不记,档位保持待报;
|
|
272
|
+
// 弹窗这轮没机会弹(回合中等)就留给下一次启动。
|
|
273
|
+
return pending !== null && isHistoricMilestone(pending) ? null : pending;
|
|
274
|
+
});
|
|
275
|
+
const starLine = starMilestone === null
|
|
276
|
+
? null
|
|
277
|
+
: splashStarLine({ usage: usageSnapshot(), keyHint: effectiveComboDisplay('star'), caught: starred });
|
|
278
|
+
// 彩蛋的渐显:标题先出,数字一秒后、求星行两秒后各跟一行(只在标语块
|
|
279
|
+
// 出现时播一次;本次会话已 star 过、或重挂时直接展开)。
|
|
280
|
+
const starLineActive = starLine !== null;
|
|
281
|
+
const starRevealInstant = starReveal === 'instant';
|
|
282
|
+
const [revealed, setRevealed] = React.useState(() => (starRevealInstant ? 2 : 0));
|
|
283
|
+
React.useEffect(() => {
|
|
284
|
+
if (!starLineActive)
|
|
285
|
+
return;
|
|
286
|
+
if (starRevealInstant || starred === true) {
|
|
287
|
+
setRevealed(2);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const timers = [
|
|
291
|
+
setTimeout(() => setRevealed(previous => Math.max(previous, 1)), 1000),
|
|
292
|
+
setTimeout(() => setRevealed(previous => Math.max(previous, 2)), 2000),
|
|
293
|
+
];
|
|
294
|
+
for (const timer of timers)
|
|
295
|
+
timer.unref?.();
|
|
296
|
+
return () => { for (const timer of timers)
|
|
297
|
+
clearTimeout(timer); };
|
|
298
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- 只在标语块出现时播一次
|
|
299
|
+
}, [starLineActive]);
|
|
300
|
+
// 显示过就把这一档记下来,下次启动不再冒出来(同档只求一次)。预览缝
|
|
301
|
+
// (`DSH_TUI_STAR_LINE=1`)不记账——那是给人看效果的,不该消耗档位。
|
|
302
|
+
React.useEffect(() => {
|
|
303
|
+
if (starMilestone !== null && !starLinePreview)
|
|
304
|
+
markStarAsked(starMilestone);
|
|
305
|
+
}, [starMilestone]);
|
|
204
306
|
// One random tip per mount: the settled header must not re-roll on every
|
|
205
307
|
// repaint (language switch, terminal resize), or the line would flicker.
|
|
206
308
|
// `tip` is a test seam; production always passes undefined and rolls.
|
|
@@ -209,20 +311,42 @@ export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whal
|
|
|
209
311
|
// the same memoized contract data the adapter checks (undefined when the
|
|
210
312
|
// install matches). `drift` is a test seam to pin or suppress it.
|
|
211
313
|
const [driftLine] = React.useState(() => drift === undefined ? upstreamDriftSummary() : drift);
|
|
212
|
-
// Indent that centers the tagline under the whale art's bounding box
|
|
314
|
+
// Indent that centers the tagline under the whale art's bounding box, from
|
|
315
|
+
// the width the line ACTUALLY shows: the star easter egg renders a longer
|
|
316
|
+
// line than `logo-tagline`, so reusing the tagline's width would push it
|
|
317
|
+
// visibly off-center.
|
|
318
|
+
const welcomeWidth = starLine === null ? stringWidth(tagline) : starLine.width;
|
|
213
319
|
const welcomePad = showWhale
|
|
214
|
-
? Math.max(0, Math.round(WHALE_CENTER -
|
|
320
|
+
? Math.max(0, Math.round((whaleGirl ? MAID_BOX_CENTER : WHALE_CENTER) - welcomeWidth / 2))
|
|
215
321
|
: 2;
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
322
|
+
// 两行标题各自用字体声明的字距;下排再按 `bottomIndent` 居中——
|
|
323
|
+
// 两者一起保证画出来的列数相等(见 splashFonts 的 tagline 契约)。
|
|
324
|
+
// 节日彩蛋换的就是这里的两排词(`titleFont` 已按当天词对重解字距);字体若自带
|
|
325
|
+
// 配色(半立体那款的灰阶)就用它,否则沿用主题的 accent→activity。
|
|
326
|
+
const { top, bottom, topKerning, bottomKerning, bottomIndent } = titleFont.tagline;
|
|
327
|
+
const bigDeepSeek = renderBigText(titleFont, top, t, titleFont.palette?.from ?? wordmarkRGB, titleFont.palette?.to ?? taglineRGB, FLASH, 60, topKerning);
|
|
328
|
+
const bigHarness = renderBigText(titleFont, bottom, t, titleFont.palette?.from ?? taglineRGB, titleFont.palette?.to ?? PALE, FLASH, 60, bottomKerning, bottomIndent);
|
|
329
|
+
// 立绘槽位的**唯一真源**:文字列的实际行数——词标 1 + 两排大字 + 两排
|
|
330
|
+
// 之间空 1 行 + 模型/目录/提示 3 行。槽位与它等高,图片既不压过文字列
|
|
331
|
+
// 也不留一截在下面(实机反馈「超出去、不和谐」);大字换字体/换词时也
|
|
332
|
+
// 自动跟着变,不写死 15。
|
|
333
|
+
const textColumnRows = bigDeepSeek.length + bigHarness.length + 5;
|
|
334
|
+
return (_jsxs(Box, { ref: ref, flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { flexDirection: "row", gap: COLUMN_GAP, width: "100%", alignItems: "center", children: [showWhale && (_jsx(Box, { flexShrink: 0, onClick: () => {
|
|
219
335
|
// Frozen (first task started): the whale is a static logo —
|
|
220
336
|
// clicks do nothing. Settled: the layered planner consumes the
|
|
221
337
|
// click on its next tick — run that tick immediately so the
|
|
222
338
|
// heart shows instantly instead of after the current delay.
|
|
223
|
-
// Intro: the whole-frame heart pass above.
|
|
339
|
+
// Intro: the whole-frame heart pass above. The maid (raster)
|
|
340
|
+
// reacts with the happy portrait instead of hearts; character-
|
|
341
|
+
// art fallback stays static.
|
|
224
342
|
if (whaleFrozen)
|
|
225
343
|
return;
|
|
344
|
+
if (maidImageActive) {
|
|
345
|
+
reactMaid();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (whaleGirl)
|
|
349
|
+
return;
|
|
226
350
|
if (settled && whaleIdle) {
|
|
227
351
|
pendingHeartRef.current = true;
|
|
228
352
|
tickRef.current?.();
|
|
@@ -231,9 +355,9 @@ export function LogoV2({ model, effort, cwd, skipIntro = false, intro, tip, whal
|
|
|
231
355
|
setHeartSeq(0);
|
|
232
356
|
setHeartKey(k => k + 1);
|
|
233
357
|
}
|
|
234
|
-
}, children: _jsx(WhaleArt, { frameIndex: frameIndex, pose: settled && whaleIdle && !whaleFrozen ? (idlePose ?? RESTING_POSE) : undefined, width:
|
|
358
|
+
}, children: whaleGirl ? (_jsx(Box, { width: WHALE_BOX_WIDTH, height: textColumnRows, flexDirection: "row", justifyContent: "center", alignItems: "center", children: maidImageActive ? (_jsx(MaidPortrait, { source: maidHappy ? (portraits?.happy ?? maidSource) : maidSource, maxColumns: WHALE_BOX_WIDTH, maxRows: textColumnRows, presentation: "transcript" })) : (_jsx(WhaleGirlArt, { width: WHALE_BOX_WIDTH })) })) : (_jsx(WhaleArt, { frameIndex: frameIndex, pose: settled && whaleIdle && !whaleFrozen ? (idlePose ?? RESTING_POSE) : undefined, width: WHALE_BOX_WIDTH })) })), (showBigTitle || showPlainTitle) && (_jsxs(Box, { flexDirection: "column", flexShrink: 1, children: [_jsxs(Text, { wrap: "truncate-end", children: [sweep('✦ dsh-TUI', t, wordmarkRGB, wordmarkShimmerRGB, 60), _jsx(Text, { dimColor: true, children: ' v' + VERSION })] }), showBigTitle ? (_jsxs(_Fragment, { children: [bigDeepSeek.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, `ds-${index}`))), _jsx(Box, { height: 1 }), bigHarness.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, `h-${index}`)))] })) : (showPlainTitle && (_jsx(Text, { color: "accent", bold: true, wrap: "truncate-end", children: "DeepSeek Harness" }))), _jsxs(Text, { wrap: "truncate-end", children: [model, effort !== undefined && _jsx(Text, { dimColor: true, children: ' · ' + capitalize(effort) + ' effort' })] }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: cwd }), _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { dimColor: true, children: tr('logo-tip-prefix') }), getLang() === 'zh' ? randomTip.zh : randomTip.en, _jsx(Text, { dimColor: true, children: ' · /tips ' + tr('logo-tip-more') })] }), driftLine != null && (_jsxs(Text, { color: "warning", wrap: "wrap", children: ["\u26A0", ' ', tOr(`logo-drift-${driftLine.kind}`, `The dsh engine (${driftLine.versions.join(' / ')}) does not match the validated ${UPSTREAM_VALIDATED_VERSION}; reinstall via npm i -g @deepseek-ai/dsh@${UPSTREAM_VALIDATED_VERSION}.`, {
|
|
235
359
|
installed: driftLine.versions.join(' / '),
|
|
236
360
|
validated: UPSTREAM_VALIDATED_VERSION,
|
|
237
361
|
primary: UPSTREAM_VALIDATED_VERSION,
|
|
238
|
-
})] }))] })] }), _jsx(Box, { marginTop: 1, paddingLeft: welcomePad, children: _jsx(Text, { children: sweep(tagline, t, taglineRGB, FLASH, 60) }) })] }));
|
|
362
|
+
})] }))] }))] }), _jsx(Box, { flexDirection: "column", marginTop: 1, ...(starLine === null || onStarClick === undefined ? {} : { onClick: onStarClick }), children: starLine === null ? (_jsx(Box, { paddingLeft: welcomePad, children: _jsx(Text, { children: sweep(tagline, t, taglineRGB, FLASH, 60) }) })) : (_jsxs(_Fragment, { children: [_jsx(Box, { paddingLeft: welcomePad, children: _jsx(Text, { children: sweep(starLine.title, t, taglineRGB, FLASH, 60) }) }), revealed >= 1 && (_jsx(Box, { paddingLeft: welcomePad, children: _jsx(Text, { dimColor: true, children: starLine.stats }) })), revealed >= 2 && starred !== true && starLine.ask !== null && (_jsx(Box, { paddingLeft: welcomePad, children: _jsx(Text, { children: starLine.ask }) }))] })) })] }));
|
|
239
363
|
}
|
|
@@ -4,8 +4,9 @@ import { type Token } from 'marked';
|
|
|
4
4
|
* Markdown 渲染组件:marked 分词 + ANSI 格式化。
|
|
5
5
|
*
|
|
6
6
|
* 表格 token 交给 MarkdownTable 渲染为带边框的 flexbox 布局,mermaid
|
|
7
|
-
* 代码块交给 MermaidDiagram 画成 box-drawing
|
|
8
|
-
*
|
|
7
|
+
* 代码块交给 MermaidDiagram 画成 box-drawing 图,`$$` 公式块交给
|
|
8
|
+
* MathBlock 排成多行 Unicode(三者都需要终端宽度,所以是独立节点而不是
|
|
9
|
+
* ANSI 字符串);行内公式在 formatToken 里转成单行 Unicode;
|
|
9
10
|
* 其余块级内容由 formatToken 转成 ANSI 字符串,按块边界分批放进
|
|
10
11
|
* Text(只去整段首尾空白)。代码块高亮由 cli-highlight 异步提供,
|
|
11
12
|
* 加载完成后自动触发一次重渲染。无 markdown 语法的纯文本走快速
|
|
@@ -17,6 +18,12 @@ type Props = {
|
|
|
17
18
|
dimColor?: boolean;
|
|
18
19
|
/** 为 false 时跳过 token 缓存(流式尾部的内容逐帧变化,缓存必然失效) */
|
|
19
20
|
cacheTokens?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Whether paragraphs may show inline math as images (`mathRendering:
|
|
23
|
+
* image`). Streaming text passes false: a paragraph switching to images
|
|
24
|
+
* mid-stream would re-wrap under the reader; the settled message switches.
|
|
25
|
+
*/
|
|
26
|
+
inlineMathImages?: boolean;
|
|
20
27
|
};
|
|
21
28
|
/**
|
|
22
29
|
* Tokens that render as their own layout node (a width-aware component)
|
|
@@ -36,7 +43,7 @@ export declare function isStandaloneToken(token: Token): boolean;
|
|
|
36
43
|
* block — the dominant long-output stall (string-width via wrap-ansi, 60%+
|
|
37
44
|
* of CPU in streaming profiles).
|
|
38
45
|
*/
|
|
39
|
-
declare function MarkdownImpl({ children, dimColor, cacheTokens }: Props): React.ReactNode;
|
|
46
|
+
declare function MarkdownImpl({ children, dimColor, cacheTokens, inlineMathImages }: Props): React.ReactNode;
|
|
40
47
|
/**
|
|
41
48
|
* Memoized Markdown: skips the whole token→ANSI→layout pipeline when the
|
|
42
49
|
* content string is the same reference (see MarkdownImpl's doc comment).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../../src/components/Markdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAU,KAAK,KAAK,EAAe,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../../src/components/Markdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAU,KAAK,KAAK,EAAe,MAAM,QAAQ,CAAA;AAYxD;;;;;;;;;;;GAWG;AAEH,KAAK,KAAK,GAAG;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,CAAA;AAyED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAEvD;AAuGD;;;;;;;;;;GAUG;AACH,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAgB,EAAE,WAAkB,EAAE,gBAAuB,EAAE,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CAkCzH;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ,gDAOpB,CAAA"}
|
|
@@ -5,8 +5,12 @@ import { Box, Text } from '../ui.js';
|
|
|
5
5
|
import { configureMarked, formatToken, stripPromptXMLTags } from '../terminal-utils/markdown.js';
|
|
6
6
|
import { getCliHighlightPromise } from '../terminal-utils/cliHighlight.js';
|
|
7
7
|
import { isMermaidLang } from '../terminal-utils/mermaid.js';
|
|
8
|
+
import { isMathBlockToken, isMathToken } from '../terminal-utils/math.js';
|
|
9
|
+
import { getMathRendering, subscribeMathRendering } from '../tuiDisplayPrefs.js';
|
|
8
10
|
import { MarkdownTable } from './MarkdownTable.js';
|
|
9
11
|
import { MermaidDiagram } from './MermaidDiagram.js';
|
|
12
|
+
import { InlineMathParagraph } from './InlineMathParagraph.js';
|
|
13
|
+
import { MathBlock } from './MathBlock.js';
|
|
10
14
|
// ---- token 缓存 ----
|
|
11
15
|
//
|
|
12
16
|
// marked.lexer 在组件重挂载时是最贵的开销;消息内容不可变,相同文本
|
|
@@ -23,13 +27,11 @@ const TOKEN_CACHE_MAX_SOURCE_LENGTH = 20_000;
|
|
|
23
27
|
const TEXT_BLOCK_BUDGET = 8192;
|
|
24
28
|
const tokenCache = new Map();
|
|
25
29
|
let tokenCacheChars = 0;
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
const MD_SYNTAX_MARKERS = /[#*`|[>\-_
|
|
29
|
-
const SYNTAX_PROBE_WINDOW = 500;
|
|
30
|
+
// 语法探针:全文都没有结构标记时才跳过 lexer,不能仅凭纯文本前缀
|
|
31
|
+
// 忽略后面的公式或 Markdown。`$` 与 `\` 覆盖 LaTeX 公式定界符。
|
|
32
|
+
const MD_SYNTAX_MARKERS = /[#*`|[>\-_~$\\]|\n\n|^\d+\. |\n\d+\. /;
|
|
30
33
|
function looksLikePlainText(s) {
|
|
31
|
-
|
|
32
|
-
return !MD_SYNTAX_MARKERS.test(probe);
|
|
34
|
+
return !MD_SYNTAX_MARKERS.test(s);
|
|
33
35
|
}
|
|
34
36
|
function lexWithCache(content, allowCache) {
|
|
35
37
|
// 快速路径:纯文本直接合成单个段落 token,不触碰 lexer。
|
|
@@ -81,19 +83,28 @@ function lexWithCache(content, allowCache) {
|
|
|
81
83
|
* rather than the newline-derived spacing of text blocks.
|
|
82
84
|
*/
|
|
83
85
|
export function isStandaloneToken(token) {
|
|
84
|
-
return token.type === 'table' || isMermaidToken(token);
|
|
86
|
+
return token.type === 'table' || isMermaidToken(token) || isMathBlockToken(token);
|
|
87
|
+
}
|
|
88
|
+
/** Whether a paragraph holds inline math anywhere in its inline tokens. */
|
|
89
|
+
function hasInlineMath(token) {
|
|
90
|
+
for (const child of token.tokens ?? []) {
|
|
91
|
+
if (isMathToken(child) || hasInlineMath(child))
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
85
95
|
}
|
|
86
96
|
function isMermaidToken(token) {
|
|
87
97
|
return token.type === 'code' && isMermaidLang(token.lang);
|
|
88
98
|
}
|
|
89
99
|
/**
|
|
90
|
-
* 把 lexer 产出的 token 列表转成 React 节点序列:table
|
|
91
|
-
*
|
|
100
|
+
* 把 lexer 产出的 token 列表转成 React 节点序列:table、mermaid 与公式块
|
|
101
|
+
* 独立渲染,其余 token 的 ANSI 文本按完整块分批拼接,只去整段首尾空白。
|
|
92
102
|
*/
|
|
93
|
-
function renderTokensToNodes(tokens, highlight, dimColor) {
|
|
103
|
+
function renderTokensToNodes(tokens, highlight, dimColor, inlineMathImages) {
|
|
94
104
|
const nodes = [];
|
|
95
105
|
let ansiText = '';
|
|
96
106
|
let textParts = [];
|
|
107
|
+
let afterOwnNode = false;
|
|
97
108
|
const flushAnsiText = () => {
|
|
98
109
|
if (!ansiText && textParts.length === 0)
|
|
99
110
|
return;
|
|
@@ -118,10 +129,26 @@ function renderTokensToNodes(tokens, highlight, dimColor) {
|
|
|
118
129
|
textParts = [];
|
|
119
130
|
};
|
|
120
131
|
for (const token of tokens) {
|
|
132
|
+
const ownNodeBefore = afterOwnNode;
|
|
133
|
+
afterOwnNode = false;
|
|
121
134
|
if (token.type === 'table') {
|
|
122
135
|
flushAnsiText();
|
|
123
136
|
nodes.push(_jsx(MarkdownTable, { token: token, highlight: highlight }, nodes.length));
|
|
124
137
|
}
|
|
138
|
+
else if (inlineMathImages && token.type === 'paragraph' && hasInlineMath(token)) {
|
|
139
|
+
flushAnsiText();
|
|
140
|
+
nodes.push(_jsx(InlineMathParagraph, { token: token, highlight: highlight }, nodes.length));
|
|
141
|
+
afterOwnNode = true;
|
|
142
|
+
}
|
|
143
|
+
else if (ownNodeBefore && token.type === 'space') {
|
|
144
|
+
// The blank line after a paragraph that became its own node is the
|
|
145
|
+
// column gap now; as text it would flush as an empty node (an extra
|
|
146
|
+
// gap row). In a text run the same newline is trimmed at the flush.
|
|
147
|
+
}
|
|
148
|
+
else if (isMathBlockToken(token)) {
|
|
149
|
+
flushAnsiText();
|
|
150
|
+
nodes.push(_jsx(MathBlock, { token: token, dimColor: dimColor }, nodes.length));
|
|
151
|
+
}
|
|
125
152
|
else if (isMermaidToken(token)) {
|
|
126
153
|
flushAnsiText();
|
|
127
154
|
nodes.push(_jsx(MermaidDiagram, { token: token, highlight: highlight, dimColor: dimColor }, nodes.length));
|
|
@@ -150,8 +177,11 @@ function renderTokensToNodes(tokens, highlight, dimColor) {
|
|
|
150
177
|
* block — the dominant long-output stall (string-width via wrap-ansi, 60%+
|
|
151
178
|
* of CPU in streaming profiles).
|
|
152
179
|
*/
|
|
153
|
-
function MarkdownImpl({ children, dimColor = false, cacheTokens = true }) {
|
|
180
|
+
function MarkdownImpl({ children, dimColor = false, cacheTokens = true, inlineMathImages = true }) {
|
|
154
181
|
const [highlight, setHighlight] = React.useState(null);
|
|
182
|
+
// Inline math is baked into the ANSI text, so the switch must invalidate
|
|
183
|
+
// the memo below (MathBlock nodes subscribe on their own).
|
|
184
|
+
const mathRendering = React.useSyncExternalStore(subscribeMathRendering, getMathRendering);
|
|
155
185
|
React.useEffect(() => {
|
|
156
186
|
let mounted = true;
|
|
157
187
|
void getCliHighlightPromise().then((loaded) => {
|
|
@@ -165,8 +195,10 @@ function MarkdownImpl({ children, dimColor = false, cacheTokens = true }) {
|
|
|
165
195
|
configureMarked();
|
|
166
196
|
const renderedNodes = React.useMemo(() => {
|
|
167
197
|
const source = stripPromptXMLTags(children);
|
|
168
|
-
return renderTokensToNodes(lexWithCache(source, cacheTokens), highlight, dimColor
|
|
169
|
-
|
|
198
|
+
return renderTokensToNodes(lexWithCache(source, cacheTokens), highlight, dimColor,
|
|
199
|
+
// Dimmed text (thinking) cannot dim an image, so it keeps Unicode.
|
|
200
|
+
inlineMathImages && mathRendering === 'image' && !dimColor);
|
|
201
|
+
}, [children, dimColor, highlight, cacheTokens, mathRendering, inlineMathImages]);
|
|
170
202
|
return (_jsx(Box, { flexDirection: "column", gap: 1, children: renderedNodes }));
|
|
171
203
|
}
|
|
172
204
|
/**
|
|
@@ -175,4 +207,5 @@ function MarkdownImpl({ children, dimColor = false, cacheTokens = true }) {
|
|
|
175
207
|
*/
|
|
176
208
|
export const Markdown = React.memo(MarkdownImpl, (prev, next) => prev.children === next.children &&
|
|
177
209
|
prev.dimColor === next.dimColor &&
|
|
178
|
-
prev.cacheTokens === next.cacheTokens
|
|
210
|
+
prev.cacheTokens === next.cacheTokens &&
|
|
211
|
+
prev.inlineMathImages === next.inlineMathImages);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type MathToken } from '../terminal-utils/math.js';
|
|
3
|
+
type Props = {
|
|
4
|
+
token: MathToken;
|
|
5
|
+
dimColor: boolean;
|
|
6
|
+
/** Override terminal width (useful for testing). */
|
|
7
|
+
forceWidth?: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function MathBlock({ token, dimColor, forceWidth }: Props): React.ReactNode;
|
|
10
|
+
/** A theme color as `#rrggbb`, or undefined for ANSI names the image cannot match. */
|
|
11
|
+
export declare function themeInkHex(color: string): string | undefined;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=MathBlock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MathBlock.d.ts","sourceRoot":"","sources":["../../../src/components/MathBlock.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,2BAA2B,CAAA;AA+B/F,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,KAAK,GAAG,KAAK,CAAC,SAAS,CA+FjF;AAgCD,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK7D"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Box, Image, Text, useTerminalImageCellSize, useTerminalImages } from '../ui.js';
|
|
4
|
+
import { useTerminalSize } from '../ink/hooks/use-terminal-size.js';
|
|
5
|
+
import { stringWidth } from '../ink/stringWidth.js';
|
|
6
|
+
import { peekMathRaster, renderMathRaster } from '../math/renderer.js';
|
|
7
|
+
import { getTheme } from '../theme.js';
|
|
8
|
+
import { LARGE_DISPLAY_EX_TO_CELL_HEIGHT, XLARGE_DISPLAY_EX_TO_CELL_HEIGHT } from '../math/layout.js';
|
|
9
|
+
import { renderDisplayMath, renderInlineMath } from '../terminal-utils/math.js';
|
|
10
|
+
import { getMathImageBacking, getMathImageScale, getMathRendering, subscribeMathImageBacking, subscribeMathImageScale, subscribeMathRendering } from '../tuiDisplayPrefs.js';
|
|
11
|
+
import { useTerminalBackground, useTheme } from './design-system/ThemeProvider.js';
|
|
12
|
+
import { useMathPreviewOpener } from './mathPreview.js';
|
|
13
|
+
/**
|
|
14
|
+
* A `$$…$$` / `\[…\]` block rendered as display-mode Unicode: fractions and
|
|
15
|
+
* operator limits stacked over several rows, indented like a code-block body.
|
|
16
|
+
* The indent is layout padding rather than leading spaces, so a wrapped
|
|
17
|
+
* single-line fallback keeps it on every row.
|
|
18
|
+
*
|
|
19
|
+
* A stacked layout cannot wrap, so when it is wider than the viewport the
|
|
20
|
+
* block falls back to the single-line form (which wraps like prose), and
|
|
21
|
+
* when there is none of that either, to the exact source. The source is also
|
|
22
|
+
* what shows while the block is still streaming (no closer yet), when the
|
|
23
|
+
* formula is unsupported, and when the setting is off.
|
|
24
|
+
*
|
|
25
|
+
* With `mathRendering: image`, a complete block is typeset by MathJax and
|
|
26
|
+
* shown as a terminal image in the theme's text color when the terminal
|
|
27
|
+
* supports graphics and reports its cell size. The Unicode rendering shows
|
|
28
|
+
* until the image is ready and stays whenever any step fails, so the image
|
|
29
|
+
* path can only upgrade a block, never lose it.
|
|
30
|
+
*/
|
|
31
|
+
/** Same viewport slack MarkdownTable and MermaidDiagram keep. */
|
|
32
|
+
const SAFETY_MARGIN = 4;
|
|
33
|
+
/** Left padding in columns, matching the code-block body indent. */
|
|
34
|
+
const INDENT_WIDTH = 2;
|
|
35
|
+
/** Tallest image a block may take; taller formulas shrink to fit. */
|
|
36
|
+
const IMAGE_MAX_ROWS = 16;
|
|
37
|
+
export function MathBlock({ token, dimColor, forceWidth }) {
|
|
38
|
+
const mode = React.useSyncExternalStore(subscribeMathRendering, getMathRendering);
|
|
39
|
+
// Display size is a user choice now (settings `mathImageScale`): bigger
|
|
40
|
+
// images are also the only way a terminal gets more pixels per stroke.
|
|
41
|
+
const imageScale = React.useSyncExternalStore(subscribeMathImageScale, getMathImageScale);
|
|
42
|
+
const exToCellHeight = imageScale === 'xlarge'
|
|
43
|
+
? XLARGE_DISPLAY_EX_TO_CELL_HEIGHT
|
|
44
|
+
: imageScale === 'large' ? LARGE_DISPLAY_EX_TO_CELL_HEIGHT : undefined;
|
|
45
|
+
// What sits behind the formula: transparent (only its own pixels) or the
|
|
46
|
+
// terminal's own background colour, composited first.
|
|
47
|
+
const backdrop = React.useSyncExternalStore(subscribeMathImageBacking, getMathImageBacking);
|
|
48
|
+
const composited = backdrop === 'terminal';
|
|
49
|
+
const terminalBackground = useTerminalBackground();
|
|
50
|
+
const enabled = mode !== 'source';
|
|
51
|
+
const { columns } = useTerminalSize();
|
|
52
|
+
const width = Math.max(0, forceWidth ?? columns);
|
|
53
|
+
const renderable = enabled && token.pending !== true;
|
|
54
|
+
const budget = width - INDENT_WIDTH - SAFETY_MARGIN;
|
|
55
|
+
// Dimmed blocks (e.g. inside thinking) keep text: an image cannot dim.
|
|
56
|
+
const wantImage = mode === 'image' && renderable && !dimColor && budget > 0;
|
|
57
|
+
const graphics = useTerminalImages(wantImage);
|
|
58
|
+
const cellSize = useTerminalImageCellSize();
|
|
59
|
+
const [themeName] = useTheme();
|
|
60
|
+
const color = themeInkHex(getTheme(themeName).text);
|
|
61
|
+
const request = wantImage && graphics && cellSize !== undefined && color !== undefined
|
|
62
|
+
? {
|
|
63
|
+
tex: token.text, display: true, color, cellSize, maxColumns: budget, maxRows: IMAGE_MAX_ROWS,
|
|
64
|
+
...(exToCellHeight === undefined ? {} : { baseExToCellHeight: exToCellHeight }),
|
|
65
|
+
}
|
|
66
|
+
: undefined;
|
|
67
|
+
const raster = useMathRaster(request);
|
|
68
|
+
const previewMath = useMathPreviewOpener();
|
|
69
|
+
// Layout is width-independent; a resize only re-checks the fit.
|
|
70
|
+
const lines = React.useMemo(() => (renderable ? renderDisplayMath(token.text) : undefined), [renderable, token.text]);
|
|
71
|
+
if (raster !== undefined && request !== undefined) {
|
|
72
|
+
// What the box shows when the renderer does not place the image (e.g. a
|
|
73
|
+
// Kitty image partly scrolled out before cropping is available): the
|
|
74
|
+
// stacked Unicode layout when it fits the box, else the one-line form
|
|
75
|
+
// wrapped across it, so every visible row of the box carries the formula.
|
|
76
|
+
const stackedFits = lines !== undefined && lines.length <= raster.rows &&
|
|
77
|
+
lines.every(line => stringWidth(line) <= raster.columns);
|
|
78
|
+
const painted = (_jsx(Image, { ...(composited ? {} : { transparent: true }), presentation: "transcript", source: raster.source, width: raster.columns, height: raster.rows, alt: token.text, copyText: token.raw.trim(), children: _jsx(Box, { width: raster.columns, height: raster.rows, overflow: "hidden", children: _jsx(Text, { dimColor: true, wrap: stackedFits ? 'truncate' : 'wrap', children: stackedFits ? lines.join('\n') : renderInlineMath(token.text) ?? token.text }) }) }));
|
|
79
|
+
// A composited formula needs a real surface: the slot carries the terminal
|
|
80
|
+
// background, so both the placement and its cells use that colour.
|
|
81
|
+
const image = composited
|
|
82
|
+
? (_jsx(Box, { width: raster.columns, height: raster.rows, flexShrink: 0, backgroundColor: terminalBackground, children: painted }))
|
|
83
|
+
: painted;
|
|
84
|
+
return (_jsx(Box, { paddingLeft: INDENT_WIDTH, children: previewMath === undefined
|
|
85
|
+
? image
|
|
86
|
+
: (_jsx(Box, { onClick: event => { event.stopImmediatePropagation(); previewMath({ tex: token.text, request, source: raster.source }); }, children: image })) }));
|
|
87
|
+
}
|
|
88
|
+
if (lines !== undefined && lines.every(line => stringWidth(line) <= budget)) {
|
|
89
|
+
return (_jsx(Box, { paddingLeft: INDENT_WIDTH, children: _jsx(Text, { dimColor: dimColor, children: lines.join('\n') }) }));
|
|
90
|
+
}
|
|
91
|
+
const linear = renderable && lines !== undefined ? renderInlineMath(token.text) : undefined;
|
|
92
|
+
if (linear !== undefined) {
|
|
93
|
+
return (_jsx(Box, { paddingLeft: INDENT_WIDTH, children: _jsx(Text, { dimColor: dimColor, children: linear }) }));
|
|
94
|
+
}
|
|
95
|
+
return _jsx(Text, { dimColor: dimColor, children: token.raw.trim() });
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The typeset image for `request`, or undefined while it renders, when it
|
|
99
|
+
* failed, or when there is no request. A cached result is used on the first
|
|
100
|
+
* render, so a block scrolled back into view does not flash its fallback.
|
|
101
|
+
*/
|
|
102
|
+
function useMathRaster(request) {
|
|
103
|
+
const cached = request === undefined ? undefined : peekMathRaster(request);
|
|
104
|
+
const [settled, setSettled] = React.useState();
|
|
105
|
+
const pending = request !== undefined && cached === undefined ? request : undefined;
|
|
106
|
+
const key = pending === undefined ? undefined : requestKey(pending);
|
|
107
|
+
React.useEffect(() => {
|
|
108
|
+
if (pending === undefined)
|
|
109
|
+
return;
|
|
110
|
+
let live = true;
|
|
111
|
+
void renderMathRaster(pending).then(result => {
|
|
112
|
+
if (live)
|
|
113
|
+
setSettled({ request: pending, raster: result.ok ? result.raster : undefined });
|
|
114
|
+
});
|
|
115
|
+
return () => { live = false; };
|
|
116
|
+
// `key` captures every field of the request.
|
|
117
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
118
|
+
}, [key]);
|
|
119
|
+
if (cached !== undefined)
|
|
120
|
+
return cached.ok ? cached.raster : undefined;
|
|
121
|
+
return settled !== undefined && request !== undefined && requestKey(settled.request) === requestKey(request)
|
|
122
|
+
? settled.raster
|
|
123
|
+
: undefined;
|
|
124
|
+
}
|
|
125
|
+
function requestKey(request) {
|
|
126
|
+
return [request.tex, request.color, request.cellSize.width, request.cellSize.height, request.maxColumns, request.maxRows, request.baseExToCellHeight ?? ''].join('\u0000');
|
|
127
|
+
}
|
|
128
|
+
/** A theme color as `#rrggbb`, or undefined for ANSI names the image cannot match. */
|
|
129
|
+
export function themeInkHex(color) {
|
|
130
|
+
if (/^#[0-9a-f]{6}$/i.test(color))
|
|
131
|
+
return color;
|
|
132
|
+
const match = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/.exec(color);
|
|
133
|
+
if (match === null)
|
|
134
|
+
return undefined;
|
|
135
|
+
return `#${match.slice(1, 4).map(channel => Math.min(255, Number(channel)).toString(16).padStart(2, '0')).join('')}`;
|
|
136
|
+
}
|
|
@@ -129,13 +129,22 @@ export declare function MessageList({ rows, expanded, expandedRows, selectedId,
|
|
|
129
129
|
* welcome line. It scrolls away with the transcript once the conversation
|
|
130
130
|
* fills the viewport.
|
|
131
131
|
*/
|
|
132
|
-
export declare function LogoHeader({ model, effort, cwd, whale, whaleIdle, working, skipIntro, }: {
|
|
132
|
+
export declare function LogoHeader({ model, effort, cwd, fontId, whale, whaleIdle, whaleGirl, starred, onStarClick, working, skipIntro, }: {
|
|
133
133
|
model: string;
|
|
134
134
|
effort?: string | undefined;
|
|
135
135
|
cwd: string;
|
|
136
|
+
/** Big-text face pin (settings `dsh-tui.splashFont`; `undefined` leaves
|
|
137
|
+
* `LogoV2` on its date rotation). Passed through to LogoV2. */
|
|
138
|
+
fontId?: string | undefined;
|
|
136
139
|
whale?: boolean;
|
|
137
140
|
/** Idle whale behaviors + working signal (passed through to LogoV2). */
|
|
138
141
|
whaleIdle?: boolean;
|
|
142
|
+
/** Maid portrait swap (passed through to LogoV2; settings `dsh-tui.whaleGirl`). */
|
|
143
|
+
whaleGirl?: boolean;
|
|
144
|
+
/** 求 star 标语行被点击(一键 star;host 不传则不可点)。 */
|
|
145
|
+
onStarClick?: () => void;
|
|
146
|
+
/** 本次会话已 star(彩蛋换「捡到星星」版)。 */
|
|
147
|
+
starred?: boolean;
|
|
139
148
|
working?: boolean;
|
|
140
149
|
/** Jump straight to the settled header (long-session resume: the ~3.4s
|
|
141
150
|
* opening animation competes with transcript mount batches). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAEvC,OAAO,EAA8B,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAE3E,OAAO,KAAK,EAAE,OAAO,EAA8D,MAAM,2BAA2B,CAAA;AAEpH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAmB/C,OAAO,EAAe,KAAK,gBAAgB,EAAqB,MAAM,yBAAyB,CAAA;AAC/F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/MessageList.tsx"],"names":[],"mappings":"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"}
|