@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,29 +1,70 @@
|
|
|
1
1
|
import { type TerminalCellSize, type TerminalImagePlacement, type TerminalImageSource } from './terminal-image.js';
|
|
2
|
+
/** Pixel rectangle of the uploaded raster to show (Kitty `x,y,w,h`). */
|
|
3
|
+
export type KittySourceRect = {
|
|
4
|
+
readonly x: number;
|
|
5
|
+
readonly y: number;
|
|
6
|
+
readonly width: number;
|
|
7
|
+
readonly height: number;
|
|
8
|
+
};
|
|
2
9
|
export interface KittyGraphicsManagerOptions {
|
|
3
10
|
/** Deterministic seed used by protocol tests; production chooses a random range. */
|
|
4
11
|
readonly firstImageId?: number;
|
|
5
12
|
/** Physical pixels per cell; defaults to a conventional 8×16 cell. */
|
|
6
13
|
readonly cellSize?: TerminalCellSize;
|
|
14
|
+
/** Clock for the re-upload failure window; protocol tests pin it. */
|
|
15
|
+
readonly now?: () => number;
|
|
7
16
|
}
|
|
8
17
|
/**
|
|
9
18
|
* Reconcile renderer image requests with Kitty image/placement state.
|
|
10
19
|
*
|
|
11
20
|
* Pixel content owns an image id while each DOM node owns a placement id.
|
|
12
21
|
* Equal immutable RGBA content is uploaded once and can back several nodes;
|
|
13
|
-
* geometry changes replace only that node's placement without flicker.
|
|
22
|
+
* geometry changes replace only that node's placement without flicker. An
|
|
23
|
+
* image no node places stays uploaded (dormant) within the retention budget,
|
|
24
|
+
* so content that scrolls back into view is re-placed, not re-sent.
|
|
14
25
|
*/
|
|
15
26
|
export declare class KittyGraphicsManager {
|
|
16
27
|
private readonly images;
|
|
17
28
|
private readonly placements;
|
|
29
|
+
/**
|
|
30
|
+
* Ids given up by a re-upload. The ENOENT that triggered it may be stale
|
|
31
|
+
* (the id was re-sent in between), so the terminal can still hold data
|
|
32
|
+
* under the old id; it is deleted on the next frame (or at exit).
|
|
33
|
+
*/
|
|
34
|
+
private readonly retiredImageIds;
|
|
18
35
|
private readonly contentHashes;
|
|
19
36
|
private nextImageId;
|
|
20
37
|
private nextPlacementId;
|
|
21
38
|
private cellSize;
|
|
39
|
+
private pass;
|
|
40
|
+
private readonly now;
|
|
22
41
|
constructor(options?: KittyGraphicsManagerOptions);
|
|
23
42
|
/** Update the physical cell ratio used by future image variants. */
|
|
24
43
|
setCellSize(cellSize: TerminalCellSize): boolean;
|
|
25
44
|
reconcile(placements: readonly TerminalImagePlacement[]): string;
|
|
26
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Forget images no node placed this pass once they are unusable (fitted for
|
|
47
|
+
* another cell geometry) or past the retention budget, oldest first.
|
|
48
|
+
*/
|
|
49
|
+
private evictDormant;
|
|
50
|
+
/**
|
|
51
|
+
* Handle a Kitty graphics reply the renderer did not ask for. ENOENT for
|
|
52
|
+
* one of our images means the terminal evicted its data (its own quota is
|
|
53
|
+
* smaller than our retention budget): upload it again and re-place every
|
|
54
|
+
* node showing it on the next frame. A second ENOENT within
|
|
55
|
+
* REUPLOAD_FAILURE_WINDOW_MS of that re-upload means the terminal refuses
|
|
56
|
+
* the image outright, so it is left as is (never an upload loop); a new
|
|
57
|
+
* content or size variant is a new image and tries again. The re-upload
|
|
58
|
+
* takes a fresh image id: every placement of the old id may still answer
|
|
59
|
+
* ENOENT, and those late replies must not count as the re-upload failing.
|
|
60
|
+
* Returns whether a repaint is needed.
|
|
61
|
+
*/
|
|
62
|
+
handleResponse(imageId: number, status: string): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* A clear/screen swap invalidated terminal-side data; resend next frame.
|
|
65
|
+
* The terminal state an abandoned image was judged against is gone too, so
|
|
66
|
+
* it gets a fresh ENOENT budget; one clear still buys at most one retry.
|
|
67
|
+
*/
|
|
27
68
|
invalidateAll(): void;
|
|
28
69
|
/** Delete every image owned by this renderer and forget their ids. */
|
|
29
70
|
deleteAll(): string;
|
|
@@ -34,7 +75,7 @@ export declare class KittyGraphicsManager {
|
|
|
34
75
|
}
|
|
35
76
|
/** Zlib-compressed direct RGBA split into protocol-compliant base64 chunks. */
|
|
36
77
|
export declare function transmitKittyRgba(imageId: number, source: TerminalImageSource): string;
|
|
37
|
-
export declare function kittyPlacement(imageId: number, placementId: number, x: number, y: number, columns: number, rows: number, zIndex?: number): string;
|
|
78
|
+
export declare function kittyPlacement(imageId: number, placementId: number, x: number, y: number, columns: number, rows: number, zIndex?: number, source?: KittySourceRect): string;
|
|
38
79
|
export declare function deleteKittyPlacement(imageId: number, placementId: number): string;
|
|
39
80
|
export declare function deleteKittyImage(imageId: number): string;
|
|
40
81
|
export declare function kittyCommand(control: string, payload?: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kitty-graphics.d.ts","sourceRoot":"","sources":["../../../src/ink/kitty-graphics.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"kitty-graphics.d.ts","sourceRoot":"","sources":["../../../src/ink/kitty-graphics.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAA;AAmE5B,wEAAwE;AACxE,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,WAAW,2BAA2B;IAC1C,oFAAoF;IACpF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAA;IACpC,qEAAqE;IACrE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAC5B;AAED;;;;;;;;GAQG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAwC;IACnE;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAe;IAC/C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoC;IAClE,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,IAAI,CAAI;IAChB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;gBAEtB,OAAO,GAAE,2BAAgC;IAUrD,oEAAoE;IACpE,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO;IAYhD,SAAS,CAAC,UAAU,EAAE,SAAS,sBAAsB,EAAE,GAAG,MAAM;IAkHhE;;;OAGG;IACH,OAAO,CAAC,YAAY;IAmCpB;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAsBxD;;;;OAIG;IACH,aAAa,IAAI,IAAI;IAWrB,sEAAsE;IACtE,SAAS,IAAI,MAAM;IASnB,OAAO,CAAC,QAAQ;IAoChB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,mBAAmB;CAQ5B;AAyCD,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,mBAAmB,GAC1B,MAAM,CAER;AAoCD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,SAAgB,EACtB,MAAM,CAAC,EAAE,eAAe,GACvB,MAAM,CAUR;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,MAAM,CAER;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,SAAK,GAAG,MAAM,CAElE"}
|
|
@@ -9,23 +9,54 @@ const ID_MAX_EXCLUSIVE = 0x7fffffff;
|
|
|
9
9
|
const PLACEMENT_ID_MAX_EXCLUSIVE = 0x40000000;
|
|
10
10
|
// Keep raster content behind terminal text and explicit panel backgrounds.
|
|
11
11
|
const IMAGE_Z_INDEX = -0x80000000;
|
|
12
|
+
/**
|
|
13
|
+
* Retention for uploaded images that no node places this frame. Leaving the
|
|
14
|
+
* viewport deletes only the placement (`d=i`), so scrolling back re-places
|
|
15
|
+
* the terminal-side data with one `a=p` instead of re-fitting, re-compressing
|
|
16
|
+
* and re-sending the whole raster — the protocol's intended use, and what
|
|
17
|
+
* mature terminal UIs do. Dormant images are evicted least-recently-used past
|
|
18
|
+
* either bound. The byte bound counts decoded RGBA (what the terminal keeps)
|
|
19
|
+
* and stays a small fraction of default terminal image quotas. A terminal
|
|
20
|
+
* configured with a smaller quota may still evict a dormant image, so
|
|
21
|
+
* placements report failures (`q=1`): an ENOENT reply marks the image for
|
|
22
|
+
* re-upload (see handleResponse).
|
|
23
|
+
*/
|
|
24
|
+
const DORMANT_MAX_IMAGES = 128;
|
|
25
|
+
const RETAINED_MAX_BYTES = 64 * 1024 * 1024;
|
|
26
|
+
/**
|
|
27
|
+
* An ENOENT this soon after re-uploading the same image means the terminal
|
|
28
|
+
* cannot keep it at all (e.g. the image exceeds its whole quota and the
|
|
29
|
+
* upload was refused): stop re-uploading instead of looping.
|
|
30
|
+
*/
|
|
31
|
+
const REUPLOAD_FAILURE_WINDOW_MS = 5000;
|
|
12
32
|
/**
|
|
13
33
|
* Reconcile renderer image requests with Kitty image/placement state.
|
|
14
34
|
*
|
|
15
35
|
* Pixel content owns an image id while each DOM node owns a placement id.
|
|
16
36
|
* Equal immutable RGBA content is uploaded once and can back several nodes;
|
|
17
|
-
* geometry changes replace only that node's placement without flicker.
|
|
37
|
+
* geometry changes replace only that node's placement without flicker. An
|
|
38
|
+
* image no node places stays uploaded (dormant) within the retention budget,
|
|
39
|
+
* so content that scrolls back into view is re-placed, not re-sent.
|
|
18
40
|
*/
|
|
19
41
|
export class KittyGraphicsManager {
|
|
20
42
|
images = new Map();
|
|
21
43
|
placements = new Map();
|
|
44
|
+
/**
|
|
45
|
+
* Ids given up by a re-upload. The ENOENT that triggered it may be stale
|
|
46
|
+
* (the id was re-sent in between), so the terminal can still hold data
|
|
47
|
+
* under the old id; it is deleted on the next frame (or at exit).
|
|
48
|
+
*/
|
|
49
|
+
retiredImageIds = [];
|
|
22
50
|
contentHashes = new WeakMap();
|
|
23
51
|
nextImageId;
|
|
24
52
|
nextPlacementId = 1;
|
|
25
53
|
cellSize;
|
|
54
|
+
pass = 0;
|
|
55
|
+
now;
|
|
26
56
|
constructor(options = {}) {
|
|
27
57
|
this.nextImageId = normalizeFirstId(options.firstImageId ?? randomInt(ID_MIN, ID_MAX_EXCLUSIVE));
|
|
28
58
|
this.cellSize = normalizeTerminalCellSize(options.cellSize ?? DEFAULT_TERMINAL_CELL_SIZE);
|
|
59
|
+
this.now = options.now ?? Date.now;
|
|
29
60
|
}
|
|
30
61
|
/** Update the physical cell ratio used by future image variants. */
|
|
31
62
|
setCellSize(cellSize) {
|
|
@@ -38,15 +69,17 @@ export class KittyGraphicsManager {
|
|
|
38
69
|
return true;
|
|
39
70
|
}
|
|
40
71
|
reconcile(placements) {
|
|
72
|
+
this.pass += 1;
|
|
41
73
|
const desiredNodes = new Set();
|
|
42
74
|
const desiredImages = new Set();
|
|
43
75
|
const desired = [];
|
|
44
|
-
const output =
|
|
76
|
+
const output = this.retiredImageIds.splice(0).map(deleteKittyImage);
|
|
45
77
|
for (const placement of placements) {
|
|
46
78
|
if (desiredNodes.has(placement.node))
|
|
47
79
|
continue;
|
|
48
80
|
desiredNodes.add(placement.node);
|
|
49
81
|
const image = this.imageFor(placement);
|
|
82
|
+
image.lastUsed = this.pass;
|
|
50
83
|
desiredImages.add(image);
|
|
51
84
|
desired.push({ placement, image });
|
|
52
85
|
}
|
|
@@ -64,6 +97,7 @@ export class KittyGraphicsManager {
|
|
|
64
97
|
y: -1,
|
|
65
98
|
columns: 0,
|
|
66
99
|
rows: 0,
|
|
100
|
+
crop: '',
|
|
67
101
|
};
|
|
68
102
|
this.placements.set(placement.node, state);
|
|
69
103
|
}
|
|
@@ -79,16 +113,22 @@ export class KittyGraphicsManager {
|
|
|
79
113
|
output.push(transmitPreparedKittyRgba(image.imageId, image.payload));
|
|
80
114
|
image.uploaded = true;
|
|
81
115
|
}
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
116
|
+
const visible = visiblePlacement(placement, image.payload);
|
|
117
|
+
const crop = visible.source === undefined
|
|
118
|
+
? ''
|
|
119
|
+
: `${visible.source.x},${visible.source.y},${visible.source.width},${visible.source.height}`;
|
|
120
|
+
const moved = state.x !== visible.x ||
|
|
121
|
+
state.y !== visible.y ||
|
|
122
|
+
state.columns !== visible.columns ||
|
|
123
|
+
state.rows !== visible.rows ||
|
|
124
|
+
state.crop !== crop;
|
|
86
125
|
if (!state.placed || moved) {
|
|
87
|
-
output.push(kittyPlacement(image.imageId, state.placementId,
|
|
88
|
-
state.x =
|
|
89
|
-
state.y =
|
|
90
|
-
state.columns =
|
|
91
|
-
state.rows =
|
|
126
|
+
output.push(kittyPlacement(image.imageId, state.placementId, visible.x, visible.y, visible.columns, visible.rows, state.zIndex, visible.source));
|
|
127
|
+
state.x = visible.x;
|
|
128
|
+
state.y = visible.y;
|
|
129
|
+
state.columns = visible.columns;
|
|
130
|
+
state.rows = visible.rows;
|
|
131
|
+
state.crop = crop;
|
|
92
132
|
state.placed = true;
|
|
93
133
|
}
|
|
94
134
|
}
|
|
@@ -101,31 +141,111 @@ export class KittyGraphicsManager {
|
|
|
101
141
|
});
|
|
102
142
|
this.placements.delete(node);
|
|
103
143
|
}
|
|
144
|
+
// Deleting an image's data also removes its placements, so an evicted
|
|
145
|
+
// image needs no separate placement delete.
|
|
146
|
+
const evicted = this.evictDormant(desiredImages);
|
|
104
147
|
for (const obsolete of obsoletePlacements) {
|
|
105
|
-
if (
|
|
148
|
+
if (evicted.has(obsolete.image))
|
|
106
149
|
continue;
|
|
107
150
|
output.push(deleteKittyPlacement(obsolete.image.imageId, obsolete.placementId));
|
|
108
151
|
}
|
|
109
|
-
for (const
|
|
110
|
-
if (desiredImages.has(image))
|
|
111
|
-
continue;
|
|
152
|
+
for (const image of evicted)
|
|
112
153
|
output.push(deleteKittyImage(image.imageId));
|
|
113
|
-
this.images.delete(key);
|
|
114
|
-
}
|
|
115
154
|
return output.join('');
|
|
116
155
|
}
|
|
117
|
-
/**
|
|
156
|
+
/**
|
|
157
|
+
* Forget images no node placed this pass once they are unusable (fitted for
|
|
158
|
+
* another cell geometry) or past the retention budget, oldest first.
|
|
159
|
+
*/
|
|
160
|
+
evictDormant(desiredImages) {
|
|
161
|
+
const evicted = new Set();
|
|
162
|
+
const dormant = [];
|
|
163
|
+
let retainedBytes = 0;
|
|
164
|
+
for (const entry of this.images) {
|
|
165
|
+
const image = entry[1];
|
|
166
|
+
if (desiredImages.has(image)) {
|
|
167
|
+
retainedBytes += image.retainedBytes;
|
|
168
|
+
}
|
|
169
|
+
else if (image.cellSize.width !== this.cellSize.width ||
|
|
170
|
+
image.cellSize.height !== this.cellSize.height) {
|
|
171
|
+
evicted.add(image);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
retainedBytes += image.retainedBytes;
|
|
175
|
+
dormant.push(entry);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
dormant.sort((a, b) => a[1].lastUsed - b[1].lastUsed);
|
|
179
|
+
let index = 0;
|
|
180
|
+
while (index < dormant.length &&
|
|
181
|
+
(dormant.length - index > DORMANT_MAX_IMAGES || retainedBytes > RETAINED_MAX_BYTES)) {
|
|
182
|
+
const image = dormant[index][1];
|
|
183
|
+
evicted.add(image);
|
|
184
|
+
retainedBytes -= image.retainedBytes;
|
|
185
|
+
index += 1;
|
|
186
|
+
}
|
|
187
|
+
for (const [key, image] of this.images) {
|
|
188
|
+
if (evicted.has(image))
|
|
189
|
+
this.images.delete(key);
|
|
190
|
+
}
|
|
191
|
+
return evicted;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Handle a Kitty graphics reply the renderer did not ask for. ENOENT for
|
|
195
|
+
* one of our images means the terminal evicted its data (its own quota is
|
|
196
|
+
* smaller than our retention budget): upload it again and re-place every
|
|
197
|
+
* node showing it on the next frame. A second ENOENT within
|
|
198
|
+
* REUPLOAD_FAILURE_WINDOW_MS of that re-upload means the terminal refuses
|
|
199
|
+
* the image outright, so it is left as is (never an upload loop); a new
|
|
200
|
+
* content or size variant is a new image and tries again. The re-upload
|
|
201
|
+
* takes a fresh image id: every placement of the old id may still answer
|
|
202
|
+
* ENOENT, and those late replies must not count as the re-upload failing.
|
|
203
|
+
* Returns whether a repaint is needed.
|
|
204
|
+
*/
|
|
205
|
+
handleResponse(imageId, status) {
|
|
206
|
+
if (!status.startsWith('ENOENT'))
|
|
207
|
+
return false;
|
|
208
|
+
let image;
|
|
209
|
+
for (const candidate of this.images.values()) {
|
|
210
|
+
if (candidate.imageId === imageId)
|
|
211
|
+
image = candidate;
|
|
212
|
+
}
|
|
213
|
+
if (image === undefined || !image.uploaded || image.abandoned)
|
|
214
|
+
return false;
|
|
215
|
+
const now = this.now();
|
|
216
|
+
if (image.reuploadedAt !== 0 && now - image.reuploadedAt < REUPLOAD_FAILURE_WINDOW_MS) {
|
|
217
|
+
image.abandoned = true;
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
image.reuploadedAt = now;
|
|
221
|
+
this.retiredImageIds.push(image.imageId);
|
|
222
|
+
image.imageId = this.allocateImageId();
|
|
223
|
+
image.uploaded = false;
|
|
224
|
+
for (const state of this.placements.values()) {
|
|
225
|
+
if (state.image === image)
|
|
226
|
+
state.placed = false;
|
|
227
|
+
}
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* A clear/screen swap invalidated terminal-side data; resend next frame.
|
|
232
|
+
* The terminal state an abandoned image was judged against is gone too, so
|
|
233
|
+
* it gets a fresh ENOENT budget; one clear still buys at most one retry.
|
|
234
|
+
*/
|
|
118
235
|
invalidateAll() {
|
|
119
|
-
for (const image of this.images.values())
|
|
236
|
+
for (const image of this.images.values()) {
|
|
120
237
|
image.uploaded = false;
|
|
238
|
+
image.abandoned = false;
|
|
239
|
+
image.reuploadedAt = 0;
|
|
240
|
+
}
|
|
121
241
|
for (const state of this.placements.values()) {
|
|
122
242
|
state.placed = false;
|
|
123
243
|
}
|
|
124
244
|
}
|
|
125
245
|
/** Delete every image owned by this renderer and forget their ids. */
|
|
126
246
|
deleteAll() {
|
|
127
|
-
const output = [...this.images.values()]
|
|
128
|
-
.map(
|
|
247
|
+
const output = [...this.retiredImageIds.splice(0), ...[...this.images.values()].map(image => image.imageId)]
|
|
248
|
+
.map(deleteKittyImage)
|
|
129
249
|
.join('');
|
|
130
250
|
this.images.clear();
|
|
131
251
|
this.placements.clear();
|
|
@@ -150,7 +270,12 @@ export class KittyGraphicsManager {
|
|
|
150
270
|
const image = {
|
|
151
271
|
imageId: this.allocateImageId(),
|
|
152
272
|
payload: prepareKittyRgba(fitted),
|
|
273
|
+
retainedBytes: fitted.width * fitted.height * 4,
|
|
274
|
+
cellSize: this.cellSize,
|
|
153
275
|
uploaded: false,
|
|
276
|
+
lastUsed: this.pass,
|
|
277
|
+
reuploadedAt: 0,
|
|
278
|
+
abandoned: false,
|
|
154
279
|
};
|
|
155
280
|
this.images.set(key, image);
|
|
156
281
|
return image;
|
|
@@ -179,6 +304,39 @@ export class KittyGraphicsManager {
|
|
|
179
304
|
return id;
|
|
180
305
|
}
|
|
181
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* The cells a placement actually occupies and, when it is clipped, the part
|
|
309
|
+
* of the uploaded raster behind them. The raster has the full cell box's
|
|
310
|
+
* exact physical aspect (see fitTerminalImageSource), so a cell edge maps to
|
|
311
|
+
* a pixel edge proportionally; the start rounds down and the end up, so a
|
|
312
|
+
* partially covered pixel row is shown rather than dropped.
|
|
313
|
+
*/
|
|
314
|
+
function visiblePlacement(placement, payload) {
|
|
315
|
+
const clip = placement.clip;
|
|
316
|
+
if (clip === undefined ||
|
|
317
|
+
(clip.x === placement.x && clip.y === placement.y &&
|
|
318
|
+
clip.columns === placement.columns && clip.rows === placement.rows)) {
|
|
319
|
+
return { x: placement.x, y: placement.y, columns: placement.columns, rows: placement.rows };
|
|
320
|
+
}
|
|
321
|
+
const left = clip.x - placement.x;
|
|
322
|
+
const top = clip.y - placement.y;
|
|
323
|
+
const sourceX = Math.floor((payload.width * left) / placement.columns);
|
|
324
|
+
const sourceY = Math.floor((payload.height * top) / placement.rows);
|
|
325
|
+
const sourceRight = Math.min(payload.width, Math.ceil((payload.width * (left + clip.columns)) / placement.columns));
|
|
326
|
+
const sourceBottom = Math.min(payload.height, Math.ceil((payload.height * (top + clip.rows)) / placement.rows));
|
|
327
|
+
return {
|
|
328
|
+
x: clip.x,
|
|
329
|
+
y: clip.y,
|
|
330
|
+
columns: clip.columns,
|
|
331
|
+
rows: clip.rows,
|
|
332
|
+
source: {
|
|
333
|
+
x: sourceX,
|
|
334
|
+
y: sourceY,
|
|
335
|
+
width: Math.max(1, sourceRight - sourceX),
|
|
336
|
+
height: Math.max(1, sourceBottom - sourceY),
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
}
|
|
182
340
|
/** Zlib-compressed direct RGBA split into protocol-compliant base64 chunks. */
|
|
183
341
|
export function transmitKittyRgba(imageId, source) {
|
|
184
342
|
return transmitPreparedKittyRgba(imageId, prepareKittyRgba(source));
|
|
@@ -208,9 +366,12 @@ function transmitPreparedKittyRgba(imageId, payload) {
|
|
|
208
366
|
})
|
|
209
367
|
.join('');
|
|
210
368
|
}
|
|
211
|
-
export function kittyPlacement(imageId, placementId, x, y, columns, rows, zIndex = IMAGE_Z_INDEX) {
|
|
369
|
+
export function kittyPlacement(imageId, placementId, x, y, columns, rows, zIndex = IMAGE_Z_INDEX, source) {
|
|
370
|
+
const crop = source === undefined
|
|
371
|
+
? ''
|
|
372
|
+
: `,x=${source.x},y=${source.y},w=${source.width},h=${source.height}`;
|
|
212
373
|
return (`\u001b[${y + 1};${x + 1}H` +
|
|
213
|
-
kittyCommand(`a=p,i=${imageId},p=${placementId},c=${columns},r=${rows},z=${zIndex},C=1,q=
|
|
374
|
+
kittyCommand(`a=p,i=${imageId},p=${placementId},c=${columns},r=${rows}${crop},z=${zIndex},C=1,q=1`));
|
|
214
375
|
}
|
|
215
376
|
export function deleteKittyPlacement(imageId, placementId) {
|
|
216
377
|
return kittyCommand(`a=d,d=i,i=${imageId},p=${placementId},q=2`);
|
|
@@ -85,7 +85,7 @@ type Options = {
|
|
|
85
85
|
previousImages?: readonly TerminalImagePlacement[];
|
|
86
86
|
};
|
|
87
87
|
/** A queued paint operation: write, clip, unclip, blit, clear, shade, noSelect, or shift. */
|
|
88
|
-
export type Operation = WriteOperation | ClipOperation | UnclipOperation | BlitOperation | ClearOperation | ShadeOperation | NoSelectOperation | ShiftOperation;
|
|
88
|
+
export type Operation = WriteOperation | ClipOperation | UnclipOperation | BlitOperation | ClearOperation | ShadeOperation | NoSelectOperation | CopyRegionOperation | SoftWrapRowOperation | ShiftOperation;
|
|
89
89
|
/**
|
|
90
90
|
* Restyle the cells already in the region at this point of the paint
|
|
91
91
|
* order: a modal layer's backdrop. Applied in sequence like a write, so
|
|
@@ -108,7 +108,8 @@ type WriteOperation = {
|
|
|
108
108
|
* means line i is a continuation of line i-1 (the `\n` before it was
|
|
109
109
|
* inserted by word-wrap, not in the source). Index 0 is always false.
|
|
110
110
|
* Undefined means the producer didn't track wrapping (e.g. fills,
|
|
111
|
-
* raw-ansi)
|
|
111
|
+
* raw-ansi): the rows it paints are marked "not a continuation", since it
|
|
112
|
+
* replaced whatever was there — see the write case in `get()`.
|
|
112
113
|
*/
|
|
113
114
|
softWrap?: boolean[];
|
|
114
115
|
};
|
|
@@ -156,6 +157,19 @@ type NoSelectOperation = {
|
|
|
156
157
|
type: 'noSelect';
|
|
157
158
|
region: Rectangle;
|
|
158
159
|
};
|
|
160
|
+
/** Row `y` continues the row above, whose content ends at `contentEnd`. */
|
|
161
|
+
type SoftWrapRowOperation = {
|
|
162
|
+
type: 'softWrapRow';
|
|
163
|
+
y: number;
|
|
164
|
+
contentEnd: number;
|
|
165
|
+
};
|
|
166
|
+
/** A region that copies as `text` (see Screen.copyRegion); paints nothing. */
|
|
167
|
+
type CopyRegionOperation = {
|
|
168
|
+
type: 'copyRegion';
|
|
169
|
+
region: Rectangle;
|
|
170
|
+
text: string;
|
|
171
|
+
id: number;
|
|
172
|
+
};
|
|
159
173
|
/**
|
|
160
174
|
* Collects write/blit/clear/clip operations from the render tree, then
|
|
161
175
|
* applies them to a Screen buffer in get(). The Screen is what gets
|
|
@@ -250,6 +264,8 @@ export default class Output {
|
|
|
250
264
|
* the mark wins regardless of what's blitted into the region.
|
|
251
265
|
* @param region - the region to mark.
|
|
252
266
|
*/
|
|
267
|
+
/** Mark row `y` as a wrap continuation (see Styles.softWrapContinuation). */
|
|
268
|
+
softWrapRow(y: number, contentEnd: number): void;
|
|
253
269
|
noSelect(region: Rectangle): void;
|
|
254
270
|
/**
|
|
255
271
|
* Record a fully visible, frame-budgeted image request. Rejected placements
|
|
@@ -272,6 +288,12 @@ export default class Output {
|
|
|
272
288
|
getImages(): readonly TerminalImagePlacement[];
|
|
273
289
|
/** Pixel ownership is determined by paint order, not just final text values. */
|
|
274
290
|
imageBacking(node: DOMElement): void;
|
|
291
|
+
/**
|
|
292
|
+
* The admitted placement's backing colour, or undefined when the raster
|
|
293
|
+
* composites transparently: its cells are then blanks, not a painted
|
|
294
|
+
* surface, so whatever the terminal shows behind the UI stays visible.
|
|
295
|
+
*/
|
|
296
|
+
imagePlacementBackground(node: DOMElement): string | undefined;
|
|
275
297
|
/**
|
|
276
298
|
* Queue a text write at a position, split across lines on newlines.
|
|
277
299
|
* @param x - the left column.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/ink/output.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,sBAAsB,CAAA;AAChE,OAAO,
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/ink/output.ts"],"names":[],"mappings":"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"}
|
package/lib/types/ink/output.js
CHANGED
|
@@ -4,7 +4,7 @@ import { getGraphemeSegmenter } from '../utils/intl.js';
|
|
|
4
4
|
import sliceAnsi from '../utils/sliceAnsi.js';
|
|
5
5
|
import { reorderBidi } from './bidi.js';
|
|
6
6
|
import { unionRect } from './layout/geometry.js';
|
|
7
|
-
import { blitRegion, cellRunSpan, createCellRun, extractHyperlinkFromStyles, filterOutHyperlinkStyles, markNoSelectRegion, OSC8_PREFIX, shadeRegion, recordCellRunEntry, recordSpacerRunEntry, replayCellRun, resetScreen, setCellAt, shiftRows, } from './screen.js';
|
|
7
|
+
import { blitRegion, cellRunSpan, createCellRun, extractHyperlinkFromStyles, filterOutHyperlinkStyles, allocateCopyRegionId, clearCopyRegionSpan, markCopyRegion, pruneCopyTexts, markNoSelectRegion, OSC8_PREFIX, shadeRegion, recordCellRunEntry, recordSpacerRunEntry, replayCellRun, resetScreen, setCellAt, shiftRows, } from './screen.js';
|
|
8
8
|
import { stringWidth } from './stringWidth.js';
|
|
9
9
|
import { expandTabs } from './tabstops.js';
|
|
10
10
|
import { TERMINAL_IMAGE_MAX_CELLS, TERMINAL_IMAGE_MAX_FRAME_BYTES, TERMINAL_IMAGE_MAX_PLACEMENTS, } from './terminal-image.js';
|
|
@@ -152,6 +152,22 @@ function isNodeInSubtree(node, root) {
|
|
|
152
152
|
}
|
|
153
153
|
return false;
|
|
154
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* One copy region id per image node for its lifetime, so rows captured
|
|
157
|
+
* during drag-to-scroll and rows still on screen name the same formula.
|
|
158
|
+
*/
|
|
159
|
+
const copyRegionIds = new WeakMap();
|
|
160
|
+
/**
|
|
161
|
+
* Copy text reaches the clipboard without passing through cells, so it never
|
|
162
|
+
* met the render path's control-character rules. Drop C0/C1 (newlines
|
|
163
|
+
* excepted: a block formula's source is multi-line) and the
|
|
164
|
+
* interlinear-annotation code points, which the copy pipeline reserves for
|
|
165
|
+
* its own row metadata.
|
|
166
|
+
*/
|
|
167
|
+
const COPY_TEXT_STRIP = /[\u0000-\u0009\u000b-\u001f\u007f-\u009f\uFFF9-\uFFFB]/g;
|
|
168
|
+
function cleanCopyText(value) {
|
|
169
|
+
return value.replace(COPY_TEXT_STRIP, '');
|
|
170
|
+
}
|
|
155
171
|
/**
|
|
156
172
|
* Slot-reuse ceiling: the clustered array is a second full memory image of
|
|
157
173
|
* the line, and pathological single-line output (base64 blobs, minified
|
|
@@ -502,6 +518,10 @@ export default class Output {
|
|
|
502
518
|
* the mark wins regardless of what's blitted into the region.
|
|
503
519
|
* @param region - the region to mark.
|
|
504
520
|
*/
|
|
521
|
+
/** Mark row `y` as a wrap continuation (see Styles.softWrapContinuation). */
|
|
522
|
+
softWrapRow(y, contentEnd) {
|
|
523
|
+
this.operations.push({ type: 'softWrapRow', y, contentEnd });
|
|
524
|
+
}
|
|
505
525
|
noSelect(region) {
|
|
506
526
|
this.operations.push({ type: 'noSelect', region });
|
|
507
527
|
}
|
|
@@ -525,7 +545,11 @@ export default class Output {
|
|
|
525
545
|
return false;
|
|
526
546
|
}
|
|
527
547
|
const presentation = node.attributes.imagePresentation;
|
|
528
|
-
const
|
|
548
|
+
const transparent = node.attributes.imageTransparent === 'transparent';
|
|
549
|
+
// Both protocols crop a partially visible content image to its visible
|
|
550
|
+
// cells (Sixel re-encodes the slice, Kitty places a source rectangle), so
|
|
551
|
+
// scrolling past a viewport edge never flips it to its text fallback.
|
|
552
|
+
const canCrop = this.terminalImagesEnabled && (presentation === 'preview' || presentation === 'transcript');
|
|
529
553
|
if (!canCrop && (left < 0 ||
|
|
530
554
|
top < 0 ||
|
|
531
555
|
left + width > this.width ||
|
|
@@ -559,6 +583,7 @@ export default class Output {
|
|
|
559
583
|
rows: height,
|
|
560
584
|
source,
|
|
561
585
|
...(presentation === 'preview' || presentation === 'transcript' ? { presentation } : {}),
|
|
586
|
+
...(transparent ? { transparent: true } : {}),
|
|
562
587
|
...(canCrop ? { clip: { x: visibleLeft, y: visibleTop, columns: visibleRight - visibleLeft, rows: visibleBottom - visibleTop } } : {}),
|
|
563
588
|
...(background !== undefined ? { background } : {}),
|
|
564
589
|
};
|
|
@@ -576,8 +601,9 @@ export default class Output {
|
|
|
576
601
|
*/
|
|
577
602
|
reuseImages(node) {
|
|
578
603
|
// A scrollable image's current clip is only known inside its ScrollBox.
|
|
579
|
-
// Descend first rather than admitting stale placements from an ancestor
|
|
580
|
-
|
|
604
|
+
// Descend first rather than admitting stale placements from an ancestor
|
|
605
|
+
// blit: a crop computed without that clip would spill past the viewport.
|
|
606
|
+
if (this.terminalImagesEnabled && this.previousImages.some(p => isNodeInSubtree(p.node, node)))
|
|
581
607
|
return false;
|
|
582
608
|
let reusedAll = true;
|
|
583
609
|
for (const placement of this.previousImages) {
|
|
@@ -650,11 +676,31 @@ export default class Output {
|
|
|
650
676
|
const placement = this.imagePlacements.find(image => image.node === node);
|
|
651
677
|
if (placement) {
|
|
652
678
|
const visible = placement.clip ?? placement;
|
|
653
|
-
|
|
679
|
+
const region = { x: visible.x, y: visible.y, width: visible.columns, height: visible.rows };
|
|
680
|
+
// An image's backing cells are blank; one with copy text (a formula's
|
|
681
|
+
// source) copies as that text, any other image is left out of copies.
|
|
682
|
+
const copyText = node.attributes['imageCopyText'];
|
|
683
|
+
const copied = typeof copyText === 'string' ? cleanCopyText(copyText) : '';
|
|
684
|
+
if (copied !== '') {
|
|
685
|
+
let id = copyRegionIds.get(node);
|
|
686
|
+
if (id === undefined)
|
|
687
|
+
copyRegionIds.set(node, id = allocateCopyRegionId());
|
|
688
|
+
this.operations.push({ type: 'copyRegion', region, text: copied, id });
|
|
689
|
+
}
|
|
690
|
+
else
|
|
691
|
+
this.noSelect(region);
|
|
654
692
|
}
|
|
655
693
|
if (this.imageReady)
|
|
656
694
|
this.imageBackingEnds.set(node, this.operations.length);
|
|
657
695
|
}
|
|
696
|
+
/**
|
|
697
|
+
* The admitted placement's backing colour, or undefined when the raster
|
|
698
|
+
* composites transparently: its cells are then blanks, not a painted
|
|
699
|
+
* surface, so whatever the terminal shows behind the UI stays visible.
|
|
700
|
+
*/
|
|
701
|
+
imagePlacementBackground(node) {
|
|
702
|
+
return this.imagePlacements.find(image => image.node === node)?.background;
|
|
703
|
+
}
|
|
658
704
|
/**
|
|
659
705
|
* Queue a text write at a position, split across lines on newlines.
|
|
660
706
|
* @param x - the left column.
|
|
@@ -810,6 +856,24 @@ export default class Output {
|
|
|
810
856
|
shiftRows(screen, operation.top, operation.bottom, operation.n);
|
|
811
857
|
continue;
|
|
812
858
|
}
|
|
859
|
+
case 'softWrapRow': {
|
|
860
|
+
// Paint order: the marker lands where the producer asked for it, and
|
|
861
|
+
// the write case above resets it when a later operation repaints that
|
|
862
|
+
// row. (This used to run in a pass after every write, which let a
|
|
863
|
+
// marker outlive an overlay that overwrote the row.)
|
|
864
|
+
if (operation.y > 0 && operation.y < screen.height) {
|
|
865
|
+
screen.softWrap[operation.y] = Math.max(1, operation.contentEnd);
|
|
866
|
+
}
|
|
867
|
+
continue;
|
|
868
|
+
}
|
|
869
|
+
case 'copyRegion': {
|
|
870
|
+
// In paint order: anything written over the image later (a menu,
|
|
871
|
+
// an overlay) clears the cells it covers, so a copy reads what is
|
|
872
|
+
// visible there rather than the formula beneath.
|
|
873
|
+
const { x, y, width, height } = operation.region;
|
|
874
|
+
markCopyRegion(screen, x, y, width, height, operation.text, operation.id);
|
|
875
|
+
continue;
|
|
876
|
+
}
|
|
813
877
|
case 'shade': {
|
|
814
878
|
// Honour the active clip like a write: a backdrop inside an
|
|
815
879
|
// overflow-hidden ancestor must not shade cells outside it.
|
|
@@ -882,6 +946,9 @@ export default class Output {
|
|
|
882
946
|
}
|
|
883
947
|
const contentEnd = writeLineToScreen(screen, line, x, lineY, screenWidth, this.stylePool, this.charCache, this.streamingSlot, this.packedOwner);
|
|
884
948
|
writeCells += contentEnd - x;
|
|
949
|
+
if (screen.copyTexts !== undefined && screen.copyTexts.size > 0) {
|
|
950
|
+
clearCopyRegionSpan(screen, lineY, x, contentEnd);
|
|
951
|
+
}
|
|
885
952
|
// See Screen.softWrap docstring for the encoding. contentEnd
|
|
886
953
|
// from writeLineToScreen is tab-expansion-aware, unlike
|
|
887
954
|
// x+stringWidth(line) which treats tabs as width 0.
|
|
@@ -890,6 +957,14 @@ export default class Output {
|
|
|
890
957
|
swBits[lineY] = isSW ? prevContentEnd : 0;
|
|
891
958
|
prevContentEnd = contentEnd;
|
|
892
959
|
}
|
|
960
|
+
else {
|
|
961
|
+
// Paint order: a producer that doesn't track wrapping (fills,
|
|
962
|
+
// raw-ansi, overlays) still replaces the row it paints, so a
|
|
963
|
+
// continuation marker an earlier softWrapRow set for this row
|
|
964
|
+
// is stale — keep it and a copy would glue the overlay's text
|
|
965
|
+
// onto the previous line.
|
|
966
|
+
swBits[lineY] = 0;
|
|
967
|
+
}
|
|
893
968
|
offsetY++;
|
|
894
969
|
}
|
|
895
970
|
continue;
|
|
@@ -907,6 +982,9 @@ export default class Output {
|
|
|
907
982
|
markNoSelectRegion(screen, x, y, width, height);
|
|
908
983
|
}
|
|
909
984
|
}
|
|
985
|
+
// Blits carry the previous frame's region texts; keep only the ones a
|
|
986
|
+
// cell still references, or the map grows by every redrawn formula.
|
|
987
|
+
pruneCopyTexts(screen);
|
|
910
988
|
// Log blit/write ratio for debugging - high write count suggests blitting isn't working
|
|
911
989
|
const totalCells = blitCells + writeCells;
|
|
912
990
|
if (totalCells > 1000 && writeCells > blitCells) {
|