@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.
Files changed (467) hide show
  1. package/README.md +60 -238
  2. package/bin/dsh-tui.js +172 -5
  3. package/cordis.patch.yml +16 -4
  4. package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -13
  5. package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -59
  6. package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -15
  7. package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -32
  8. package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -59
  9. package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -166
  10. package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -42
  11. package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -143
  12. package/dsh-ecosystem-spec/registry/README.md +14 -14
  13. package/dsh-ecosystem-spec/registry/host-descriptor.tui.example.json +56 -56
  14. package/dsh-ecosystem-spec/registry/permissions-0.1.json +13 -13
  15. package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -149
  16. package/lib/types/cc/hyperlink.d.ts +7 -1
  17. package/lib/types/cc/hyperlink.d.ts.map +1 -1
  18. package/lib/types/cc/hyperlink.js +3 -2
  19. package/lib/types/cc/markdown.d.ts.map +1 -1
  20. package/lib/types/cc/markdown.js +33 -3
  21. package/lib/types/cc/sessionColors.d.ts +27 -0
  22. package/lib/types/cc/sessionColors.d.ts.map +1 -0
  23. package/lib/types/cc/sessionColors.js +39 -0
  24. package/lib/types/commands.d.ts.map +1 -1
  25. package/lib/types/commands.js +10 -2
  26. package/lib/types/components/ActivityPicker.d.ts +4 -1
  27. package/lib/types/components/ActivityPicker.d.ts.map +1 -1
  28. package/lib/types/components/ActivityPicker.js +2 -2
  29. package/lib/types/components/AutoRecapRow.d.ts +23 -0
  30. package/lib/types/components/AutoRecapRow.d.ts.map +1 -0
  31. package/lib/types/components/AutoRecapRow.js +23 -0
  32. package/lib/types/components/BtwPanel.d.ts.map +1 -1
  33. package/lib/types/components/BtwPanel.js +1 -1
  34. package/lib/types/components/Chat/SubagentMessage.d.ts +2 -1
  35. package/lib/types/components/Chat/SubagentMessage.d.ts.map +1 -1
  36. package/lib/types/components/Chat/SubagentMessage.js +11 -3
  37. package/lib/types/components/ColorPicker.d.ts +17 -0
  38. package/lib/types/components/ColorPicker.d.ts.map +1 -0
  39. package/lib/types/components/ColorPicker.js +20 -0
  40. package/lib/types/components/CommandSuggestions.d.ts +23 -4
  41. package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
  42. package/lib/types/components/CommandSuggestions.js +41 -14
  43. package/lib/types/components/ContextBarView.d.ts +33 -0
  44. package/lib/types/components/ContextBarView.d.ts.map +1 -0
  45. package/lib/types/components/ContextBarView.js +46 -0
  46. package/lib/types/components/EffortInputBorder.d.ts +12 -1
  47. package/lib/types/components/EffortInputBorder.d.ts.map +1 -1
  48. package/lib/types/components/EffortInputBorder.js +22 -5
  49. package/lib/types/components/EffortSlider.d.ts +4 -1
  50. package/lib/types/components/EffortSlider.d.ts.map +1 -1
  51. package/lib/types/components/EffortSlider.js +4 -2
  52. package/lib/types/components/ExtensionDialog.js +6 -2
  53. package/lib/types/components/FileActionsPanel.d.ts +22 -0
  54. package/lib/types/components/FileActionsPanel.d.ts.map +1 -0
  55. package/lib/types/components/FileActionsPanel.js +28 -0
  56. package/lib/types/components/FileSuggestions.d.ts +26 -7
  57. package/lib/types/components/FileSuggestions.d.ts.map +1 -1
  58. package/lib/types/components/FileSuggestions.js +39 -12
  59. package/lib/types/components/GoalTodoPanel.d.ts +26 -2
  60. package/lib/types/components/GoalTodoPanel.d.ts.map +1 -1
  61. package/lib/types/components/GoalTodoPanel.js +86 -17
  62. package/lib/types/components/HelpMenu.d.ts +7 -1
  63. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  64. package/lib/types/components/HelpMenu.js +12 -4
  65. package/lib/types/components/HistorySearchDialog.d.ts +4 -1
  66. package/lib/types/components/HistorySearchDialog.d.ts.map +1 -1
  67. package/lib/types/components/HistorySearchDialog.js +2 -2
  68. package/lib/types/components/LangPicker.d.ts +14 -0
  69. package/lib/types/components/LangPicker.d.ts.map +1 -0
  70. package/lib/types/components/LangPicker.js +17 -0
  71. package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
  72. package/lib/types/components/LoadedContextPanel.js +3 -1
  73. package/lib/types/components/Markdown.d.ts.map +1 -1
  74. package/lib/types/components/Markdown.js +12 -3
  75. package/lib/types/components/MessageList.d.ts +45 -2
  76. package/lib/types/components/MessageList.d.ts.map +1 -1
  77. package/lib/types/components/MessageList.js +560 -41
  78. package/lib/types/components/ModelPicker.d.ts +27 -2
  79. package/lib/types/components/ModelPicker.d.ts.map +1 -1
  80. package/lib/types/components/ModelPicker.js +26 -6
  81. package/lib/types/components/PermissionsPicker.d.ts +21 -0
  82. package/lib/types/components/PermissionsPicker.d.ts.map +1 -0
  83. package/lib/types/components/PermissionsPicker.js +27 -0
  84. package/lib/types/components/PlanPicker.d.ts +15 -0
  85. package/lib/types/components/PlanPicker.d.ts.map +1 -0
  86. package/lib/types/components/PlanPicker.js +18 -0
  87. package/lib/types/components/PresetPicker.d.ts +4 -1
  88. package/lib/types/components/PresetPicker.d.ts.map +1 -1
  89. package/lib/types/components/PresetPicker.js +2 -2
  90. package/lib/types/components/PromptInput.d.ts +4 -3
  91. package/lib/types/components/PromptInput.d.ts.map +1 -1
  92. package/lib/types/components/PromptInput.js +602 -75
  93. package/lib/types/components/RecapPanel.d.ts +25 -0
  94. package/lib/types/components/RecapPanel.d.ts.map +1 -0
  95. package/lib/types/components/RecapPanel.js +55 -0
  96. package/lib/types/components/RewindPicker.d.ts +12 -1
  97. package/lib/types/components/RewindPicker.d.ts.map +1 -1
  98. package/lib/types/components/RewindPicker.js +6 -4
  99. package/lib/types/components/ScrollbarGutter.d.ts +28 -0
  100. package/lib/types/components/ScrollbarGutter.d.ts.map +1 -0
  101. package/lib/types/components/ScrollbarGutter.js +119 -0
  102. package/lib/types/components/Select.d.ts +8 -1
  103. package/lib/types/components/Select.d.ts.map +1 -1
  104. package/lib/types/components/Select.js +4 -2
  105. package/lib/types/components/SkillsPicker.d.ts +4 -1
  106. package/lib/types/components/SkillsPicker.d.ts.map +1 -1
  107. package/lib/types/components/SkillsPicker.js +2 -2
  108. package/lib/types/components/SubagentCard.d.ts +2 -1
  109. package/lib/types/components/SubagentCard.d.ts.map +1 -1
  110. package/lib/types/components/SubagentCard.js +9 -2
  111. package/lib/types/components/SubagentDashboard.d.ts +4 -0
  112. package/lib/types/components/SubagentDashboard.d.ts.map +1 -1
  113. package/lib/types/components/SubagentDashboard.js +9 -1
  114. package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
  115. package/lib/types/components/SubagentDetailScene.js +5 -4
  116. package/lib/types/components/SuggestionCard.d.ts +65 -0
  117. package/lib/types/components/SuggestionCard.d.ts.map +1 -0
  118. package/lib/types/components/SuggestionCard.js +77 -0
  119. package/lib/types/components/ThemePicker.d.ts +4 -1
  120. package/lib/types/components/ThemePicker.d.ts.map +1 -1
  121. package/lib/types/components/ThemePicker.js +2 -2
  122. package/lib/types/components/ThinkingToggle.d.ts +4 -1
  123. package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
  124. package/lib/types/components/ThinkingToggle.js +2 -2
  125. package/lib/types/components/TimelineRail.d.ts +53 -0
  126. package/lib/types/components/TimelineRail.d.ts.map +1 -0
  127. package/lib/types/components/TimelineRail.js +197 -0
  128. package/lib/types/components/WorkspaceFlowPicker.d.ts +6 -1
  129. package/lib/types/components/WorkspaceFlowPicker.d.ts.map +1 -1
  130. package/lib/types/components/WorkspaceFlowPicker.js +4 -2
  131. package/lib/types/components/WorkspaceMenuPicker.d.ts +19 -0
  132. package/lib/types/components/WorkspaceMenuPicker.d.ts.map +1 -0
  133. package/lib/types/components/WorkspaceMenuPicker.js +19 -0
  134. package/lib/types/components/WorkspacePicker.d.ts +4 -1
  135. package/lib/types/components/WorkspacePicker.d.ts.map +1 -1
  136. package/lib/types/components/WorkspacePicker.js +2 -2
  137. package/lib/types/components/approvals/ApprovalPanel.d.ts.map +1 -1
  138. package/lib/types/components/approvals/ApprovalPanel.js +5 -1
  139. package/lib/types/components/design-system/ListItem.d.ts +8 -1
  140. package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
  141. package/lib/types/components/design-system/ListItem.js +8 -3
  142. package/lib/types/components/design-system/ThemeProvider.d.ts +7 -0
  143. package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
  144. package/lib/types/components/design-system/ThemeProvider.js +2 -1
  145. package/lib/types/components/messages/AssistantTextMessage.d.ts +5 -2
  146. package/lib/types/components/messages/AssistantTextMessage.d.ts.map +1 -1
  147. package/lib/types/components/messages/AssistantTextMessage.js +6 -2
  148. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -1
  149. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  150. package/lib/types/components/messages/AssistantThinkingMessage.js +10 -4
  151. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +15 -1
  152. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  153. package/lib/types/components/messages/AssistantToolUseMessage.js +37 -7
  154. package/lib/types/components/messages/UserPromptMessage.d.ts +2 -1
  155. package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
  156. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +7 -3
  157. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  158. package/lib/types/components/questions/AskUserQuestionPanel.js +75 -11
  159. package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
  160. package/lib/types/components/questions/PlanReviewPanel.js +13 -2
  161. package/lib/types/components/sessions/SessionListRow.d.ts +4 -1
  162. package/lib/types/components/sessions/SessionListRow.d.ts.map +1 -1
  163. package/lib/types/components/sessions/SessionListRow.js +4 -2
  164. package/lib/types/components/trajectory/HotspotView.d.ts +7 -1
  165. package/lib/types/components/trajectory/HotspotView.d.ts.map +1 -1
  166. package/lib/types/components/trajectory/HotspotView.js +8 -2
  167. package/lib/types/components/trajectory/Ledger.d.ts +9 -1
  168. package/lib/types/components/trajectory/Ledger.d.ts.map +1 -1
  169. package/lib/types/components/trajectory/Ledger.js +23 -5
  170. package/lib/types/components/trajectory/WaveBand.d.ts +10 -1
  171. package/lib/types/components/trajectory/WaveBand.d.ts.map +1 -1
  172. package/lib/types/components/trajectory/WaveBand.js +7 -2
  173. package/lib/types/dsh-adapter/channel.d.ts +117 -7
  174. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  175. package/lib/types/dsh-adapter/channel.js +1301 -122
  176. package/lib/types/dsh-adapter/compat/index.d.ts +8 -6
  177. package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
  178. package/lib/types/dsh-adapter/compat/index.js +8 -6
  179. package/lib/types/dsh-adapter/compat/sessionLog.d.ts +150 -0
  180. package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
  181. package/lib/types/dsh-adapter/compat/sessionLog.js +518 -41
  182. package/lib/types/dsh-adapter/contract.d.ts +1 -1
  183. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  184. package/lib/types/dsh-adapter/contract.js +1 -0
  185. package/lib/types/dsh-adapter/extension-events.d.ts +1 -1
  186. package/lib/types/dsh-adapter/extension-events.d.ts.map +1 -1
  187. package/lib/types/dsh-adapter/index.d.ts +20 -2
  188. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  189. package/lib/types/dsh-adapter/index.js +9 -1
  190. package/lib/types/dsh-adapter/plugin.d.ts +0 -9
  191. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  192. package/lib/types/dsh-adapter/plugin.js +453 -14
  193. package/lib/types/dsh-adapter/presets.d.ts +18 -0
  194. package/lib/types/dsh-adapter/presets.d.ts.map +1 -1
  195. package/lib/types/dsh-adapter/presets.js +31 -0
  196. package/lib/types/dsh-adapter/providerWizard.d.ts +29 -1
  197. package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
  198. package/lib/types/dsh-adapter/providerWizard.js +89 -5
  199. package/lib/types/dsh-adapter/questions.d.ts +19 -2
  200. package/lib/types/dsh-adapter/questions.d.ts.map +1 -1
  201. package/lib/types/dsh-adapter/questions.js +53 -10
  202. package/lib/types/dsh-adapter/recap.d.ts +49 -0
  203. package/lib/types/dsh-adapter/recap.d.ts.map +1 -0
  204. package/lib/types/dsh-adapter/recap.js +121 -0
  205. package/lib/types/dsh-adapter/sessionTree.d.ts +314 -0
  206. package/lib/types/dsh-adapter/sessionTree.d.ts.map +1 -0
  207. package/lib/types/dsh-adapter/sessionTree.js +954 -0
  208. package/lib/types/dsh-adapter/shortcuts.d.ts +15 -44
  209. package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -1
  210. package/lib/types/dsh-adapter/shortcuts.js +28 -165
  211. package/lib/types/dsh-adapter/types.d.ts +1 -1
  212. package/lib/types/dsh-adapter/types.d.ts.map +1 -1
  213. package/lib/types/herdr.js +1 -1
  214. package/lib/types/i18n.d.ts +770 -181
  215. package/lib/types/i18n.d.ts.map +1 -1
  216. package/lib/types/i18n.js +257 -80
  217. package/lib/types/ink/components/AlternateScreen.d.ts.map +1 -1
  218. package/lib/types/ink/components/AlternateScreen.js +13 -1
  219. package/lib/types/ink/components/App.d.ts +12 -1
  220. package/lib/types/ink/components/App.d.ts.map +1 -1
  221. package/lib/types/ink/components/App.js +101 -4
  222. package/lib/types/ink/components/ClockContext.d.ts.map +1 -1
  223. package/lib/types/ink/components/ClockContext.js +2 -0
  224. package/lib/types/ink/components/ScrollBox.d.ts.map +1 -1
  225. package/lib/types/ink/components/ScrollBox.js +170 -91
  226. package/lib/types/ink/constants.d.ts +9 -0
  227. package/lib/types/ink/constants.d.ts.map +1 -1
  228. package/lib/types/ink/constants.js +9 -0
  229. package/lib/types/ink/events/click-event.d.ts +7 -16
  230. package/lib/types/ink/events/click-event.d.ts.map +1 -1
  231. package/lib/types/ink/events/click-event.js +16 -19
  232. package/lib/types/ink/events/event-handlers.d.ts +11 -1
  233. package/lib/types/ink/events/event-handlers.d.ts.map +1 -1
  234. package/lib/types/ink/events/event-handlers.js +2 -0
  235. package/lib/types/ink/events/input-event.d.ts +9 -0
  236. package/lib/types/ink/events/input-event.d.ts.map +1 -1
  237. package/lib/types/ink/events/input-event.js +4 -0
  238. package/lib/types/ink/events/pointer-event.d.ts +61 -0
  239. package/lib/types/ink/events/pointer-event.d.ts.map +1 -0
  240. package/lib/types/ink/events/pointer-event.js +61 -0
  241. package/lib/types/ink/events/wheel-event.d.ts +17 -0
  242. package/lib/types/ink/events/wheel-event.d.ts.map +1 -0
  243. package/lib/types/ink/events/wheel-event.js +20 -0
  244. package/lib/types/ink/geometry-trace.d.ts +51 -0
  245. package/lib/types/ink/geometry-trace.d.ts.map +1 -0
  246. package/lib/types/ink/geometry-trace.js +83 -0
  247. package/lib/types/ink/hit-test.d.ts +56 -1
  248. package/lib/types/ink/hit-test.d.ts.map +1 -1
  249. package/lib/types/ink/hit-test.js +146 -8
  250. package/lib/types/ink/ink.d.ts +58 -1
  251. package/lib/types/ink/ink.d.ts.map +1 -1
  252. package/lib/types/ink/ink.js +230 -29
  253. package/lib/types/ink/log-update.d.ts.map +1 -1
  254. package/lib/types/ink/log-update.js +21 -0
  255. package/lib/types/ink/node-cache.d.ts +5 -0
  256. package/lib/types/ink/node-cache.d.ts.map +1 -1
  257. package/lib/types/ink/parse-keypress.d.ts +8 -0
  258. package/lib/types/ink/parse-keypress.d.ts.map +1 -1
  259. package/lib/types/ink/parse-keypress.js +101 -12
  260. package/lib/types/ink/render-node-to-output.d.ts +10 -0
  261. package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
  262. package/lib/types/ink/render-node-to-output.js +111 -18
  263. package/lib/types/ink/timeline-rail.d.ts +138 -0
  264. package/lib/types/ink/timeline-rail.d.ts.map +1 -0
  265. package/lib/types/ink/timeline-rail.js +179 -0
  266. package/lib/types/ink/wrap-text.d.ts.map +1 -1
  267. package/lib/types/ink/wrap-text.js +47 -5
  268. package/lib/types/migrationPrefs.d.ts +60 -0
  269. package/lib/types/migrationPrefs.d.ts.map +1 -0
  270. package/lib/types/migrationPrefs.js +97 -0
  271. package/lib/types/modelGroups.d.ts +72 -0
  272. package/lib/types/modelGroups.d.ts.map +1 -0
  273. package/lib/types/modelGroups.js +97 -0
  274. package/lib/types/modelRecents.d.ts +39 -0
  275. package/lib/types/modelRecents.d.ts.map +1 -0
  276. package/lib/types/modelRecents.js +97 -0
  277. package/lib/types/native-ts/yoga-layout/index.d.ts +11 -0
  278. package/lib/types/native-ts/yoga-layout/index.d.ts.map +1 -1
  279. package/lib/types/native-ts/yoga-layout/index.js +31 -1
  280. package/lib/types/oauth.d.ts +15 -0
  281. package/lib/types/oauth.d.ts.map +1 -0
  282. package/lib/types/oauth.js +14 -0
  283. package/lib/types/reload.d.ts +109 -0
  284. package/lib/types/reload.d.ts.map +1 -0
  285. package/lib/types/reload.js +118 -0
  286. package/lib/types/screens/Chat.d.ts +3 -1
  287. package/lib/types/screens/Chat.d.ts.map +1 -1
  288. package/lib/types/screens/Chat.js +1377 -371
  289. package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
  290. package/lib/types/screens/SessionBrowser.js +56 -29
  291. package/lib/types/screens/SessionTree.d.ts +27 -0
  292. package/lib/types/screens/SessionTree.d.ts.map +1 -0
  293. package/lib/types/screens/SessionTree.js +555 -0
  294. package/lib/types/screens/Settings.d.ts.map +1 -1
  295. package/lib/types/screens/Settings.js +64 -22
  296. package/lib/types/screens/StatusLine.d.ts +0 -8
  297. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  298. package/lib/types/screens/StatusLine.js +224 -45
  299. package/lib/types/screens/StatusMetrics.d.ts +35 -3
  300. package/lib/types/screens/StatusMetrics.d.ts.map +1 -1
  301. package/lib/types/screens/StatusMetrics.js +63 -8
  302. package/lib/types/screens/TrajectoryScene.d.ts.map +1 -1
  303. package/lib/types/screens/TrajectoryScene.js +81 -14
  304. package/lib/types/screens/chatOverlay.d.ts +237 -0
  305. package/lib/types/screens/chatOverlay.d.ts.map +1 -0
  306. package/lib/types/screens/chatOverlay.js +116 -0
  307. package/lib/types/tips.d.ts.map +1 -1
  308. package/lib/types/tips.js +64 -10
  309. package/lib/types/tuiDisplayPrefs.d.ts +15 -0
  310. package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
  311. package/lib/types/tuiDisplayPrefs.js +9 -0
  312. package/lib/types/update.d.ts +139 -0
  313. package/lib/types/update.d.ts.map +1 -1
  314. package/lib/types/update.js +382 -30
  315. package/lib/types/utils/debug.d.ts +10 -0
  316. package/lib/types/utils/debug.d.ts.map +1 -1
  317. package/lib/types/utils/debug.js +24 -0
  318. package/lib/types/utils/fileTarget.d.ts +46 -0
  319. package/lib/types/utils/fileTarget.d.ts.map +1 -0
  320. package/lib/types/utils/fileTarget.js +178 -0
  321. package/lib/types/utils/keymap.d.ts +134 -0
  322. package/lib/types/utils/keymap.d.ts.map +1 -0
  323. package/lib/types/utils/keymap.js +311 -0
  324. package/lib/types/utils/mentions.d.ts +25 -2
  325. package/lib/types/utils/mentions.d.ts.map +1 -1
  326. package/lib/types/utils/mentions.js +69 -10
  327. package/lib/types/utils/openExternal.d.ts +50 -0
  328. package/lib/types/utils/openExternal.d.ts.map +1 -0
  329. package/lib/types/utils/openExternal.js +170 -0
  330. package/lib/types/utils/paths.d.ts.map +1 -1
  331. package/lib/types/utils/paths.js +1 -0
  332. package/node_modules/@deepseek-harness-tui/dsh-auth/LICENSE +21 -0
  333. package/node_modules/@deepseek-harness-tui/dsh-auth/README.md +140 -0
  334. package/node_modules/@deepseek-harness-tui/dsh-auth/cordis.patch.yml +11 -0
  335. package/node_modules/@deepseek-harness-tui/dsh-auth/dsh-plugin.json +44 -0
  336. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/command.d.ts +14 -0
  337. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/command.js +67 -0
  338. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/credentials.d.ts +64 -0
  339. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/credentials.js +170 -0
  340. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/index.d.ts +79 -0
  341. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/index.js +196 -0
  342. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.d.ts +68 -0
  343. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.js +193 -0
  344. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/opener.d.ts +32 -0
  345. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/opener.js +101 -0
  346. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/profiles.d.ts +31 -0
  347. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/profiles.js +68 -0
  348. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/service.d.ts +69 -0
  349. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/service.js +129 -0
  350. package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +70 -0
  351. package/node_modules/@dsh-std/command/CHANGELOG.md +8 -8
  352. package/node_modules/@dsh-std/command/LICENSE +21 -21
  353. package/node_modules/@dsh-std/command/README.md +26 -26
  354. package/node_modules/@dsh-std/command/README.zh.md +28 -28
  355. package/node_modules/@dsh-std/command/lib/index.js.map +1 -1
  356. package/node_modules/@dsh-std/command/package.json +22 -22
  357. package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  358. package/node_modules/@dsh-std/connection/LICENSE +21 -21
  359. package/node_modules/@dsh-std/connection/README.md +42 -42
  360. package/node_modules/@dsh-std/connection/README.zh.md +42 -42
  361. package/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  362. package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  363. package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  364. package/node_modules/@dsh-std/connection/package.json +20 -20
  365. package/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  366. package/node_modules/@dsh-std/core/LICENSE +21 -21
  367. package/node_modules/@dsh-std/core/README.md +13 -13
  368. package/node_modules/@dsh-std/core/README.zh.md +13 -13
  369. package/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  370. package/node_modules/@dsh-std/core/package.json +21 -21
  371. package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
  372. package/node_modules/@dsh-std/manifest/LICENSE +21 -21
  373. package/node_modules/@dsh-std/manifest/README.md +5 -5
  374. package/node_modules/@dsh-std/manifest/README.zh.md +5 -5
  375. package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
  376. package/node_modules/@dsh-std/manifest/package.json +20 -20
  377. package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
  378. package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -8
  379. package/node_modules/@dsh-std/messages/LICENSE +21 -21
  380. package/node_modules/@dsh-std/messages/README.md +5 -5
  381. package/node_modules/@dsh-std/messages/README.zh.md +7 -7
  382. package/node_modules/@dsh-std/messages/lib/index.js.map +1 -1
  383. package/node_modules/@dsh-std/messages/package.json +20 -20
  384. package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -54
  385. package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
  386. package/node_modules/@dsh-std/presentation/LICENSE +21 -21
  387. package/node_modules/@dsh-std/presentation/README.md +27 -27
  388. package/node_modules/@dsh-std/presentation/README.zh.md +29 -29
  389. package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
  390. package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  391. package/node_modules/@dsh-std/presentation/package.json +25 -25
  392. package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -8
  393. package/node_modules/@dsh-std/storage/LICENSE +21 -21
  394. package/node_modules/@dsh-std/storage/README.md +5 -5
  395. package/node_modules/@dsh-std/storage/README.zh.md +7 -7
  396. package/node_modules/@dsh-std/storage/lib/index.js.map +1 -1
  397. package/node_modules/@dsh-std/storage/package.json +20 -20
  398. package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -56
  399. package/package.json +19 -5
  400. package/presets/liangshen/.dsh-tui-managed.json +1 -1
  401. package/presets/liangshen/instruction-hint.mjs +8 -0
  402. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  403. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -21
  404. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -42
  405. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -42
  406. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  407. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  408. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  409. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -20
  410. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  411. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -21
  412. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -13
  413. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -13
  414. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  415. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -21
  416. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
  417. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -21
  418. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -5
  419. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -5
  420. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
  421. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -20
  422. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
  423. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
  424. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -21
  425. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -27
  426. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -29
  427. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
  428. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  429. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -25
  430. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  431. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -21
  432. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -13
  433. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -13
  434. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  435. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -21
  436. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  437. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -21
  438. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -13
  439. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -13
  440. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  441. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -21
  442. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  443. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -21
  444. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -13
  445. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -13
  446. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  447. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -21
  448. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  449. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -21
  450. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -42
  451. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -42
  452. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  453. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  454. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  455. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -20
  456. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  457. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -21
  458. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -13
  459. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -13
  460. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  461. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -21
  462. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  463. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -21
  464. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -13
  465. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -13
  466. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  467. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -21
@@ -8,8 +8,10 @@
8
8
  * yellow ≥ 20, red below.
9
9
  */
10
10
  /** Context bar segments — DeepSeek blue family (dark-theme friendly: deep
11
- * navy → brand blue, neutral grey free segment; labels adapt to width). */
12
- const USED_SEGMENTS = [
11
+ * navy → brand blue, neutral grey free segment; labels adapt to width).
12
+ * Exported for the hoverable JSX bar (ContextBarView), which re-derives
13
+ * the same column split this module's ANSI path renders. */
14
+ export const USED_SEGMENTS = [
13
15
  { key: 'system', color: '#22305F', labels: ['system', 'sys', 's'] }, // deep navy
14
16
  { key: 'prompt', color: '#2B3D78', labels: ['prompt', 'pr', 'p'] }, // navy
15
17
  { key: 'assistant', color: '#344A92', labels: ['assistant', 'ast', 'a'] }, // indigo
@@ -49,7 +51,9 @@ export function formatTokens(count) {
49
51
  return `${Math.round(value / 1000000)}M`;
50
52
  }
51
53
  // --- Context bar (pi-nano-context) ---
52
- function centeredText(text, width) {
54
+ /** Center `text` in `width` cells (plain spaces, no ANSI). Exported for
55
+ * ContextBarView's JSX used-segment labels. */
56
+ export function centeredText(text, width) {
53
57
  const textWidth = plainWidth(text);
54
58
  if (textWidth > width)
55
59
  return ' '.repeat(width);
@@ -57,7 +61,9 @@ function centeredText(text, width) {
57
61
  const right = width - textWidth - left;
58
62
  return `${' '.repeat(left)}${text}${' '.repeat(right)}`;
59
63
  }
60
- function chooseLabel(labels, width) {
64
+ /** Pick the longest label that fits `width` cells. Exported for
65
+ * ContextBarView's JSX segments (same fallback ladder as the ANSI path). */
66
+ export function chooseLabel(labels, width) {
61
67
  for (const label of labels) {
62
68
  if (plainWidth(label) <= width)
63
69
  return label;
@@ -81,7 +87,13 @@ function chooseRightAlignedText(options, width, blockedUntil) {
81
87
  }
82
88
  return '';
83
89
  }
84
- function renderFreeSegment(options, width, fill, text) {
90
+ /**
91
+ * Compose the free segment's plain text: the `free` label centered, the
92
+ * usage readout right-aligned into whatever width remains. Shared by the
93
+ * ANSI string path (renderContextBar) and the hoverable JSX bar
94
+ * (ContextBarView) so both render pixel-identical content.
95
+ */
96
+ export function composeFreeSegmentText(options, width) {
85
97
  if (width <= 0)
86
98
  return '';
87
99
  const content = Array.from({ length: width }, () => ' ');
@@ -100,7 +112,12 @@ function renderFreeSegment(options, width, fill, text) {
100
112
  content[labelStart + offset] = char;
101
113
  }
102
114
  }
103
- return background(fill, foreground(text, content.join('')));
115
+ return content.join('');
116
+ }
117
+ function renderFreeSegment(options, width, fill, text) {
118
+ if (width <= 0)
119
+ return '';
120
+ return background(fill, foreground(text, composeFreeSegmentText(options, width)));
104
121
  }
105
122
  /** Largest-remainder column allocation (pi-nano-context). */
106
123
  function allocateProportionally(values, columns) {
@@ -123,8 +140,9 @@ function allocateProportionally(values, columns) {
123
140
  }
124
141
  return allocatedColumns;
125
142
  }
126
- /** Give every visible used segment at least one column before sharing the rest. */
127
- function allocateBarColumns(values, width) {
143
+ /** Give every visible used segment at least one column before sharing the
144
+ * rest. Exported for ContextBarView (hoverable JSX twin of the bar). */
145
+ export function allocateBarColumns(values, width) {
128
146
  const visibleUsedSegments = USED_SEGMENTS
129
147
  .map((_, index) => index)
130
148
  .filter(index => (values[index] ?? 0) > 0);
@@ -161,6 +179,43 @@ export function renderContextBar(segments, usedTokens, contextWindow, width, col
161
179
  const free = formatTokens(contextWindow - usedTokens);
162
180
  return `${used}${renderFreeSegment([`ctx ${total} ${percent} ${free}`, `${total} ${percent} ${free}`, `${total} ${percent}`, percent], freeWidth, colors?.freeFill ?? FREE_SEGMENT_FILL, colors?.freeText ?? FREE_SEGMENT_TEXT)}`;
163
181
  }
182
+ // --- Mini context bar (footer ctx-field hover) ---
183
+ /** Context-pressure thresholds, shared with contextPressurePct's amber/red
184
+ * footer convention (amber ≥ 80%, red ≥ 95%). */
185
+ const PRESSURE_WARN = 80;
186
+ const PRESSURE_DANGER = 95;
187
+ /** Pressure-colored text: green below 80%, amber ≥ 80, red ≥ 95.
188
+ * @param pct - Context occupancy percent (0–100+).
189
+ * @param text - Text to color.
190
+ * @returns The ANSI 24-bit color-wrapped text.
191
+ */
192
+ export function pressureColor(pct, text) {
193
+ const key = pct >= PRESSURE_DANGER ? 'error' : pct >= PRESSURE_WARN ? 'warning' : 'success';
194
+ return `\x1b[38;2;${colorHex(key)}m${text}\x1b[39m`;
195
+ }
196
+ /** Compact 1/8-cell context gauge for the footer's ctx field on hover:
197
+ * `▕██████▋···▏`, fill proportional to context occupancy, colored by the
198
+ * amber/red pressure thresholds. Same block ramp as the TPS gauge.
199
+ * @param usedTokens - Total context tokens in use.
200
+ * @param contextWindow - Context window size in tokens.
201
+ * @param width - Gauge width in terminal columns (fill cells, brackets excluded).
202
+ * @returns The ANSI gauge string, or '' for a non-positive window.
203
+ */
204
+ export function renderMiniContextBar(usedTokens, contextWindow, width = 10) {
205
+ if (contextWindow <= 0 || width <= 0)
206
+ return '';
207
+ const pct = Math.min(100, Math.max(0, (usedTokens / contextWindow) * 100));
208
+ const frac = pct / 100;
209
+ const eighths = Math.round(frac * width * 8);
210
+ const full = Math.floor(eighths / 8);
211
+ const rem = eighths % 8;
212
+ let fill = '█'.repeat(Math.min(full, width));
213
+ if (full < width && rem > 0) {
214
+ fill += HBLOCKS[rem];
215
+ }
216
+ const track = TRACK.repeat(Math.max(0, width - fill.length));
217
+ return `▕${pressureColor(pct, fill)}${`\x1b[2m${track}\x1b[22m`}▏`;
218
+ }
164
219
  // --- TPS gauge + sparkline (pi-tps-meter) ---
165
220
  const BLOCKS = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];
166
221
  const HBLOCKS = [' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉'];
@@ -1 +1 @@
1
- {"version":3,"file":"TrajectoryScene.d.ts","sourceRoot":"","sources":["../../../src/screens/TrajectoryScene.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAczB,OAAO,EAML,KAAK,SAAS,EACf,MAAM,oCAAoC,CAAA;AAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AA+BxD,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,SAAS,CAAA;AAEnD,wBAAgB,eAAe,CAAC,EAC9B,OAAO,EACP,KAAK,EACL,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB;;;;OAIG;IACH,KAAK,EAAE,SAAS,CAAA;IAChB,sDAAsD;IACtD,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CAyYlB"}
1
+ {"version":3,"file":"TrajectoryScene.d.ts","sourceRoot":"","sources":["../../../src/screens/TrajectoryScene.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAezB,OAAO,EAML,KAAK,SAAS,EACf,MAAM,oCAAoC,CAAA;AAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AA+BxD,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,SAAS,CAAA;AAEnD,wBAAgB,eAAe,CAAC,EAC9B,OAAO,EACP,KAAK,EACL,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB;;;;OAIG;IACH,KAAK,EAAE,SAAS,CAAA;IAChB,sDAAsD;IACtD,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CA2hBlB"}
@@ -64,6 +64,11 @@ export function TrajectoryScene({ channel, build, onClose, }) {
64
64
  const [arrivalFrom, setArrivalFrom] = React.useState(Number.MAX_SAFE_INTEGER);
65
65
  /** Cursor pinned to the tail until the user scrolls away from it. */
66
66
  const [follow, setFollow] = React.useState(true);
67
+ /** Mouse hover states for the tab segments and the sort/projection label. */
68
+ const [hoverTab, setHoverTab] = React.useState(null);
69
+ const [hoverAxis, setHoverAxis] = React.useState(false);
70
+ /** Hover state for the header ✕ exit button. */
71
+ const [closeHovered, setCloseHovered] = React.useState(false);
67
72
  // ── projection ───────────────────────────────────────────────────────────
68
73
  const nodes = build.nodes;
69
74
  const query = React.useMemo(() => parseQuery(queryText), [queryText]);
@@ -147,6 +152,40 @@ export function TrajectoryScene({ channel, build, onClose, }) {
147
152
  setExpanded(false);
148
153
  setInspectScroll(0);
149
154
  }, [tick]);
155
+ /**
156
+ * Jump back to the timeline, positioned on a hotspot group's first member —
157
+ * the keyboard Enter path, shared with the mouse row click.
158
+ */
159
+ const jumpFromHotspot = React.useCallback((row) => {
160
+ switchView('timeline');
161
+ if (row !== undefined) {
162
+ const target = indexes.indexOf(row.firstIndex);
163
+ setCursor(target >= 0 ? target : 0);
164
+ setFollow(false);
165
+ }
166
+ }, [indexes, switchView]);
167
+ /** Mouse wheel over the content area: move the selection, not a viewport. */
168
+ const handleWheel = React.useCallback((event) => {
169
+ if (view === 'hotspot') {
170
+ const total = hotspotRows(agg).length;
171
+ const direction = event.deltaY >= 0 ? 1 : -1;
172
+ setHotCursor(previous => Math.max(0, Math.min(total - 1, previous + direction)));
173
+ return;
174
+ }
175
+ if (expanded) {
176
+ // Expanded inspector owns the wheel: same page step as j/k.
177
+ const direction = event.deltaY >= 0 ? 1 : -1;
178
+ setInspectScroll(previous => Math.max(0, previous + direction * Math.max(1, inspectorRows - 2)));
179
+ return;
180
+ }
181
+ move(event.deltaY);
182
+ }, [view, agg, expanded, inspectorRows, move]);
183
+ /** Jump the timeline cursor to a filtered index (keyboard jump semantics). */
184
+ const jumpTo = React.useCallback((index) => {
185
+ setInspectScroll(0);
186
+ setCursor(index);
187
+ setFollow(index >= filtered.length - 1);
188
+ }, [filtered.length]);
150
189
  // ── keys ─────────────────────────────────────────────────────────────────
151
190
  useInput((input, key) => {
152
191
  // The query line owns the keyboard while open, so a `q` typed into a
@@ -208,14 +247,7 @@ export function TrajectoryScene({ channel, build, onClose, }) {
208
247
  }
209
248
  if (key.return) {
210
249
  // Jump back to the timeline, positioned on the group's first member.
211
- const row = hotspotRows(agg)[hotCursor];
212
- switchView('timeline');
213
- if (row !== undefined) {
214
- const target = indexes.indexOf(row.firstIndex);
215
- setCursor(target >= 0 ? target : 0);
216
- setFollow(false);
217
- }
218
- return;
250
+ return jumpFromHotspot(hotspotRows(agg)[hotCursor]);
219
251
  }
220
252
  return;
221
253
  }
@@ -286,16 +318,42 @@ export function TrajectoryScene({ channel, build, onClose, }) {
286
318
  (totals.errors > 0 ? ` \u00b7 ${t('traj-errors', { n: totals.errors })}` : '') +
287
319
  (totals.retries > 0 ? ` \u00b7 ${t('traj-retries', { n: totals.retries })}` : '') +
288
320
  ` \u00b7 ${formatDuration(totals.spanMs)}`;
289
- const headerLine = spread(`\u2726 ${t('traj-title')} ${channel.sessionTitle ?? channel.cwd}`, totalsText, bandWidth);
290
- const header = (_jsx(Box, { width: "100%", height: 1, flexShrink: 0, children: _jsxs(Text, { children: [_jsx(Text, { color: "claude", bold: true, children: `\u2726 ${t('traj-title')}` }), _jsx(Text, { color: "subtle", children: headerLine.left.slice((`\u2726 ${t('traj-title')}`).length) }), _jsx(Text, { children: headerLine.gap }), _jsx(Text, { color: totals.errors > 0 ? 'error' : 'subtle', children: headerLine.right })] }) }));
321
+ // ✕ 退出按钮占 2 格(` ✕`):预量测行给右端留出预算,按钮钉在末列
322
+ const CLOSE_WIDTH = 2;
323
+ const headerLine = spread(`\u2726 ${t('traj-title')} ${channel.sessionTitle ?? channel.cwd}`, totalsText, bandWidth - CLOSE_WIDTH);
324
+ const header = (_jsxs(Box, { width: "100%", height: 1, flexShrink: 0, children: [_jsx(Box, { flexShrink: 0, width: bandWidth - CLOSE_WIDTH, children: _jsxs(Text, { children: [_jsx(Text, { color: "claude", bold: true, children: `\u2726 ${t('traj-title')}` }), _jsx(Text, { color: "subtle", children: headerLine.left.slice((`\u2726 ${t('traj-title')}`).length) }), _jsx(Text, { children: headerLine.gap }), _jsx(Text, { color: totals.errors > 0 ? 'error' : 'subtle', children: headerLine.right })] }) }), _jsx(Box, { flexShrink: 0, width: CLOSE_WIDTH,
325
+ // 可点击退出(q/Esc 的鼠标等价)——hover 提亮给出可点指示
326
+ onClick: () => onClose(), onMouseEnter: () => setCloseHovered(true), onMouseLeave: () => setCloseHovered(false), children: _jsx(Text, { color: closeHovered ? 'text' : 'subtle', children: ' ✕' }) })] }));
291
327
  const axisLabel = view === 'hotspot' ? t(`traj-sort-${sort}`) : t(`traj-proj-${projection}`);
292
- const tabsLeft = `${view === 'timeline' ? '\u25cf' : '\u25cb'} ${t('traj-tab-timeline')} ` +
293
- `${view === 'hotspot' ? '\u25cf' : '\u25cb'} ${t('traj-tab-hotspot')}`;
328
+ const tabTimelineText = `${view === 'timeline' ? '\u25cf' : '\u25cb'} ${t('traj-tab-timeline')} `;
329
+ const tabHotspotText = `${view === 'hotspot' ? '\u25cf' : '\u25cb'} ${t('traj-tab-hotspot')}`;
294
330
  const queryText_ = queryOpen || !query.empty
295
331
  ? ` / ${queryText}${queryOpen ? '\u258c' : ''} ${t('traj-matches', { n: filtered.length, total: nodes.length })}`
296
332
  : '';
333
+ const tabsLeft = tabTimelineText + tabHotspotText;
297
334
  const tabsLine = spread(tabsLeft + queryText_, axisLabel, bandWidth);
298
- const tabs = (_jsx(Box, { width: "100%", height: 1, flexShrink: 0, children: _jsxs(Text, { children: [_jsx(Text, { color: view === 'timeline' ? 'permission' : 'subtle', bold: view === 'timeline', children: tabsLine.left.slice(0, tabsLeft.length) }), _jsx(Text, { color: "suggestion", children: tabsLine.left.slice(tabsLeft.length) }), _jsx(Text, { children: tabsLine.gap }), _jsx(Text, { color: "subtle", children: tabsLine.right })] }) }));
335
+ // Segment truncation mirrors spread's left-clip: the query tail yields
336
+ // first, then the far tab label — the line stays exactly one row.
337
+ const leftRoom = stringWidth(tabsLine.left);
338
+ const hotspotShown = truncateWidth(tabHotspotText, Math.max(0, leftRoom - stringWidth(tabTimelineText)));
339
+ const queryShown = queryText_ === ''
340
+ ? ''
341
+ : truncateWidth(queryText_, Math.max(0, leftRoom - stringWidth(tabTimelineText) - stringWidth(hotspotShown)));
342
+ const tabs = (_jsxs(Box, { width: "100%", height: 1, flexShrink: 0, children: [_jsx(Box, { flexShrink: 0, width: stringWidth(tabTimelineText), onClick: () => switchView('timeline'), onMouseEnter: () => setHoverTab('timeline'), onMouseLeave: () => setHoverTab(previous => (previous === 'timeline' ? null : previous)), children: _jsx(Text, { color: view === 'timeline' ? 'permission' : hoverTab === 'timeline' ? 'text' : 'subtle', bold: view === 'timeline', children: tabTimelineText }) }), _jsx(Box, { flexShrink: 0, width: stringWidth(hotspotShown), onClick: () => switchView('hotspot'), onMouseEnter: () => setHoverTab('hotspot'), onMouseLeave: () => setHoverTab(previous => (previous === 'hotspot' ? null : previous)), children: _jsx(Text, { color: view === 'hotspot' ? 'permission' : hoverTab === 'hotspot' ? 'text' : 'subtle', bold: view === 'hotspot', children: hotspotShown }) }), queryShown !== '' && (_jsx(Box, { flexShrink: 0, width: stringWidth(queryShown), onClick: () => setQueryOpen(true), children: _jsx(Text, { color: "suggestion", children: queryShown }) })), _jsx(Box, { flexGrow: 1, flexShrink: 1, onClick: () => { if (!queryOpen)
343
+ setQueryOpen(true); }, children: _jsx(Text, { children: tabsLine.gap }) }), _jsx(Box, { flexShrink: 0,
344
+ // +1 slack: ink breaks a wrap line exactly AT the box width, so a
345
+ // wide-char-ending label (按耗时) at an exact fit loses its last
346
+ // glyph to a clipped second line (the truncateWidth doc's trap).
347
+ // The flexGrow gap absorbs the extra cell.
348
+ width: stringWidth(tabsLine.right) + 1, onClick: () => {
349
+ if (view === 'hotspot') {
350
+ setSort(previous => HOTSPOT_SORTS[(HOTSPOT_SORTS.indexOf(previous) + 1) % HOTSPOT_SORTS.length]);
351
+ }
352
+ else {
353
+ setProjection(previous => WAVE_PROJECTIONS[(WAVE_PROJECTIONS.indexOf(previous) + 1) % WAVE_PROJECTIONS.length]);
354
+ }
355
+ setSwitchTick(tick);
356
+ }, onMouseEnter: () => setHoverAxis(true), onMouseLeave: () => setHoverAxis(false), children: _jsx(Text, { color: hoverAxis ? 'text' : 'subtle', children: tabsLine.right }) })] }));
299
357
  const hints = view === 'hotspot'
300
358
  ? t('traj-hint-hotspot')
301
359
  : queryOpen
@@ -303,5 +361,14 @@ export function TrajectoryScene({ channel, build, onClose, }) {
303
361
  : expanded
304
362
  ? t('traj-hint-expanded')
305
363
  : t('traj-hint-timeline');
306
- return (_jsxs(Box, { ref: ref, flexDirection: "column", width: "100%", paddingX: 1, children: [header, tabs, _jsx(WaveBand, { band: band, width: bandWidth, cursorColumn: columnOfIndex(band, indexes[clampedCursor] ?? 0), viewportStart: columnOfIndex(band, indexes[windowStart] ?? 0), viewportEnd: columnOfIndex(band, indexes[Math.min(filtered.length - 1, windowStart + ledgerRows - 1)] ?? 0), matches: matchColumns, tick: tick, alertTick: alertTick }), _jsx(Box, { height: 1, flexShrink: 0, children: _jsx(Text, { children: " " }) }), view === 'timeline' ? (_jsxs(_Fragment, { children: [_jsx(Ledger, { rows: filtered, start: windowStart, height: ledgerRows, cursor: clampedCursor, width: columns - 4, tick: tick, arrivalTick: arrivalTick, arrivalFrom: arrivalFrom }), _jsx(Divider, { color: "permission", width: bandWidth }), _jsx(Inspector, { node: focused, detail: detail, height: inspectorRows, width: columns - 4, expanded: expanded, scroll: inspectScroll })] })) : (_jsx(HotspotView, { agg: agg, sort: sort, width: columns - 4, height: ledgerRows + inspectorRows + 1, cursor: hotCursor, tick: tick, switchTick: switchTick })), _jsx(Box, { height: 1, flexShrink: 0, children: _jsx(Text, { children: " " }) }), _jsx(Box, { width: "100%", height: 1, flexShrink: 0, children: _jsxs(Text, { dimColor: true, italic: true, wrap: "truncate", children: [_jsx(HintLine, { text: hints }), totals.tokens.input > 0 ? (_jsx(Text, { color: "subtle", children: ` ${formatTokens(totals.tokens.input)}→${formatTokens(totals.tokens.output)}` })) : ('')] }) })] }));
364
+ return (_jsxs(Box, { ref: ref, flexDirection: "column", width: "100%", paddingX: 1, children: [header, tabs, _jsx(WaveBand, { band: band, width: bandWidth, cursorColumn: columnOfIndex(band, indexes[clampedCursor] ?? 0), viewportStart: columnOfIndex(band, indexes[windowStart] ?? 0), viewportEnd: columnOfIndex(band, indexes[Math.min(filtered.length - 1, windowStart + ledgerRows - 1)] ?? 0), matches: matchColumns, tick: tick, alertTick: alertTick, onColumnClick: column => {
365
+ // 点击波形列(或标尺行)= 跳到该列最近事件;空列继承前驱的
366
+ // firstIndex,空档区点击落在空档开始处。查询过滤掉的行不跳。
367
+ const nodeIndex = band.buckets[column]?.firstIndex ?? -1;
368
+ if (nodeIndex < 0)
369
+ return;
370
+ const target = indexes.indexOf(nodeIndex);
371
+ if (target >= 0)
372
+ jumpTo(target);
373
+ } }), _jsx(Box, { height: 1, flexShrink: 0, children: _jsx(Text, { children: " " }) }), _jsx("ink-box", { style: { flexDirection: 'column', flexGrow: 1, flexShrink: 1, overflow: 'hidden', width: '100%' }, onWheel: handleWheel, children: view === 'timeline' ? (_jsxs(_Fragment, { children: [_jsx(Ledger, { rows: filtered, start: windowStart, height: ledgerRows, cursor: clampedCursor, width: columns - 4, tick: tick, arrivalTick: arrivalTick, arrivalFrom: arrivalFrom, onRowClick: index => jumpTo(index) }), _jsx(Divider, { color: "permission", width: bandWidth }), _jsx(Inspector, { node: focused, detail: detail, height: inspectorRows, width: columns - 4, expanded: expanded, scroll: inspectScroll })] })) : (_jsx(HotspotView, { agg: agg, sort: sort, width: columns - 4, height: ledgerRows + inspectorRows + 1, cursor: hotCursor, tick: tick, switchTick: switchTick, onRowClick: index => jumpFromHotspot(hotspotRows(agg)[index]) })) }), _jsx(Box, { height: 1, flexShrink: 0, children: _jsx(Text, { children: " " }) }), _jsx(Box, { width: "100%", height: 1, flexShrink: 0, children: _jsxs(Text, { dimColor: true, italic: true, wrap: "truncate", children: [_jsx(HintLine, { text: hints }), totals.tokens.input > 0 ? (_jsx(Text, { color: "subtle", children: ` ${formatTokens(totals.tokens.input)}→${formatTokens(totals.tokens.output)}` })) : ('')] }) })] }));
307
374
  }
@@ -0,0 +1,237 @@
1
+ /**
2
+ * The chat screen's transient-dialog layer (the pickers, dialogs and panels
3
+ * that float above the prompt in `<OverlayAbove>`, plus /tips) as one
4
+ * explicit state machine.
5
+ *
6
+ * Previously this layer lived in ~28 sibling `useState` booleans+indices in
7
+ * Chat.tsx, with mutual exclusion emerging from "an open picker makes the
8
+ * prompt inert, so no second open command can be typed", and with two
9
+ * hand-maintained OR-aggregates (`promptSelectionActive`,
10
+ * `dialogOverlayOpen`) whose comments warned they must stay exactly in sync
11
+ * with the per-panel render conditions. A single discriminated union makes
12
+ * the exclusion structural — one variable can only hold one variant — and
13
+ * turns both aggregates into derivations that cannot drift.
14
+ *
15
+ * Design constraints, in order:
16
+ * 1. Behavior-preserving: every keyboard path, open/close side effect and
17
+ * async-callback landing keeps its observable behavior. The one
18
+ * deliberate change: an async OPEN landing while another overlay is up
19
+ * (e.g. `/effort`'s listEfforts resolving after the user opened
20
+ * `/model`) now REPLACES it instead of stacking two panels — the
21
+ * stacked rendering was an unreachable-by-keyboard race, not a feature.
22
+ * 2. Pure and total: the reducer is a plain function, unit-tested by
23
+ * scripts/verify-chat-overlay.ts without a renderer. Actions that no
24
+ * longer apply (an async result landing after the overlay changed) are
25
+ * ignored rather than writing orphan state.
26
+ * 3. Async data caches (model list, preset roster, …) stay OUTSIDE the
27
+ * union in Chat.tsx: they persist across open/close so a reopened
28
+ * picker can paint the previous list while the fresh one loads,
29
+ * exactly as before.
30
+ */
31
+ import type { ChatRow } from '../dsh-adapter/channel.js';
32
+ import type { TuiRewindMode } from '../dsh-adapter/extension-events.js';
33
+ import type { TuiWorkspaceCommandResult } from '../workspaces.js';
34
+ /** The `kind: 'choices'` result a workspace command can return. */
35
+ export type WorkspaceFlowChoices = Extract<TuiWorkspaceCommandResult, {
36
+ kind: 'choices';
37
+ }>;
38
+ /** Text-entry sub-state of the workspace flow (Tab into a choice's input). */
39
+ export type WorkspaceFlowInput = {
40
+ choiceId: string;
41
+ value: string;
42
+ cursor: number;
43
+ placeholder?: string;
44
+ };
45
+ export type ChatOverlay = {
46
+ kind: 'none';
47
+ } | {
48
+ kind: 'thinking';
49
+ focus: number;
50
+ } | {
51
+ kind: 'workspace-picker';
52
+ index: number;
53
+ } | {
54
+ kind: 'workspace-menu';
55
+ index: number;
56
+ } | {
57
+ kind: 'workspace-flow';
58
+ flow: WorkspaceFlowChoices;
59
+ index: number;
60
+ busy: boolean;
61
+ input: WorkspaceFlowInput | null;
62
+ } | {
63
+ kind: 'model';
64
+ index: number;
65
+ } | {
66
+ kind: 'skills';
67
+ index: number;
68
+ } | {
69
+ kind: 'activity';
70
+ index: number;
71
+ } | {
72
+ kind: 'color';
73
+ index: number;
74
+ } | {
75
+ kind: 'effort';
76
+ index: number;
77
+ } | {
78
+ kind: 'preset';
79
+ index: number;
80
+ } | {
81
+ kind: 'theme';
82
+ index: number;
83
+ } | {
84
+ kind: 'permission';
85
+ index: number;
86
+ } | {
87
+ kind: 'plan';
88
+ index: number;
89
+ } | {
90
+ kind: 'lang';
91
+ index: number;
92
+ } | {
93
+ kind: 'history';
94
+ query: string;
95
+ cursor: number;
96
+ focus: number;
97
+ } | {
98
+ kind: 'rewind';
99
+ index: number;
100
+ confirm: ChatRow | null;
101
+ modes: readonly TuiRewindMode[] | null;
102
+ modeIndex: number;
103
+ busy: boolean;
104
+ } | {
105
+ kind: 'search';
106
+ } | {
107
+ kind: 'tips';
108
+ }
109
+ /**
110
+ * Click-to-act file menu: opened by clicking a file path in the
111
+ * transcript (tool cards, markdown code spans / plain text, file://
112
+ * links). `index` is the focused action row (0 = open, 1 = reveal in
113
+ * file manager, 2 = copy absolute path). `isDir` tells the panel whether
114
+ * the target is a directory (first row reads "open folder").
115
+ */
116
+ | {
117
+ kind: 'file-actions';
118
+ path: string;
119
+ index: number;
120
+ isDir: boolean;
121
+ };
122
+ export declare const NO_OVERLAY: ChatOverlay;
123
+ export type ChatOverlayAction =
124
+ /** Open a variant, replacing whatever is up (including `none`). */
125
+ {
126
+ type: 'open';
127
+ overlay: ChatOverlay;
128
+ }
129
+ /** Close unconditionally (only dispatched from the open overlay's own keys). */
130
+ | {
131
+ type: 'close';
132
+ }
133
+ /** Close only if the given kind is still up — the safe form for async
134
+ * callbacks (a loader failing after the user already moved on). */
135
+ | {
136
+ type: 'close-if';
137
+ kind: ChatOverlay['kind'];
138
+ }
139
+ /**
140
+ * Open only while the current kind is one of `when` — the safe form for an
141
+ * OPEN that arrives from an async callback (`/effort`'s level list, the
142
+ * workspace target list, a workspace command's choices). A user who opened
143
+ * something else during the round trip keeps what they opened; the stale
144
+ * open is dropped. Synchronous opens keep using plain `open`.
145
+ */
146
+ | {
147
+ type: 'open-if';
148
+ overlay: ChatOverlay;
149
+ when: readonly ChatOverlay['kind'][];
150
+ }
151
+ /**
152
+ * Move the focused row by one with wrap-around, over a list of `count`
153
+ * entries. On `rewind` this targets whichever cursor the sub-state focuses
154
+ * (mode list when a plugin offered modes, else the candidate list). A
155
+ * `count <= 0` move is a no-op (an empty list has no focus to move).
156
+ */
157
+ | {
158
+ type: 'move';
159
+ delta: 1 | -1;
160
+ count: number;
161
+ }
162
+ /** Set the focused row to an absolute index — an async loader landing
163
+ * with the authoritative focus (model list / preset roster), or a mouse
164
+ * click on a row of a panel that stays open (effort slider, workspace
165
+ * flow). Ignored unless that panel is still up. */
166
+ | {
167
+ type: 'set-index';
168
+ kind: 'model' | 'preset' | 'effort' | 'workspace-flow' | 'rewind' | 'file-actions';
169
+ index: number;
170
+ }
171
+ /** Edit the history-search draft (query text, caret, focused match). */
172
+ | {
173
+ type: 'history-edit';
174
+ query?: string;
175
+ cursor?: number;
176
+ focus?: number;
177
+ }
178
+ /** Workspace flow: an action is running (keys except Esc are swallowed). */
179
+ | {
180
+ type: 'flow-busy';
181
+ busy: boolean;
182
+ }
183
+ /** Workspace flow: enter (object) or leave (null) the text-input state. */
184
+ | {
185
+ type: 'flow-input';
186
+ input: WorkspaceFlowInput | null;
187
+ }
188
+ /** Workspace flow: edit the text-input draft in place. */
189
+ | {
190
+ type: 'flow-input-edit';
191
+ value: string;
192
+ cursor: number;
193
+ }
194
+ /** Rewind: the plugin decision round-trip started / was abandoned. */
195
+ | {
196
+ type: 'rewind-busy';
197
+ busy: boolean;
198
+ }
199
+ /** Rewind: the plugin decision landed — show the confirm pane (modes turn
200
+ * it into a choice list). Stale decisions are dropped by the caller's
201
+ * request token before dispatch; a changed overlay drops them here. */
202
+ | {
203
+ type: 'rewind-decision';
204
+ confirm: ChatRow;
205
+ modes: readonly TuiRewindMode[] | null;
206
+ }
207
+ /** Rewind: Esc from the confirm/modes pane back to the candidate list. */
208
+ | {
209
+ type: 'rewind-back';
210
+ };
211
+ /**
212
+ * One-step wrap-around cursor move — the single source of the wrapping rule
213
+ * every list overlay uses (Chat.tsx's effort slider reads it too, to apply
214
+ * the newly focused level in the same keystroke that dispatches the move).
215
+ */
216
+ export declare function wrapIndex(index: number, delta: 1 | -1, count: number): number;
217
+ export declare function chatOverlayReducer(state: ChatOverlay, action: ChatOverlayAction): ChatOverlay;
218
+ /**
219
+ * Whether the `<OverlayAbove>` wrapper mounts. Mounting is all-or-nothing:
220
+ * the renderer's removed-absolute-node blit detection only fires when the
221
+ * removed subtree itself is `position: absolute` (dom.ts
222
+ * collectRemovedRects), so the whole overlay must leave the tree when its
223
+ * last panel closes — see the mount-site comment in Chat.tsx.
224
+ *
225
+ * The per-kind data gates mirror the per-panel render conditions verbatim:
226
+ * a picker whose async list has not landed (or came back trivially small)
227
+ * paints nothing, so the wrapper must not mount for it either. `tips`
228
+ * returns true even though the panel renders in the prompt slot rather than
229
+ * inside the overlay — preserved verbatim from the boolean-era aggregate
230
+ * (the empty absolute wrapper is zero-size and paints nothing).
231
+ */
232
+ export declare function dialogOverlayVisible(overlay: ChatOverlay, gates: {
233
+ workspaceTargetCount: number;
234
+ effortOptionCount: number;
235
+ presetOptionCount: number;
236
+ }): boolean;
237
+ //# sourceMappingURL=chatOverlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chatOverlay.d.ts","sourceRoot":"","sources":["../../../src/screens/chatOverlay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ export const NO_OVERLAY = { kind: 'none' };
2
+ /**
3
+ * One-step wrap-around cursor move — the single source of the wrapping rule
4
+ * every list overlay uses (Chat.tsx's effort slider reads it too, to apply
5
+ * the newly focused level in the same keystroke that dispatches the move).
6
+ */
7
+ export function wrapIndex(index, delta, count) {
8
+ return delta === -1
9
+ ? (index <= 0 ? count - 1 : index - 1)
10
+ : (index >= count - 1 ? 0 : index + 1);
11
+ }
12
+ export function chatOverlayReducer(state, action) {
13
+ switch (action.type) {
14
+ case 'open':
15
+ return action.overlay;
16
+ case 'close':
17
+ return NO_OVERLAY;
18
+ case 'close-if':
19
+ return state.kind === action.kind ? NO_OVERLAY : state;
20
+ case 'open-if':
21
+ return action.when.includes(state.kind) ? action.overlay : state;
22
+ case 'move': {
23
+ if (action.count <= 0)
24
+ return state;
25
+ if (state.kind === 'rewind') {
26
+ // The confirm pane with plugin modes has its own cursor; the plain
27
+ // confirm pane has none (Enter/Esc only — a move must not disturb
28
+ // the list index behind it).
29
+ if (state.confirm !== null) {
30
+ return state.modes !== null
31
+ ? { ...state, modeIndex: wrapIndex(state.modeIndex, action.delta, action.count) }
32
+ : state;
33
+ }
34
+ return { ...state, index: wrapIndex(state.index, action.delta, action.count) };
35
+ }
36
+ if (state.kind === 'thinking') {
37
+ return { ...state, focus: wrapIndex(state.focus, action.delta, action.count) };
38
+ }
39
+ if (state.kind === 'workspace-picker'
40
+ || state.kind === 'workspace-menu'
41
+ || state.kind === 'workspace-flow'
42
+ || state.kind === 'model'
43
+ || state.kind === 'skills'
44
+ || state.kind === 'activity'
45
+ || state.kind === 'color'
46
+ || state.kind === 'effort'
47
+ || state.kind === 'preset'
48
+ || state.kind === 'theme'
49
+ || state.kind === 'permission'
50
+ || state.kind === 'plan'
51
+ || state.kind === 'lang'
52
+ || state.kind === 'file-actions') {
53
+ return { ...state, index: wrapIndex(state.index, action.delta, action.count) };
54
+ }
55
+ if (state.kind === 'history') {
56
+ return { ...state, focus: wrapIndex(state.focus, action.delta, action.count) };
57
+ }
58
+ return state;
59
+ }
60
+ case 'set-index':
61
+ return state.kind === action.kind ? { ...state, index: action.index } : state;
62
+ case 'history-edit':
63
+ return state.kind === 'history'
64
+ ? {
65
+ ...state,
66
+ ...(action.query === undefined ? {} : { query: action.query }),
67
+ ...(action.cursor === undefined ? {} : { cursor: action.cursor }),
68
+ ...(action.focus === undefined ? {} : { focus: action.focus }),
69
+ }
70
+ : state;
71
+ case 'flow-busy':
72
+ return state.kind === 'workspace-flow' ? { ...state, busy: action.busy } : state;
73
+ case 'flow-input':
74
+ return state.kind === 'workspace-flow' ? { ...state, input: action.input } : state;
75
+ case 'flow-input-edit':
76
+ return state.kind === 'workspace-flow' && state.input !== null
77
+ ? { ...state, input: { ...state.input, value: action.value, cursor: action.cursor } }
78
+ : state;
79
+ case 'rewind-busy':
80
+ return state.kind === 'rewind' ? { ...state, busy: action.busy } : state;
81
+ case 'rewind-decision':
82
+ return state.kind === 'rewind'
83
+ ? { ...state, busy: false, confirm: action.confirm, modes: action.modes, modeIndex: 0 }
84
+ : state;
85
+ case 'rewind-back':
86
+ return state.kind === 'rewind' ? { ...state, confirm: null, modes: null } : state;
87
+ }
88
+ }
89
+ /**
90
+ * Whether the `<OverlayAbove>` wrapper mounts. Mounting is all-or-nothing:
91
+ * the renderer's removed-absolute-node blit detection only fires when the
92
+ * removed subtree itself is `position: absolute` (dom.ts
93
+ * collectRemovedRects), so the whole overlay must leave the tree when its
94
+ * last panel closes — see the mount-site comment in Chat.tsx.
95
+ *
96
+ * The per-kind data gates mirror the per-panel render conditions verbatim:
97
+ * a picker whose async list has not landed (or came back trivially small)
98
+ * paints nothing, so the wrapper must not mount for it either. `tips`
99
+ * returns true even though the panel renders in the prompt slot rather than
100
+ * inside the overlay — preserved verbatim from the boolean-era aggregate
101
+ * (the empty absolute wrapper is zero-size and paints nothing).
102
+ */
103
+ export function dialogOverlayVisible(overlay, gates) {
104
+ switch (overlay.kind) {
105
+ case 'none':
106
+ return false;
107
+ case 'workspace-picker':
108
+ return gates.workspaceTargetCount > 0;
109
+ case 'effort':
110
+ return gates.effortOptionCount > 1;
111
+ case 'preset':
112
+ return gates.presetOptionCount > 0;
113
+ default:
114
+ return true;
115
+ }
116
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"tips.d.ts","sourceRoot":"","sources":["../../src/tips.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;AAEhF,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,QAAQ,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX;AAED,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAMzE,CAAA;AAED,eAAO,MAAM,IAAI,EAAE,SAAS,GAAG,EAwjB9B,CAAA;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAM,MAAoB,GAAG,GAAG,CAErE;AAED,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,GAAG,EAAE,CAElD"}
1
+ {"version":3,"file":"tips.d.ts","sourceRoot":"","sources":["../../src/tips.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;AAEhF,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,QAAQ,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX;AAED,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAMzE,CAAA;AAED,eAAO,MAAM,IAAI,EAAE,SAAS,GAAG,EA8mB9B,CAAA;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAM,MAAoB,GAAG,GAAG,CAErE;AAED,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,GAAG,EAAE,CAElD"}