@deepseek-harness-tui/dsh-tui 0.6.0 → 0.7.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.
Files changed (379) hide show
  1. package/README.md +74 -21
  2. package/bin/dsh-tui.js +115 -25
  3. package/cordis.patch.yml +69 -17
  4. package/cordis.yml +50 -12
  5. package/lib/types/activityPrefs.d.ts +1 -1
  6. package/lib/types/activityPrefs.js +3 -3
  7. package/lib/types/cc/figures.d.ts +27 -20
  8. package/lib/types/cc/figures.d.ts.map +1 -1
  9. package/lib/types/cc/figures.js +43 -34
  10. package/lib/types/cc/format.d.ts +18 -9
  11. package/lib/types/cc/format.d.ts.map +1 -1
  12. package/lib/types/cc/format.js +26 -18
  13. package/lib/types/cc/markdown.d.ts +31 -16
  14. package/lib/types/cc/markdown.d.ts.map +1 -1
  15. package/lib/types/cc/markdown.js +283 -260
  16. package/lib/types/cc/terminal.d.ts +10 -7
  17. package/lib/types/cc/terminal.d.ts.map +1 -1
  18. package/lib/types/cc/terminal.js +62 -50
  19. package/lib/types/command-trees.d.ts +3 -0
  20. package/lib/types/command-trees.d.ts.map +1 -0
  21. package/lib/types/command-trees.js +4 -0
  22. package/lib/types/commands.d.ts +37 -1
  23. package/lib/types/commands.d.ts.map +1 -1
  24. package/lib/types/commands.js +68 -3
  25. package/lib/types/components/ActivityLine.d.ts +1 -1
  26. package/lib/types/components/ActivityLine.d.ts.map +1 -1
  27. package/lib/types/components/ActivityPicker.d.ts.map +1 -1
  28. package/lib/types/components/ActivityPicker.js +3 -4
  29. package/lib/types/components/BtwPanel.d.ts +16 -0
  30. package/lib/types/components/BtwPanel.d.ts.map +1 -0
  31. package/lib/types/components/BtwPanel.js +47 -0
  32. package/lib/types/components/CommandSuggestions.d.ts +4 -2
  33. package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
  34. package/lib/types/components/CommandSuggestions.js +2 -2
  35. package/lib/types/components/EffortSlider.d.ts +15 -0
  36. package/lib/types/components/EffortSlider.d.ts.map +1 -0
  37. package/lib/types/components/EffortSlider.js +17 -0
  38. package/lib/types/components/GoalTodoPanel.d.ts +1 -1
  39. package/lib/types/components/GoalTodoPanel.d.ts.map +1 -1
  40. package/lib/types/components/HelpMenu.d.ts +5 -2
  41. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  42. package/lib/types/components/HelpMenu.js +8 -3
  43. package/lib/types/components/HistorySearchDialog.d.ts +1 -1
  44. package/lib/types/components/HistorySearchDialog.d.ts.map +1 -1
  45. package/lib/types/components/HistorySearchDialog.js +21 -10
  46. package/lib/types/components/InterruptedByUser.d.ts +2 -2
  47. package/lib/types/components/InterruptedByUser.d.ts.map +1 -1
  48. package/lib/types/components/InterruptedByUser.js +4 -3
  49. package/lib/types/components/LoadedContextPanel.d.ts +1 -1
  50. package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
  51. package/lib/types/components/LogoV2.d.ts.map +1 -1
  52. package/lib/types/components/LogoV2.js +2 -1
  53. package/lib/types/components/Markdown.d.ts +11 -11
  54. package/lib/types/components/Markdown.d.ts.map +1 -1
  55. package/lib/types/components/Markdown.js +63 -57
  56. package/lib/types/components/MarkdownTable.d.ts +1 -1
  57. package/lib/types/components/MarkdownTable.js +2 -2
  58. package/lib/types/components/MessageList.d.ts +10 -2
  59. package/lib/types/components/MessageList.d.ts.map +1 -1
  60. package/lib/types/components/MessageList.js +17 -10
  61. package/lib/types/components/ModelPicker.d.ts +4 -1
  62. package/lib/types/components/ModelPicker.d.ts.map +1 -1
  63. package/lib/types/components/ModelPicker.js +16 -4
  64. package/lib/types/components/OverlayAbove.d.ts +20 -0
  65. package/lib/types/components/OverlayAbove.d.ts.map +1 -0
  66. package/lib/types/components/OverlayAbove.js +18 -0
  67. package/lib/types/components/PresetPicker.d.ts +1 -1
  68. package/lib/types/components/PresetPicker.d.ts.map +1 -1
  69. package/lib/types/components/PresetPicker.js +2 -3
  70. package/lib/types/components/PromptInput.d.ts +5 -4
  71. package/lib/types/components/PromptInput.d.ts.map +1 -1
  72. package/lib/types/components/PromptInput.js +186 -39
  73. package/lib/types/components/ResumePicker.d.ts +15 -4
  74. package/lib/types/components/ResumePicker.d.ts.map +1 -1
  75. package/lib/types/components/ResumePicker.js +25 -9
  76. package/lib/types/components/RewindPicker.d.ts +1 -1
  77. package/lib/types/components/RewindPicker.d.ts.map +1 -1
  78. package/lib/types/components/RewindPicker.js +14 -5
  79. package/lib/types/components/SearchBox.d.ts +1 -1
  80. package/lib/types/components/SearchBox.js +1 -1
  81. package/lib/types/components/Spinner/GlimmerMessage.d.ts +1 -2
  82. package/lib/types/components/Spinner/GlimmerMessage.d.ts.map +1 -1
  83. package/lib/types/components/Spinner/GlimmerMessage.js +1 -2
  84. package/lib/types/components/Spinner/SpinnerAnimationRow.d.ts +1 -1
  85. package/lib/types/components/Spinner/SpinnerAnimationRow.js +2 -2
  86. package/lib/types/components/Spinner/SpinnerGlyph.d.ts +1 -1
  87. package/lib/types/components/Spinner/SpinnerGlyph.js +1 -1
  88. package/lib/types/components/Spinner/spinnerUtils.d.ts +13 -18
  89. package/lib/types/components/Spinner/spinnerUtils.d.ts.map +1 -1
  90. package/lib/types/components/Spinner/spinnerUtils.js +67 -71
  91. package/lib/types/components/Spinner/useStalledAnimation.d.ts +1 -2
  92. package/lib/types/components/Spinner/useStalledAnimation.d.ts.map +1 -1
  93. package/lib/types/components/Spinner/useStalledAnimation.js +1 -2
  94. package/lib/types/components/StreamingMarkdown.d.ts +1 -1
  95. package/lib/types/components/StreamingMarkdown.js +1 -1
  96. package/lib/types/components/ThemePicker.d.ts +13 -9
  97. package/lib/types/components/ThemePicker.d.ts.map +1 -1
  98. package/lib/types/components/ThemePicker.js +21 -15
  99. package/lib/types/components/ThinkingToggle.d.ts +1 -1
  100. package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
  101. package/lib/types/components/ThinkingToggle.js +8 -8
  102. package/lib/types/components/ToolUseLoader.d.ts +1 -1
  103. package/lib/types/components/ToolUseLoader.js +1 -1
  104. package/lib/types/components/WorkingSpinner.d.ts +2 -2
  105. package/lib/types/components/WorkingSpinner.js +2 -2
  106. package/lib/types/components/WorkspaceFlowPicker.d.ts +15 -0
  107. package/lib/types/components/WorkspaceFlowPicker.d.ts.map +1 -0
  108. package/lib/types/components/WorkspaceFlowPicker.js +19 -0
  109. package/lib/types/components/WorkspacePicker.d.ts +9 -0
  110. package/lib/types/components/WorkspacePicker.d.ts.map +1 -0
  111. package/lib/types/components/WorkspacePicker.js +13 -0
  112. package/lib/types/components/approvals/ApprovalPanel.d.ts +1 -1
  113. package/lib/types/components/approvals/ApprovalPanel.d.ts.map +1 -1
  114. package/lib/types/components/approvals/ApprovalPanel.js +2 -1
  115. package/lib/types/components/design-system/Byline.d.ts +1 -1
  116. package/lib/types/components/design-system/Byline.js +1 -1
  117. package/lib/types/components/design-system/Divider.d.ts +1 -1
  118. package/lib/types/components/design-system/Divider.js +1 -1
  119. package/lib/types/components/design-system/HintLine.d.ts +12 -0
  120. package/lib/types/components/design-system/HintLine.d.ts.map +1 -0
  121. package/lib/types/components/design-system/HintLine.js +15 -0
  122. package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +1 -1
  123. package/lib/types/components/design-system/KeyboardShortcutHint.js +1 -1
  124. package/lib/types/components/design-system/ListItem.d.ts +2 -2
  125. package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
  126. package/lib/types/components/design-system/ListItem.js +35 -3
  127. package/lib/types/components/design-system/LoadingState.d.ts +1 -2
  128. package/lib/types/components/design-system/LoadingState.d.ts.map +1 -1
  129. package/lib/types/components/design-system/LoadingState.js +1 -2
  130. package/lib/types/components/design-system/Pane.d.ts +2 -2
  131. package/lib/types/components/design-system/Pane.js +2 -2
  132. package/lib/types/components/design-system/ProgressBar.d.ts +1 -2
  133. package/lib/types/components/design-system/ProgressBar.d.ts.map +1 -1
  134. package/lib/types/components/design-system/ProgressBar.js +1 -2
  135. package/lib/types/components/design-system/StatusIcon.d.ts +2 -2
  136. package/lib/types/components/design-system/StatusIcon.js +2 -2
  137. package/lib/types/components/design-system/ThemeProvider.d.ts +1 -1
  138. package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
  139. package/lib/types/components/design-system/ThemeProvider.js +87 -26
  140. package/lib/types/components/design-system/ThemedBox.d.ts +1 -1
  141. package/lib/types/components/design-system/ThemedBox.js +1 -1
  142. package/lib/types/components/design-system/ThemedText.d.ts +2 -2
  143. package/lib/types/components/design-system/ThemedText.js +2 -2
  144. package/lib/types/components/listWindow.d.ts +26 -0
  145. package/lib/types/components/listWindow.d.ts.map +1 -0
  146. package/lib/types/components/listWindow.js +47 -0
  147. package/lib/types/components/messages/AssistantTextMessage.d.ts +1 -2
  148. package/lib/types/components/messages/AssistantTextMessage.d.ts.map +1 -1
  149. package/lib/types/components/messages/AssistantTextMessage.js +1 -2
  150. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -2
  151. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  152. package/lib/types/components/messages/AssistantThinkingMessage.js +6 -6
  153. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +12 -4
  154. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  155. package/lib/types/components/messages/AssistantToolUseMessage.js +9 -5
  156. package/lib/types/components/messages/MessageMetadata.d.ts +1 -1
  157. package/lib/types/components/messages/MessageMetadata.js +1 -1
  158. package/lib/types/components/messages/UserPromptMessage.d.ts +1 -1
  159. package/lib/types/components/messages/UserPromptMessage.js +1 -1
  160. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +5 -1
  161. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  162. package/lib/types/components/questions/AskUserQuestionPanel.js +11 -9
  163. package/lib/types/components/questions/PlanReviewPanel.d.ts +1 -1
  164. package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
  165. package/lib/types/components/questions/PlanReviewPanel.js +3 -2
  166. package/lib/types/components/trajectory/HotspotView.d.ts +14 -0
  167. package/lib/types/components/trajectory/HotspotView.d.ts.map +1 -0
  168. package/lib/types/components/trajectory/HotspotView.js +83 -0
  169. package/lib/types/components/trajectory/Inspector.d.ts +31 -0
  170. package/lib/types/components/trajectory/Inspector.d.ts.map +1 -0
  171. package/lib/types/components/trajectory/Inspector.js +67 -0
  172. package/lib/types/components/trajectory/Ledger.d.ts +20 -0
  173. package/lib/types/components/trajectory/Ledger.d.ts.map +1 -0
  174. package/lib/types/components/trajectory/Ledger.js +112 -0
  175. package/lib/types/components/trajectory/MiniWake.d.ts +24 -0
  176. package/lib/types/components/trajectory/MiniWake.d.ts.map +1 -0
  177. package/lib/types/components/trajectory/MiniWake.js +99 -0
  178. package/lib/types/components/trajectory/WaveBand.d.ts +33 -0
  179. package/lib/types/components/trajectory/WaveBand.d.ts.map +1 -0
  180. package/lib/types/components/trajectory/WaveBand.js +145 -0
  181. package/lib/types/customTheme.d.ts +6 -6
  182. package/lib/types/customTheme.d.ts.map +1 -1
  183. package/lib/types/customTheme.js +15 -12
  184. package/lib/types/dsh-adapter/approvals.d.ts.map +1 -0
  185. package/lib/types/{channel.d.ts → dsh-adapter/channel.d.ts} +184 -43
  186. package/lib/types/dsh-adapter/channel.d.ts.map +1 -0
  187. package/lib/types/{channel.js → dsh-adapter/channel.js} +972 -201
  188. package/lib/types/dsh-adapter/childStderr.d.ts.map +1 -0
  189. package/lib/types/{childStderr.js → dsh-adapter/childStderr.js} +1 -1
  190. package/lib/types/dsh-adapter/command-trees.d.ts +27 -0
  191. package/lib/types/dsh-adapter/command-trees.d.ts.map +1 -0
  192. package/lib/types/dsh-adapter/command-trees.js +42 -0
  193. package/lib/types/dsh-adapter/compat/index.d.ts +22 -0
  194. package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -0
  195. package/lib/types/{compat → dsh-adapter/compat}/index.js +7 -4
  196. package/lib/types/dsh-adapter/compat/sessionLog.d.ts +86 -0
  197. package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -0
  198. package/lib/types/dsh-adapter/compat/sessionLog.js +347 -0
  199. package/lib/types/dsh-adapter/contract.d.ts +20 -0
  200. package/lib/types/dsh-adapter/contract.d.ts.map +1 -0
  201. package/lib/types/dsh-adapter/contract.js +109 -0
  202. package/lib/types/dsh-adapter/index.d.ts +80 -0
  203. package/lib/types/dsh-adapter/index.d.ts.map +1 -0
  204. package/lib/types/dsh-adapter/index.js +45 -0
  205. package/lib/types/dsh-adapter/invariant.d.ts.map +1 -0
  206. package/lib/types/dsh-adapter/packaged-skills.d.ts.map +1 -0
  207. package/lib/types/{plugin.d.ts → dsh-adapter/plugin.d.ts} +17 -0
  208. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -0
  209. package/lib/types/{plugin.js → dsh-adapter/plugin.js} +280 -80
  210. package/lib/types/dsh-adapter/presets.d.ts.map +1 -0
  211. package/lib/types/dsh-adapter/providerWizard.d.ts +91 -0
  212. package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -0
  213. package/lib/types/dsh-adapter/providerWizard.js +332 -0
  214. package/lib/types/{questions.d.ts → dsh-adapter/questions.d.ts} +7 -2
  215. package/lib/types/dsh-adapter/questions.d.ts.map +1 -0
  216. package/lib/types/{questions.js → dsh-adapter/questions.js} +15 -7
  217. package/lib/types/dsh-adapter/sideQuestion.d.ts +38 -0
  218. package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -0
  219. package/lib/types/dsh-adapter/sideQuestion.js +69 -0
  220. package/lib/types/dsh-adapter/trajectory/aggregate.d.ts +46 -0
  221. package/lib/types/dsh-adapter/trajectory/aggregate.d.ts.map +1 -0
  222. package/lib/types/dsh-adapter/trajectory/aggregate.js +207 -0
  223. package/lib/types/dsh-adapter/trajectory/guards.d.ts +177 -0
  224. package/lib/types/dsh-adapter/trajectory/guards.d.ts.map +1 -0
  225. package/lib/types/dsh-adapter/trajectory/guards.js +235 -0
  226. package/lib/types/dsh-adapter/trajectory/index.d.ts +16 -0
  227. package/lib/types/dsh-adapter/trajectory/index.d.ts.map +1 -0
  228. package/lib/types/dsh-adapter/trajectory/index.js +15 -0
  229. package/lib/types/dsh-adapter/trajectory/inspect.d.ts +40 -0
  230. package/lib/types/dsh-adapter/trajectory/inspect.d.ts.map +1 -0
  231. package/lib/types/dsh-adapter/trajectory/inspect.js +160 -0
  232. package/lib/types/dsh-adapter/trajectory/projection.d.ts +128 -0
  233. package/lib/types/dsh-adapter/trajectory/projection.d.ts.map +1 -0
  234. package/lib/types/dsh-adapter/trajectory/projection.js +653 -0
  235. package/lib/types/dsh-adapter/trajectory/types.d.ts +232 -0
  236. package/lib/types/dsh-adapter/trajectory/types.d.ts.map +1 -0
  237. package/lib/types/dsh-adapter/trajectory/types.js +70 -0
  238. package/lib/types/dsh-adapter/trajectory/wave.d.ts +45 -0
  239. package/lib/types/dsh-adapter/trajectory/wave.d.ts.map +1 -0
  240. package/lib/types/dsh-adapter/trajectory/wave.js +210 -0
  241. package/lib/types/dsh-adapter/types.d.ts +23 -0
  242. package/lib/types/dsh-adapter/types.d.ts.map +1 -0
  243. package/lib/types/dsh-adapter/types.js +1 -0
  244. package/lib/types/dsh-adapter/workspace.d.ts +22 -0
  245. package/lib/types/dsh-adapter/workspace.d.ts.map +1 -0
  246. package/lib/types/dsh-adapter/workspace.js +16 -0
  247. package/lib/types/dsh-adapter/workspaces.d.ts +118 -0
  248. package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -0
  249. package/lib/types/dsh-adapter/workspaces.js +290 -0
  250. package/lib/types/effortPrefs.d.ts +1 -1
  251. package/lib/types/effortPrefs.js +3 -3
  252. package/lib/types/history.js +2 -2
  253. package/lib/types/hooks/useBlink.d.ts +1 -1
  254. package/lib/types/hooks/useBlink.js +1 -1
  255. package/lib/types/i18n.d.ts +977 -36
  256. package/lib/types/i18n.d.ts.map +1 -1
  257. package/lib/types/i18n.js +307 -30
  258. package/lib/types/index.d.ts +1 -69
  259. package/lib/types/index.d.ts.map +1 -1
  260. package/lib/types/index.js +3 -31
  261. package/lib/types/ink/components/App.d.ts.map +1 -1
  262. package/lib/types/ink/components/App.js +33 -19
  263. package/lib/types/ink/dom.d.ts +15 -0
  264. package/lib/types/ink/dom.d.ts.map +1 -1
  265. package/lib/types/ink/dom.js +32 -0
  266. package/lib/types/ink/hooks/use-input.d.ts.map +1 -1
  267. package/lib/types/ink/hooks/use-input.js +8 -0
  268. package/lib/types/ink/hooks/use-terminal-size.d.ts +1 -1
  269. package/lib/types/ink/hooks/use-terminal-size.js +1 -1
  270. package/lib/types/ink/ink.d.ts.map +1 -1
  271. package/lib/types/ink/ink.js +109 -28
  272. package/lib/types/ink/input-suppression.d.ts +20 -0
  273. package/lib/types/ink/input-suppression.d.ts.map +1 -0
  274. package/lib/types/ink/input-suppression.js +26 -0
  275. package/lib/types/ink/log-update.js +21 -6
  276. package/lib/types/ink/parse-keypress.d.ts +31 -0
  277. package/lib/types/ink/parse-keypress.d.ts.map +1 -1
  278. package/lib/types/ink/parse-keypress.js +442 -8
  279. package/lib/types/ink/terminal-querier.d.ts +5 -1
  280. package/lib/types/ink/terminal-querier.d.ts.map +1 -1
  281. package/lib/types/ink/terminal-querier.js +27 -3
  282. package/lib/types/ink/terminal.d.ts +18 -0
  283. package/lib/types/ink/terminal.d.ts.map +1 -1
  284. package/lib/types/ink/terminal.js +32 -4
  285. package/lib/types/ink/termio/csi.d.ts +10 -0
  286. package/lib/types/ink/termio/csi.d.ts.map +1 -1
  287. package/lib/types/ink/termio/csi.js +20 -0
  288. package/lib/types/ink/termio/tokenize.js +10 -0
  289. package/lib/types/modelPrefs.d.ts +1 -1
  290. package/lib/types/modelPrefs.js +3 -3
  291. package/lib/types/presetPrefs.d.ts +1 -1
  292. package/lib/types/presetPrefs.js +3 -3
  293. package/lib/types/screens/Chat.d.ts +20 -4
  294. package/lib/types/screens/Chat.d.ts.map +1 -1
  295. package/lib/types/screens/Chat.js +655 -55
  296. package/lib/types/screens/StatusLine.d.ts +17 -2
  297. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  298. package/lib/types/screens/StatusLine.js +12 -4
  299. package/lib/types/screens/TrajectoryScene.d.ts +16 -0
  300. package/lib/types/screens/TrajectoryScene.d.ts.map +1 -0
  301. package/lib/types/screens/TrajectoryScene.js +305 -0
  302. package/lib/types/sessionHistory.d.ts +9 -1
  303. package/lib/types/sessionHistory.d.ts.map +1 -1
  304. package/lib/types/sessionHistory.js +56 -16
  305. package/lib/types/sessionModes.d.ts +29 -0
  306. package/lib/types/sessionModes.d.ts.map +1 -0
  307. package/lib/types/sessionModes.js +45 -0
  308. package/lib/types/theme.d.ts +27 -3
  309. package/lib/types/theme.d.ts.map +1 -1
  310. package/lib/types/theme.js +48 -4
  311. package/lib/types/themePrefs.d.ts +3 -3
  312. package/lib/types/themePrefs.js +5 -5
  313. package/lib/types/trajectory/format.d.ts +100 -0
  314. package/lib/types/trajectory/format.d.ts.map +1 -0
  315. package/lib/types/trajectory/format.js +213 -0
  316. package/lib/types/trajectory/motion.d.ts +99 -0
  317. package/lib/types/trajectory/motion.d.ts.map +1 -0
  318. package/lib/types/trajectory/motion.js +143 -0
  319. package/lib/types/trajectory/query.d.ts +83 -0
  320. package/lib/types/trajectory/query.d.ts.map +1 -0
  321. package/lib/types/trajectory/query.js +187 -0
  322. package/lib/types/trajectoryPrefs.d.ts +36 -0
  323. package/lib/types/trajectoryPrefs.d.ts.map +1 -0
  324. package/lib/types/trajectoryPrefs.js +65 -0
  325. package/lib/types/update.d.ts +3 -3
  326. package/lib/types/update.d.ts.map +1 -1
  327. package/lib/types/update.js +18 -7
  328. package/lib/types/utils/clipboard.d.ts +101 -29
  329. package/lib/types/utils/clipboard.d.ts.map +1 -1
  330. package/lib/types/utils/clipboard.js +533 -55
  331. package/lib/types/utils/debug.d.ts +1 -1
  332. package/lib/types/utils/debug.js +2 -2
  333. package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
  334. package/lib/types/utils/execFileNoThrow.js +16 -6
  335. package/lib/types/utils/externalEditor.d.ts +115 -0
  336. package/lib/types/utils/externalEditor.d.ts.map +1 -0
  337. package/lib/types/utils/externalEditor.js +270 -0
  338. package/lib/types/utils/fullscreen.d.ts +2 -2
  339. package/lib/types/utils/fullscreen.js +3 -3
  340. package/lib/types/utils/loaded-context.d.ts +1 -1
  341. package/lib/types/utils/loaded-context.d.ts.map +1 -1
  342. package/lib/types/utils/modifiers.d.ts +24 -0
  343. package/lib/types/utils/modifiers.d.ts.map +1 -1
  344. package/lib/types/utils/modifiers.js +27 -0
  345. package/lib/types/utils/paths.d.ts +45 -0
  346. package/lib/types/utils/paths.d.ts.map +1 -0
  347. package/lib/types/utils/paths.js +69 -0
  348. package/lib/types/utils/shellQuote.d.ts +14 -0
  349. package/lib/types/utils/shellQuote.d.ts.map +1 -0
  350. package/lib/types/utils/shellQuote.js +39 -0
  351. package/lib/types/utils/workspaceRoot.d.ts +21 -0
  352. package/lib/types/utils/workspaceRoot.d.ts.map +1 -0
  353. package/lib/types/utils/workspaceRoot.js +47 -0
  354. package/lib/types/workspaces.d.ts +3 -0
  355. package/lib/types/workspaces.d.ts.map +1 -0
  356. package/lib/types/workspaces.js +4 -0
  357. package/package.json +26 -8
  358. package/lib/types/approvals.d.ts.map +0 -1
  359. package/lib/types/channel.d.ts.map +0 -1
  360. package/lib/types/childStderr.d.ts.map +0 -1
  361. package/lib/types/compat/index.d.ts +0 -20
  362. package/lib/types/compat/index.d.ts.map +0 -1
  363. package/lib/types/compat/sessionLog.d.ts +0 -40
  364. package/lib/types/compat/sessionLog.d.ts.map +0 -1
  365. package/lib/types/compat/sessionLog.js +0 -226
  366. package/lib/types/invariant.d.ts.map +0 -1
  367. package/lib/types/packaged-skills.d.ts.map +0 -1
  368. package/lib/types/plugin.d.ts.map +0 -1
  369. package/lib/types/presets.d.ts.map +0 -1
  370. package/lib/types/questions.d.ts.map +0 -1
  371. /package/lib/types/{approvals.d.ts → dsh-adapter/approvals.d.ts} +0 -0
  372. /package/lib/types/{approvals.js → dsh-adapter/approvals.js} +0 -0
  373. /package/lib/types/{childStderr.d.ts → dsh-adapter/childStderr.d.ts} +0 -0
  374. /package/lib/types/{invariant.d.ts → dsh-adapter/invariant.d.ts} +0 -0
  375. /package/lib/types/{invariant.js → dsh-adapter/invariant.js} +0 -0
  376. /package/lib/types/{packaged-skills.d.ts → dsh-adapter/packaged-skills.d.ts} +0 -0
  377. /package/lib/types/{packaged-skills.js → dsh-adapter/packaged-skills.js} +0 -0
  378. /package/lib/types/{presets.d.ts → dsh-adapter/presets.d.ts} +0 -0
  379. /package/lib/types/{presets.js → dsh-adapter/presets.js} +0 -0
@@ -5,20 +5,28 @@ import UserQuestionService from '@deepseek-ai/dsh-user-questions';
5
5
  import * as toolAskUser from '@deepseek-ai/dsh-tool-ask-user';
6
6
  import { createChannel } from './channel.js';
7
7
  import { createChildStderrReporter, installChildStderrGuard } from './childStderr.js';
8
- import { logForDebugging } from './utils/debug.js';
8
+ import { logForDebugging } from '../utils/debug.js';
9
9
  import { QuestionStore } from './questions.js';
10
10
  import { ApprovalStore } from './approvals.js';
11
11
  import { registerPackagedSkills } from './packaged-skills.js';
12
- import { readActivityFrames } from './activityPrefs.js';
13
- import { readModelPref } from './modelPrefs.js';
14
- import { explicitModelRoute, recordedModelRoute, resolveModelRoute, validateModelRoute } from './modelRoute.js';
15
- import { readPresetPref } from './presetPrefs.js';
12
+ import { readActivityFrames } from '../activityPrefs.js';
13
+ import { readModelPref } from '../modelPrefs.js';
14
+ import { explicitModelRoute, recordedModelRoute, resolveModelRoute, validateModelRoute } from '../modelRoute.js';
15
+ import { readPresetPref } from '../presetPrefs.js';
16
16
  import { composePreset, resolvePersistedPreset, runningPresetOf } from './presets.js';
17
- import { writeResumeTarget } from './sessionHistory.js';
18
- import { checkForTuiUpdate, installedTuiVersion, isVersionNewer, resolveDshProfileName, resolveTuiUpdateTarget, updateTuiAndRestart } from './update.js';
19
- import { isLang, resolveStartupLang, setLang, t } from './i18n.js';
20
- import { Chat } from './screens/Chat.js';
21
- import { render, ThemeProvider, AlternateScreen } from './ui.js';
17
+ import { ensureLegacySessionEventTypes } from './compat/index.js';
18
+ import { clearResumeTarget, writeResumeTarget } from '../sessionHistory.js';
19
+ import { resolveSessionCwd } from '../utils/workspaceRoot.js';
20
+ import { checkForTuiUpdate, installedTuiVersion, isVersionNewer, resolveDshProfileName, resolveTuiUpdateTarget, updateTuiAndRestart } from '../update.js';
21
+ import { isLang, resolveStartupLang, setLang, t } from '../i18n.js';
22
+ import { detectLegacyEnv, migrateLegacyDataDir, RENAMED_ENV } from '../utils/paths.js';
23
+ import { Chat } from '../screens/Chat.js';
24
+ import { attachSessionToWorkspace } from './workspace.js';
25
+ import { render, ThemeProvider, AlternateScreen } from '../ui.js';
26
+ import instances from '../ink/instances.js';
27
+ import { cursorMove, DISABLE_KITTY_KEYBOARD, DISABLE_MODIFY_OTHER_KEYS, DISABLE_WIN32_INPUT_MODE } from '../ink/termio/csi.js';
28
+ import { DBP, DFE, DISABLE_MOUSE_TRACKING, EXIT_ALT_SCREEN, SHOW_CURSOR } from '../ink/termio/dec.js';
29
+ import { CLEAR_ITERM2_PROGRESS, CLEAR_TAB_STATUS, supportsTabStatus, wrapForMultiplexer } from '../ink/termio/osc.js';
22
30
  /**
23
31
  * Claude Code style interactive TUI front door for DeepSeek Harness agents.
24
32
  *
@@ -32,23 +40,43 @@ export async function apply(ctx, config) {
32
40
  if (!process.stdout.isTTY) {
33
41
  throw new Error('dsh-tui requires an interactive terminal (stdout must be a TTY).');
34
42
  }
35
- // UI language resolution: CC_TUI_LANG env var wins, then cordis.yml
43
+ // Data-directory rename (~/.dsh-cc → ~/.dsh-tui, issue #120): copy the
44
+ // legacy directory before ANY preference read below (resolveStartupLang
45
+ // already touches lang.json). Copy, not move — old launchers keep working
46
+ // and the user deletes the legacy directory themselves.
47
+ const migrated = migrateLegacyDataDir();
48
+ // UI language resolution: DSH_TUI_LANG env var wins, then cordis.yml
36
49
  // `lang`, then the persisted `/lang` choice, then `zh`. Must settle
37
50
  // before the first render so every module resolves strings in the same
38
51
  // language.
39
- const envLang = process.env.CC_TUI_LANG;
52
+ const envLang = process.env.DSH_TUI_LANG;
40
53
  setLang(isLang(envLang) ? envLang : isLang(config.lang) ? config.lang : resolveStartupLang());
54
+ // Rename notices must land before the first render — stderr writes break
55
+ // the fullscreen UI once it is up. The bin launcher prints the same
56
+ // warnings; this covers direct `dsh --profile dsh-tui` boots.
57
+ if (migrated) {
58
+ ctx.logger.warn('dsh-tui: data directory copied from ~/.dsh-cc to ~/.dsh-tui (legacy kept)');
59
+ if (process.stderr.isTTY) {
60
+ process.stderr.write(`\n[dsh-tui] ${t('legacy-dir-migrated')}\n`);
61
+ }
62
+ }
63
+ for (const oldName of detectLegacyEnv()) {
64
+ ctx.logger.warn(`dsh-tui: env ${oldName} renamed to ${RENAMED_ENV[oldName]}; the old name no longer takes effect`);
65
+ if (process.stderr.isTTY) {
66
+ process.stderr.write(`\n[dsh-tui] ${t('legacy-env-renamed', { old: oldName, new: RENAMED_ENV[oldName] })}\n`);
67
+ }
68
+ }
41
69
  // /update restart verification: the pre-update process stamps the version
42
70
  // it was leaving behind; if the freshly loaded one is not newer, the
43
71
  // package manager "succeeded" without actually moving the version (mirror
44
72
  // lag, cached manifest, wrong profile). Say so instead of silently
45
73
  // pretending the update landed.
46
74
  {
47
- const updatedFrom = process.env.DSH_CC_UPDATED_FROM;
75
+ const updatedFrom = process.env.DSH_TUI_UPDATED_FROM;
48
76
  if (updatedFrom !== undefined) {
49
77
  // Assigning undefined would stringify to "undefined" and leak the
50
78
  // marker into every child process; remove it for real.
51
- delete process.env.DSH_CC_UPDATED_FROM;
79
+ delete process.env.DSH_TUI_UPDATED_FROM;
52
80
  const now = installedTuiVersion();
53
81
  if (now === undefined || !isVersionNewer(now, updatedFrom)) {
54
82
  ctx.logger.warn(`dsh-tui: /update restarted but the version did not advance (still ${now ?? 'unknown'}, was ${updatedFrom})`);
@@ -74,10 +102,22 @@ export async function apply(ctx, config) {
74
102
  // Packaged skills (/audit, /bug, …): contribute them through the host's
75
103
  // skill registry so they resolve with zero manual copying.
76
104
  registerPackagedSkills(ctx);
77
- userQuestions.registerProvider({
78
- ask: request => questionStore.ask(request),
79
- });
80
- ctx.effect(() => () => questionStore.rejectAll());
105
+ // Yield to an incumbent provider instead of crashing the whole plugin tree
106
+ // (issue #98): the harness allows exactly ONE user-questions provider per
107
+ // context, and stacking this TUI onto a profile that already carries
108
+ // @deepseek-ai/dsh-web-app (its api-gateway registers first) used to fail
109
+ // the boot with DUPLICATE_PROVIDER. The incumbent UI then owns questionnaire
110
+ // rendering; this TUI's ask_user_question requests are answered there.
111
+ try {
112
+ userQuestions.registerProvider({
113
+ ask: request => questionStore.ask(request),
114
+ });
115
+ ctx.effect(() => () => questionStore.rejectAll());
116
+ }
117
+ catch (error) {
118
+ if (error.code !== 'DUPLICATE_PROVIDER')
119
+ throw error;
120
+ }
81
121
  // Child-process stderr guard (issue #17): MCP servers spawned with an
82
122
  // inherited stderr (the MCP SDK's stdio default) write straight to the
83
123
  // terminal device from the child process, bypassing the renderer's own
@@ -111,20 +151,61 @@ export async function apply(ctx, config) {
111
151
  model: config.model,
112
152
  };
113
153
  // Atomic route resolution (issue #67): a complete cordis.yml route wins
114
- // whole, else the persisted `/model` choice wins whole, else the harness
115
- // defaults — a provider-only config pin never merges with the persisted
116
- // model half. resolveAgent validates this route on create and reports the
117
- // one actually used, so the status line shows the real request route.
118
- const startupRoute = resolveModelRoute(configuredRoute, readModelPref());
119
- const meta = { cwd: config.cwd ?? process.cwd() };
154
+ // whole, else the persisted `/model` choice wins whole, else Harness's
155
+ // provider-neutral agent-default-model selection. The local DeepSeek pair
156
+ // remains the final fallback for bare embedders without that service. This
157
+ // lets optional provider bundles supply the same default to Web and TUI
158
+ // without patching this front door by name.
159
+ const configuredDefault = ctx.get('agentDefaultModel')?.currentSelection?.();
160
+ const harnessDefault = typeof configuredDefault?.provider === 'string'
161
+ && configuredDefault.provider.length > 0
162
+ && typeof configuredDefault.model === 'string'
163
+ && configuredDefault.model.length > 0
164
+ ? { provider: configuredDefault.provider, model: configuredDefault.model }
165
+ : undefined;
166
+ const startupRoute = resolveModelRoute(configuredRoute, readModelPref(), harnessDefault);
167
+ // Session cwd (issue #96): explicit cordis.yml `cwd` wins; otherwise the
168
+ // git worktree root containing the launch directory (the launch directory
169
+ // itself outside any worktree), so `@` completion and mention expansion
170
+ // see the repository, not an arbitrary launch subdirectory. Resolved ONCE
171
+ // here — the agent meta and the channel must agree.
172
+ const requestedWorkspace = config.workspace ?? process.env.DSH_TUI_WORKSPACE_TARGET;
173
+ const initialWorkspace = requestedWorkspace === undefined
174
+ ? undefined
175
+ : await ctx.tuiWorkspaces.resolve(requestedWorkspace);
176
+ if (requestedWorkspace !== undefined && initialWorkspace === undefined) {
177
+ throw new Error(`dsh-tui: unsupported or unavailable workspace target: ${requestedWorkspace}`);
178
+ }
179
+ const sessionCwd = initialWorkspace?.cwd ?? resolveSessionCwd(config.cwd);
180
+ const meta = { cwd: sessionCwd };
120
181
  const { agent, handle, agentPreset, route: createdRoute } = await resolveAgent(ctx, config.sessionId, configuredRoute, startupRoute, meta, config.preset);
182
+ try {
183
+ // Opening a persisted TUI session is an explicit ownership action too.
184
+ // Older TUI versions only wrote the Session log, so attaching on every
185
+ // startup repairs those durable-but-ungrouped sessions idempotently.
186
+ const attached = await attachSessionToWorkspace(ctx, meta.cwd, agent.session.id);
187
+ if (!attached) {
188
+ ctx.logger.warn(`dsh-tui: session "${agent.session.id}" has no workspace ownership because workspaceRegistry is not mounted`);
189
+ }
190
+ }
191
+ catch (error) {
192
+ // The Session is already published and durable, matching Web's partial
193
+ // failure contract. Keep the TUI usable but make the missing ownership
194
+ // loud instead of silently leaving the conversation Ungrouped.
195
+ ctx.logger.warn(`dsh-tui: session "${agent.session.id}" workspace attachment failed: ${error instanceof Error ? error.message : String(error)}`);
196
+ }
121
197
  // Status-line route: the exact route the agent runs with — on create the
122
198
  // validated startup resolution, on resume the route the target session's
123
199
  // own records carry (a complete cordis.yml pin wins over them).
124
200
  const displayRoute = createdRoute ?? startupRoute;
125
201
  const channel = createChannel(ctx, agent, {
126
202
  model: displayRoute.model,
127
- cwd: config.cwd ?? process.cwd(),
203
+ // A RESUMED session keeps its persisted header cwd (issue #96 review):
204
+ // pre-upgrade sessions recorded the launch directory, and re-resolving
205
+ // from the current launch directory would split @ expansion / file
206
+ // completion (state.cwd) from the agent's own workspace record. Fresh
207
+ // sessions record sessionCwd at creation, so both agree there.
208
+ cwd: agent.session.header.cwd ?? sessionCwd,
128
209
  provider: displayRoute.provider,
129
210
  // Raw cordis.yml route (undefined when unset): the channel's
130
211
  // new-session path re-resolves prefs against these, and resume passes
@@ -142,6 +223,9 @@ export async function apply(ctx, config) {
142
223
  // persisted `/preset` choice; undefined adopts the roster default.
143
224
  configuredPreset: config.preset,
144
225
  agentPreset,
226
+ // Shift+Tab session-mode cycle (undefined → the built-in default/
227
+ // plan/full cycle in sessionModes.ts).
228
+ modes: config.modes,
145
229
  handle,
146
230
  });
147
231
  // DSH approval seam: the permission layer asks ApprovalService.request(),
@@ -189,66 +273,44 @@ export async function apply(ctx, config) {
189
273
  // Mirror the funnel's internal exited flag for the /update and
190
274
  // background-check guards that still read the outer one.
191
275
  exited = true;
192
- try {
193
- writeResumeTarget(channel.agentId);
194
- }
195
- catch {
196
- // Best effort — the resume marker is a launcher nicety; a stale
197
- // marker must never block a clean exit.
198
- }
199
- try {
200
- instance?.unmount();
201
- }
202
- catch {
203
- // The terminal state may already be gone (broken pipe, alt session);
204
- // the exit path must never throw.
205
- }
206
276
  if (error !== undefined) {
207
- // Error-driven unmount (render crash): stay loud and exit non-zero.
208
- // A success code + resume hint here would tell wrappers/CI the
209
- // session ended cleanly while the TUI actually crashed.
210
277
  const message = error instanceof Error ? error.message : String(error);
211
278
  ctx.logger.error(`dsh-tui: exit after error: ${message}`);
212
- if (process.stderr.isTTY) {
213
- process.stderr.write(`\ndsh-tui crashed: ${message}\n`);
214
- }
215
- disposeRootAndExit(ctx, 1);
279
+ void finishExit(ctx, instance, config.fullscreen === true, undefined, `dsh-tui crashed: ${message}`, () => disposeRootAndExit(ctx, 1));
216
280
  return;
217
281
  }
218
282
  if (updateRequested) {
219
- if (process.stdout.isTTY) {
220
- process.stdout.write('\nUpdating @deepseek-harness-tui/dsh-tui and restarting…\n');
283
+ try {
284
+ writeResumeTarget(channel.agentId);
285
+ }
286
+ catch {
287
+ // Resume persistence is best effort and must never block an update.
221
288
  }
222
- disposeRootAndThen(ctx, () => {
223
- // updateRequested only flips when onUpdate exists, which itself
224
- // requires a resolved profile — narrow for the call below.
225
- const updateProfile = profile;
226
- if (updateProfile === undefined) {
227
- process.stderr.write('\ndsh-tui update aborted: no dsh profile resolved.\n');
228
- process.exit(1);
229
- }
230
- void updateTuiAndRestart(channel.agentId, updateProfile).then(({ updateCode, restartCode }) => {
231
- if (updateCode !== 0) {
232
- // The session survives: its log lives in DSH persistence and
233
- // resume.txt was already written. A bare non-zero exit would
234
- // drop the user into a shell with no way back in.
235
- process.stderr.write(`\ndsh-tui update failed (exit ${updateCode}). Your session is preserved — resume with:\n` +
236
- `${resumeCommand(profile, channel.agentId)}\n\n`);
237
- }
238
- process.exit(restartCode);
239
- }, updateError => {
240
- const message = updateError instanceof Error ? updateError.message : String(updateError);
241
- process.stderr.write(`\ndsh-tui update failed: ${message}. Your session is preserved — resume with:\n` +
242
- `${resumeCommand(profile, channel.agentId)}\n\n`);
243
- process.exit(1);
244
- });
245
- });
289
+ void finishExit(ctx, instance, config.fullscreen === true, 'Updating @deepseek-harness-tui/dsh-tui and restarting…', undefined, () => runUpdate(ctx, profile, channel.agentId));
246
290
  return;
247
291
  }
248
- if (process.stdout.isTTY) {
249
- process.stdout.write(`\nResume with (set the env var, then boot the profile):\n${resumeCommand(profile, channel.agentId)}\n\n`);
292
+ // Judge against the live session behind the channel (channel.agentId),
293
+ // not the boot-time agent captured above: /resume, /new and /model swap
294
+ // the active agent, so the captured reference can go stale (see
295
+ // isExitResumable).
296
+ const resumable = isExitResumable({
297
+ pendingCount: channel.pending.length,
298
+ liveAgent: ctx.agents.get(SessionId(channel.agentId)),
299
+ startupAgent: agent,
300
+ });
301
+ try {
302
+ if (resumable)
303
+ writeResumeTarget(channel.agentId);
304
+ else
305
+ clearResumeTarget();
250
306
  }
251
- disposeRootAndExit(ctx, 0);
307
+ catch {
308
+ // Resume persistence is best effort and must never block shutdown.
309
+ }
310
+ const hint = resumable
311
+ ? `Resume with the command below:\n${resumeCommand(profile, channel.agentId)}`
312
+ : undefined;
313
+ void finishExit(ctx, instance, config.fullscreen === true, hint, undefined, () => disposeRootAndExit(ctx, 0));
252
314
  },
253
315
  });
254
316
  const handleExit = funnel.handleExit;
@@ -256,6 +318,9 @@ export async function apply(ctx, config) {
256
318
  channel,
257
319
  questionStore,
258
320
  approvalStore,
321
+ // The trajectory scene enters the alt screen itself in inline mode; in
322
+ // fullscreen the tree is already wrapped below, so it must not nest.
323
+ fullscreen: config.fullscreen === true,
259
324
  onExit: () => handleExit(),
260
325
  // Only a `dsh --profile <name>` launch has a profile installation for
261
326
  // `/update` to act on; source checkouts and `--config` overlays get the
@@ -278,7 +343,7 @@ export async function apply(ctx, config) {
278
343
  }
279
344
  channel.notify(t('update-starting'));
280
345
  updateRequested = true;
281
- instance?.unmount();
346
+ handleExit();
282
347
  });
283
348
  },
284
349
  });
@@ -343,6 +408,10 @@ async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRou
343
408
  return { agent: existing, agentPreset: runningPresetOf(existing.session) };
344
409
  }
345
410
  try {
411
+ // Compat boundary: register vouched-for legacy event types before the
412
+ // strict read path (issue #153) — same seam as the /resume picker,
413
+ // here for the launch-time --resume flow. In-process only.
414
+ ensureLegacySessionEventTypes();
346
415
  // The resumed session keeps the preset its log records (last
347
416
  // `agent-preset/selected` wins over the creation header), never the
348
417
  // caller's current preference.
@@ -430,6 +499,136 @@ export function createExitFunnel(deps) {
430
499
  },
431
500
  };
432
501
  }
502
+ /**
503
+ * Whether a user exit should leave the resume marker (and print the resume
504
+ * hint). Must be judged against the LIVE session behind the channel, not the
505
+ * boot-time agent apply() captured: /resume, /new and /model swap the active
506
+ * agent (channel.agentId follows, the old handle is disposed), so the
507
+ * captured reference can point at a stale session — wiping a marker the
508
+ * resume path just wrote (boot empty → /resume into history) or rewriting it
509
+ * to a fresh empty session (boot with history → /new). `liveAgent` is the
510
+ * registry lookup of channel.agentId; it falls back to the captured agent
511
+ * when the lookup misses. Exported for scripts/verify-exit-resume-marker.
512
+ */
513
+ export function isExitResumable(deps) {
514
+ const agent = deps.liveAgent ?? deps.startupAgent;
515
+ return (deps.pendingCount > 0 ||
516
+ agent.session.events.some(event => event.type === 'user/message' && event.data.source.kind === 'user'));
517
+ }
518
+ /** Finish terminal I/O before handing control to a process-level exit action. */
519
+ async function finishExit(ctx, instance, fullscreen, notice, stderrNotice, done) {
520
+ try {
521
+ const runtime = readInkShutdownState(instances.get(process.stdout));
522
+ if (runtime === undefined && instance !== undefined) {
523
+ ctx.logger.debug('dsh-tui: Ink runtime unavailable during shutdown; using generic terminal cleanup');
524
+ }
525
+ const cursor = fullscreen ? '' : cursorMoveToFrameEnd(runtime);
526
+ try {
527
+ runtime?.detachForShutdown?.();
528
+ }
529
+ catch {
530
+ ctx.logger.debug('dsh-tui: Ink shutdown detach failed; continuing with generic terminal cleanup');
531
+ }
532
+ const cleanup = [
533
+ fullscreen ? EXIT_ALT_SCREEN : '',
534
+ cursor,
535
+ DISABLE_MOUSE_TRACKING,
536
+ DISABLE_MODIFY_OTHER_KEYS,
537
+ DISABLE_KITTY_KEYBOARD,
538
+ DISABLE_WIN32_INPUT_MODE,
539
+ DFE,
540
+ DBP,
541
+ SHOW_CURSOR,
542
+ CLEAR_ITERM2_PROGRESS,
543
+ supportsTabStatus() ? wrapForMultiplexer(CLEAR_TAB_STATUS) : '',
544
+ ].join('');
545
+ const suffix = notice === undefined ? '' : `${notice}\n`;
546
+ await writeStream(process.stdout, `${cleanup}\r\n${suffix}`);
547
+ if (stderrNotice !== undefined) {
548
+ await writeStream(process.stderr, `\n${stderrNotice}\n`);
549
+ }
550
+ }
551
+ catch {
552
+ ctx.logger.debug('dsh-tui: terminal cleanup failed; continuing with process shutdown');
553
+ }
554
+ done();
555
+ }
556
+ function readInkShutdownState(value) {
557
+ if (value === null || typeof value !== 'object')
558
+ return undefined;
559
+ const candidate = value;
560
+ if (candidate.detachForShutdown !== undefined && typeof candidate.detachForShutdown !== 'function')
561
+ return undefined;
562
+ if (candidate.frontFrame !== undefined && !isFrameState(candidate.frontFrame))
563
+ return undefined;
564
+ if (candidate.displayCursor !== undefined && candidate.displayCursor !== null && !isCursorState(candidate.displayCursor))
565
+ return undefined;
566
+ return value;
567
+ }
568
+ function isFrameState(value) {
569
+ if (value === null || typeof value !== 'object')
570
+ return false;
571
+ const cursor = value.cursor;
572
+ return cursor === undefined || isCursorState(cursor);
573
+ }
574
+ function isCursorState(value) {
575
+ if (value === null || typeof value !== 'object')
576
+ return false;
577
+ const cursor = value;
578
+ return typeof cursor.x === 'number' && typeof cursor.y === 'number';
579
+ }
580
+ function cursorMoveToFrameEnd(runtime) {
581
+ const frame = runtime?.frontFrame?.cursor;
582
+ if (frame === undefined)
583
+ return '';
584
+ const parked = runtime?.displayCursor ?? frame;
585
+ return cursorMove(frame.x - parked.x, frame.y - parked.y);
586
+ }
587
+ function writeStream(stream, data) {
588
+ if (data.length === 0)
589
+ return Promise.resolve();
590
+ return new Promise(resolve => {
591
+ let settled = false;
592
+ const finish = () => {
593
+ if (settled)
594
+ return;
595
+ settled = true;
596
+ resolve();
597
+ };
598
+ const timer = setTimeout(finish, 1000);
599
+ timer.unref();
600
+ try {
601
+ stream.write(data, () => {
602
+ clearTimeout(timer);
603
+ finish();
604
+ });
605
+ }
606
+ catch {
607
+ clearTimeout(timer);
608
+ finish();
609
+ }
610
+ });
611
+ }
612
+ function runUpdate(ctx, profile, sessionId) {
613
+ disposeRootAndThen(ctx, () => {
614
+ if (profile === undefined) {
615
+ process.stderr.write(`\n${t('update-aborted-no-profile')}\n`);
616
+ process.exit(1);
617
+ }
618
+ void updateTuiAndRestart(sessionId, profile).then(({ updateCode, restartCode }) => {
619
+ if (updateCode !== 0) {
620
+ process.stderr.write(`\ndsh-tui update failed (exit ${updateCode}). Your session is preserved — resume with:\n` +
621
+ `${resumeCommand(profile, sessionId)}\n\n`);
622
+ }
623
+ process.exit(restartCode);
624
+ }, updateError => {
625
+ const message = updateError instanceof Error ? updateError.message : String(updateError);
626
+ process.stderr.write(`\ndsh-tui update failed: ${message}. Your session is preserved — resume with:\n` +
627
+ `${resumeCommand(profile, sessionId)}\n\n`);
628
+ process.exit(1);
629
+ });
630
+ });
631
+ }
433
632
  /**
434
633
  * Dispose the whole application before process exit, with a bounded fallback.
435
634
  * Mirrors the deleted dsh-tui front-door exit semantics.
@@ -440,15 +639,16 @@ function disposeRootAndExit(ctx, code) {
440
639
  /**
441
640
  * The real way back into a session after the TUI process is gone. The
442
641
  * package ships no `dsh-tui` bin — resuming means feeding the session id
443
- * through `DSH_CC_RESUME_SESSION` (what cordis.patch.yml's `sessionId` reads)
444
- * and booting the same profile; on Windows the repo's dsh-tui.cmd wrapper
445
- * does this via --resume + ~/.dsh-cc/resume.txt.
642
+ * through `DSH_TUI_RESUME_SESSION` (what cordis.patch.yml's `sessionId`
643
+ * reads; the pre-rename DSH_CC_ spelling still works, issue #120) and
644
+ * booting the same profile; on Windows the repo's dsh-tui.cmd wrapper
645
+ * does this via --resume + ~/.dsh-tui/resume.txt.
446
646
  */
447
647
  function resumeCommand(profile, sessionId) {
448
648
  const boot = profile === undefined ? 'dsh --config cordis.yml' : `dsh --profile ${profile}`;
449
649
  return process.platform === 'win32'
450
650
  ? `dsh-tui --resume ${sessionId}`
451
- : `DSH_CC_RESUME_SESSION=${sessionId} ${boot}`;
651
+ : `DSH_TUI_RESUME_SESSION=${sessionId} ${boot}`;
452
652
  }
453
653
  /**
454
654
  * Dispose the Cordis tree, then run a process-level handoff action. The
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAGzD,0EAA0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAA;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,+DAA+D;AAC/D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,IAAI,IAAI,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAAA;IAC3C,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAC9C,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAC/D,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAClE,yEAAyE;IACzE,UAAU,CAAC,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAC3D;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAEnE;AAED,kEAAkE;AAClE,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAmBhG;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAqB5G;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,MAAM,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChC,MAAM,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;CACnD,GAAG,MAAM,GAAG,SAAS,CAErB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAKpG"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * `/provider` wizard — interactively adds an LLM provider route at runtime.
3
+ *
4
+ * The wizard is a sequence of `QuestionStore` asks (the same panel the
5
+ * model-facing `ask_user_question` tool uses), so it needs no UI state of
6
+ * its own. All side effects go through {@link ProviderSetupHost}, which the
7
+ * channel implements over the dsh settings/credentials/llm seams:
8
+ *
9
+ * profile → settings `llm-pi-ai.providers.<route>` (dsh-llm-pi-ai watches
10
+ * the section and registers the route without a restart)
11
+ * key → credentials store (`~/.dsh/.credentials.yaml`, 0600), named by
12
+ * the derived `<ROUTE>_API_KEY` env-style ref the profile's
13
+ * `apiKeyEnv` points at
14
+ *
15
+ * The module is React-free so `scripts/verify-provider-wizard.mjs` can drive
16
+ * it headless with a stubbed host and scripted answers.
17
+ */
18
+ import { type AskUserQuestionAnswer, type AskUserQuestionRequest } from '@deepseek-ai/dsh-user-questions';
19
+ import type { LlmDiscoveredModel } from '@deepseek-ai/dsh-llm';
20
+ /** Route id rule shared with the dsh configuration surface (web Models page). */
21
+ export declare const PROVIDER_ROUTE_ID: RegExp;
22
+ /** Wire protocols dsh-llm-pi-ai can serve on a manually declared route. */
23
+ export declare const PROVIDER_PROTOCOLS: readonly ["openai-completions", "openai-responses", "anthropic-messages"];
24
+ /**
25
+ * Derive the credential ref for a route, matching the official web UI
26
+ * convention so TUI- and web-added providers resolve the same key.
27
+ */
28
+ export declare function deriveKeyRef(route: string): string;
29
+ /** One catalog route the mounted adapters offer for activation. */
30
+ export interface CatalogProviderCandidate {
31
+ readonly provider: string;
32
+ readonly displayName: string;
33
+ }
34
+ /**
35
+ * Runtime capabilities the wizard needs, implemented by the channel over
36
+ * `ctx.settings` / `ctx.credentials` / `ctx.llm`. `undefined` from
37
+ * `channel.providerSetup()` means the bare cordis.yml start (no dsh-base
38
+ * services) and the command refuses to run.
39
+ */
40
+ export interface ProviderSetupHost {
41
+ /** Catalog routes activatable via the `llm-pi-ai` settings section. */
42
+ listCatalogProviders(): readonly CatalogProviderCandidate[];
43
+ /** Whether a profile (any layer) already exists for the route. */
44
+ routeExists(route: string): boolean;
45
+ /** Interrogate a draft endpoint; the draft key is never persisted. */
46
+ discoverModels(request: {
47
+ provider?: string;
48
+ baseURL?: string;
49
+ api?: string;
50
+ apiKey?: string;
51
+ }): Promise<readonly LlmDiscoveredModel[]>;
52
+ /** Whether the process environment already provides this ref (shadow). */
53
+ envShadows(ref: string): boolean;
54
+ /**
55
+ * Read the currently stored value for rollback purposes; undefined when no
56
+ * credential exists under the ref. Only called when {@link envShadows} is
57
+ * false, so the value comes from a writable/seeded store, never the env.
58
+ */
59
+ readCredential(ref: string): Promise<string | undefined>;
60
+ /** Persist the key under the ref; rejects when env-shadowed or invalid. */
61
+ writeCredential(ref: string, value: string): void | Promise<void>;
62
+ /** Best-effort rollback of a just-written credential. */
63
+ removeCredential(ref: string): void | Promise<void>;
64
+ /**
65
+ * Persist the provider profile under `llm-pi-ai.providers.<route>`;
66
+ * rejects when the adapter's validation deems it unserviceable.
67
+ */
68
+ writeProfile(route: string, profile: Record<string, unknown>): Promise<void>;
69
+ }
70
+ export interface ProviderWizardDeps {
71
+ readonly host: ProviderSetupHost;
72
+ readonly ask: (request: AskUserQuestionRequest, options?: {
73
+ redact?: boolean;
74
+ }) => Promise<AskUserQuestionAnswer>;
75
+ readonly notify: (text: string, options?: {
76
+ color?: 'error' | 'warning' | 'success';
77
+ timeoutMs?: number;
78
+ }) => void;
79
+ readonly pushLocal: (title: string, lines: readonly string[]) => void;
80
+ /** Live turn state; the model-switch question is skipped while working. */
81
+ readonly working: () => boolean;
82
+ readonly switchModel: (provider: string, model: string) => Promise<boolean>;
83
+ }
84
+ export type ProviderWizardOutcome = 'added' | 'cancelled' | 'failed';
85
+ /**
86
+ * Run the add-provider wizard. Resolves 'cancelled' when the user dismisses
87
+ * any question (Esc) — nothing has been written at that point by design:
88
+ * all asks complete before the first side effect.
89
+ */
90
+ export declare function runProviderWizard(deps: ProviderWizardDeps): Promise<ProviderWizardOutcome>;
91
+ //# sourceMappingURL=providerWizard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providerWizard.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/providerWizard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAEL,KAAK,qBAAqB,EAE1B,KAAK,sBAAsB,EAC5B,MAAM,iCAAiC,CAAA;AACxC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,iFAAiF;AACjF,eAAO,MAAM,iBAAiB,QAAoC,CAAA;AAElE,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,2EAIrB,CAAA;AAEV;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,mEAAmE;AACnE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,uEAAuE;IACvE,oBAAoB,IAAI,SAAS,wBAAwB,EAAE,CAAA;IAC3D,kEAAkE;IAClE,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;IACnC,sEAAsE;IACtE,cAAc,CAAC,OAAO,EAAE;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,GAAG,OAAO,CAAC,SAAS,kBAAkB,EAAE,CAAC,CAAA;IAC1C,0EAA0E;IAC1E,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IAChC;;;;OAIG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IACxD,2EAA2E;IAC3E,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE,yDAAyD;IACzD,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7E;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAA;IAChC,QAAQ,CAAC,GAAG,EAAE,CACZ,OAAO,EAAE,sBAAsB,EAC/B,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAC3B,OAAO,CAAC,qBAAqB,CAAC,CAAA;IACnC,QAAQ,CAAC,MAAM,EAAE,CACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KACtE,IAAI,CAAA;IACT,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAA;IACrE,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAA;IAC/B,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAC5E;AAED,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,WAAW,GAAG,QAAQ,CAAA;AAgDpE;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,qBAAqB,CAAC,CA4MhC"}