@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
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Box, Text, useInput, useTerminalImages, useTerminalSize } from '../ui.js';
|
|
4
|
+
import { getLang, subscribeLang, t } from '../i18n.js';
|
|
5
|
+
import { Divider } from './design-system/Divider.js';
|
|
6
|
+
import { HintLine } from './design-system/HintLine.js';
|
|
7
|
+
import { ListItem } from './design-system/ListItem.js';
|
|
8
|
+
import { MaidPortrait, useMaidPortraits } from './maidPortrait.js';
|
|
9
|
+
import { useTerminalBackground } from './design-system/ThemeProvider.js';
|
|
10
|
+
import { STANDARD_FRAME_INDEX, WhaleArt } from './Whale.js';
|
|
11
|
+
import { OPENING_SEQUENCES, WHALE_FRAME_INDEX } from './whaleFrames.js';
|
|
12
|
+
/** Art slot width — the pixel whale fallback is 40 columns wide, and the
|
|
13
|
+
* raster portrait fits inside the same slot so the card width never moves. */
|
|
14
|
+
const ART_COLUMNS = 40;
|
|
15
|
+
/** Art slot height: 18 rows (confetti 3 + whale 13 in the celebration), and
|
|
16
|
+
* the text column is pinned to the same height (see the column's comment). */
|
|
17
|
+
const ART_ROWS = 18;
|
|
18
|
+
/** Text column width: every copy line, button and hint stays on ONE row
|
|
19
|
+
* (the "排版不舒适" report: no stranded `⭐`, no mid-sentence breaks). */
|
|
20
|
+
const TEXT_COLUMNS = 48;
|
|
21
|
+
/** Portrait + text side by side need this many columns (art 40 + gap 2 +
|
|
22
|
+
* text 48 + card chrome 6); below that the card drops the art and stacks
|
|
23
|
+
* text at the narrower width. */
|
|
24
|
+
const MIN_ART_COLUMNS = 98;
|
|
25
|
+
/** Card height with the art (18 art rows + 2 border rows); terminals shorter
|
|
26
|
+
* than this + 2 margin rows get the text-only card. */
|
|
27
|
+
const MIN_ART_ROWS = 23;
|
|
28
|
+
/** Dwell on the standard pose before the fallback whale's intro loops. */
|
|
29
|
+
const WHALE_REST_MS = 3000;
|
|
30
|
+
/** How long the celebration stays before the card closes itself. */
|
|
31
|
+
const CELEBRATION_MS = 4200;
|
|
32
|
+
/**
|
|
33
|
+
* The one-time "asks for a star" startup modal (usage milestones `99h` /
|
|
34
|
+
* `999 launches`, see `usageStats.ts`). Chat mounts it over a dimmed
|
|
35
|
+
* click-catcher on boot when `dueStarModal()` says the moment arrived —
|
|
36
|
+
* never mid-turn, at most one milestone per boot, `Esc`/click-outside
|
|
37
|
+
* closes, and unmounting hands the keyboard straight back (nothing is left
|
|
38
|
+
* registered, so it cannot steal keys after closing).
|
|
39
|
+
*
|
|
40
|
+
* Composition follows the house design system: the milestone title sits in
|
|
41
|
+
* the card's top border, the two actions are `ListItem` rows (pointer,
|
|
42
|
+
* focus colour, hover background — the same component every picker uses),
|
|
43
|
+
* a `Divider` separates the footer, and the hint line is a `HintLine` with
|
|
44
|
+
* its bold key. The art slot shows the raster maid first, the animated
|
|
45
|
+
* pixel whale otherwise.
|
|
46
|
+
*
|
|
47
|
+
* A successful star switches the card into a short CELEBRATION instead of
|
|
48
|
+
* closing silently: confetti falls over the whale, which spouts on a loop,
|
|
49
|
+
* with a thank-you line — then the card closes itself. A failed attempt
|
|
50
|
+
* keeps the card open with the reason and the browser escape hatch.
|
|
51
|
+
*/
|
|
52
|
+
export function StarPrompt({ milestone, actions, onClose, initialPhase = 'ask', }) {
|
|
53
|
+
React.useSyncExternalStore(subscribeLang, getLang);
|
|
54
|
+
const { columns, rows } = useTerminalSize();
|
|
55
|
+
const imagesAvailable = useTerminalImages();
|
|
56
|
+
const portraits = useMaidPortraits(imagesAvailable);
|
|
57
|
+
const maidSource = portraits?.normal;
|
|
58
|
+
// 卡片底色用**终端真底色**(OSC 11)而不是主题的卡片色:后者是一整块
|
|
59
|
+
// 与终端背景无关的实色板,压在带背景图的终端上很僵硬;用真底色时卡片
|
|
60
|
+
// 与终端同色、只靠边框和暗化的背景区分层次,同时它也是真图立绘的不透明
|
|
61
|
+
// 衬底(Sixel 没有 alpha,透明像素得合成到某个实色上)。
|
|
62
|
+
const terminalBackground = useTerminalBackground();
|
|
63
|
+
const withArt = columns >= MIN_ART_COLUMNS && rows >= MIN_ART_ROWS;
|
|
64
|
+
const [phase, setPhase] = React.useState(initialPhase);
|
|
65
|
+
const [failure, setFailure] = React.useState('');
|
|
66
|
+
const [selected, setSelected] = React.useState(0);
|
|
67
|
+
// Some terminals report one Enter twice (parsed Return then raw CR); the
|
|
68
|
+
// modal must not fire its action twice for one press.
|
|
69
|
+
const lastEnterRef = React.useRef(0);
|
|
70
|
+
const live = React.useRef(true);
|
|
71
|
+
React.useEffect(() => () => { live.current = false; }, []);
|
|
72
|
+
const runStar = () => {
|
|
73
|
+
if (phase === 'working' || phase === 'done')
|
|
74
|
+
return;
|
|
75
|
+
setPhase('working');
|
|
76
|
+
void Promise.resolve(actions.onStar()).then(attempt => {
|
|
77
|
+
if (!live.current)
|
|
78
|
+
return;
|
|
79
|
+
if (attempt.kind === 'starred') {
|
|
80
|
+
setPhase('done');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
setFailure(attempt.kind === 'failed'
|
|
84
|
+
? t('star-failed', { detail: attempt.detail, url: attempt.url })
|
|
85
|
+
: t(attempt.kind === 'no-gh' ? 'star-no-gh' : 'star-not-authed', { url: attempt.url }));
|
|
86
|
+
// gh 缺失/未登录这类"本机没法一键"的结局:光标直接落到浏览器那一行,
|
|
87
|
+
// 用户按一下 Enter 就打开浏览器自己去点(不必先按 ↓)。
|
|
88
|
+
if (attempt.kind === 'no-gh' || attempt.kind === 'not-authed')
|
|
89
|
+
setSelected(1);
|
|
90
|
+
setPhase('failed');
|
|
91
|
+
}, (error) => {
|
|
92
|
+
if (!live.current)
|
|
93
|
+
return;
|
|
94
|
+
setFailure(t('star-failed', { detail: String(error), url: '' }));
|
|
95
|
+
setPhase('failed');
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
// The celebration bows out on its own; a key press closes it early.
|
|
99
|
+
React.useEffect(() => {
|
|
100
|
+
if (phase !== 'done')
|
|
101
|
+
return;
|
|
102
|
+
const timer = setTimeout(onClose, CELEBRATION_MS);
|
|
103
|
+
return () => { clearTimeout(timer); };
|
|
104
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- 只在进入庆祝时起表
|
|
105
|
+
}, [phase]);
|
|
106
|
+
useInput((input, key) => {
|
|
107
|
+
if (phase === 'done') {
|
|
108
|
+
onClose();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (key.escape) {
|
|
112
|
+
onClose();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (key.upArrow || key.downArrow || key.tab) {
|
|
116
|
+
setSelected(previous => (previous + 1) % 2);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (key.return) {
|
|
120
|
+
const now = Date.now();
|
|
121
|
+
if (now - lastEnterRef.current < 50)
|
|
122
|
+
return;
|
|
123
|
+
lastEnterRef.current = now;
|
|
124
|
+
if (selected === 0)
|
|
125
|
+
runStar();
|
|
126
|
+
else
|
|
127
|
+
actions.onOpen();
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
const textColumns = withArt ? TEXT_COLUMNS : Math.max(24, Math.min(TEXT_COLUMNS, columns - 6));
|
|
131
|
+
const cardColumns = withArt ? 96 : Math.min(columns, textColumns + 6);
|
|
132
|
+
// 卡片 = 艺术槽 + 上下边框。absolute 卡片的高度上限由**根节点高度**决定:
|
|
133
|
+
// 根只有内容高(内联模式的夹具)时,卡片顶端会被裁掉——夹具因此把 Chat
|
|
134
|
+
// 包在视口大小的 Box 里(真机 alt-screen 的根就是整屏)。
|
|
135
|
+
const cardRows = withArt ? ART_ROWS + 2 : 18;
|
|
136
|
+
const left = Math.max(0, Math.floor((columns - cardColumns) / 2));
|
|
137
|
+
const bottom = Math.max(0, Math.min(Math.floor((rows - cardRows) / 2), rows - cardRows));
|
|
138
|
+
const celebrating = phase === 'done';
|
|
139
|
+
const title = celebrating
|
|
140
|
+
? t('star-modal-thanks-title')
|
|
141
|
+
: milestone.hours !== undefined
|
|
142
|
+
? t('star-modal-title-hours', { hours: milestone.hours })
|
|
143
|
+
: t('star-modal-title-launches', { launches: milestone.launches ?? 0 });
|
|
144
|
+
return (_jsxs(_Fragment, { children: [_jsx(Box, { position: "absolute", bottom: 0, left: 0, width: "100%", height: rows, flexShrink: 0, backdrop: "dim", onClick: onClose }), _jsx(Box, { position: "absolute", left: left, bottom: bottom, width: cardColumns, height: cardRows, flexDirection: "column", flexShrink: 0, overflow: "hidden", backgroundColor: terminalBackground, opaque: true, onClick: event => { event.stopImmediatePropagation(); }, children: _jsxs(Box, { flexDirection: "row", gap: 2, alignItems: "center", justifyContent: "center", borderStyle: "round", borderColor: "inactive", paddingX: 2, backgroundColor: terminalBackground, children: [withArt && (_jsx(ArtSlot, { celebrating: celebrating, phase: phase, imagesAvailable: imagesAvailable, maidSource: maidSource, maidHappy: portraits?.happy, background: terminalBackground })), _jsxs(Box, { flexDirection: "column", width: textColumns, ...(withArt ? { height: ART_ROWS } : {}), children: [_jsx(Box, { height: 1, flexShrink: 0, children: _jsx(Text, { color: "accent", bold: true, wrap: "truncate-end", children: title }) }), _jsx(Box, { height: 1 }), celebrating ? (_jsxs(_Fragment, { children: [_jsx(Text, { wrap: "wrap", children: t('star-modal-thanks-1') }), _jsx(Box, { height: 1 }), _jsx(Text, { wrap: "wrap", children: t('star-modal-thanks-2') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-thanks-3') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-thanks-4') }), _jsx(Box, { flexGrow: 1 }), _jsx(Divider, { width: textColumns }), _jsx(Box, { height: 1 }), _jsx(Text, { dimColor: true, wrap: "wrap", children: _jsx(HintLine, { text: t('star-modal-thanks-hint') }) })] })) : (_jsxs(_Fragment, { children: [_jsx(Text, { wrap: "wrap", children: t('star-modal-body-1') }), _jsx(Box, { height: 1 }), _jsx(Text, { wrap: "wrap", children: t('star-modal-body-2') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-body-3') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-body-4') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-body-5') }), _jsx(Text, { wrap: "wrap", children: t('star-modal-body-6') }), _jsx(Box, { height: 1 }), _jsx(ListItem, { isFocused: selected === 0, disabled: phase === 'working', declareCursor: false, onClick: event => {
|
|
145
|
+
event.stopImmediatePropagation();
|
|
146
|
+
setSelected(0);
|
|
147
|
+
runStar();
|
|
148
|
+
}, children: phase === 'working' ? t('star-modal-working') : t('star-modal-star') }), _jsx(ListItem, { isFocused: selected === 1, declareCursor: false, onClick: event => {
|
|
149
|
+
event.stopImmediatePropagation();
|
|
150
|
+
setSelected(1);
|
|
151
|
+
actions.onOpen();
|
|
152
|
+
}, children: t('star-modal-open') }), phase === 'failed' && (_jsxs(_Fragment, { children: [_jsx(Box, { height: 1 }), _jsx(Text, { color: "error", wrap: "wrap", children: failure })] })), phase !== 'failed' && (_jsxs(_Fragment, { children: [_jsx(Box, { height: 1 }), _jsx(Divider, { width: textColumns })] })), _jsx(Box, { height: 1 }), _jsx(Text, { dimColor: true, wrap: "wrap", children: _jsx(HintLine, { text: t('star-modal-hint') }) })] }))] })] }) })] }));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The card's art column: the raster maid first, the animated pixel whale
|
|
156
|
+
* otherwise. While celebrating it shows the **happy maid** (raster→raster in
|
|
157
|
+
* the same pixel canvas, so the swap is a clean erase+draw) under the star
|
|
158
|
+
* field; without image protocols the whale spouts instead — character
|
|
159
|
+
* blocks never take this slot.
|
|
160
|
+
*/
|
|
161
|
+
function ArtSlot({ celebrating, phase, imagesAvailable, maidSource, maidHappy, background, }) {
|
|
162
|
+
const raster = imagesAvailable && maidSource !== undefined;
|
|
163
|
+
const frame = useWhaleFrames(celebrating && !raster ? 'celebrate' : raster || phase === 'working' ? 'none' : 'intro');
|
|
164
|
+
if (celebrating && raster) {
|
|
165
|
+
return (_jsxs(Box, { width: ART_COLUMNS, height: ART_ROWS, flexShrink: 0, flexDirection: "column", alignItems: "center", justifyContent: "center", backgroundColor: background, children: [_jsx(Confetti, { width: ART_COLUMNS }), _jsx(MaidPortrait, { source: maidHappy ?? maidSource, maxColumns: ART_COLUMNS, maxRows: ART_ROWS - CONFETTI_ROWS, presentation: "preview" })] }));
|
|
166
|
+
}
|
|
167
|
+
if (celebrating) {
|
|
168
|
+
return (_jsxs(Box, { width: ART_COLUMNS, height: ART_ROWS, flexShrink: 0, flexDirection: "column", alignItems: "center", justifyContent: "center", backgroundColor: background, opaque: true, children: [_jsx(Confetti, { width: ART_COLUMNS }), _jsx(WhaleArt, { frameIndex: frame, width: ART_COLUMNS })] }));
|
|
169
|
+
}
|
|
170
|
+
if (raster) {
|
|
171
|
+
return (_jsx(Box, { width: ART_COLUMNS, height: ART_ROWS, flexShrink: 0, flexDirection: "row", justifyContent: "center", alignItems: "center", children: _jsx(MaidPortrait, { source: maidSource, maxColumns: ART_COLUMNS, maxRows: ART_ROWS, presentation: "preview" }) }));
|
|
172
|
+
}
|
|
173
|
+
return (_jsx(Box, { width: ART_COLUMNS, height: ART_ROWS, flexShrink: 0, flexDirection: "row", justifyContent: "center", alignItems: "center", children: _jsx(WhaleArt, { frameIndex: frame, width: ART_COLUMNS }) }));
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Drive the art slot's frame: `intro` loops the classic opener with a rest
|
|
177
|
+
* on the standard pose, `celebrate` loops the water spout (the thank-you
|
|
178
|
+
* animation), `none` parks on the standard pose with no timer at all.
|
|
179
|
+
*/
|
|
180
|
+
function useWhaleFrames(mode) {
|
|
181
|
+
const [frame, setFrame] = React.useState(STANDARD_FRAME_INDEX);
|
|
182
|
+
React.useEffect(() => {
|
|
183
|
+
if (mode === 'none') {
|
|
184
|
+
setFrame(STANDARD_FRAME_INDEX);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const sequence = mode === 'celebrate' ? CELEBRATION_FRAMES : OPENING_SEQUENCES.classic;
|
|
188
|
+
let step = 0;
|
|
189
|
+
let timer;
|
|
190
|
+
const tick = () => {
|
|
191
|
+
const current = sequence[step] ?? sequence[0];
|
|
192
|
+
setFrame(current.frame);
|
|
193
|
+
const last = step === sequence.length - 1;
|
|
194
|
+
step = (step + 1) % sequence.length;
|
|
195
|
+
const rest = mode === 'celebrate' ? 0 : WHALE_REST_MS;
|
|
196
|
+
timer = setTimeout(tick, last ? (rest || current.ms) : current.ms);
|
|
197
|
+
timer.unref?.();
|
|
198
|
+
};
|
|
199
|
+
tick();
|
|
200
|
+
return () => { if (timer !== undefined)
|
|
201
|
+
clearTimeout(timer); };
|
|
202
|
+
}, [mode]);
|
|
203
|
+
return frame;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* The celebration loop, paced instead of frantic: the spout blooms up with
|
|
207
|
+
* easing (130→100ms), falls back slower (110→180ms), rests, then ONE gentle
|
|
208
|
+
* tail wag, then rests again——约 3.2s 一轮,与卡片的关闭时间同量级。
|
|
209
|
+
*/
|
|
210
|
+
const CELEBRATION_FRAMES = [
|
|
211
|
+
{ frame: WHALE_FRAME_INDEX.spout1, ms: 130 },
|
|
212
|
+
{ frame: WHALE_FRAME_INDEX.spout2, ms: 120 },
|
|
213
|
+
{ frame: WHALE_FRAME_INDEX.spout3, ms: 110 },
|
|
214
|
+
{ frame: WHALE_FRAME_INDEX.spout4, ms: 100 },
|
|
215
|
+
{ frame: WHALE_FRAME_INDEX.spout5, ms: 100 },
|
|
216
|
+
{ frame: WHALE_FRAME_INDEX.spout6, ms: 110 },
|
|
217
|
+
{ frame: WHALE_FRAME_INDEX.spout5, ms: 120 },
|
|
218
|
+
{ frame: WHALE_FRAME_INDEX.spout4, ms: 130 },
|
|
219
|
+
{ frame: WHALE_FRAME_INDEX.spout3, ms: 150 },
|
|
220
|
+
{ frame: WHALE_FRAME_INDEX.spout2, ms: 170 },
|
|
221
|
+
{ frame: WHALE_FRAME_INDEX.spout1, ms: 190 },
|
|
222
|
+
{ frame: STANDARD_FRAME_INDEX, ms: 620 },
|
|
223
|
+
{ frame: WHALE_FRAME_INDEX.tail1, ms: 180 },
|
|
224
|
+
{ frame: WHALE_FRAME_INDEX.tail2, ms: 200 },
|
|
225
|
+
{ frame: WHALE_FRAME_INDEX.tail3, ms: 200 },
|
|
226
|
+
{ frame: WHALE_FRAME_INDEX.tail4, ms: 180 },
|
|
227
|
+
{ frame: STANDARD_FRAME_INDEX, ms: 520 },
|
|
228
|
+
];
|
|
229
|
+
/** 星光两行、稀疏:主星(常亮,金色)+ 闪烁星(各列相位不同,同一帧只有
|
|
230
|
+
* 三分之一亮着)——比随机撒点安静,也比满屏星星精致。 */
|
|
231
|
+
const CONFETTI_GLYPHS = ['✦', '✧'];
|
|
232
|
+
const CONFETTI_COLORS = ['warning', 'accent', 'activity'];
|
|
233
|
+
const CONFETTI_FRAMES = 3;
|
|
234
|
+
const CONFETTI_ROWS = 2;
|
|
235
|
+
/** 每几列一颗主星(常亮)。 */
|
|
236
|
+
const CONFETTI_ANCHOR_STRIDE = 7;
|
|
237
|
+
const CONFETTI = Array.from({ length: CONFETTI_FRAMES }, (_, frameIndex) => Array.from({ length: CONFETTI_ROWS }, (_, row) => {
|
|
238
|
+
const runs = [];
|
|
239
|
+
let current = undefined;
|
|
240
|
+
let buffer = '';
|
|
241
|
+
for (let column = 0; column < ART_COLUMNS; column++) {
|
|
242
|
+
const anchor = column % CONFETTI_ANCHOR_STRIDE === 0;
|
|
243
|
+
// 闪烁星:每列一个固定相位,逐帧轮到自己亮一次(在 3 帧里亮 1 帧)。
|
|
244
|
+
const twinkle = !anchor
|
|
245
|
+
&& column % 2 === 0
|
|
246
|
+
&& (column / 2 + row) % CONFETTI_FRAMES === frameIndex;
|
|
247
|
+
const glyph = anchor ? CONFETTI_GLYPHS[0] : twinkle ? CONFETTI_GLYPHS[1] : ' ';
|
|
248
|
+
const color = anchor
|
|
249
|
+
? CONFETTI_COLORS[0]
|
|
250
|
+
: twinkle
|
|
251
|
+
? (column / 2) % 2 === 0 ? CONFETTI_COLORS[1] : CONFETTI_COLORS[2]
|
|
252
|
+
: undefined;
|
|
253
|
+
if (color !== current) {
|
|
254
|
+
if (buffer !== '')
|
|
255
|
+
runs.push({ text: buffer, color: current });
|
|
256
|
+
buffer = '';
|
|
257
|
+
current = color;
|
|
258
|
+
}
|
|
259
|
+
buffer += glyph;
|
|
260
|
+
}
|
|
261
|
+
if (buffer !== '')
|
|
262
|
+
runs.push({ text: buffer, color: current });
|
|
263
|
+
return runs;
|
|
264
|
+
}));
|
|
265
|
+
/** One confetti band, advancing a frame every 160ms while it is mounted. */
|
|
266
|
+
function Confetti({ width }) {
|
|
267
|
+
const frame = useConfettiFrame();
|
|
268
|
+
const rows = CONFETTI[frame] ?? CONFETTI[0];
|
|
269
|
+
return (_jsx(Box, { flexDirection: "column", flexShrink: 0, width: width, children: rows.map((runs, index) => (_jsx(Text, { wrap: "truncate-end", children: runs.map((run, runIndex) => (_jsx(Text, { color: run.color, children: run.text }, runIndex))) }, index))) }));
|
|
270
|
+
}
|
|
271
|
+
function useConfettiFrame() {
|
|
272
|
+
const [frame, setFrame] = React.useState(0);
|
|
273
|
+
React.useEffect(() => {
|
|
274
|
+
const timer = setInterval(() => {
|
|
275
|
+
setFrame(previous => (previous + 1) % CONFETTI_FRAMES);
|
|
276
|
+
}, 220);
|
|
277
|
+
timer.unref?.();
|
|
278
|
+
return () => { clearInterval(timer); };
|
|
279
|
+
}, []);
|
|
280
|
+
return frame;
|
|
281
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StreamingMarkdown.d.ts","sourceRoot":"","sources":["../../../src/components/StreamingMarkdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"StreamingMarkdown.d.ts","sourceRoot":"","sources":["../../../src/components/StreamingMarkdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAwMzB,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,QAAgB,GACjB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,GAAG,KAAK,CAAC,SAAS,CA2JlB"}
|
|
@@ -2,8 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { marked } from 'marked';
|
|
4
4
|
import Box from '../ink/components/Box.js';
|
|
5
|
-
import { formatToken, stripPromptXMLTags } from '../terminal-utils/markdown.js';
|
|
5
|
+
import { configureMarked, formatToken, stripPromptXMLTags } from '../terminal-utils/markdown.js';
|
|
6
6
|
import { t } from '../i18n.js';
|
|
7
|
+
import { isMathBlockToken, mayBecomeCodeSpan } from '../terminal-utils/math.js';
|
|
7
8
|
import { isStandaloneToken, Markdown } from './Markdown.js';
|
|
8
9
|
/**
|
|
9
10
|
* Renders streaming markdown in sealed groups of completed top-level blocks.
|
|
@@ -177,6 +178,9 @@ export function StreamingMarkdown({ children, dimColor = false, }) {
|
|
|
177
178
|
const prefixVisibleRef = React.useRef(false);
|
|
178
179
|
const prefixEndsWithNodeRef = React.useRef(false);
|
|
179
180
|
const prefixTrailingEmptyTextRef = React.useRef(false);
|
|
181
|
+
// The boundary lex below must see the same tokenizer extensions (math
|
|
182
|
+
// blocks) as the Markdown children, or the two disagree on block edges.
|
|
183
|
+
configureMarked();
|
|
180
184
|
const stripped = stripPromptXMLTags(children);
|
|
181
185
|
// Reset if text was replaced (defensive; normally unmount handles this)
|
|
182
186
|
if (!stripped.startsWith(prefixRef.current)) {
|
|
@@ -209,6 +213,19 @@ export function StreamingMarkdown({ children, dimColor = false, }) {
|
|
|
209
213
|
while (lastContentIdx >= 0 && tokens[lastContentIdx].type === 'space') {
|
|
210
214
|
lastContentIdx--;
|
|
211
215
|
}
|
|
216
|
+
// A block formula after a paragraph with an open backtick run is
|
|
217
|
+
// provisional until a blank line: the run's closer may still arrive and
|
|
218
|
+
// turn both into one code span, so the paragraph stays unsealed.
|
|
219
|
+
let consumed = 0;
|
|
220
|
+
for (let i = 0; i < lastContentIdx; i++) {
|
|
221
|
+
const token = tokens[i];
|
|
222
|
+
if (token.type === 'paragraph' && isMathBlockToken(tokens[i + 1]) &&
|
|
223
|
+
mayBecomeCodeSpan(token.raw, stripped.substring(boundary + consumed + token.raw.length))) {
|
|
224
|
+
lastContentIdx = i;
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
consumed += token.raw.length;
|
|
228
|
+
}
|
|
212
229
|
let advance = 0;
|
|
213
230
|
for (let i = 0; i < lastContentIdx; i++) {
|
|
214
231
|
advance += tokens[i].raw.length;
|
|
@@ -249,7 +266,7 @@ export function StreamingMarkdown({ children, dimColor = false, }) {
|
|
|
249
266
|
}
|
|
250
267
|
}
|
|
251
268
|
if (blocks.definitions) {
|
|
252
|
-
return _jsx(Markdown, { dimColor: dimColor, cacheTokens: false, children: stripped });
|
|
269
|
+
return _jsx(Markdown, { dimColor: dimColor, inlineMathImages: false, cacheTokens: false, children: stripped });
|
|
253
270
|
}
|
|
254
271
|
const stablePrefix = prefixRef.current;
|
|
255
272
|
const prefixTail = blocks.tail;
|
|
@@ -275,5 +292,5 @@ export function StreamingMarkdown({ children, dimColor = false, }) {
|
|
|
275
292
|
// an overlapping empty/duplicate boundary.
|
|
276
293
|
const hasDistinctSuffix = unstableSuffix !== '' &&
|
|
277
294
|
(stablePrefix === '' || !unstableSuffix.startsWith(stablePrefix));
|
|
278
|
-
return (_jsxs(Box, { flexDirection: "column", children: [blocks.blocks.map((block, index) => (_jsx(Box, { flexDirection: "column", marginTop: block.gap, children: _jsx(Markdown, { dimColor: dimColor, children: block.text }) }, index))), prefixTail && (_jsx(Box, { flexDirection: "column", marginTop: blocks.tailGap, children: _jsx(Markdown, { dimColor: dimColor, children: prefixTail }) }, "prefix")), hasDistinctSuffix && (_jsx(Box, { flexDirection: "column", marginTop: boundaryGap, children: _jsx(Markdown, { dimColor: dimColor, cacheTokens: false, children: unstableSuffix }) }, "suffix"))] }));
|
|
295
|
+
return (_jsxs(Box, { flexDirection: "column", children: [blocks.blocks.map((block, index) => (_jsx(Box, { flexDirection: "column", marginTop: block.gap, children: _jsx(Markdown, { dimColor: dimColor, inlineMathImages: false, children: block.text }) }, index))), prefixTail && (_jsx(Box, { flexDirection: "column", marginTop: blocks.tailGap, children: _jsx(Markdown, { dimColor: dimColor, inlineMathImages: false, children: prefixTail }) }, "prefix")), hasDistinctSuffix && (_jsx(Box, { flexDirection: "column", marginTop: boundaryGap, children: _jsx(Markdown, { dimColor: dimColor, inlineMathImages: false, cacheTokens: false, children: unstableSuffix }) }, "suffix"))] }));
|
|
279
296
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimelineRail.d.ts","sourceRoot":"","sources":["../../../src/components/TimelineRail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAEpE,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,yBAAyB,CAAA;AAwBhC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,aAAa,EACb,YAAY,EACZ,YAAY,GACb,EAAE;IACD,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;IAC9B,qEAAqE;IACrE,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;IAClC,gEAAgE;IAChE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB;sCACkC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB;6DACyD;IACzD,YAAY,EAAE,OAAO,CAAA;IACrB;;;;;OAKG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACtC,GAAG,KAAK,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"TimelineRail.d.ts","sourceRoot":"","sources":["../../../src/components/TimelineRail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAEpE,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,yBAAyB,CAAA;AAwBhC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,aAAa,EACb,YAAY,EACZ,YAAY,GACb,EAAE;IACD,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;IAC9B,qEAAqE;IACrE,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;IAClC,gEAAgE;IAChE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB;sCACkC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB;6DACyD;IACzD,YAAY,EAAE,OAAO,CAAA;IACrB;;;;;OAKG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACtC,GAAG,KAAK,CAAC,SAAS,CA+NlB"}
|
|
@@ -177,7 +177,15 @@ export function TimelineRail({ handle, turns, activeId, upId, downId, terminalWi
|
|
|
177
177
|
const cardH = lines.length + 2;
|
|
178
178
|
if (cardH <= viewport) {
|
|
179
179
|
const top = Math.max(0, Math.min(tickRow - Math.floor(cardH / 2), viewport - cardH));
|
|
180
|
-
card = (_jsx(Box, { position: "absolute", top: top, right: RAIL_WIDTH + 1, width: cardW, height: cardH, flexDirection: "column", flexShrink: 0, borderStyle: "round", borderColor: "inactive",
|
|
180
|
+
card = (_jsx(Box, { position: "absolute", top: top, right: RAIL_WIDTH + 1, width: cardW, height: cardH, flexDirection: "column", flexShrink: 0, borderStyle: "round", borderColor: "inactive",
|
|
181
|
+
// An opaque surface, like every other card floating over the
|
|
182
|
+
// transcript (Tooltip's card uses the same token). Without it
|
|
183
|
+
// the card is translucent: the rows underneath show through
|
|
184
|
+
// the padding/border columns, so the transcript's own fills
|
|
185
|
+
// leak out beside each preview line (reported from a real
|
|
186
|
+
// session: one line leaked the message background, the next a
|
|
187
|
+
// terminal-default gap).
|
|
188
|
+
backgroundColor: "toolCardBackground", paddingX: 1,
|
|
181
189
|
// The card floats LEFT of the rail over selectable
|
|
182
190
|
// transcript text; fence its own rect so a drag that
|
|
183
191
|
// happens under a dwell-popped preview never copies the
|
|
@@ -11,14 +11,23 @@ import { type WhaleLayerPose } from './whaleLayers.js';
|
|
|
11
11
|
*/
|
|
12
12
|
type Rgb = readonly [number, number, number];
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
14
|
+
* Half-block row encoder for true-color letter-grid sprites (the pixel
|
|
15
|
+
* whale's frames): `pixel(x, y)` returns the color of sprite cell (x, y)
|
|
16
|
+
* or `undefined` for transparent.
|
|
17
|
+
*
|
|
18
|
+
* Render one sprite to ANSI rows (one per sprite row pair). Consecutive
|
|
19
|
+
* cells sharing one style are run-length encoded; every row spans the full
|
|
20
|
+
* sprite width (transparent cells write plain spaces, so the blank cells of
|
|
21
|
+
* a diff region are re-output and overwrite whatever the previous frame
|
|
22
|
+
* painted there), and each row closes with an erase-to-EOL: the text
|
|
23
|
+
* pipeline may trim trailing whitespace, and the erase guarantees the
|
|
24
|
+
* terminal itself clears every cell past the row's last glyph — no ghost
|
|
25
|
+
* pixels can survive a frame switch.
|
|
26
|
+
*/
|
|
27
|
+
export declare function renderCellRows(width: number, height: number, pixel: (x: number, y: number) => Rgb | undefined): string[];
|
|
28
|
+
/**
|
|
29
|
+
* Render one letter-grid frame to ANSI rows under its own palette — the
|
|
30
|
+
* thin adapter over {@link renderCellRows} the whale frames use.
|
|
22
31
|
*/
|
|
23
32
|
export declare function renderSpriteRows(sprite: readonly string[], palette: Record<string, Rgb | undefined>): string[];
|
|
24
33
|
/** Render one composed pose (body + action layers) to ANSI rows, cached. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Whale.d.ts","sourceRoot":"","sources":["../../../src/components/Whale.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,EAA6B,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjF;;;;;;;;GAQG;AAEH,KAAK,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAoB5C
|
|
1
|
+
{"version":3,"file":"Whale.d.ts","sourceRoot":"","sources":["../../../src/components/Whale.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,EAA6B,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjF;;;;;;;;GAQG;AAEH,KAAK,GAAG,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAoB5C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,GAAG,GAAG,SAAS,GAC/C,MAAM,EAAE,CAyCV;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,SAAS,CAAC,GAAG,MAAM,EAAE,CAG9G;AAWD,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,EAAE,CAO/D;AAGD,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,EACvB,UAAiC,EACjC,IAAI,EACJ,KAAK,GACN,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,KAAK,CAAC,SAAS,CAWlB"}
|
|
@@ -19,25 +19,27 @@ const ERASE_TO_EOL = '\x1b[K';
|
|
|
19
19
|
/** Reset the background plane to the terminal default (fg keeps its SGR). */
|
|
20
20
|
const BG_DEFAULT = '\x1b[49m';
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
22
|
+
* Half-block row encoder for true-color letter-grid sprites (the pixel
|
|
23
|
+
* whale's frames): `pixel(x, y)` returns the color of sprite cell (x, y)
|
|
24
|
+
* or `undefined` for transparent.
|
|
25
|
+
*
|
|
26
|
+
* Render one sprite to ANSI rows (one per sprite row pair). Consecutive
|
|
27
|
+
* cells sharing one style are run-length encoded; every row spans the full
|
|
28
|
+
* sprite width (transparent cells write plain spaces, so the blank cells of
|
|
29
|
+
* a diff region are re-output and overwrite whatever the previous frame
|
|
30
|
+
* painted there), and each row closes with an erase-to-EOL: the text
|
|
31
|
+
* pipeline may trim trailing whitespace, and the erase guarantees the
|
|
32
|
+
* terminal itself clears every cell past the row's last glyph — no ghost
|
|
33
|
+
* pixels can survive a frame switch.
|
|
30
34
|
*/
|
|
31
|
-
export function
|
|
35
|
+
export function renderCellRows(width, height, pixel) {
|
|
32
36
|
const rows = [];
|
|
33
|
-
for (let
|
|
34
|
-
const upper = sprite[r];
|
|
35
|
-
const lower = sprite[r + 1] ?? '';
|
|
37
|
+
for (let y = 0; y < height; y += 2) {
|
|
36
38
|
let out = '';
|
|
37
39
|
let current = '';
|
|
38
|
-
for (let x = 0; x <
|
|
39
|
-
const up =
|
|
40
|
-
const lo =
|
|
40
|
+
for (let x = 0; x < width; x++) {
|
|
41
|
+
const up = pixel(x, y);
|
|
42
|
+
const lo = pixel(x, y + 1);
|
|
41
43
|
let seq;
|
|
42
44
|
let ch;
|
|
43
45
|
if (up !== undefined && lo !== undefined) {
|
|
@@ -76,6 +78,14 @@ export function renderSpriteRows(sprite, palette) {
|
|
|
76
78
|
}
|
|
77
79
|
return rows;
|
|
78
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Render one letter-grid frame to ANSI rows under its own palette — the
|
|
83
|
+
* thin adapter over {@link renderCellRows} the whale frames use.
|
|
84
|
+
*/
|
|
85
|
+
export function renderSpriteRows(sprite, palette) {
|
|
86
|
+
const width = sprite.reduce((max, row) => Math.max(max, row.length), 0);
|
|
87
|
+
return renderCellRows(width, sprite.length, (x, y) => palette[sprite[y]?.[x] ?? '']);
|
|
88
|
+
}
|
|
79
89
|
/** Pre-rendered ANSI rows for every whale frame, computed once at module load. */
|
|
80
90
|
const RENDERED = WHALE_FRAMES.map(frame => renderSpriteRows(frame.rows, PALETTE));
|
|
81
91
|
/**
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The maid portrait (鲸鱼娘) that can stand in for the header's pixel whale
|
|
4
|
+
* (settings `dsh-tui.whaleGirl`): the author-designed 30×30 true-color
|
|
5
|
+
* sprite in `whaleGirlSprite.ts`, rendered with the same half-block
|
|
6
|
+
* technique as the whale — one `▀`/`▄` cell packs two sprite rows, so the
|
|
7
|
+
* portrait shows at 30 columns × 15 rows. A static portrait by design: the
|
|
8
|
+
* whale's idle planner and click-hearts stay whale-only, so `dsh-tui.whaleIdle`
|
|
9
|
+
* has nothing to animate here (documented with the setting).
|
|
10
|
+
*/
|
|
11
|
+
/** Pre-rendered ANSI rows, computed once at module load. */
|
|
12
|
+
export declare const WHALE_GIRL_ROWS: readonly string[];
|
|
13
|
+
/**
|
|
14
|
+
* The portrait's center column when it fills the whale's 40-column box
|
|
15
|
+
* (indented (40−30)/2 = 5, so the art spans columns 5..34 → center 19.5).
|
|
16
|
+
* The welcome tagline centers on this instead of `WHALE_CENTER` in maid
|
|
17
|
+
* mode, keeping the caption under the art it belongs to.
|
|
18
|
+
*/
|
|
19
|
+
export declare const WHALE_GIRL_CENTER = 19.5;
|
|
20
|
+
/**
|
|
21
|
+
* The maid portrait as an Ink component: 15 rows × 30 columns. `width` pins
|
|
22
|
+
* the box (the header passes the whale's 40-column box so the neighbouring
|
|
23
|
+
* text column never shifts) and centers the portrait inside it; without it
|
|
24
|
+
* the component is exactly the portrait's own 30 columns (the star modal).
|
|
25
|
+
*/
|
|
26
|
+
export declare function WhaleGirlArt({ width }: {
|
|
27
|
+
width?: number;
|
|
28
|
+
}): React.ReactNode;
|
|
29
|
+
//# sourceMappingURL=WhaleGirl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WhaleGirl.d.ts","sourceRoot":"","sources":["../../../src/components/WhaleGirl.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB;;;;;;;;GAQG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAI5C,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAErC;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC,SAAS,CAW3E"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from '../ui.js';
|
|
3
|
+
import { renderCellRows } from './Whale.js';
|
|
4
|
+
import { WHALE_GIRL_COLS, WHALE_GIRL_SPRITE, WHALE_GIRL_SPRITE_ROWS } from './whaleGirlSprite.js';
|
|
5
|
+
/**
|
|
6
|
+
* The maid portrait (鲸鱼娘) that can stand in for the header's pixel whale
|
|
7
|
+
* (settings `dsh-tui.whaleGirl`): the author-designed 30×30 true-color
|
|
8
|
+
* sprite in `whaleGirlSprite.ts`, rendered with the same half-block
|
|
9
|
+
* technique as the whale — one `▀`/`▄` cell packs two sprite rows, so the
|
|
10
|
+
* portrait shows at 30 columns × 15 rows. A static portrait by design: the
|
|
11
|
+
* whale's idle planner and click-hearts stay whale-only, so `dsh-tui.whaleIdle`
|
|
12
|
+
* has nothing to animate here (documented with the setting).
|
|
13
|
+
*/
|
|
14
|
+
/** Pre-rendered ANSI rows, computed once at module load. */
|
|
15
|
+
export const WHALE_GIRL_ROWS = renderCellRows(WHALE_GIRL_COLS, WHALE_GIRL_SPRITE_ROWS, (x, y) => WHALE_GIRL_SPRITE[y]?.[x] ?? undefined);
|
|
16
|
+
/**
|
|
17
|
+
* The portrait's center column when it fills the whale's 40-column box
|
|
18
|
+
* (indented (40−30)/2 = 5, so the art spans columns 5..34 → center 19.5).
|
|
19
|
+
* The welcome tagline centers on this instead of `WHALE_CENTER` in maid
|
|
20
|
+
* mode, keeping the caption under the art it belongs to.
|
|
21
|
+
*/
|
|
22
|
+
export const WHALE_GIRL_CENTER = 19.5;
|
|
23
|
+
/**
|
|
24
|
+
* The maid portrait as an Ink component: 15 rows × 30 columns. `width` pins
|
|
25
|
+
* the box (the header passes the whale's 40-column box so the neighbouring
|
|
26
|
+
* text column never shifts) and centers the portrait inside it; without it
|
|
27
|
+
* the component is exactly the portrait's own 30 columns (the star modal).
|
|
28
|
+
*/
|
|
29
|
+
export function WhaleGirlArt({ width }) {
|
|
30
|
+
const pad = width === undefined ? 0 : Math.max(0, Math.floor((width - WHALE_GIRL_COLS) / 2));
|
|
31
|
+
return (_jsx(Box, { flexDirection: "column", flexShrink: 0, width: width, children: WHALE_GIRL_ROWS.map((row, index) => (_jsxs(Text, { wrap: "truncate-end", children: [pad > 0 ? ' '.repeat(pad) : '', row] }, index))) }));
|
|
32
|
+
}
|
|
@@ -7,7 +7,7 @@ import type { SpinnerMode } from './Spinner/spinnerMode.js';
|
|
|
7
7
|
*
|
|
8
8
|
* Random verb is picked once per turn (per mount of the spinner).
|
|
9
9
|
*/
|
|
10
|
-
export declare function WorkingSpinner({ mode, hasActiveTools, responseLengthRef, uploadTokensRef, loadingStartTimeRef, totalPausedMsRef, pauseStartTimeRef, thinkingStatus, }: {
|
|
10
|
+
export declare function WorkingSpinner({ mode, hasActiveTools, responseLengthRef, uploadTokensRef, loadingStartTimeRef, totalPausedMsRef, pauseStartTimeRef, thinkingStatus, suffix, }: {
|
|
11
11
|
mode: SpinnerMode;
|
|
12
12
|
hasActiveTools: boolean;
|
|
13
13
|
responseLengthRef: React.RefObject<number>;
|
|
@@ -17,6 +17,9 @@ export declare function WorkingSpinner({ mode, hasActiveTools, responseLengthRef
|
|
|
17
17
|
totalPausedMsRef: React.RefObject<number>;
|
|
18
18
|
pauseStartTimeRef: React.RefObject<number | null>;
|
|
19
19
|
thinkingStatus: 'thinking' | number | null;
|
|
20
|
+
/** Extra leading field (e.g. the auto-compaction badge) shown before the
|
|
21
|
+
* timer/token counters; omitted for an ordinary turn. */
|
|
22
|
+
suffix?: string;
|
|
20
23
|
}): React.ReactNode;
|
|
21
24
|
/**
|
|
22
25
|
* Tracks thinking status: 'thinking' while the model is streaming reasoning,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkingSpinner.d.ts","sourceRoot":"","sources":["../../../src/components/WorkingSpinner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAM3D;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,
|
|
1
|
+
{"version":3,"file":"WorkingSpinner.d.ts","sourceRoot":"","sources":["../../../src/components/WorkingSpinner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAM3D;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,MAAM,GACP,EAAE;IACD,IAAI,EAAE,WAAW,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;IACvB,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAC1C,+EAA+E;IAC/E,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACxC,mBAAmB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAC5C,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACzC,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACjD,cAAc,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAAA;IAC1C;8DAC0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,KAAK,CAAC,SAAS,CA4BlB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,OAAO,GAClB,UAAU,GAAG,MAAM,GAAG,IAAI,CA6C5B"}
|
|
@@ -13,12 +13,12 @@ import { sample } from 'lodash-es';
|
|
|
13
13
|
*
|
|
14
14
|
* Random verb is picked once per turn (per mount of the spinner).
|
|
15
15
|
*/
|
|
16
|
-
export function WorkingSpinner({ mode, hasActiveTools, responseLengthRef, uploadTokensRef, loadingStartTimeRef, totalPausedMsRef, pauseStartTimeRef, thinkingStatus, }) {
|
|
16
|
+
export function WorkingSpinner({ mode, hasActiveTools, responseLengthRef, uploadTokensRef, loadingStartTimeRef, totalPausedMsRef, pauseStartTimeRef, thinkingStatus, suffix, }) {
|
|
17
17
|
const { columns } = useTerminalSize();
|
|
18
18
|
// Pick a random verb once per spinner mount (per turn).
|
|
19
19
|
const [randomVerb] = useState(() => sample(SPINNER_VERBS) ?? 'Working');
|
|
20
20
|
const message = `${tOr(`spinner-verb-${randomVerb.toLowerCase()}`, randomVerb)}…`;
|
|
21
|
-
return (_jsx(Box, { flexDirection: "column", width: "100%", alignItems: "flex-start", children: _jsx(SpinnerAnimationRow, { mode: mode, reducedMotion: false, hasActiveTools: hasActiveTools, responseLengthRef: responseLengthRef, uploadTokensRef: uploadTokensRef, message: message, messageColor: "accent", shimmerColor: "accentShimmer", loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, spinnerSuffix: null, verbose: true, columns: columns, thinkingStatus: thinkingStatus }) }));
|
|
21
|
+
return (_jsx(Box, { flexDirection: "column", width: "100%", alignItems: "flex-start", children: _jsx(SpinnerAnimationRow, { mode: mode, reducedMotion: false, hasActiveTools: hasActiveTools, responseLengthRef: responseLengthRef, uploadTokensRef: uploadTokensRef, message: message, messageColor: "accent", shimmerColor: "accentShimmer", loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, spinnerSuffix: suffix === undefined ? null : suffix, verbose: true, columns: columns, thinkingStatus: thinkingStatus }) }));
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* Tracks thinking status: 'thinking' while the model is streaming reasoning,
|