@deepseek-harness-tui/dsh-tui 0.8.7 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -10
- package/bin/dsh-tui.js +1 -1
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +4 -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/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/CommandSuggestions.d.ts +21 -4
- package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
- package/lib/types/components/CommandSuggestions.js +41 -14
- 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/FileSuggestions.d.ts +26 -5
- package/lib/types/components/FileSuggestions.d.ts.map +1 -1
- package/lib/types/components/FileSuggestions.js +53 -16
- 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/LogoV2.d.ts +5 -1
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +12 -3
- 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 +43 -2
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +553 -41
- package/lib/types/components/ModelPicker.d.ts +4 -1
- package/lib/types/components/ModelPicker.d.ts.map +1 -1
- package/lib/types/components/ModelPicker.js +2 -2
- 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 +273 -50
- 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 +68 -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 +6 -1
- 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 +63 -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 +190 -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/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 +8 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +4 -2
- 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.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +34 -2
- 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 +27 -6
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +432 -66
- package/lib/types/dsh-adapter/contract.d.ts +58 -18
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +124 -36
- package/lib/types/dsh-adapter/index.d.ts +10 -2
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +10 -13
- 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 +136 -6
- package/lib/types/i18n.d.ts +194 -16
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +73 -10
- 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 +268 -52
- 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 +16 -3
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
- package/lib/types/ink/render-node-to-output.js +144 -25
- package/lib/types/ink/selection.d.ts +29 -4
- package/lib/types/ink/selection.d.ts.map +1 -1
- package/lib/types/ink/selection.js +41 -5
- 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/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +819 -337
- package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
- package/lib/types/screens/SessionBrowser.js +56 -29
- 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 +2 -1
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +17 -1
- 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 +221 -0
- package/lib/types/screens/chatOverlay.d.ts.map +1 -0
- package/lib/types/screens/chatOverlay.js +114 -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/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/fileSuggestions.d.ts +19 -0
- package/lib/types/utils/fileSuggestions.d.ts.map +1 -0
- package/lib/types/utils/fileSuggestions.js +40 -0
- package/lib/types/utils/mentions.d.ts.map +1 -1
- package/lib/types/utils/mentions.js +3 -1
- package/lib/types/utils/paths.d.ts.map +1 -1
- package/lib/types/utils/paths.js +1 -0
- package/package.json +69 -66
package/lib/types/i18n.js
CHANGED
|
@@ -109,6 +109,8 @@ const dict = {
|
|
|
109
109
|
'model-switch-fork-failed': { zh: '无法切换模型 · {{err}}', en: 'Cannot switch models · {{err}}' },
|
|
110
110
|
'model-switch-failed': { zh: '模型切换失败 · {{err}}', en: 'Model switch failed · {{err}}' },
|
|
111
111
|
'model-switch-attach-failed': { zh: '模型已切换,但工作区挂载失败 · {{err}}', en: 'Model switched, but workspace attachment failed · {{err}}' },
|
|
112
|
+
'model-usage': { zh: '用法:/model <provider/model>(如 deepseek/deepseek-v4-flash)', en: 'Usage: /model <provider/model> (e.g. deepseek/deepseek-v4-flash)' },
|
|
113
|
+
'model-unknown': { zh: '未知模型「{{spec}}」· /model 查看全部', en: 'Unknown model "{{spec}}" · /model to view all' },
|
|
112
114
|
'compact-unavailable': { zh: '压缩不可用——当前 leaf 没有压缩服务', en: 'Compaction unavailable · no compaction service in this leaf' },
|
|
113
115
|
'compact-while-working': { zh: '回合运行中,无法压缩会话', en: 'Cannot compact while a turn is running' },
|
|
114
116
|
'compact-working': { zh: '正在压缩会话…', en: 'Compacting conversation…' },
|
|
@@ -183,6 +185,10 @@ const dict = {
|
|
|
183
185
|
'workspace-flow-input-empty': { zh: '目录路径不能为空', en: 'Directory path cannot be empty' },
|
|
184
186
|
'workspace-flow-loading': { zh: '正在连接并读取目录… · Esc 关闭', en: 'Connecting and loading directories… · Esc to close' },
|
|
185
187
|
'workspace-command-usage': { zh: '用法:/workspace resume | rename <名称> | open <路径或 URI>{{commands}}', en: 'Usage: /workspace resume | rename <name> | open <path-or-URI>{{commands}}' },
|
|
188
|
+
'workspace-menu-title': { zh: 'Workspace 操作', en: 'Workspace actions' },
|
|
189
|
+
'workspace-menu-resume-desc': { zh: '切换到另一个工作区', en: 'Switch to another workspace' },
|
|
190
|
+
'workspace-menu-rename-desc': { zh: '重命名当前工作区(需输入名称)', en: 'Rename the current workspace (needs a name)' },
|
|
191
|
+
'workspace-menu-open-desc': { zh: '打开路径或工作区 URI(需输入路径)', en: 'Open a path or workspace URI (needs a path)' },
|
|
186
192
|
'workspace-open-usage': { zh: '用法:/workspace open <路径或 URI>', en: 'Usage: /workspace open <path-or-URI>' },
|
|
187
193
|
'workspace-rename-usage': { zh: '用法:/workspace rename <名称>', en: 'Usage: /workspace rename <name>' },
|
|
188
194
|
'workspace-command-unknown': { zh: '未知的 workspace 子命令:{{command}}', en: 'Unknown workspace subcommand: {{command}}' },
|
|
@@ -216,11 +222,23 @@ const dict = {
|
|
|
216
222
|
'login-base-url': { zh: 'Base URL: {{url}}', en: 'Base URL: {{url}}' },
|
|
217
223
|
'login-official-endpoint': { zh: '官方端点', en: 'official endpoint' },
|
|
218
224
|
'login-logout-hint': { zh: '使用 /provider 管理 DSH 凭据;若来源为 env,请删除对应环境变量并重启 dsh-tui', en: 'Manage DSH credentials with /provider; for env sources, remove the corresponding environment variable and restart dsh-tui' },
|
|
219
|
-
'
|
|
220
|
-
'
|
|
221
|
-
'
|
|
222
|
-
'
|
|
223
|
-
'
|
|
225
|
+
'permission-policy-hint': { zh: 'DSH 权限策略由 fs-policy / bash-sandbox 配置决定(当前 leaf:workspace 内读写、写入需已读文件)。', en: 'DSH permission policy is set by fs-policy / bash-sandbox config (current leaf: read/write in workspace, writes need a prior read).' },
|
|
226
|
+
'permission-approval-hint': { zh: '审批通道已挂载:命令申请权限提升(sandbox_permissions)时弹出审批条,Yes 放行一次、No / Esc 拒绝。', en: 'The approval channel is mounted: sandbox escalations (sandbox_permissions) raise an approval bar — Yes allows once, No / Esc rejects.' },
|
|
227
|
+
'permission-root-hint': { zh: '当前文件系统策略以工作目录为根:{{cwd}}', en: 'Current filesystem policy is rooted at the working directory: {{cwd}}' },
|
|
228
|
+
'permission-path-hint': { zh: '模型工具相对路径均解析自该目录;跨目录访问由 fs-policy 拦截。', en: 'Relative paths of model tools resolve from this directory; cross-directory access is blocked by fs-policy.' },
|
|
229
|
+
'permission-current': { zh: '当前预设 {{name}}', en: 'Current preset {{name}}' },
|
|
230
|
+
'permission-picker-title': { zh: '权限预设', en: 'Permission preset' },
|
|
231
|
+
'permission-preset-readonly': { zh: '只读', en: 'Read-only' },
|
|
232
|
+
'permission-preset-readonly-desc': { zh: '会话只读:不写文件、不执行命令', en: 'Read-only session: no file writes, no commands' },
|
|
233
|
+
'permission-preset-workspace-write': { zh: '工作区读写', en: 'Workspace read/write' },
|
|
234
|
+
'permission-preset-workspace-write-desc': { zh: '工作区内读写;写入需先读该文件', en: 'Read/write inside the workspace; writes need a prior read' },
|
|
235
|
+
'permission-preset-full-access': { zh: '完全访问', en: 'Full access' },
|
|
236
|
+
'permission-preset-full-access-desc': { zh: '不受限读写,无需审批', en: 'Unrestricted access, no approvals' },
|
|
237
|
+
'plan-picker-title': { zh: '计划模式', en: 'Plan mode' },
|
|
238
|
+
'plan-mode-on': { zh: '开启', en: 'On' },
|
|
239
|
+
'plan-mode-on-desc': { zh: '进入计划模式:只读,先规划后动手', en: 'Enter plan mode: read-only, plan before acting' },
|
|
240
|
+
'plan-mode-off': { zh: '关闭', en: 'Off' },
|
|
241
|
+
'plan-mode-off-desc': { zh: '退出计划模式,恢复正常执行', en: 'Exit plan mode, back to normal execution' },
|
|
224
242
|
'hooks-not-mounted': { zh: 'DSH hooks(dsh-hooks-claude / dsh-hooks-codex)未在本 leaf 挂载。', en: 'DSH hooks (dsh-hooks-claude / dsh-hooks-codex) are not mounted in this leaf.' },
|
|
225
243
|
'hooks-mount-hint': { zh: '需要时可在 cordis.yml 挂载对应 hooks 插件。', en: 'Mount the matching hooks plugin in cordis.yml when needed.' },
|
|
226
244
|
'update-unavailable': { zh: '当前运行方式不支持自动更新(需经 dsh --profile 启动),请在终端执行 dsh plugin --profile <name> update @deepseek-harness-tui/dsh-tui', en: 'Automatic update is unavailable in this launch mode (needs dsh --profile). Run dsh plugin --profile <name> update @deepseek-harness-tui/dsh-tui in a terminal.' },
|
|
@@ -294,6 +312,24 @@ const dict = {
|
|
|
294
312
|
'logo-tagline': { zh: '探索未至之境!', en: 'Explore the uncharted!' },
|
|
295
313
|
'logo-tip-prefix': { zh: '提示:', en: 'Tip: ' },
|
|
296
314
|
'logo-tip-more': { zh: '更多技巧', en: 'more tips' },
|
|
315
|
+
// Upstream-drift notice (merged one-liner under the tip; copy explains
|
|
316
|
+
// the problem AND the fix — the command pins the validated line).
|
|
317
|
+
'logo-drift-newer': {
|
|
318
|
+
zh: 'dsh 引擎为 {{installed}},比本界面验证过的 {{validated}} 新,可能出现兼容问题;求稳可执行 npm i -g @deepseek-ai/dsh@{{primary}} 降级,或等待 dsh-tui 适配新版。',
|
|
319
|
+
en: 'The dsh engine ({{installed}}) is newer than the {{validated}} this UI is validated against, so issues are possible; downgrade via npm i -g @deepseek-ai/dsh@{{primary}} for stability, or wait for a dsh-tui update.',
|
|
320
|
+
},
|
|
321
|
+
'logo-drift-older': {
|
|
322
|
+
zh: 'dsh 引擎为 {{installed}},低于本界面验证过的 {{validated}},部分功能可能不可用;建议执行 npm i -g @deepseek-ai/dsh@{{primary}} 升级。',
|
|
323
|
+
en: 'The dsh engine ({{installed}}) is older than the {{validated}} this UI is validated against; some features may be missing. Upgrade via npm i -g @deepseek-ai/dsh@{{primary}}.',
|
|
324
|
+
},
|
|
325
|
+
'logo-drift-mixed': {
|
|
326
|
+
zh: '检测到 dsh 引擎多版本混装({{installed}}),容易出现奇怪问题;建议执行 npm i -g @deepseek-ai/dsh@{{primary}} 统一版本。',
|
|
327
|
+
en: 'Mixed dsh engine versions detected ({{installed}}), which can cause odd behavior; unify them via npm i -g @deepseek-ai/dsh@{{primary}}.',
|
|
328
|
+
},
|
|
329
|
+
'logo-drift-broken': {
|
|
330
|
+
zh: 'dsh 引擎版本异常({{installed}}),本界面验证过 {{validated}};建议执行 npm i -g @deepseek-ai/dsh@{{primary}} 重装。',
|
|
331
|
+
en: 'Unexpected dsh engine versions ({{installed}}); this UI is validated against {{validated}}. Reinstall via npm i -g @deepseek-ai/dsh@{{primary}}.',
|
|
332
|
+
},
|
|
297
333
|
// ── components/PromptInput.tsx ──────────────────────────────────────
|
|
298
334
|
'input-sent-after-turn': { zh: '已发送,当前回合结束后处理', en: 'Sent, processed after the current turn' },
|
|
299
335
|
'input-interrupted-next': { zh: '已插话 · 下一步立即处理', en: 'Interrupted · processed next' },
|
|
@@ -326,6 +362,24 @@ const dict = {
|
|
|
326
362
|
'frame-tail-1': { zh: '摆尾巴1', en: 'tail1' },
|
|
327
363
|
'frame-tail-2': { zh: '摆尾巴2', en: 'tail2' },
|
|
328
364
|
'frame-tail-3': { zh: '摆尾巴3', en: 'tail3' },
|
|
365
|
+
// ── components/SuggestionCard.tsx(/ 命令菜单 · @ 文件菜单)─────────
|
|
366
|
+
'sugg-commands-title': { zh: '命令', en: 'commands' },
|
|
367
|
+
'sugg-files-title': { zh: '文件', en: 'files' },
|
|
368
|
+
'sugg-count': { zh: '共 {{n}} 项', en: '{{n}} items' },
|
|
369
|
+
'sugg-more-above': { zh: '↑{{n}}', en: '↑{{n}}' },
|
|
370
|
+
'sugg-more-below': { zh: '↓{{n}}', en: '↓{{n}}' },
|
|
371
|
+
// 二级补全子项描述(/lang /theme /effort /preset /activity 的 children)
|
|
372
|
+
'sugg-status-desc': { zh: '显示当前选择', en: 'Show the current choice' },
|
|
373
|
+
'sugg-lang-zh-desc': { zh: '切换界面语言到中文', en: 'Switch the UI language to Chinese' },
|
|
374
|
+
'sugg-lang-en-desc': { zh: '切换界面语言到英文', en: 'Switch the UI language to English' },
|
|
375
|
+
'sugg-theme-auto-desc': { zh: '跟随终端背景自动切换', en: 'Follow the terminal background' },
|
|
376
|
+
'sugg-theme-builtin-desc': { zh: '内置主题', en: 'Built-in theme' },
|
|
377
|
+
'sugg-theme-user-desc': { zh: '用户主题({{base}} 基底)', en: 'User theme ({{base}} base)' },
|
|
378
|
+
'sugg-effort-level-desc': { zh: '思考强度档位', en: 'Reasoning effort level' },
|
|
379
|
+
'sugg-activity-frames-desc': { zh: '列出或切换动画帧预设', en: 'List or switch frame presets' },
|
|
380
|
+
'sugg-activity-frame-desc': { zh: '动画帧预设', en: 'Animation frame preset' },
|
|
381
|
+
// ── dsh-adapter/plugin.ts(/settings 全屏设置)───────────────────────
|
|
382
|
+
'settings-fullscreen-restart': { zh: '全屏设置已保存,重启 dsh-tui 后生效', en: 'Fullscreen preference saved — restart dsh-tui to apply' },
|
|
329
383
|
// ── components/HelpMenu.tsx ─────────────────────────────────────────
|
|
330
384
|
'help-for-commands': { zh: '/ 查看命令', en: '/ for commands' },
|
|
331
385
|
'help-this-help': { zh: '? 查看本帮助', en: '? for this help' },
|
|
@@ -342,6 +396,8 @@ const dict = {
|
|
|
342
396
|
'help-complete-command': { zh: 'tab 补全命令', en: 'tab to complete command' },
|
|
343
397
|
'help-cycle-mode': { zh: 'shift+tab 切换模式', en: 'shift+tab to cycle mode' },
|
|
344
398
|
'help-open-editor': { zh: 'ctrl+g 打开编辑器', en: 'ctrl+g to open editor' },
|
|
399
|
+
'help-fold-todos': { zh: '{{mod}}q 折叠待办', en: '{{mod}}q to fold todos' },
|
|
400
|
+
'goal-todo-fold-hint': { zh: '{{mod}}q 折叠', en: '{{mod}}q to fold' },
|
|
345
401
|
'help-commands-title': { zh: '命令:', en: 'commands:' },
|
|
346
402
|
'help-scroll-hint': {
|
|
347
403
|
zh: '↑/↓ 滚动 · PgUp/PgDn 翻页 · Home/End 首尾 · Esc 关闭',
|
|
@@ -442,6 +498,8 @@ const dict = {
|
|
|
442
498
|
'skills-loading-subtitle': { zh: '正在查询技能注册表…', en: 'Querying the skill registry…' },
|
|
443
499
|
'skills-empty': { zh: '当前会话没有可用技能', en: 'No skills available in this session' },
|
|
444
500
|
'skills-load-failed': { zh: '技能列表加载失败', en: 'Failed to load the skill list' },
|
|
501
|
+
'skills-unknown': { zh: '未知技能「{{name}}」', en: 'Unknown skill "{{name}}"' },
|
|
502
|
+
'skills-not-invocable': { zh: '技能「{{name}}」不可直接调用', en: 'Skill "{{name}}" is not directly invocable' },
|
|
445
503
|
'plugin-scene-crashed': { zh: '插件场景「{{id}}」渲染崩溃:{{err}}(已自动关闭)', en: 'Plugin scene "{{id}}" crashed while rendering: {{err}} (closed)' },
|
|
446
504
|
'skills-source-bundled': { zh: '内置', en: 'built-in' },
|
|
447
505
|
'skills-source-user': { zh: '用户', en: 'user' },
|
|
@@ -531,8 +589,9 @@ const dict = {
|
|
|
531
589
|
'rename-current': { zh: '当前名称 {{title}}', en: 'Current title {{title}}' },
|
|
532
590
|
'rename-done': { zh: '已重命名为「{{title}}」', en: 'Renamed to "{{title}}"' },
|
|
533
591
|
'compact-summary-folded': { zh: '摘要已折叠', en: 'Summary folded' },
|
|
534
|
-
'new-message': { zh: '{{n}} 条新消息', en: '1 new message' },
|
|
535
|
-
'new-messages': { zh: '{{n}} 条新消息', en: '{{n}} new messages' },
|
|
592
|
+
'new-message': { zh: '↓ {{n}} 条新消息', en: '↓ 1 new message' },
|
|
593
|
+
'new-messages': { zh: '↓ {{n}} 条新消息', en: '↓ {{n}} new messages' },
|
|
594
|
+
'back-to-bottom': { zh: '↓ 回到底部(Enter/End)', en: '↓ back to bottom (Enter/End)' },
|
|
536
595
|
// ── components/ThemePicker.tsx ──────────────────────────────────────
|
|
537
596
|
'theme-builtin-base': { zh: '内置 · {{name}} 基底', en: 'Built-in · {{name}} base' },
|
|
538
597
|
'theme-auto-base': { zh: '内置 · 跟随系统/终端背景自动选择 light/dark', en: 'Built-in · follows the system/terminal background (light/dark)' },
|
|
@@ -685,7 +744,6 @@ const dict = {
|
|
|
685
744
|
'cmd-desc-provider': { zh: '添加模型提供方(内置目录或自定义 API 端点)' },
|
|
686
745
|
'cmd-desc-login': { zh: '查看 API 凭证状态' },
|
|
687
746
|
'cmd-desc-logout': { zh: '清除 API 凭证' },
|
|
688
|
-
'cmd-desc-permissions': { zh: '查看权限策略状态' },
|
|
689
747
|
'cmd-desc-add-dir': { zh: '查看文件系统策略范围' },
|
|
690
748
|
'cmd-desc-hooks': { zh: '查看 hooks 状态' },
|
|
691
749
|
'cmd-desc-mcp': { zh: '查看 MCP 状态' },
|
|
@@ -723,6 +781,9 @@ const dict = {
|
|
|
723
781
|
'lang-switched': { zh: '语言已切换:{{lang}}(已保存)', en: 'Language switched: {{lang}} (saved)' },
|
|
724
782
|
'lang-unknown': { zh: '未知语言「{{lang}}」· /lang 查看全部(en / zh)', en: 'Unknown language "{{lang}}" · /lang to view all (en / zh)' },
|
|
725
783
|
'lang-switch-failed': { zh: '语言「{{lang}}」切换失败(无法写入 ~/.dsh-tui/lang.json)', en: 'Language "{{lang}}" switch failed (cannot write ~/.dsh-tui/lang.json)' },
|
|
784
|
+
'lang-picker-title': { zh: '界面语言', en: 'UI language' },
|
|
785
|
+
'lang-zh-desc': { zh: '简体中文(默认)', en: 'Simplified Chinese (default)' },
|
|
786
|
+
'lang-en-desc': { zh: 'English(英文)', en: 'English' },
|
|
726
787
|
// ── screens/StatusLine.tsx ───────────────────────────────────────────
|
|
727
788
|
'status-cache-label': { zh: '缓存 ', en: 'cache ' },
|
|
728
789
|
// ── screens/TrajectoryScene.tsx(issue #80 演进:全屏轨迹场景)──────────
|
|
@@ -824,10 +885,12 @@ export function t(key, params = {}) {
|
|
|
824
885
|
* lives in `LOCAL_COMMANDS` / the DSH registry, the dict carries zh only).
|
|
825
886
|
* @param key - Dictionary key, computed at runtime so it is not type-checked.
|
|
826
887
|
* @param fallback - Text used when no translation exists.
|
|
888
|
+
* @param params - Placeholder values substituted into whichever text wins.
|
|
827
889
|
*/
|
|
828
|
-
export function tOr(key, fallback) {
|
|
890
|
+
export function tOr(key, fallback, params = {}) {
|
|
829
891
|
const entry = dict[key];
|
|
830
|
-
|
|
892
|
+
const template = entry?.[activeLang] ?? fallback;
|
|
893
|
+
return template.replace(/\{\{(\w+)\}\}/g, (match, name) => name in params ? String(params[name]) : match);
|
|
831
894
|
}
|
|
832
895
|
// ── persistence (~/.dsh-tui/lang.json) ─────────────────────────────────
|
|
833
896
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlternateScreen.d.ts","sourceRoot":"","sources":["../../../../src/ink/components/AlternateScreen.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AlternateScreen.d.ts","sourceRoot":"","sources":["../../../../src/ink/components/AlternateScreen.tsx"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,EAAE,KAAA,OAyDjC"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { c as _c } from "react/compiler-runtime";
|
|
3
3
|
import { useContext, useInsertionEffect } from 'react';
|
|
4
4
|
import instances from '../instances.js';
|
|
5
|
+
import { logMouseDebug } from '../../utils/debug.js';
|
|
5
6
|
import { DISABLE_MOUSE_TRACKING, ENABLE_MOUSE_TRACKING, ENTER_ALT_SCREEN, EXIT_ALT_SCREEN } from '../termio/dec.js';
|
|
6
7
|
import { TerminalWriteContext } from '../useTerminalNotification.js';
|
|
7
8
|
import Box from './Box.js';
|
|
@@ -36,13 +37,24 @@ export function AlternateScreen(t0) {
|
|
|
36
37
|
let t3;
|
|
37
38
|
if ($[0] !== mouseTracking || $[1] !== writeRaw) {
|
|
38
39
|
t2 = () => {
|
|
39
|
-
|
|
40
|
+
// Same fallback as Chat's reanchor plumbing: embedders and test
|
|
41
|
+
// harnesses render with a stdout that is not process.stdout, so the
|
|
42
|
+
// strict key lookup would miss the only live instance and the
|
|
43
|
+
// alt-screen flag would never flip — silently killing click/hover
|
|
44
|
+
// dispatch (both are gated on altScreenActive). The "any instance"
|
|
45
|
+
// fallback is deliberately narrowed to the SINGLE-instance case:
|
|
46
|
+
// with several live Ink instances (multi-app embedding, tests
|
|
47
|
+
// running in parallel) guessing the first one would flip the wrong
|
|
48
|
+
// app's alt-screen state.
|
|
49
|
+
const ink = instances.get(process.stdout) ?? (instances.size === 1 ? instances.values().next().value : undefined);
|
|
50
|
+
logMouseDebug('alt-screen enter', { mouseTracking, inkFound: ink !== undefined, writeRaw: !!writeRaw, stack: new Error().stack?.split('\n').slice(2, 5).join(' | ') });
|
|
40
51
|
if (!writeRaw) {
|
|
41
52
|
return;
|
|
42
53
|
}
|
|
43
54
|
writeRaw(ENTER_ALT_SCREEN + "\x1B[2J\x1B[H" + (mouseTracking ? ENABLE_MOUSE_TRACKING : ""));
|
|
44
55
|
ink?.setAltScreenActive(true, mouseTracking);
|
|
45
56
|
return () => {
|
|
57
|
+
logMouseDebug('alt-screen exit', { stack: new Error().stack?.split('\n').slice(2, 5).join(' | ') });
|
|
46
58
|
ink?.setAltScreenActive(false);
|
|
47
59
|
ink?.clearTextSelection();
|
|
48
60
|
writeRaw((mouseTracking ? DISABLE_MOUSE_TRACKING : "") + EXIT_ALT_SCREEN);
|
|
@@ -15,13 +15,15 @@ type Props = {
|
|
|
15
15
|
readonly terminalRows: number;
|
|
16
16
|
readonly selection: SelectionState;
|
|
17
17
|
readonly onSelectionChange: () => void;
|
|
18
|
-
readonly onClickAt: (col: number, row: number) => boolean;
|
|
18
|
+
readonly onClickAt: (col: number, row: number, button?: number) => boolean;
|
|
19
19
|
readonly onHoverAt: (col: number, row: number) => void;
|
|
20
|
+
readonly onWheelAt: (col: number, row: number, deltaY: number, deltaX: number, button?: number) => boolean;
|
|
20
21
|
readonly getHyperlinkAt: (col: number, row: number) => string | undefined;
|
|
21
22
|
readonly onOpenHyperlink: (url: string) => void;
|
|
22
23
|
readonly onMultiClick: (col: number, row: number, count: 2 | 3) => void;
|
|
23
24
|
readonly onSelectionDrag: (col: number, row: number) => void;
|
|
24
25
|
readonly onStdinResume?: () => void;
|
|
26
|
+
readonly onTerminalFocus?: (focused: boolean) => void;
|
|
25
27
|
readonly onCursorDeclaration?: CursorDeclarationSetter;
|
|
26
28
|
readonly dispatchKeyboardEvent: (parsedKey: ParsedKey) => void;
|
|
27
29
|
};
|
|
@@ -51,6 +53,15 @@ export default class App extends PureComponent<Props, State> {
|
|
|
51
53
|
pendingHyperlinkTimer: ReturnType<typeof setTimeout> | null;
|
|
52
54
|
lastHoverCol: number;
|
|
53
55
|
lastHoverRow: number;
|
|
56
|
+
/**
|
|
57
|
+
* Reset all transient pointer state. Called by Ink when the alt screen
|
|
58
|
+
* is entered/exited and on resize: rects, hover targets, and the click
|
|
59
|
+
* chain from the previous screen geometry/scene must not leak into the
|
|
60
|
+
* new one (stale hover sets would suppress the next real onMouseEnter;
|
|
61
|
+
* a stale clickCount could turn the first click on a fresh screen into
|
|
62
|
+
* a double-click).
|
|
63
|
+
*/
|
|
64
|
+
resetPointerState(): void;
|
|
54
65
|
lastStdinTime: number;
|
|
55
66
|
writeRaw: (data: string) => void;
|
|
56
67
|
isRawModeSupported(): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../../src/ink/components/App.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../../src/ink/components/App.tsx"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,8 @@ import { logForDebugging } from "../../utils/debug.js";
|
|
|
5
5
|
import { stopCapturingEarlyInput } from "../../utils/earlyInput.js";
|
|
6
6
|
import { isEnvTruthy } from "../../utils/envUtils.js";
|
|
7
7
|
import { isMouseClicksDisabled } from "../../utils/fullscreen.js";
|
|
8
|
+
import { isInputSuppressed } from "../input-suppression.js";
|
|
9
|
+
import { logMouseDebug } from "../../utils/debug.js";
|
|
8
10
|
import { logError } from "../../utils/log.js";
|
|
9
11
|
import { EventEmitter } from "../events/emitter.js";
|
|
10
12
|
import { InputEvent } from "../events/input-event.js";
|
|
@@ -83,6 +85,34 @@ export default class App extends PureComponent {
|
|
|
83
85
|
// repeat events (drag-then-release at same cell, etc.).
|
|
84
86
|
lastHoverCol = -1;
|
|
85
87
|
lastHoverRow = -1;
|
|
88
|
+
/**
|
|
89
|
+
* Reset all transient pointer state. Called by Ink when the alt screen
|
|
90
|
+
* is entered/exited and on resize: rects, hover targets, and the click
|
|
91
|
+
* chain from the previous screen geometry/scene must not leak into the
|
|
92
|
+
* new one (stale hover sets would suppress the next real onMouseEnter;
|
|
93
|
+
* a stale clickCount could turn the first click on a fresh screen into
|
|
94
|
+
* a double-click).
|
|
95
|
+
*/
|
|
96
|
+
resetPointerState() {
|
|
97
|
+
this.clickCount = 0;
|
|
98
|
+
this.lastClickTime = 0;
|
|
99
|
+
this.lastClickCol = -1;
|
|
100
|
+
this.lastClickRow = -1;
|
|
101
|
+
this.lastHoverCol = -1;
|
|
102
|
+
this.lastHoverRow = -1;
|
|
103
|
+
if (this.pendingHyperlinkTimer) {
|
|
104
|
+
clearTimeout(this.pendingHyperlinkTimer);
|
|
105
|
+
this.pendingHyperlinkTimer = null;
|
|
106
|
+
}
|
|
107
|
+
// A drag interrupted by a screen swap has no release coming — settle
|
|
108
|
+
// the selection so copy-on-select fires rather than orphaning
|
|
109
|
+
// isDragging with its drag-to-scroll timer running.
|
|
110
|
+
const sel = this.props.selection;
|
|
111
|
+
if (sel.isDragging) {
|
|
112
|
+
finishSelection(sel);
|
|
113
|
+
this.props.onSelectionChange();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
86
116
|
// Timestamp of last stdin chunk. Used to detect long gaps (tmux attach,
|
|
87
117
|
// ssh reconnect, laptop wake) and trigger terminal mode re-assert.
|
|
88
118
|
// Initialized to now so startup doesn't false-trigger.
|
|
@@ -94,6 +124,9 @@ export default class App extends PureComponent {
|
|
|
94
124
|
// <AlternateScreen>'s insertion effect every frame, flapping the alt
|
|
95
125
|
// screen on/off.
|
|
96
126
|
writeRaw = (data) => {
|
|
127
|
+
if (data.includes("\x1b[?1049")) {
|
|
128
|
+
logMouseDebug("stdout:1049", { len: data.length, head: data.slice(0, 60) });
|
|
129
|
+
}
|
|
97
130
|
this.props.stdout.write(data);
|
|
98
131
|
};
|
|
99
132
|
// Determines if TTY is supported on the provided stdin
|
|
@@ -400,6 +433,32 @@ export default class App extends PureComponent {
|
|
|
400
433
|
// Helper to process all keys within a single discrete update context.
|
|
401
434
|
// discreteUpdates expects (fn, a, b, c, d) -> fn(a, b, c, d)
|
|
402
435
|
function processKeysInBatch(app, items, _unused1, _unused2) {
|
|
436
|
+
// Mouse-chain diagnostics: the single choke point every parsed mouse and
|
|
437
|
+
// wheel event passes through. Empty log here = the terminal never sent
|
|
438
|
+
// the sequences (tracking modes, ConPTY) rather than an in-app loss.
|
|
439
|
+
if (process.env.DSH_TUI_DEBUG_MOUSE) {
|
|
440
|
+
for (const item of items) {
|
|
441
|
+
if (item.kind === "mouse") {
|
|
442
|
+
logMouseDebug("mouse arrive", {
|
|
443
|
+
button: item.button,
|
|
444
|
+
action: item.action,
|
|
445
|
+
col: item.col,
|
|
446
|
+
row: item.row,
|
|
447
|
+
clicksDisabled: isMouseClicksDisabled(),
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
else if (item.kind === "key" &&
|
|
451
|
+
(item.name === "wheelup" || item.name === "wheeldown")) {
|
|
452
|
+
logMouseDebug("wheel arrive", { name: item.name });
|
|
453
|
+
}
|
|
454
|
+
else if (item.kind === "key") {
|
|
455
|
+
logMouseDebug("key arrive", {
|
|
456
|
+
name: item.name,
|
|
457
|
+
seq: (item.sequence ?? "").slice(0, 10),
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
403
462
|
// Update interaction time for notification timeout tracking.
|
|
404
463
|
// This is called from the central input handler to avoid having multiple
|
|
405
464
|
// stdin listeners that can cause race conditions and dropped input.
|
|
@@ -429,6 +488,10 @@ function processKeysInBatch(app, items, _unused1, _unused2) {
|
|
|
429
488
|
// Handle terminal focus events (DECSET 1004)
|
|
430
489
|
if (sequence === FOCUS_IN) {
|
|
431
490
|
app.handleTerminalFocus(true);
|
|
491
|
+
// Refocus is the first observable moment after a terminal-side
|
|
492
|
+
// mode reset (conpty drops 1049/mouse on DPI moves, renderer
|
|
493
|
+
// restarts, window snapping): probe and self-heal.
|
|
494
|
+
app.props.onTerminalFocus?.(true);
|
|
432
495
|
const event = new TerminalFocusEvent("terminalfocus");
|
|
433
496
|
app.internal_eventEmitter.emit("terminalfocus", event);
|
|
434
497
|
continue;
|
|
@@ -458,6 +521,37 @@ function processKeysInBatch(app, items, _unused1, _unused2) {
|
|
|
458
521
|
app.handleSuspend();
|
|
459
522
|
continue;
|
|
460
523
|
}
|
|
524
|
+
// Wheel keys carry the pointer position (SGR/X10 col/row). Route
|
|
525
|
+
// position-first: if a scroll container sits under the pointer, its
|
|
526
|
+
// onWheel consumes the event and the legacy global keybinding path
|
|
527
|
+
// never fires — exactly one layer scrolls. Events without coords
|
|
528
|
+
// (shouldn't happen for wheel) or over non-scroll areas fall
|
|
529
|
+
// through to the normal input path (Chat scrolls the transcript).
|
|
530
|
+
// Skipped during the post-handoff suppression window: a terminal
|
|
531
|
+
// replay burst can contain mouse-wheel fragments, and use-input's
|
|
532
|
+
// choke point never sees events consumed here.
|
|
533
|
+
if ((item.name === "wheelup" ||
|
|
534
|
+
item.name === "wheeldown" ||
|
|
535
|
+
item.name === "wheelleft" ||
|
|
536
|
+
item.name === "wheelright") &&
|
|
537
|
+
item.mouseCol !== undefined &&
|
|
538
|
+
item.mouseRow !== undefined &&
|
|
539
|
+
!isInputSuppressed()) {
|
|
540
|
+
const step = (item.name === "wheelup" || item.name === "wheelleft") ? -3 : 3;
|
|
541
|
+
const deltaY = item.name === "wheelup" || item.name === "wheeldown" ? step : 0;
|
|
542
|
+
const deltaX = item.name === "wheelleft" || item.name === "wheelright" ? step : 0;
|
|
543
|
+
const consumed = app.props.onWheelAt(item.mouseCol, item.mouseRow, deltaY, deltaX);
|
|
544
|
+
if (consumed) {
|
|
545
|
+
logMouseDebug("wheel routed by position", {
|
|
546
|
+
col: item.mouseCol,
|
|
547
|
+
row: item.mouseRow,
|
|
548
|
+
deltaY,
|
|
549
|
+
deltaX,
|
|
550
|
+
name: item.name,
|
|
551
|
+
});
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
461
555
|
app.handleInput(sequence);
|
|
462
556
|
const event = new InputEvent(item);
|
|
463
557
|
app.internal_eventEmitter.emit("input", event);
|
|
@@ -472,9 +566,12 @@ export function handleMouseEvent(app, m) {
|
|
|
472
566
|
if (isMouseClicksDisabled())
|
|
473
567
|
return;
|
|
474
568
|
const sel = app.props.selection;
|
|
475
|
-
// Terminal coords are 1-indexed; screen buffer is 0-indexed
|
|
476
|
-
|
|
477
|
-
|
|
569
|
+
// Terminal coords are 1-indexed; screen buffer is 0-indexed. Clamp to
|
|
570
|
+
// the current frame's dimensions: a resize (or a terminal reporting a
|
|
571
|
+
// stale position) can deliver coordinates outside the screen buffer,
|
|
572
|
+
// and selection/hyperlink reads assume in-bounds cells.
|
|
573
|
+
const col = Math.max(0, Math.min(m.col - 1, app.props.terminalColumns - 1));
|
|
574
|
+
const row = Math.max(0, Math.min(m.row - 1, app.props.terminalRows - 1));
|
|
478
575
|
const baseButton = m.button & 0x03;
|
|
479
576
|
if (m.action === "press") {
|
|
480
577
|
if ((m.button & 0x20) !== 0 && baseButton === 3) {
|
|
@@ -582,7 +679,7 @@ export function handleMouseEvent(app, m) {
|
|
|
582
679
|
// Single click: dispatch DOM click immediately (cursor repositioning
|
|
583
680
|
// etc. are latency-sensitive). If no DOM handler consumed it, defer
|
|
584
681
|
// the hyperlink check so a second click can cancel it.
|
|
585
|
-
if (!app.props.onClickAt(col, row)) {
|
|
682
|
+
if (!app.props.onClickAt(col, row, m.button)) {
|
|
586
683
|
// Resolve the hyperlink URL synchronously while the screen buffer
|
|
587
684
|
// still reflects what the user clicked — deferring only the
|
|
588
685
|
// browser-open so double-click can cancel it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClockContext.d.ts","sourceRoot":"","sources":["../../../../src/ink/components/ClockContext.tsx"],"names":[],"mappings":"AACA,OAAO,KAA6C,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ClockContext.d.ts","sourceRoot":"","sources":["../../../../src/ink/components/ClockContext.tsx"],"names":[],"mappings":"AACA,OAAO,KAA6C,MAAM,OAAO,CAAC;AAIlE,MAAM,MAAM,KAAK,GAAG;IAClB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,SAAS,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;IACpE,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,CAAC;AACF,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,KAAK,CA2DzD;AACD,eAAO,MAAM,YAAY,6BAAoC,CAAC;AAM9D,wBAAgB,aAAa,CAAC,EAAE,KAAA,OAiC/B"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { c as _c } from "react/compiler-runtime";
|
|
3
3
|
import { createContext, useEffect, useState } from 'react';
|
|
4
4
|
import { FRAME_INTERVAL_MS } from '../constants.js';
|
|
5
|
+
import { noteFrameCause } from '../geometry-trace.js';
|
|
5
6
|
import { useTerminalFocus } from '../hooks/use-terminal-focus.js';
|
|
6
7
|
export function createClock(tickIntervalMs) {
|
|
7
8
|
const subscribers = new Map();
|
|
@@ -13,6 +14,7 @@ export function createClock(tickIntervalMs) {
|
|
|
13
14
|
let tickTime = 0;
|
|
14
15
|
function tick() {
|
|
15
16
|
tickTime = Date.now() - startTime;
|
|
17
|
+
noteFrameCause('animation');
|
|
16
18
|
for (const onChange of subscribers.keys()) {
|
|
17
19
|
onChange();
|
|
18
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScrollBox.d.ts","sourceRoot":"","sources":["../../../../src/ink/components/ScrollBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAE,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"ScrollBox.d.ts","sourceRoot":"","sources":["../../../../src/ink/components/ScrollBox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAE,KAAK,GAAG,EAAsD,MAAM,OAAO,CAAC;AACpH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAK5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B;;;;;;OAMG;IACH,eAAe,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,oBAAoB,EAAE,MAAM,MAAM,CAAC;IACnC,iBAAiB,EAAE,MAAM,MAAM,CAAC;IAChC;;;OAGG;IACH,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB;;;;;OAKG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IAChD;;;;;;;OAOG;IACH,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CAC5E,CAAC;AACF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC,GAAG;IACjG,GAAG,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC;IAC3B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF;;;;;;;;;GASG;AACH,iBAAS,SAAS,CAAC,EACjB,QAAQ,EACR,GAAG,EACH,YAAY,EACZ,GAAG,KAAK,EACT,EAAE,iBAAiB,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,SAAS,CAqOrD;AACD,eAAe,SAAS,CAAC"}
|