@deepseek-harness-tui/dsh-tui 0.8.8 → 0.9.1
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 +60 -238
- package/bin/dsh-tui.js +172 -5
- package/cordis.patch.yml +16 -4
- package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -13
- package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -59
- package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -15
- package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -32
- package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -59
- package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -166
- package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -42
- package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -143
- package/dsh-ecosystem-spec/registry/README.md +14 -14
- package/dsh-ecosystem-spec/registry/host-descriptor.tui.example.json +56 -56
- package/dsh-ecosystem-spec/registry/permissions-0.1.json +13 -13
- package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -149
- package/lib/types/cc/hyperlink.d.ts +7 -1
- package/lib/types/cc/hyperlink.d.ts.map +1 -1
- package/lib/types/cc/hyperlink.js +3 -2
- package/lib/types/cc/markdown.d.ts.map +1 -1
- package/lib/types/cc/markdown.js +33 -3
- package/lib/types/cc/sessionColors.d.ts +27 -0
- package/lib/types/cc/sessionColors.d.ts.map +1 -0
- package/lib/types/cc/sessionColors.js +39 -0
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +10 -2
- package/lib/types/components/ActivityPicker.d.ts +4 -1
- package/lib/types/components/ActivityPicker.d.ts.map +1 -1
- package/lib/types/components/ActivityPicker.js +2 -2
- package/lib/types/components/AutoRecapRow.d.ts +23 -0
- package/lib/types/components/AutoRecapRow.d.ts.map +1 -0
- package/lib/types/components/AutoRecapRow.js +23 -0
- package/lib/types/components/BtwPanel.d.ts.map +1 -1
- package/lib/types/components/BtwPanel.js +1 -1
- package/lib/types/components/Chat/SubagentMessage.d.ts +2 -1
- package/lib/types/components/Chat/SubagentMessage.d.ts.map +1 -1
- package/lib/types/components/Chat/SubagentMessage.js +11 -3
- package/lib/types/components/ColorPicker.d.ts +17 -0
- package/lib/types/components/ColorPicker.d.ts.map +1 -0
- package/lib/types/components/ColorPicker.js +20 -0
- package/lib/types/components/CommandSuggestions.d.ts +23 -4
- package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
- package/lib/types/components/CommandSuggestions.js +41 -14
- package/lib/types/components/ContextBarView.d.ts +33 -0
- package/lib/types/components/ContextBarView.d.ts.map +1 -0
- package/lib/types/components/ContextBarView.js +46 -0
- package/lib/types/components/EffortInputBorder.d.ts +12 -1
- package/lib/types/components/EffortInputBorder.d.ts.map +1 -1
- package/lib/types/components/EffortInputBorder.js +22 -5
- package/lib/types/components/EffortSlider.d.ts +4 -1
- package/lib/types/components/EffortSlider.d.ts.map +1 -1
- package/lib/types/components/EffortSlider.js +4 -2
- package/lib/types/components/ExtensionDialog.js +6 -2
- package/lib/types/components/FileActionsPanel.d.ts +22 -0
- package/lib/types/components/FileActionsPanel.d.ts.map +1 -0
- package/lib/types/components/FileActionsPanel.js +28 -0
- package/lib/types/components/FileSuggestions.d.ts +26 -7
- package/lib/types/components/FileSuggestions.d.ts.map +1 -1
- package/lib/types/components/FileSuggestions.js +39 -12
- package/lib/types/components/GoalTodoPanel.d.ts +26 -2
- package/lib/types/components/GoalTodoPanel.d.ts.map +1 -1
- package/lib/types/components/GoalTodoPanel.js +86 -17
- package/lib/types/components/HelpMenu.d.ts +7 -1
- package/lib/types/components/HelpMenu.d.ts.map +1 -1
- package/lib/types/components/HelpMenu.js +12 -4
- package/lib/types/components/HistorySearchDialog.d.ts +4 -1
- package/lib/types/components/HistorySearchDialog.d.ts.map +1 -1
- package/lib/types/components/HistorySearchDialog.js +2 -2
- package/lib/types/components/LangPicker.d.ts +14 -0
- package/lib/types/components/LangPicker.d.ts.map +1 -0
- package/lib/types/components/LangPicker.js +17 -0
- package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
- package/lib/types/components/LoadedContextPanel.js +3 -1
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +12 -3
- package/lib/types/components/MessageList.d.ts +45 -2
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +560 -41
- package/lib/types/components/ModelPicker.d.ts +27 -2
- package/lib/types/components/ModelPicker.d.ts.map +1 -1
- package/lib/types/components/ModelPicker.js +26 -6
- package/lib/types/components/PermissionsPicker.d.ts +21 -0
- package/lib/types/components/PermissionsPicker.d.ts.map +1 -0
- package/lib/types/components/PermissionsPicker.js +27 -0
- package/lib/types/components/PlanPicker.d.ts +15 -0
- package/lib/types/components/PlanPicker.d.ts.map +1 -0
- package/lib/types/components/PlanPicker.js +18 -0
- package/lib/types/components/PresetPicker.d.ts +4 -1
- package/lib/types/components/PresetPicker.d.ts.map +1 -1
- package/lib/types/components/PresetPicker.js +2 -2
- package/lib/types/components/PromptInput.d.ts +4 -3
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +602 -75
- package/lib/types/components/RecapPanel.d.ts +25 -0
- package/lib/types/components/RecapPanel.d.ts.map +1 -0
- package/lib/types/components/RecapPanel.js +55 -0
- package/lib/types/components/RewindPicker.d.ts +12 -1
- package/lib/types/components/RewindPicker.d.ts.map +1 -1
- package/lib/types/components/RewindPicker.js +6 -4
- package/lib/types/components/ScrollbarGutter.d.ts +28 -0
- package/lib/types/components/ScrollbarGutter.d.ts.map +1 -0
- package/lib/types/components/ScrollbarGutter.js +119 -0
- package/lib/types/components/Select.d.ts +8 -1
- package/lib/types/components/Select.d.ts.map +1 -1
- package/lib/types/components/Select.js +4 -2
- package/lib/types/components/SkillsPicker.d.ts +4 -1
- package/lib/types/components/SkillsPicker.d.ts.map +1 -1
- package/lib/types/components/SkillsPicker.js +2 -2
- package/lib/types/components/SubagentCard.d.ts +2 -1
- package/lib/types/components/SubagentCard.d.ts.map +1 -1
- package/lib/types/components/SubagentCard.js +9 -2
- package/lib/types/components/SubagentDashboard.d.ts +4 -0
- package/lib/types/components/SubagentDashboard.d.ts.map +1 -1
- package/lib/types/components/SubagentDashboard.js +9 -1
- package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
- package/lib/types/components/SubagentDetailScene.js +5 -4
- package/lib/types/components/SuggestionCard.d.ts +65 -0
- package/lib/types/components/SuggestionCard.d.ts.map +1 -0
- package/lib/types/components/SuggestionCard.js +77 -0
- package/lib/types/components/ThemePicker.d.ts +4 -1
- package/lib/types/components/ThemePicker.d.ts.map +1 -1
- package/lib/types/components/ThemePicker.js +2 -2
- package/lib/types/components/ThinkingToggle.d.ts +4 -1
- package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
- package/lib/types/components/ThinkingToggle.js +2 -2
- package/lib/types/components/TimelineRail.d.ts +53 -0
- package/lib/types/components/TimelineRail.d.ts.map +1 -0
- package/lib/types/components/TimelineRail.js +197 -0
- package/lib/types/components/WorkspaceFlowPicker.d.ts +6 -1
- package/lib/types/components/WorkspaceFlowPicker.d.ts.map +1 -1
- package/lib/types/components/WorkspaceFlowPicker.js +4 -2
- package/lib/types/components/WorkspaceMenuPicker.d.ts +19 -0
- package/lib/types/components/WorkspaceMenuPicker.d.ts.map +1 -0
- package/lib/types/components/WorkspaceMenuPicker.js +19 -0
- package/lib/types/components/WorkspacePicker.d.ts +4 -1
- package/lib/types/components/WorkspacePicker.d.ts.map +1 -1
- package/lib/types/components/WorkspacePicker.js +2 -2
- package/lib/types/components/approvals/ApprovalPanel.d.ts.map +1 -1
- package/lib/types/components/approvals/ApprovalPanel.js +5 -1
- package/lib/types/components/design-system/ListItem.d.ts +8 -1
- package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
- package/lib/types/components/design-system/ListItem.js +8 -3
- package/lib/types/components/design-system/ThemeProvider.d.ts +7 -0
- package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
- package/lib/types/components/design-system/ThemeProvider.js +2 -1
- package/lib/types/components/messages/AssistantTextMessage.d.ts +5 -2
- package/lib/types/components/messages/AssistantTextMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantTextMessage.js +6 -2
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +10 -4
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +15 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +37 -7
- package/lib/types/components/messages/UserPromptMessage.d.ts +2 -1
- package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts +7 -3
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +75 -11
- package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
- package/lib/types/components/questions/PlanReviewPanel.js +13 -2
- package/lib/types/components/sessions/SessionListRow.d.ts +4 -1
- package/lib/types/components/sessions/SessionListRow.d.ts.map +1 -1
- package/lib/types/components/sessions/SessionListRow.js +4 -2
- package/lib/types/components/trajectory/HotspotView.d.ts +7 -1
- package/lib/types/components/trajectory/HotspotView.d.ts.map +1 -1
- package/lib/types/components/trajectory/HotspotView.js +8 -2
- package/lib/types/components/trajectory/Ledger.d.ts +9 -1
- package/lib/types/components/trajectory/Ledger.d.ts.map +1 -1
- package/lib/types/components/trajectory/Ledger.js +23 -5
- package/lib/types/components/trajectory/WaveBand.d.ts +10 -1
- package/lib/types/components/trajectory/WaveBand.d.ts.map +1 -1
- package/lib/types/components/trajectory/WaveBand.js +7 -2
- package/lib/types/dsh-adapter/channel.d.ts +117 -7
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +1301 -122
- package/lib/types/dsh-adapter/compat/index.d.ts +8 -6
- package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/index.js +8 -6
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts +150 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/sessionLog.js +518 -41
- package/lib/types/dsh-adapter/contract.d.ts +1 -1
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +1 -0
- package/lib/types/dsh-adapter/extension-events.d.ts +1 -1
- package/lib/types/dsh-adapter/extension-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.d.ts +20 -2
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +9 -1
- package/lib/types/dsh-adapter/plugin.d.ts +0 -9
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +453 -14
- package/lib/types/dsh-adapter/presets.d.ts +18 -0
- package/lib/types/dsh-adapter/presets.d.ts.map +1 -1
- package/lib/types/dsh-adapter/presets.js +31 -0
- package/lib/types/dsh-adapter/providerWizard.d.ts +29 -1
- package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
- package/lib/types/dsh-adapter/providerWizard.js +89 -5
- package/lib/types/dsh-adapter/questions.d.ts +19 -2
- package/lib/types/dsh-adapter/questions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/questions.js +53 -10
- package/lib/types/dsh-adapter/recap.d.ts +49 -0
- package/lib/types/dsh-adapter/recap.d.ts.map +1 -0
- package/lib/types/dsh-adapter/recap.js +121 -0
- package/lib/types/dsh-adapter/sessionTree.d.ts +314 -0
- package/lib/types/dsh-adapter/sessionTree.d.ts.map +1 -0
- package/lib/types/dsh-adapter/sessionTree.js +954 -0
- package/lib/types/dsh-adapter/shortcuts.d.ts +15 -44
- package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -1
- package/lib/types/dsh-adapter/shortcuts.js +28 -165
- package/lib/types/dsh-adapter/types.d.ts +1 -1
- package/lib/types/dsh-adapter/types.d.ts.map +1 -1
- package/lib/types/herdr.js +1 -1
- package/lib/types/i18n.d.ts +770 -181
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +257 -80
- package/lib/types/ink/components/AlternateScreen.d.ts.map +1 -1
- package/lib/types/ink/components/AlternateScreen.js +13 -1
- package/lib/types/ink/components/App.d.ts +12 -1
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +101 -4
- package/lib/types/ink/components/ClockContext.d.ts.map +1 -1
- package/lib/types/ink/components/ClockContext.js +2 -0
- package/lib/types/ink/components/ScrollBox.d.ts.map +1 -1
- package/lib/types/ink/components/ScrollBox.js +170 -91
- package/lib/types/ink/constants.d.ts +9 -0
- package/lib/types/ink/constants.d.ts.map +1 -1
- package/lib/types/ink/constants.js +9 -0
- package/lib/types/ink/events/click-event.d.ts +7 -16
- package/lib/types/ink/events/click-event.d.ts.map +1 -1
- package/lib/types/ink/events/click-event.js +16 -19
- package/lib/types/ink/events/event-handlers.d.ts +11 -1
- package/lib/types/ink/events/event-handlers.d.ts.map +1 -1
- package/lib/types/ink/events/event-handlers.js +2 -0
- package/lib/types/ink/events/input-event.d.ts +9 -0
- package/lib/types/ink/events/input-event.d.ts.map +1 -1
- package/lib/types/ink/events/input-event.js +4 -0
- package/lib/types/ink/events/pointer-event.d.ts +61 -0
- package/lib/types/ink/events/pointer-event.d.ts.map +1 -0
- package/lib/types/ink/events/pointer-event.js +61 -0
- package/lib/types/ink/events/wheel-event.d.ts +17 -0
- package/lib/types/ink/events/wheel-event.d.ts.map +1 -0
- package/lib/types/ink/events/wheel-event.js +20 -0
- package/lib/types/ink/geometry-trace.d.ts +51 -0
- package/lib/types/ink/geometry-trace.d.ts.map +1 -0
- package/lib/types/ink/geometry-trace.js +83 -0
- package/lib/types/ink/hit-test.d.ts +56 -1
- package/lib/types/ink/hit-test.d.ts.map +1 -1
- package/lib/types/ink/hit-test.js +146 -8
- package/lib/types/ink/ink.d.ts +58 -1
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +230 -29
- package/lib/types/ink/log-update.d.ts.map +1 -1
- package/lib/types/ink/log-update.js +21 -0
- package/lib/types/ink/node-cache.d.ts +5 -0
- package/lib/types/ink/node-cache.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.d.ts +8 -0
- package/lib/types/ink/parse-keypress.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.js +101 -12
- package/lib/types/ink/render-node-to-output.d.ts +10 -0
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
- package/lib/types/ink/render-node-to-output.js +111 -18
- package/lib/types/ink/timeline-rail.d.ts +138 -0
- package/lib/types/ink/timeline-rail.d.ts.map +1 -0
- package/lib/types/ink/timeline-rail.js +179 -0
- package/lib/types/ink/wrap-text.d.ts.map +1 -1
- package/lib/types/ink/wrap-text.js +47 -5
- package/lib/types/migrationPrefs.d.ts +60 -0
- package/lib/types/migrationPrefs.d.ts.map +1 -0
- package/lib/types/migrationPrefs.js +97 -0
- package/lib/types/modelGroups.d.ts +72 -0
- package/lib/types/modelGroups.d.ts.map +1 -0
- package/lib/types/modelGroups.js +97 -0
- package/lib/types/modelRecents.d.ts +39 -0
- package/lib/types/modelRecents.d.ts.map +1 -0
- package/lib/types/modelRecents.js +97 -0
- package/lib/types/native-ts/yoga-layout/index.d.ts +11 -0
- package/lib/types/native-ts/yoga-layout/index.d.ts.map +1 -1
- package/lib/types/native-ts/yoga-layout/index.js +31 -1
- package/lib/types/oauth.d.ts +15 -0
- package/lib/types/oauth.d.ts.map +1 -0
- package/lib/types/oauth.js +14 -0
- package/lib/types/reload.d.ts +109 -0
- package/lib/types/reload.d.ts.map +1 -0
- package/lib/types/reload.js +118 -0
- package/lib/types/screens/Chat.d.ts +3 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +1377 -371
- package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
- package/lib/types/screens/SessionBrowser.js +56 -29
- package/lib/types/screens/SessionTree.d.ts +27 -0
- package/lib/types/screens/SessionTree.d.ts.map +1 -0
- package/lib/types/screens/SessionTree.js +555 -0
- package/lib/types/screens/Settings.d.ts.map +1 -1
- package/lib/types/screens/Settings.js +64 -22
- package/lib/types/screens/StatusLine.d.ts +0 -8
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +224 -45
- package/lib/types/screens/StatusMetrics.d.ts +35 -3
- package/lib/types/screens/StatusMetrics.d.ts.map +1 -1
- package/lib/types/screens/StatusMetrics.js +63 -8
- package/lib/types/screens/TrajectoryScene.d.ts.map +1 -1
- package/lib/types/screens/TrajectoryScene.js +81 -14
- package/lib/types/screens/chatOverlay.d.ts +237 -0
- package/lib/types/screens/chatOverlay.d.ts.map +1 -0
- package/lib/types/screens/chatOverlay.js +116 -0
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +64 -10
- package/lib/types/tuiDisplayPrefs.d.ts +15 -0
- package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
- package/lib/types/tuiDisplayPrefs.js +9 -0
- package/lib/types/update.d.ts +139 -0
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +382 -30
- package/lib/types/utils/debug.d.ts +10 -0
- package/lib/types/utils/debug.d.ts.map +1 -1
- package/lib/types/utils/debug.js +24 -0
- package/lib/types/utils/fileTarget.d.ts +46 -0
- package/lib/types/utils/fileTarget.d.ts.map +1 -0
- package/lib/types/utils/fileTarget.js +178 -0
- package/lib/types/utils/keymap.d.ts +134 -0
- package/lib/types/utils/keymap.d.ts.map +1 -0
- package/lib/types/utils/keymap.js +311 -0
- package/lib/types/utils/mentions.d.ts +25 -2
- package/lib/types/utils/mentions.d.ts.map +1 -1
- package/lib/types/utils/mentions.js +69 -10
- package/lib/types/utils/openExternal.d.ts +50 -0
- package/lib/types/utils/openExternal.d.ts.map +1 -0
- package/lib/types/utils/openExternal.js +170 -0
- package/lib/types/utils/paths.d.ts.map +1 -1
- package/lib/types/utils/paths.js +1 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/LICENSE +21 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/README.md +140 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/cordis.patch.yml +11 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/dsh-plugin.json +44 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/command.d.ts +14 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/command.js +67 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/credentials.d.ts +64 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/credentials.js +170 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/index.d.ts +79 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/index.js +196 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.d.ts +68 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.js +193 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/opener.d.ts +32 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/opener.js +101 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/profiles.d.ts +31 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/profiles.js +68 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/service.d.ts +69 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/service.js +129 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +70 -0
- package/node_modules/@dsh-std/command/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/command/LICENSE +21 -21
- package/node_modules/@dsh-std/command/README.md +26 -26
- package/node_modules/@dsh-std/command/README.zh.md +28 -28
- package/node_modules/@dsh-std/command/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/command/package.json +22 -22
- package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/node_modules/@dsh-std/connection/README.md +42 -42
- package/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/node_modules/@dsh-std/connection/package.json +20 -20
- package/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/core/LICENSE +21 -21
- package/node_modules/@dsh-std/core/README.md +13 -13
- package/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/core/package.json +21 -21
- package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
- package/node_modules/@dsh-std/manifest/LICENSE +21 -21
- package/node_modules/@dsh-std/manifest/README.md +5 -5
- package/node_modules/@dsh-std/manifest/README.zh.md +5 -5
- package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/manifest/package.json +20 -20
- package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
- package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/messages/LICENSE +21 -21
- package/node_modules/@dsh-std/messages/README.md +5 -5
- package/node_modules/@dsh-std/messages/README.zh.md +7 -7
- package/node_modules/@dsh-std/messages/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/messages/package.json +20 -20
- package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -54
- package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
- package/node_modules/@dsh-std/presentation/LICENSE +21 -21
- package/node_modules/@dsh-std/presentation/README.md +27 -27
- package/node_modules/@dsh-std/presentation/README.zh.md +29 -29
- package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
- package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/presentation/package.json +25 -25
- package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/storage/LICENSE +21 -21
- package/node_modules/@dsh-std/storage/README.md +5 -5
- package/node_modules/@dsh-std/storage/README.zh.md +7 -7
- package/node_modules/@dsh-std/storage/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/storage/package.json +20 -20
- package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -56
- package/package.json +19 -5
- package/presets/liangshen/.dsh-tui-managed.json +1 -1
- package/presets/liangshen/instruction-hint.mjs +8 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -42
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -20
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -5
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -5
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -20
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -27
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -29
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -25
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -42
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -20
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -21
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DOMElement } from './dom.js';
|
|
2
|
+
import type { Rectangle } from './layout/geometry.js';
|
|
2
3
|
import type Output from './output.js';
|
|
3
4
|
import type { Screen } from './screen.js';
|
|
4
5
|
import { type StyledSegment } from './squash-text-nodes.js';
|
|
@@ -22,6 +23,15 @@ export type ScrollHint = {
|
|
|
22
23
|
bottom: number;
|
|
23
24
|
delta: number;
|
|
24
25
|
};
|
|
26
|
+
export type AbsoluteHitEntry = {
|
|
27
|
+
node: DOMElement;
|
|
28
|
+
rect: Rectangle;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* The current frame's absolute-positioned nodes in paint order.
|
|
32
|
+
* @returns read-only list; reverse-iterate for topmost-first hit-testing.
|
|
33
|
+
*/
|
|
34
|
+
export declare function getAbsoluteHitList(): readonly AbsoluteHitEntry[];
|
|
25
35
|
/** Reset the scroll hint for the next frame and rotate the absolute-rect buffers. */
|
|
26
36
|
export declare function resetScrollHint(): void;
|
|
27
37
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-node-to-output.d.ts","sourceRoot":"","sources":["../../../src/ink/render-node-to-output.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"render-node-to-output.d.ts","sourceRoot":"","sources":["../../../src/ink/render-node-to-output.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAGrD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AAErC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAqBxC,6CAA6C;AAC7C,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAOD;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAkBvE,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAAA;AAGpE;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,gBAAgB,EAAE,CAEhE;AAED,qFAAqF;AACrF,wBAAgB,eAAe,IAAI,IAAI,CAKtC;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CAEjD;AASD,8DAA8D;AAC9D,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,UAAU,GAAG,IAAI,CAEtD;AAgBD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAGD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,IAAI,YAAY,EAAE,CAIpD;AAoFD;;;;;GAKG;AACH,iBAAS,qBAAqB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,EAAE,CASlE;AAED;;;;;;;;;;;GAWG;AACH,iBAAS,wBAAwB,CAC/B,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,aAAa,EAAE,EACzB,aAAa,EAAE,MAAM,EAAE,EACvB,aAAa,EAAE,MAAM,EACrB,WAAW,GAAE,OAAe,GAC3B,MAAM,CA0GR;AA+DD;;;;;;;;;GASG;AACH,iBAAS,kBAAkB,CACzB,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAM9B,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,wBAAwB,CAAC,EAAE,KAAK,CAAA;CACjC,GACA,IAAI,CAq9BN;AA0OD,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,CAAA;AAE1D,eAAe,kBAAkB,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import indentString from 'indent-string';
|
|
2
2
|
import { applyTextStyles } from './colorize.js';
|
|
3
|
+
import { GEOMETRY_TRACE_ENABLED, noteScrollGeometry } from './geometry-trace.js';
|
|
3
4
|
import getMaxWidth from './get-max-width.js';
|
|
4
5
|
import { LayoutDisplay, LayoutEdge } from './layout/node.js';
|
|
5
6
|
import { nodeCache, pendingClears } from './node-cache.js';
|
|
@@ -41,11 +42,20 @@ let scrollHint = null;
|
|
|
41
42
|
// still have the rect.
|
|
42
43
|
let absoluteRectsPrev = [];
|
|
43
44
|
let absoluteRectsCur = [];
|
|
45
|
+
let absoluteHitList = [];
|
|
46
|
+
/**
|
|
47
|
+
* The current frame's absolute-positioned nodes in paint order.
|
|
48
|
+
* @returns read-only list; reverse-iterate for topmost-first hit-testing.
|
|
49
|
+
*/
|
|
50
|
+
export function getAbsoluteHitList() {
|
|
51
|
+
return absoluteHitList;
|
|
52
|
+
}
|
|
44
53
|
/** Reset the scroll hint for the next frame and rotate the absolute-rect buffers. */
|
|
45
54
|
export function resetScrollHint() {
|
|
46
55
|
scrollHint = null;
|
|
47
56
|
absoluteRectsPrev = absoluteRectsCur;
|
|
48
57
|
absoluteRectsCur = [];
|
|
58
|
+
absoluteHitList = [];
|
|
49
59
|
}
|
|
50
60
|
/**
|
|
51
61
|
* The scroll hint captured this frame, or null.
|
|
@@ -359,18 +369,34 @@ function renderNodeToOutput(node, output, options) {
|
|
|
359
369
|
let y = offsetY + yogaTop;
|
|
360
370
|
const width = yogaNode.getComputedWidth();
|
|
361
371
|
const height = yogaNode.getComputedHeight();
|
|
362
|
-
// Absolute-positioned overlays
|
|
363
|
-
//
|
|
364
|
-
//
|
|
365
|
-
//
|
|
366
|
-
//
|
|
367
|
-
//
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
372
|
+
// Absolute-positioned overlays anchored above their parent
|
|
373
|
+
// (bottom='100%') compute negative screen y when their content is
|
|
374
|
+
// taller than the space above the anchor. Do NOT clamp y to 0 here:
|
|
375
|
+
// shifting the node down breaks the bottom-anchoring contract — the
|
|
376
|
+
// panel's BOTTOM would overflow past the anchor and paint over the
|
|
377
|
+
// composer/status rows below it (small-terminal overlay reports).
|
|
378
|
+
// Instead let the y<0 rows clip naturally: setCellAt drops cells above
|
|
379
|
+
// row 0 and blitRegion clamps in screen space, so the panel keeps its
|
|
380
|
+
// bottom pinned at the anchor and only loses its topmost rows — the
|
|
381
|
+
// same semantics as CSS clipping above the containing block. Producers
|
|
382
|
+
// prevent the case entirely by maxHeight-ing the overlay to the actual
|
|
383
|
+
// space above the anchor (OverlayAbove), so clipping is the last
|
|
384
|
+
// resort, not the layout.
|
|
371
385
|
// Check if we can skip this subtree (clean node with unchanged layout).
|
|
372
386
|
// Blit cells from previous screen instead of re-rendering.
|
|
373
387
|
const cached = nodeCache.get(node);
|
|
388
|
+
// The node's EFFECTIVE background = its own + the inherited one. When it
|
|
389
|
+
// changed since the last frame (hover on/off toggles a row's
|
|
390
|
+
// backgroundColor, a parent's bg swap changes every child's inherited
|
|
391
|
+
// value), prevScreen still holds the OLD background — a clean child
|
|
392
|
+
// blitting it would resurrect the stale color (stuck hover highlights:
|
|
393
|
+
// the row's fill is skipped once the bg is removed, its clean children
|
|
394
|
+
// then blit the previous bg'd cells, the frame equals prevScreen, the
|
|
395
|
+
// diff finds nothing, and the highlight never clears). Compare against
|
|
396
|
+
// the value recorded at the previous render and refuse the blit when it
|
|
397
|
+
// moved.
|
|
398
|
+
const effectiveBg = node.style.backgroundColor ?? inheritedBackgroundColor;
|
|
399
|
+
const bgChanged = cached?.bg !== effectiveBg;
|
|
374
400
|
if (!node.dirty &&
|
|
375
401
|
!skipSelfBlit &&
|
|
376
402
|
node.pendingScrollDelta === undefined &&
|
|
@@ -379,6 +405,7 @@ function renderNodeToOutput(node, output, options) {
|
|
|
379
405
|
cached.y === y &&
|
|
380
406
|
cached.width === width &&
|
|
381
407
|
cached.height === height &&
|
|
408
|
+
!bgChanged &&
|
|
382
409
|
prevScreen) {
|
|
383
410
|
const fx = Math.floor(x);
|
|
384
411
|
const fy = Math.floor(y);
|
|
@@ -387,6 +414,7 @@ function renderNodeToOutput(node, output, options) {
|
|
|
387
414
|
output.blit(prevScreen, fx, fy, fw, fh);
|
|
388
415
|
if (node.style.position === 'absolute') {
|
|
389
416
|
absoluteRectsCur.push(cached);
|
|
417
|
+
absoluteHitList.push({ node, rect: cached });
|
|
390
418
|
}
|
|
391
419
|
// Absolute descendants can paint outside this node's layout bounds
|
|
392
420
|
// (e.g. a slash menu with position='absolute' bottom='100%' floats
|
|
@@ -593,7 +621,29 @@ function renderNodeToOutput(node, output, options) {
|
|
|
593
621
|
// within the viewport (equal to the scroll container's
|
|
594
622
|
// paddingTop), and innerHeight already subtracts padding, so
|
|
595
623
|
// including it double-counts padding and inflates maxScroll.
|
|
596
|
-
|
|
624
|
+
let scrollHeight = contentYoga?.getComputedHeight() ?? 0;
|
|
625
|
+
// Defensive extent floor: the wrapper's Yoga height can land ONE LINE
|
|
626
|
+
// short of its children's laid-out extent (the engine's flex-basis
|
|
627
|
+
// measure cache and the child's final subtree layout can disagree by
|
|
628
|
+
// a row — measured on resume of a long session: wrapper 286 while the
|
|
629
|
+
// last row's bottom sat at 287, stable across forced re-layouts). A
|
|
630
|
+
// short scrollHeight clamps maxScroll below the real bottom, so the
|
|
631
|
+
// sticky pin parks the viewport a line up and the tail line culls
|
|
632
|
+
// against the viewport edge — permanently invisible AND unreachable
|
|
633
|
+
// (no scroll position ever shows it; the user loses the newest
|
|
634
|
+
// message). The children's real extent is the authoritative floor.
|
|
635
|
+
// O(direct children) — the windowed list keeps this tiny, and the
|
|
636
|
+
// painter walks the same nodes right below.
|
|
637
|
+
if (content !== undefined) {
|
|
638
|
+
for (const child of content.childNodes) {
|
|
639
|
+
const childYoga = child.yogaNode;
|
|
640
|
+
if (childYoga === undefined)
|
|
641
|
+
continue;
|
|
642
|
+
const bottom = childYoga.getComputedTop() + childYoga.getComputedHeight();
|
|
643
|
+
if (bottom > scrollHeight)
|
|
644
|
+
scrollHeight = bottom;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
597
647
|
// Capture previous scroll bounds BEFORE overwriting — the at-bottom
|
|
598
648
|
// follow check compares against last frame's max.
|
|
599
649
|
const prevScrollHeight = node.scrollHeight ?? scrollHeight;
|
|
@@ -735,7 +785,17 @@ function renderNodeToOutput(node, output, options) {
|
|
|
735
785
|
// Keep the pre-frame position on a shrink frame (measurement
|
|
736
786
|
// artifact) instead of clamping to the shrunken maxScroll — the
|
|
737
787
|
// clamp would persist the yank even after content grows back.
|
|
738
|
-
|
|
788
|
+
// Exception: a STICKY view must stay pinned to the bottom. A width
|
|
789
|
+
// change clears MessageList's row-height cache, collapsing the
|
|
790
|
+
// estimated scrollHeight; freezing the pre-shrink scrollTop then
|
|
791
|
+
// parks it PAST the whole shrunken content — every child culls and
|
|
792
|
+
// the frame paints only the bottom chrome. With the resize erase
|
|
793
|
+
// (needsEraseBeforePaint) that lands as a pure blank screen with
|
|
794
|
+
// just the input box, and an idle app produces no follow-up frame
|
|
795
|
+
// to heal it (user-reported full-screen loss on pane-width jitter —
|
|
796
|
+
// issue #421; repro-resize-blank). Clamping a sticky view to the shrunken
|
|
797
|
+
// maxScroll is exactly its contract — show the bottom.
|
|
798
|
+
let scrollTop = shrunk && !sticky ? cur : Math.max(0, Math.min(cur, maxScroll));
|
|
739
799
|
// Virtual-scroll clamp: if scrollTop raced past the currently-mounted
|
|
740
800
|
// range (burst PageUp before React re-renders), render at the EDGE of
|
|
741
801
|
// the mounted children instead of blank spacer. Do NOT write back to
|
|
@@ -744,7 +804,15 @@ function renderNodeToOutput(node, output, options) {
|
|
|
744
804
|
// the right range. Not scheduling scrollDrainNode here keeps the
|
|
745
805
|
// clamp passive — React's commit → resetAfterCommit → onRender will
|
|
746
806
|
// paint again with fresh bounds.
|
|
747
|
-
|
|
807
|
+
// Cap both bounds at maxScroll: the clamp bounds come from
|
|
808
|
+
// MessageList's height ESTIMATES while maxScroll comes from the
|
|
809
|
+
// frame's actual Yoga height. A width change resets the estimates
|
|
810
|
+
// (row-height cache clear), and a stale bound can point PAST the
|
|
811
|
+
// shrunken content bottom — the painted viewport then sits entirely
|
|
812
|
+
// below the content and every child culls to blank (the sticky
|
|
813
|
+
// full-screen loss — issue #421; repro-resize-blank). Nothing renderable exists
|
|
814
|
+
// below maxScroll regardless of what the estimates claim.
|
|
815
|
+
const clamped = Math.max(Math.min(cMin ?? -Infinity, maxScroll), Math.min(scrollTop, Math.min(cMax ?? Infinity, maxScroll)));
|
|
748
816
|
node.scrollTop = scrollTop;
|
|
749
817
|
// Clamp hitting top/bottom consumes any remainder. Set drainPending
|
|
750
818
|
// only after clamp so a wasted no-op frame isn't scheduled.
|
|
@@ -752,6 +820,28 @@ function renderNodeToOutput(node, output, options) {
|
|
|
752
820
|
node.pendingScrollDelta = undefined;
|
|
753
821
|
if (node.pendingScrollDelta !== undefined)
|
|
754
822
|
scrollDrainNode = node;
|
|
823
|
+
// Geometry forensics (#421/#433): everything that decides where this
|
|
824
|
+
// viewport painted — captured AFTER all clamps so the trace shows the
|
|
825
|
+
// final renderScrollTop, not the requested one.
|
|
826
|
+
if (GEOMETRY_TRACE_ENABLED) {
|
|
827
|
+
noteScrollGeometry({
|
|
828
|
+
sticky,
|
|
829
|
+
shrunk,
|
|
830
|
+
grew,
|
|
831
|
+
atBottom,
|
|
832
|
+
scrollTopBeforeFollow,
|
|
833
|
+
cur,
|
|
834
|
+
scrollTop,
|
|
835
|
+
renderScrollTop: clamped,
|
|
836
|
+
scrollHeight,
|
|
837
|
+
prevScrollHeight,
|
|
838
|
+
innerHeight,
|
|
839
|
+
maxScroll,
|
|
840
|
+
prevMaxScroll,
|
|
841
|
+
clampMin: cMin ?? null,
|
|
842
|
+
clampMax: cMax ?? null,
|
|
843
|
+
});
|
|
844
|
+
}
|
|
755
845
|
// Wheel-drain selection translate (#438): the drain moved content
|
|
756
846
|
// by (scrollTop - scrollTopBeforeFollow) rows this frame, minus
|
|
757
847
|
// what at-bottom follow already reported above (followDelta is 0
|
|
@@ -1092,11 +1182,12 @@ function renderNodeToOutput(node, output, options) {
|
|
|
1092
1182
|
// backgroundColor and opaque both disable child blit: the fill
|
|
1093
1183
|
// overwrites the entire interior each render, so any child whose
|
|
1094
1184
|
// layout position shifted would blit stale cells from prevScreen
|
|
1095
|
-
// on top of the fresh fill.
|
|
1096
|
-
//
|
|
1097
|
-
//
|
|
1098
|
-
//
|
|
1099
|
-
|
|
1185
|
+
// on top of the fresh fill. bgChanged (effective background moved,
|
|
1186
|
+
// e.g. a hover highlight removed) must disable child blit for the
|
|
1187
|
+
// same reason: the old fill lives in prevScreen and the children's
|
|
1188
|
+
// blits would resurrect it — the frame then equals prevScreen and
|
|
1189
|
+
// the diff never clears the stale highlight.
|
|
1190
|
+
ownBackgroundColor || node.style.opaque || bgChanged ? undefined : prevScreen, boxBackgroundColor);
|
|
1100
1191
|
}
|
|
1101
1192
|
if (needsClip) {
|
|
1102
1193
|
output.unclip();
|
|
@@ -1110,10 +1201,11 @@ function renderNodeToOutput(node, output, options) {
|
|
|
1110
1201
|
renderChildren(node, output, x, y, hasRemovedChild, prevScreen, inheritedBackgroundColor);
|
|
1111
1202
|
}
|
|
1112
1203
|
// Cache layout bounds for dirty tracking
|
|
1113
|
-
const rect = { x, y, width, height, top: yogaTop };
|
|
1204
|
+
const rect = { x, y, width, height, top: yogaTop, bg: effectiveBg };
|
|
1114
1205
|
nodeCache.set(node, rect);
|
|
1115
1206
|
if (node.style.position === 'absolute') {
|
|
1116
1207
|
absoluteRectsCur.push(rect);
|
|
1208
|
+
absoluteHitList.push({ node, rect });
|
|
1117
1209
|
}
|
|
1118
1210
|
node.dirty = false;
|
|
1119
1211
|
}
|
|
@@ -1227,6 +1319,7 @@ function blitEscapingAbsoluteDescendants(node, output, prevScreen, px, py, pw, p
|
|
|
1227
1319
|
const cached = nodeCache.get(elem);
|
|
1228
1320
|
if (cached) {
|
|
1229
1321
|
absoluteRectsCur.push(cached);
|
|
1322
|
+
absoluteHitList.push({ node: elem, rect: cached });
|
|
1230
1323
|
const cx = Math.floor(cached.x);
|
|
1231
1324
|
const cy = Math.floor(cached.y);
|
|
1232
1325
|
const cw = Math.floor(cached.width);
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timeline rail — the pure geometry model behind the fullscreen
|
|
3
|
+
* transcript's turn navigator (a port of Grok Build's timeline sidebar
|
|
4
|
+
* semantics onto the dsh Ink tree).
|
|
5
|
+
*
|
|
6
|
+
* The rail is a 2-column gutter REPLACING the classic scrollbar: one tick
|
|
7
|
+
* per user turn, where tick position encodes CONVERSATION ORDER, not
|
|
8
|
+
* scroll proportion. Geometry is computed into a single frozen structure
|
|
9
|
+
* consumed by both the renderer and mouse hit-testing, so what you see is
|
|
10
|
+
* always what you can click ("看得到但点不中" impossible by construction).
|
|
11
|
+
*
|
|
12
|
+
* Viewport semantics (all derived from the same turn-top list, mirroring
|
|
13
|
+
* grok-pager's ScrollbackState):
|
|
14
|
+
*
|
|
15
|
+
* - active: the LAST turn whose prompt top is at-or-above the viewport
|
|
16
|
+
* top (the turn whose content owns the top row — "the turn being
|
|
17
|
+
* read"). When pre-turn content (logo / loaded-context panel) owns the
|
|
18
|
+
* top, the FIRST turn stands in. Never the newest-turn clamp: its
|
|
19
|
+
* one-step-off-bottom highlight leap is exactly what this rule avoids.
|
|
20
|
+
* - up target: the last turn STRICTLY above the viewport top. From
|
|
21
|
+
* mid-turn it first aligns the current turn's own prompt, and it can
|
|
22
|
+
* never name a trailing turn no scroll could bring to the top
|
|
23
|
+
* (the stuck-▲ bug).
|
|
24
|
+
* - down target: the FIRST turn whose prompt top is strictly below the
|
|
25
|
+
* viewport top AND reachable (top ≤ maxScroll — the renderer clamps
|
|
26
|
+
* scrollTop to maxScroll, so a turn below it could never own the top
|
|
27
|
+
* row; naming it would make ▼ repeat itself forever).
|
|
28
|
+
*
|
|
29
|
+
* Not ported (deliberately): ratatui Buffer drawing and Rust state
|
|
30
|
+
* organization — algorithms only, per the reference report.
|
|
31
|
+
*/
|
|
32
|
+
/** Columns the rail reserves (widest tick glyph). */
|
|
33
|
+
export declare const RAIL_WIDTH = 2;
|
|
34
|
+
/** Terminals narrower than this hide the rail (transcript needs the cols). */
|
|
35
|
+
export declare const RAIL_MIN_TERMINAL_WIDTH = 60;
|
|
36
|
+
/** Fewer turns than this and the rail is noise. */
|
|
37
|
+
export declare const RAIL_MIN_TURNS = 2;
|
|
38
|
+
/** Stored preview cap (chars). Render paths re-truncate to card width. */
|
|
39
|
+
export declare const PREVIEW_MAX_CHARS = 120;
|
|
40
|
+
/** One user turn, as the rail sees it. Identity is the row id — never an
|
|
41
|
+
* array index (deletion / rewind / loadOlder would mis-target it). */
|
|
42
|
+
export interface TimelineTurn {
|
|
43
|
+
/** ChatRow id of the user message (jump/preview target). */
|
|
44
|
+
id: number;
|
|
45
|
+
/** Content-space top of the prompt TEXT (scrollTo(target) pins it to
|
|
46
|
+
* the viewport top). */
|
|
47
|
+
top: number;
|
|
48
|
+
/** First non-empty prompt line, char-capped (see clipPreview). */
|
|
49
|
+
preview: string;
|
|
50
|
+
/**
|
|
51
|
+
* True while the row sits BEFORE the fold window (older than the most
|
|
52
|
+
* recent MAX_RENDERED_ROWS rows): its top is unknown (unmounted since
|
|
53
|
+
* before the fold; `top` carries −1) and clicking the tick must first
|
|
54
|
+
* reveal the folded history (Chat: showAll + force-mount + seek) rather
|
|
55
|
+
* than scrollTo(−1). Rendering a tick for it is still correct — the
|
|
56
|
+
* turn EXISTS and is navigable, it is just folded away right now
|
|
57
|
+
* (drawing only window turns read as "the rail covers just 2-3 nodes"
|
|
58
|
+
* on tool-heavy sessions where 300 rows ≈ a handful of turns).
|
|
59
|
+
*/
|
|
60
|
+
folded?: boolean;
|
|
61
|
+
}
|
|
62
|
+
/** The per-commit snapshot MessageList reports and the rail + sticky
|
|
63
|
+
* header consume — one source so the two can never disagree. */
|
|
64
|
+
export interface TimelineSnapshot {
|
|
65
|
+
/** Turns in conversation order. */
|
|
66
|
+
turns: ReadonlyArray<TimelineTurn>;
|
|
67
|
+
/** Turn owning the viewport top row; first turn while pre-turn content
|
|
68
|
+
* owns the top; null only when there are no turns. */
|
|
69
|
+
activeId: number | null;
|
|
70
|
+
/** ▲ target (strictly above the top), null at the first turn. */
|
|
71
|
+
upId: number | null;
|
|
72
|
+
/** ▼ target (below the top and reachable), null at the end. */
|
|
73
|
+
downId: number | null;
|
|
74
|
+
}
|
|
75
|
+
/** Per-render rail geometry: where the ticks and chevrons landed. */
|
|
76
|
+
export interface RailGeometry {
|
|
77
|
+
/** Turn-index window shown as ticks: [windowStart, windowEnd). */
|
|
78
|
+
windowStart: number;
|
|
79
|
+
windowEnd: number;
|
|
80
|
+
/** Row of the ▲ chevron (block-local, within the rail column). */
|
|
81
|
+
upRow: number;
|
|
82
|
+
/** Row of the first tick. */
|
|
83
|
+
tickTop: number;
|
|
84
|
+
/** Row of the ▼ chevron. */
|
|
85
|
+
downRow: number;
|
|
86
|
+
}
|
|
87
|
+
/** What a rail row is. */
|
|
88
|
+
export type RailHit = {
|
|
89
|
+
kind: 'up';
|
|
90
|
+
} | {
|
|
91
|
+
kind: 'down';
|
|
92
|
+
} | {
|
|
93
|
+
kind: 'tick';
|
|
94
|
+
index: number;
|
|
95
|
+
};
|
|
96
|
+
/** Single eligibility policy: setting, terminal width, turn count, and
|
|
97
|
+
* geometric feasibility in one place. */
|
|
98
|
+
export declare function railEligible(opts: {
|
|
99
|
+
turnCount: number;
|
|
100
|
+
terminalWidth: number;
|
|
101
|
+
viewportRows: number;
|
|
102
|
+
/** False when the content fits the viewport (inline mode / fresh
|
|
103
|
+
* session): nothing to navigate, the terminal's own scrollback owns
|
|
104
|
+
* the wheel. */
|
|
105
|
+
scrollable: boolean;
|
|
106
|
+
}): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Compute rail geometry, or null when the rail must not render.
|
|
109
|
+
*
|
|
110
|
+
* Windowing: when turns outnumber tick rows (viewport − 2 chevrons), slide
|
|
111
|
+
* a window around the ACTIVE turn; at the bottom prefer the tail so the
|
|
112
|
+
* newest ticks stay visible — but never exclude the active turn, or no
|
|
113
|
+
* tick would highlight. The chevron+tick block is vertically centered in
|
|
114
|
+
* the rail column.
|
|
115
|
+
*/
|
|
116
|
+
export declare function computeRailGeometry(turnCount: number, viewportRows: number, activeIndex: number | null, atBottom: boolean): RailGeometry | null;
|
|
117
|
+
/**
|
|
118
|
+
* Which rail interaction a block-local row lands on. The whole rail width
|
|
119
|
+
* is the hit target (no pixel-hunting the glyph).
|
|
120
|
+
*/
|
|
121
|
+
export declare function railHit(geo: RailGeometry, row: number): RailHit | null;
|
|
122
|
+
/**
|
|
123
|
+
* First non-empty line, char-capped with a `…` marker. Bounded work: the
|
|
124
|
+
* scan stops at the first non-empty line and slices at the cap, so a huge
|
|
125
|
+
* one-line prompt costs O(cap), not O(line length). Char cap (not display
|
|
126
|
+
* width) on purpose — this bounds the stored snapshot; the hover card
|
|
127
|
+
* re-wraps to its own width (wrapPreviewLines).
|
|
128
|
+
*/
|
|
129
|
+
export declare function clipPreview(text: string, maxChars?: number): string;
|
|
130
|
+
/**
|
|
131
|
+
* Wrap a preview to at most 2 lines by DISPLAY width (CJK-aware — a
|
|
132
|
+
* terminal cell column budget, not a char count). The last line is
|
|
133
|
+
* ellipsized when content remains. Char-by-char accumulation keeps
|
|
134
|
+
* surrogate pairs and (best-effort) combining sequences intact by never
|
|
135
|
+
* splitting below a low surrogate.
|
|
136
|
+
*/
|
|
137
|
+
export declare function wrapPreviewLines(preview: string, maxWidth: number): string[];
|
|
138
|
+
//# sourceMappingURL=timeline-rail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline-rail.d.ts","sourceRoot":"","sources":["../../../src/ink/timeline-rail.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,qDAAqD;AACrD,eAAO,MAAM,UAAU,IAAI,CAAA;AAE3B,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,KAAK,CAAA;AAEzC,mDAAmD;AACnD,eAAO,MAAM,cAAc,IAAI,CAAA;AAE/B,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,MAAM,CAAA;AAEpC;uEACuE;AACvE,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAA;IACV;6BACyB;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;iEACiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,mCAAmC;IACnC,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;IAClC;2DACuD;IACvD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,iEAAiE;IACjE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,qEAAqE;AACrE,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IACb,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,0BAA0B;AAC1B,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GACd;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEnC;0CAC0C;AAC1C,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB;;qBAEiB;IACjB,UAAU,EAAE,OAAO,CAAA;CACpB,GAAG,OAAO,CAOV;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,QAAQ,EAAE,OAAO,GAChB,YAAY,GAAG,IAAI,CAuBrB;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAUtE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAoB,GAAG,MAAM,CAkB9E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA+B5E"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timeline rail — the pure geometry model behind the fullscreen
|
|
3
|
+
* transcript's turn navigator (a port of Grok Build's timeline sidebar
|
|
4
|
+
* semantics onto the dsh Ink tree).
|
|
5
|
+
*
|
|
6
|
+
* The rail is a 2-column gutter REPLACING the classic scrollbar: one tick
|
|
7
|
+
* per user turn, where tick position encodes CONVERSATION ORDER, not
|
|
8
|
+
* scroll proportion. Geometry is computed into a single frozen structure
|
|
9
|
+
* consumed by both the renderer and mouse hit-testing, so what you see is
|
|
10
|
+
* always what you can click ("看得到但点不中" impossible by construction).
|
|
11
|
+
*
|
|
12
|
+
* Viewport semantics (all derived from the same turn-top list, mirroring
|
|
13
|
+
* grok-pager's ScrollbackState):
|
|
14
|
+
*
|
|
15
|
+
* - active: the LAST turn whose prompt top is at-or-above the viewport
|
|
16
|
+
* top (the turn whose content owns the top row — "the turn being
|
|
17
|
+
* read"). When pre-turn content (logo / loaded-context panel) owns the
|
|
18
|
+
* top, the FIRST turn stands in. Never the newest-turn clamp: its
|
|
19
|
+
* one-step-off-bottom highlight leap is exactly what this rule avoids.
|
|
20
|
+
* - up target: the last turn STRICTLY above the viewport top. From
|
|
21
|
+
* mid-turn it first aligns the current turn's own prompt, and it can
|
|
22
|
+
* never name a trailing turn no scroll could bring to the top
|
|
23
|
+
* (the stuck-▲ bug).
|
|
24
|
+
* - down target: the FIRST turn whose prompt top is strictly below the
|
|
25
|
+
* viewport top AND reachable (top ≤ maxScroll — the renderer clamps
|
|
26
|
+
* scrollTop to maxScroll, so a turn below it could never own the top
|
|
27
|
+
* row; naming it would make ▼ repeat itself forever).
|
|
28
|
+
*
|
|
29
|
+
* Not ported (deliberately): ratatui Buffer drawing and Rust state
|
|
30
|
+
* organization — algorithms only, per the reference report.
|
|
31
|
+
*/
|
|
32
|
+
import { stringWidth } from './stringWidth.js';
|
|
33
|
+
/** Columns the rail reserves (widest tick glyph). */
|
|
34
|
+
export const RAIL_WIDTH = 2;
|
|
35
|
+
/** Terminals narrower than this hide the rail (transcript needs the cols). */
|
|
36
|
+
export const RAIL_MIN_TERMINAL_WIDTH = 60;
|
|
37
|
+
/** Fewer turns than this and the rail is noise. */
|
|
38
|
+
export const RAIL_MIN_TURNS = 2;
|
|
39
|
+
/** Stored preview cap (chars). Render paths re-truncate to card width. */
|
|
40
|
+
export const PREVIEW_MAX_CHARS = 120;
|
|
41
|
+
/** Single eligibility policy: setting, terminal width, turn count, and
|
|
42
|
+
* geometric feasibility in one place. */
|
|
43
|
+
export function railEligible(opts) {
|
|
44
|
+
return (opts.scrollable &&
|
|
45
|
+
opts.turnCount >= RAIL_MIN_TURNS &&
|
|
46
|
+
opts.terminalWidth >= RAIL_MIN_TERMINAL_WIDTH &&
|
|
47
|
+
opts.viewportRows >= 3);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Compute rail geometry, or null when the rail must not render.
|
|
51
|
+
*
|
|
52
|
+
* Windowing: when turns outnumber tick rows (viewport − 2 chevrons), slide
|
|
53
|
+
* a window around the ACTIVE turn; at the bottom prefer the tail so the
|
|
54
|
+
* newest ticks stay visible — but never exclude the active turn, or no
|
|
55
|
+
* tick would highlight. The chevron+tick block is vertically centered in
|
|
56
|
+
* the rail column.
|
|
57
|
+
*/
|
|
58
|
+
export function computeRailGeometry(turnCount, viewportRows, activeIndex, atBottom) {
|
|
59
|
+
if (turnCount < RAIL_MIN_TURNS)
|
|
60
|
+
return null;
|
|
61
|
+
const maxTicks = viewportRows - 2;
|
|
62
|
+
if (maxTicks < 1)
|
|
63
|
+
return null;
|
|
64
|
+
let start = 0;
|
|
65
|
+
if (turnCount > maxTicks) {
|
|
66
|
+
const tailStart = turnCount - maxTicks;
|
|
67
|
+
const anchor = activeIndex ?? turnCount - 1;
|
|
68
|
+
start = atBottom
|
|
69
|
+
? Math.min(anchor, tailStart)
|
|
70
|
+
: Math.min(Math.max(0, anchor - Math.floor(maxTicks / 2)), tailStart);
|
|
71
|
+
}
|
|
72
|
+
const shown = Math.min(turnCount, maxTicks);
|
|
73
|
+
// Vertically center the ▲ + ticks + ▼ stack, like the web rail.
|
|
74
|
+
const blockTop = Math.max(0, Math.floor((viewportRows - (shown + 2)) / 2));
|
|
75
|
+
return {
|
|
76
|
+
windowStart: start,
|
|
77
|
+
windowEnd: start + shown,
|
|
78
|
+
upRow: blockTop,
|
|
79
|
+
tickTop: blockTop + 1,
|
|
80
|
+
downRow: blockTop + 1 + shown,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Which rail interaction a block-local row lands on. The whole rail width
|
|
85
|
+
* is the hit target (no pixel-hunting the glyph).
|
|
86
|
+
*/
|
|
87
|
+
export function railHit(geo, row) {
|
|
88
|
+
if (row === geo.upRow)
|
|
89
|
+
return { kind: 'up' };
|
|
90
|
+
if (row === geo.downRow)
|
|
91
|
+
return { kind: 'down' };
|
|
92
|
+
if (row >= geo.tickTop) {
|
|
93
|
+
const rel = row - geo.tickTop;
|
|
94
|
+
if (rel < geo.windowEnd - geo.windowStart) {
|
|
95
|
+
return { kind: 'tick', index: geo.windowStart + rel };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* First non-empty line, char-capped with a `…` marker. Bounded work: the
|
|
102
|
+
* scan stops at the first non-empty line and slices at the cap, so a huge
|
|
103
|
+
* one-line prompt costs O(cap), not O(line length). Char cap (not display
|
|
104
|
+
* width) on purpose — this bounds the stored snapshot; the hover card
|
|
105
|
+
* re-wraps to its own width (wrapPreviewLines).
|
|
106
|
+
*/
|
|
107
|
+
export function clipPreview(text, maxChars = PREVIEW_MAX_CHARS) {
|
|
108
|
+
let line = '';
|
|
109
|
+
let rest = text;
|
|
110
|
+
while (rest.length > 0) {
|
|
111
|
+
const nl = rest.indexOf('\n');
|
|
112
|
+
const head = nl === -1 ? rest : rest.slice(0, nl);
|
|
113
|
+
rest = nl === -1 ? '' : rest.slice(nl + 1);
|
|
114
|
+
const trimmed = head.trim();
|
|
115
|
+
if (trimmed.length > 0) {
|
|
116
|
+
line = trimmed;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (line.length <= maxChars)
|
|
121
|
+
return line;
|
|
122
|
+
// Keep the cap INCLUDING the ellipsis marker, like grok's preview. Slice
|
|
123
|
+
// by CODE POINTS, not UTF-16 units — a surrogate pair split mid-pair
|
|
124
|
+
// would emit a lone surrogate to the terminal.
|
|
125
|
+
return `${[...line].slice(0, maxChars - 1).join('')}…`;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Wrap a preview to at most 2 lines by DISPLAY width (CJK-aware — a
|
|
129
|
+
* terminal cell column budget, not a char count). The last line is
|
|
130
|
+
* ellipsized when content remains. Char-by-char accumulation keeps
|
|
131
|
+
* surrogate pairs and (best-effort) combining sequences intact by never
|
|
132
|
+
* splitting below a low surrogate.
|
|
133
|
+
*/
|
|
134
|
+
export function wrapPreviewLines(preview, maxWidth) {
|
|
135
|
+
const widthOf = stringWidth;
|
|
136
|
+
const lines = [];
|
|
137
|
+
let current = '';
|
|
138
|
+
let currentW = 0;
|
|
139
|
+
for (const ch of preview) {
|
|
140
|
+
const w = widthOf(ch);
|
|
141
|
+
if (w <= 0) {
|
|
142
|
+
// Zero-width (combining marks, ZWJ): attach for free.
|
|
143
|
+
current += ch;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (currentW + w > maxWidth) {
|
|
147
|
+
if (lines.length === 1) {
|
|
148
|
+
// Second line full → ellipsize in place and stop.
|
|
149
|
+
return [lines[0], ellipsize(current, maxWidth)];
|
|
150
|
+
}
|
|
151
|
+
lines.push(current);
|
|
152
|
+
current = ch;
|
|
153
|
+
currentW = w;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
current += ch;
|
|
157
|
+
currentW += w;
|
|
158
|
+
}
|
|
159
|
+
if (current.length > 0 || lines.length === 0)
|
|
160
|
+
lines.push(current);
|
|
161
|
+
if (lines.length > 2) {
|
|
162
|
+
// Cannot happen (we stop after the second), kept for exhaustiveness.
|
|
163
|
+
return [lines[0], ellipsize(lines[1], maxWidth)];
|
|
164
|
+
}
|
|
165
|
+
return lines.slice(0, 2);
|
|
166
|
+
}
|
|
167
|
+
function ellipsize(line, maxWidth) {
|
|
168
|
+
// Make room for '…' (1 col) then hard-cut by display width.
|
|
169
|
+
let out = '';
|
|
170
|
+
let w = 0;
|
|
171
|
+
for (const ch of line) {
|
|
172
|
+
const cw = stringWidth(ch);
|
|
173
|
+
if (cw > 0 && w + cw > maxWidth - 1)
|
|
174
|
+
break;
|
|
175
|
+
out += ch;
|
|
176
|
+
w += cw;
|
|
177
|
+
}
|
|
178
|
+
return `${out}…`;
|
|
179
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-text.d.ts","sourceRoot":"","sources":["../../../src/ink/wrap-text.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"wrap-text.d.ts","sourceRoot":"","sources":["../../../src/ink/wrap-text.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAoFzC;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,GAC3B,MAAM,CAoCR"}
|