@deepseek-harness-tui/dsh-tui 0.9.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. package/README.md +69 -256
  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 +6 -0
  26. package/lib/types/components/AutoRecapRow.d.ts +23 -0
  27. package/lib/types/components/AutoRecapRow.d.ts.map +1 -0
  28. package/lib/types/components/AutoRecapRow.js +23 -0
  29. package/lib/types/components/ColorPicker.d.ts +17 -0
  30. package/lib/types/components/ColorPicker.d.ts.map +1 -0
  31. package/lib/types/components/ColorPicker.js +20 -0
  32. package/lib/types/components/CommandSuggestions.d.ts +3 -1
  33. package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
  34. package/lib/types/components/ContextBarView.d.ts +33 -0
  35. package/lib/types/components/ContextBarView.d.ts.map +1 -0
  36. package/lib/types/components/ContextBarView.js +46 -0
  37. package/lib/types/components/EffortInputBorder.d.ts +12 -1
  38. package/lib/types/components/EffortInputBorder.d.ts.map +1 -1
  39. package/lib/types/components/EffortInputBorder.js +22 -5
  40. package/lib/types/components/FileActionsPanel.d.ts +22 -0
  41. package/lib/types/components/FileActionsPanel.d.ts.map +1 -0
  42. package/lib/types/components/FileActionsPanel.js +28 -0
  43. package/lib/types/components/FileSuggestions.d.ts +3 -1
  44. package/lib/types/components/FileSuggestions.d.ts.map +1 -1
  45. package/lib/types/components/MessageList.d.ts +3 -1
  46. package/lib/types/components/MessageList.d.ts.map +1 -1
  47. package/lib/types/components/MessageList.js +13 -6
  48. package/lib/types/components/ModelPicker.d.ts +26 -4
  49. package/lib/types/components/ModelPicker.d.ts.map +1 -1
  50. package/lib/types/components/ModelPicker.js +26 -6
  51. package/lib/types/components/PromptInput.d.ts.map +1 -1
  52. package/lib/types/components/PromptInput.js +365 -57
  53. package/lib/types/components/RecapPanel.d.ts +25 -0
  54. package/lib/types/components/RecapPanel.d.ts.map +1 -0
  55. package/lib/types/components/RecapPanel.js +55 -0
  56. package/lib/types/components/ScrollbarGutter.d.ts.map +1 -1
  57. package/lib/types/components/ScrollbarGutter.js +55 -4
  58. package/lib/types/components/SubagentCard.d.ts.map +1 -1
  59. package/lib/types/components/SubagentCard.js +6 -4
  60. package/lib/types/components/SuggestionCard.d.ts +4 -2
  61. package/lib/types/components/SuggestionCard.d.ts.map +1 -1
  62. package/lib/types/components/TimelineRail.d.ts.map +1 -1
  63. package/lib/types/components/TimelineRail.js +9 -2
  64. package/lib/types/components/design-system/ThemeProvider.d.ts +7 -0
  65. package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
  66. package/lib/types/components/design-system/ThemeProvider.js +2 -1
  67. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +8 -1
  68. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  69. package/lib/types/components/messages/AssistantToolUseMessage.js +36 -8
  70. package/lib/types/components/questions/AskUserQuestionPanel.d.ts +7 -3
  71. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  72. package/lib/types/components/questions/AskUserQuestionPanel.js +41 -9
  73. package/lib/types/dsh-adapter/channel.d.ts +101 -2
  74. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  75. package/lib/types/dsh-adapter/channel.js +969 -93
  76. package/lib/types/dsh-adapter/compat/index.d.ts +8 -6
  77. package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
  78. package/lib/types/dsh-adapter/compat/index.js +8 -6
  79. package/lib/types/dsh-adapter/compat/sessionLog.d.ts +150 -0
  80. package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
  81. package/lib/types/dsh-adapter/compat/sessionLog.js +518 -41
  82. package/lib/types/dsh-adapter/contract.d.ts +1 -1
  83. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  84. package/lib/types/dsh-adapter/contract.js +1 -0
  85. package/lib/types/dsh-adapter/extension-events.d.ts +1 -1
  86. package/lib/types/dsh-adapter/extension-events.d.ts.map +1 -1
  87. package/lib/types/dsh-adapter/index.d.ts +10 -0
  88. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  89. package/lib/types/dsh-adapter/index.js +5 -0
  90. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  91. package/lib/types/dsh-adapter/plugin.js +317 -8
  92. package/lib/types/dsh-adapter/presets.d.ts +18 -0
  93. package/lib/types/dsh-adapter/presets.d.ts.map +1 -1
  94. package/lib/types/dsh-adapter/presets.js +31 -0
  95. package/lib/types/dsh-adapter/providerWizard.d.ts +29 -1
  96. package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
  97. package/lib/types/dsh-adapter/providerWizard.js +89 -5
  98. package/lib/types/dsh-adapter/questions.d.ts +19 -2
  99. package/lib/types/dsh-adapter/questions.d.ts.map +1 -1
  100. package/lib/types/dsh-adapter/questions.js +53 -10
  101. package/lib/types/dsh-adapter/recap.d.ts +49 -0
  102. package/lib/types/dsh-adapter/recap.d.ts.map +1 -0
  103. package/lib/types/dsh-adapter/recap.js +121 -0
  104. package/lib/types/dsh-adapter/sessionTree.d.ts +314 -0
  105. package/lib/types/dsh-adapter/sessionTree.d.ts.map +1 -0
  106. package/lib/types/dsh-adapter/sessionTree.js +954 -0
  107. package/lib/types/dsh-adapter/shortcuts.d.ts +15 -44
  108. package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -1
  109. package/lib/types/dsh-adapter/shortcuts.js +28 -165
  110. package/lib/types/dsh-adapter/types.d.ts +1 -1
  111. package/lib/types/dsh-adapter/types.d.ts.map +1 -1
  112. package/lib/types/herdr.js +1 -1
  113. package/lib/types/i18n.d.ts +604 -176
  114. package/lib/types/i18n.d.ts.map +1 -1
  115. package/lib/types/i18n.js +206 -72
  116. package/lib/types/ink/log-update.d.ts.map +1 -1
  117. package/lib/types/ink/log-update.js +21 -0
  118. package/lib/types/migrationPrefs.d.ts +60 -0
  119. package/lib/types/migrationPrefs.d.ts.map +1 -0
  120. package/lib/types/migrationPrefs.js +97 -0
  121. package/lib/types/modelGroups.d.ts +72 -0
  122. package/lib/types/modelGroups.d.ts.map +1 -0
  123. package/lib/types/modelGroups.js +97 -0
  124. package/lib/types/modelRecents.d.ts +39 -0
  125. package/lib/types/modelRecents.d.ts.map +1 -0
  126. package/lib/types/modelRecents.js +97 -0
  127. package/lib/types/native-ts/yoga-layout/index.d.ts +11 -0
  128. package/lib/types/native-ts/yoga-layout/index.d.ts.map +1 -1
  129. package/lib/types/native-ts/yoga-layout/index.js +31 -1
  130. package/lib/types/oauth.d.ts +15 -0
  131. package/lib/types/oauth.d.ts.map +1 -0
  132. package/lib/types/oauth.js +14 -0
  133. package/lib/types/plugin-spec/registry.d.ts +1 -1
  134. package/lib/types/plugin-spec/registry.js +1 -1
  135. package/lib/types/reload.d.ts +109 -0
  136. package/lib/types/reload.d.ts.map +1 -0
  137. package/lib/types/reload.js +118 -0
  138. package/lib/types/screens/Chat.d.ts +3 -1
  139. package/lib/types/screens/Chat.d.ts.map +1 -1
  140. package/lib/types/screens/Chat.js +588 -64
  141. package/lib/types/screens/SessionTree.d.ts +27 -0
  142. package/lib/types/screens/SessionTree.d.ts.map +1 -0
  143. package/lib/types/screens/SessionTree.js +555 -0
  144. package/lib/types/screens/StatusLine.d.ts +0 -9
  145. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  146. package/lib/types/screens/StatusLine.js +215 -52
  147. package/lib/types/screens/StatusMetrics.d.ts +35 -3
  148. package/lib/types/screens/StatusMetrics.d.ts.map +1 -1
  149. package/lib/types/screens/StatusMetrics.js +63 -8
  150. package/lib/types/screens/chatOverlay.d.ts +17 -1
  151. package/lib/types/screens/chatOverlay.d.ts.map +1 -1
  152. package/lib/types/screens/chatOverlay.js +3 -1
  153. package/lib/types/tips.d.ts.map +1 -1
  154. package/lib/types/tips.js +22 -4
  155. package/lib/types/update.d.ts +159 -0
  156. package/lib/types/update.d.ts.map +1 -1
  157. package/lib/types/update.js +496 -30
  158. package/lib/types/utils/debug.d.ts +1 -1
  159. package/lib/types/utils/debug.js +3 -3
  160. package/lib/types/utils/fileTarget.d.ts +46 -0
  161. package/lib/types/utils/fileTarget.d.ts.map +1 -0
  162. package/lib/types/utils/fileTarget.js +178 -0
  163. package/lib/types/utils/keymap.d.ts +134 -0
  164. package/lib/types/utils/keymap.d.ts.map +1 -0
  165. package/lib/types/utils/keymap.js +311 -0
  166. package/lib/types/utils/mentions.d.ts +25 -2
  167. package/lib/types/utils/mentions.d.ts.map +1 -1
  168. package/lib/types/utils/mentions.js +69 -10
  169. package/lib/types/utils/openExternal.d.ts +50 -0
  170. package/lib/types/utils/openExternal.d.ts.map +1 -0
  171. package/lib/types/utils/openExternal.js +170 -0
  172. package/node_modules/@deepseek-harness-tui/dsh-auth/LICENSE +21 -0
  173. package/node_modules/@deepseek-harness-tui/dsh-auth/README.md +140 -0
  174. package/node_modules/@deepseek-harness-tui/dsh-auth/cordis.patch.yml +11 -0
  175. package/node_modules/@deepseek-harness-tui/dsh-auth/dsh-plugin.json +44 -0
  176. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/command.d.ts +14 -0
  177. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/command.js +67 -0
  178. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/credentials.d.ts +64 -0
  179. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/credentials.js +170 -0
  180. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/index.d.ts +79 -0
  181. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/index.js +196 -0
  182. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.d.ts +68 -0
  183. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.js +193 -0
  184. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/opener.d.ts +32 -0
  185. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/opener.js +101 -0
  186. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/profiles.d.ts +31 -0
  187. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/profiles.js +68 -0
  188. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/service.d.ts +69 -0
  189. package/node_modules/@deepseek-harness-tui/dsh-auth/lib/service.js +129 -0
  190. package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +70 -0
  191. package/node_modules/@dsh-std/command/CHANGELOG.md +8 -8
  192. package/node_modules/@dsh-std/command/LICENSE +21 -21
  193. package/node_modules/@dsh-std/command/README.md +26 -26
  194. package/node_modules/@dsh-std/command/README.zh.md +28 -28
  195. package/node_modules/@dsh-std/command/lib/index.js.map +1 -1
  196. package/node_modules/@dsh-std/command/package.json +22 -22
  197. package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  198. package/node_modules/@dsh-std/connection/LICENSE +21 -21
  199. package/node_modules/@dsh-std/connection/README.md +42 -42
  200. package/node_modules/@dsh-std/connection/README.zh.md +42 -42
  201. package/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  202. package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  203. package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  204. package/node_modules/@dsh-std/connection/package.json +20 -20
  205. package/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  206. package/node_modules/@dsh-std/core/LICENSE +21 -21
  207. package/node_modules/@dsh-std/core/README.md +13 -13
  208. package/node_modules/@dsh-std/core/README.zh.md +13 -13
  209. package/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  210. package/node_modules/@dsh-std/core/package.json +21 -21
  211. package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
  212. package/node_modules/@dsh-std/manifest/LICENSE +21 -21
  213. package/node_modules/@dsh-std/manifest/README.md +5 -5
  214. package/node_modules/@dsh-std/manifest/README.zh.md +5 -5
  215. package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
  216. package/node_modules/@dsh-std/manifest/package.json +20 -20
  217. package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
  218. package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -8
  219. package/node_modules/@dsh-std/messages/LICENSE +21 -21
  220. package/node_modules/@dsh-std/messages/README.md +5 -5
  221. package/node_modules/@dsh-std/messages/README.zh.md +7 -7
  222. package/node_modules/@dsh-std/messages/lib/index.js.map +1 -1
  223. package/node_modules/@dsh-std/messages/package.json +20 -20
  224. package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -54
  225. package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
  226. package/node_modules/@dsh-std/presentation/LICENSE +21 -21
  227. package/node_modules/@dsh-std/presentation/README.md +27 -27
  228. package/node_modules/@dsh-std/presentation/README.zh.md +29 -29
  229. package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
  230. package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  231. package/node_modules/@dsh-std/presentation/package.json +25 -25
  232. package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -8
  233. package/node_modules/@dsh-std/storage/LICENSE +21 -21
  234. package/node_modules/@dsh-std/storage/README.md +5 -5
  235. package/node_modules/@dsh-std/storage/README.zh.md +7 -7
  236. package/node_modules/@dsh-std/storage/lib/index.js.map +1 -1
  237. package/node_modules/@dsh-std/storage/package.json +20 -20
  238. package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -56
  239. package/package.json +17 -5
  240. package/presets/liangshen/.dsh-tui-managed.json +1 -1
  241. package/presets/liangshen/instruction-hint.mjs +8 -0
  242. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  243. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -21
  244. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -42
  245. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -42
  246. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  247. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  248. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  249. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -20
  250. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  251. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -21
  252. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -13
  253. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -13
  254. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  255. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -21
  256. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
  257. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -21
  258. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -5
  259. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -5
  260. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
  261. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -20
  262. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
  263. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
  264. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -21
  265. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -27
  266. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -29
  267. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
  268. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
  269. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -25
  270. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  271. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -21
  272. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -13
  273. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -13
  274. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  275. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -21
  276. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  277. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -21
  278. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -13
  279. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -13
  280. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  281. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -21
  282. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  283. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -21
  284. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -13
  285. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -13
  286. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  287. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -21
  288. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
  289. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -21
  290. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -42
  291. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -42
  292. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
  293. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
  294. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
  295. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -20
  296. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  297. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -21
  298. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -13
  299. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -13
  300. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  301. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -21
  302. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
  303. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -21
  304. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -13
  305. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -13
  306. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -1
  307. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -21
@@ -1,5 +1,6 @@
1
1
  import Schema from '@deepseek-ai/schemastery';
2
2
  import { DEFAULT_STATUS_BAR } from '../tuiDisplayPrefs.js';
3
+ import { SHORTCUT_ACTIONS } from '../utils/keymap.js';
3
4
  export const name = 'dsh-tui';
4
5
  // `tuiWorkspaces` must stay OUT of this code-level inject (issue #183): the
5
6
  // dsh CLI resolves the bundle's cordis.patch.yml from the FIRST copy of this
@@ -32,6 +33,7 @@ export const Config = Schema.object({
32
33
  thinkingFold: Schema.union(['preview', 'full']).default('preview'),
33
34
  toolBackground: Schema.union(['none', 'subtle', 'strong']).default('none'),
34
35
  scrollGutter: Schema.union(['timeline', 'scrollbar', 'hidden']).default('timeline'),
36
+ promptSessionLabel: Schema.boolean().default(false),
35
37
  statusBar: Schema.object({
36
38
  compact: Schema.boolean().default(DEFAULT_STATUS_BAR.compact),
37
39
  model: Schema.boolean().default(DEFAULT_STATUS_BAR.model),
@@ -51,6 +53,9 @@ export const Config = Schema.object({
51
53
  trajectory: Schema.boolean().default(DEFAULT_STATUS_BAR.trajectory),
52
54
  shortcutHint: Schema.boolean().default(DEFAULT_STATUS_BAR.shortcutHint),
53
55
  }).default({ ...DEFAULT_STATUS_BAR }),
56
+ // One optional combo string per customizable action (no defaults: unset
57
+ // keeps the built-in binding; see Config.shortcuts).
58
+ shortcuts: Schema.object(Object.fromEntries(SHORTCUT_ACTIONS.map(action => [action.id, Schema.string().required(false)]))).required(false),
54
59
  modes: Schema.array(Schema.object({
55
60
  id: Schema.string(),
56
61
  label: Schema.string().required(false),
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/plugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,wBAAwB,CAAA;AAGhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AA6DnC,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAm8BvE;AA6GD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,GAAG;IACjF,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB,CAcA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,KAAK,GAAG,SAAS,CAAA;IAC5B,YAAY,EAAE,KAAK,CAAA;CACpB,GAAG,OAAO,CAQV"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/plugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAe,MAAM,wBAAwB,CAAA;AAGhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAsEnC,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAitCvE;AAsHD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,GAAG;IACjF,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB,CAcA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,KAAK,GAAG,SAAS,CAAA;IAC5B,YAAY,EAAE,KAAK,CAAA;CACpB,GAAG,OAAO,CAQV"}
@@ -13,17 +13,19 @@ import { ApprovalStore } from './approvals.js';
13
13
  import { registerPackagedSkills } from './packaged-skills.js';
14
14
  import { registerPromptDebug } from './promptDebug.js';
15
15
  import { readActivityFrames } from '../activityPrefs.js';
16
+ import { commitFullscreenFactoryMigration, planFullscreenFactoryMigration, readAppliedMigrations } from '../migrationPrefs.js';
16
17
  import { readModelPref } from '../modelPrefs.js';
17
18
  import { explicitModelRoute, recordedModelRoute, resolveModelRoute, validateModelRoute } from '../modelRoute.js';
18
19
  import { readPresetPref } from '../presetPrefs.js';
19
- import { composePreset, filterMinimalPresetTools, resolvePersistedPreset, runningPresetOf } from './presets.js';
20
+ import { composePreset, filterMinimalPresetTools, resolvePersistedPreset, resolvePersistedRoute, runningPresetOf } from './presets.js';
20
21
  import { ensurePackagedPresets } from './packaged-presets.js';
21
22
  import { ensureLegacySessionEventTypes } from './compat/index.js';
22
23
  import { clearResumeTarget, writeResumeTarget } from '../sessionHistory.js';
23
24
  import { resolveSessionCwd } from '../utils/workspaceRoot.js';
24
- import { checkForTuiUpdate, installedTuiVersion, isBootDeadlockTarget, isVersionNewer, resolveDshProfileName, resolveTuiUpdateTarget, updateTuiAndRestart } from '../update.js';
25
+ import { beginRestartAttempt, checkForTuiUpdate, installedTuiVersion, isBootDeadlockTarget, isVersionNewer, logRestartEvent, resolveDshProfileName, resolveTuiUpdateTarget, restartTui, updateTuiAndRestart, writeHandoffNotice } from '../update.js';
25
26
  import { getLang, isLang, resolveStartupLang, setLang, t, writeLangPref } from '../i18n.js';
26
27
  import { DEFAULT_STATUS_BAR, normalizeScrollGutter, normalizeStatusBar, normalizeToolBackground } from '../tuiDisplayPrefs.js';
28
+ import { draftComboConflicts, effectiveComboString, parseComboDraft, setKeymapOverrides, SHORTCUT_ACTIONS, } from '../utils/keymap.js';
27
29
  import { detectLegacyEnv, migrateLegacyDataDir, RENAMED_ENV } from '../utils/paths.js';
28
30
  import { attachHerdrIntegration } from '../herdr.js';
29
31
  import { logMouseDebug } from '../utils/debug.js';
@@ -63,7 +65,65 @@ import { CLEAR_ITERM2_PROGRESS, CLEAR_TAB_STATUS, supportsTabStatus, wrapForMult
63
65
  */
64
66
  let lastBootedFullscreen;
65
67
  export async function apply(ctx, config) {
68
+ // /restart handoff diagnosis: the replacement process is marked by env and
69
+ // logs its boot progress to ~/.dsh-tui/restart.log (ordinary launches stay
70
+ // silent). First line lands before anything in this function can throw.
71
+ if (process.env.DSH_TUI_RESTART_CHILD === '1') {
72
+ logRestartEvent('boot: plugin apply', {
73
+ stdoutTty: process.stdout.isTTY === true,
74
+ stdinTty: process.stdin.isTTY === true,
75
+ stderrTty: process.stderr.isTTY === true,
76
+ });
77
+ // Field evidence (2026-08-24): the restarted TUI mounts but takes no
78
+ // input, and the terminal's DA reply surfaced on PS's prompt line in an
79
+ // earlier attempt — meaning NO process was reading console input. Probe
80
+ // whether THIS process's stdin pump ever sees bytes: wrap read()
81
+ // transparently (delegates; purely observational) and sample the pump
82
+ // state, so the log distinguishes "bytes never arrive" (console-level
83
+ // theft/mode) from "bytes arrive but the UI ignores them".
84
+ const probedStdin = process.stdin;
85
+ const originalRead = probedStdin.read.bind(probedStdin);
86
+ let loggedChunks = 0;
87
+ probedStdin.read = ((...args) => {
88
+ const chunk = originalRead(...args);
89
+ if (chunk !== null && chunk !== '' && loggedChunks < 12) {
90
+ loggedChunks += 1;
91
+ const text = String(chunk);
92
+ logRestartEvent('boot: stdin chunk arrived', {
93
+ bytes: text.length,
94
+ preview: text.slice(0, 24).replace(/[^\x20-\x7e]/g, '.'),
95
+ });
96
+ }
97
+ return chunk;
98
+ });
99
+ const sampleStdinState = (label) => {
100
+ logRestartEvent(`boot: ${label}`, {
101
+ isRaw: probedStdin.isRaw === true,
102
+ readableListeners: probedStdin.listenerCount('readable'),
103
+ dataListeners: probedStdin.listenerCount('data'),
104
+ paused: probedStdin.isPaused,
105
+ buffered: probedStdin.readableLength,
106
+ chunksSeen: loggedChunks,
107
+ });
108
+ };
109
+ sampleStdinState('stdin state at plugin apply');
110
+ let pendingSamples = 0;
111
+ const sampleAt = (delayMs, label) => {
112
+ pendingSamples += 1;
113
+ const timer = setTimeout(() => {
114
+ pendingSamples -= 1;
115
+ sampleStdinState(label);
116
+ }, delayMs);
117
+ timer.unref?.();
118
+ };
119
+ sampleAt(2000, 'stdin state +2s');
120
+ sampleAt(5000, 'stdin state +5s');
121
+ sampleAt(12000, 'stdin state +12s');
122
+ }
66
123
  if (!process.stdout.isTTY) {
124
+ if (process.env.DSH_TUI_RESTART_CHILD === '1') {
125
+ logRestartEvent('boot: TTY gate failed - stdout is not a TTY');
126
+ }
67
127
  throw new Error('dsh-tui requires an interactive terminal (stdout must be a TTY).');
68
128
  }
69
129
  // The official profile launcher owns the system preset root and replaces
@@ -324,6 +384,10 @@ export async function apply(ctx, config) {
324
384
  // only explicit values so the target session's own record wins.
325
385
  configuredModel: config.model,
326
386
  configuredProvider: config.provider,
387
+ // Raw cordis.yml `lang` / `activityFrames`: /reload must not override a
388
+ // static deployment choice with the persisted preference.
389
+ configuredLang: config.lang,
390
+ configuredActivityFrames: config.activityFrames,
327
391
  effort: config.effort,
328
392
  activity: config.activity,
329
393
  // Explicit cordis.yml value (static deployment choice) wins over the
@@ -344,6 +408,7 @@ export async function apply(ctx, config) {
344
408
  thinkingFold: config.thinkingFold,
345
409
  toolBackground: config.toolBackground,
346
410
  scrollGutter: config.scrollGutter,
411
+ promptSessionLabel: config.promptSessionLabel,
347
412
  statusBar: config.statusBar,
348
413
  handle,
349
414
  });
@@ -373,11 +438,13 @@ export async function apply(ctx, config) {
373
438
  // user layer in settings.yaml wins over cordis.yml's diffLayout, and
374
439
  // watch() lands commits on the live channel — no recompose needed.
375
440
  ctx.inject(['settings'], (settingsCtx) => {
376
- const scope = settingsCtx.settings.register(settingsNamespace('dsh-tui'), Schema.object({
441
+ const tuiSettingsNs = settingsNamespace('dsh-tui');
442
+ const scope = settingsCtx.settings.register(tuiSettingsNs, Schema.object({
377
443
  diffLayout: Schema.union(['auto', 'split', 'unified']).default('auto'),
378
444
  thinkingFold: Schema.union(['preview', 'full']).default('preview'),
379
445
  toolBackground: Schema.union(['none', 'subtle', 'strong']).default('none'),
380
446
  scrollGutter: Schema.union(['timeline', 'scrollbar', 'hidden']).default('timeline'),
447
+ promptSessionLabel: Schema.boolean().default(false),
381
448
  statusBar: Schema.object({
382
449
  compact: Schema.boolean().default(DEFAULT_STATUS_BAR.compact),
383
450
  model: Schema.boolean().default(DEFAULT_STATUS_BAR.model),
@@ -409,6 +476,10 @@ export async function apply(ctx, config) {
409
476
  // Same no-default rule: unset keeps cordis.yml's `fullscreen`
410
477
  // decisive; set overrides it from the next boot on.
411
478
  fullscreen: Schema.boolean(),
479
+ // Built-in action-shortcut overrides, one optional combo string per
480
+ // action (see src/utils/keymap.ts). Unset keeps the default binding
481
+ // and the section's format() shows the effective combos.
482
+ shortcuts: Schema.object(Object.fromEntries(SHORTCUT_ACTIONS.map(action => [action.id, Schema.string().required(false)]))).required(false),
412
483
  }));
413
484
  const applyLayout = (value) => {
414
485
  channel.setDiffLayout(value.diffLayout ?? config.diffLayout ?? 'auto');
@@ -445,17 +516,57 @@ export async function apply(ctx, config) {
445
516
  channel.setThinkingFold(value.thinkingFold ?? config.thinkingFold ?? 'preview');
446
517
  channel.setToolBackground(normalizeToolBackground(value.toolBackground ?? config.toolBackground));
447
518
  channel.setScrollGutter(normalizeScrollGutter(value.scrollGutter ?? config.scrollGutter));
519
+ channel.setPromptSessionLabel(value.promptSessionLabel ?? config.promptSessionLabel ?? false);
448
520
  channel.setStatusBar(normalizeStatusBar(value.statusBar ?? config.statusBar));
449
521
  };
522
+ // Shortcut overrides resolve per action: settings user layer wins over
523
+ // cordis.yml's `shortcuts` (same precedence as every other field);
524
+ // unset everywhere keeps the registry default. Applied live into the
525
+ // keymap module — the very next keypress matches the new combos.
526
+ const applyShortcuts = (value) => {
527
+ const userLayer = value.shortcuts ?? {};
528
+ const configLayer = config.shortcuts ?? {};
529
+ const merged = {};
530
+ for (const action of SHORTCUT_ACTIONS) {
531
+ const user = userLayer[action.id];
532
+ const pinned = configLayer[action.id];
533
+ const chosen = typeof user === 'string' && user.trim() !== ''
534
+ ? user
535
+ : (typeof pinned === 'string' && pinned.trim() !== '' ? pinned : undefined);
536
+ if (chosen !== undefined)
537
+ merged[action.id] = chosen;
538
+ }
539
+ setKeymapOverrides(merged);
540
+ };
450
541
  const apply = (next) => {
451
542
  applyLayout(next);
452
543
  applyWhale(next);
453
544
  applyMinimal(next);
454
545
  applyLang(next);
455
546
  applyDisplay(next);
547
+ applyShortcuts(next);
456
548
  applyFullscreen(next);
457
549
  };
458
- apply(scope.get());
550
+ // One-time fullscreen factory-default migration (companion to the
551
+ // schema + cordis.patch.yml flip false→true): a `fullscreen: false`
552
+ // pinned in the settings user layer BEFORE the flip keeps overriding
553
+ // the new default on every boot. The first boot past this code clears
554
+ // that stale explicit choice; the migrations.json marker makes it
555
+ // strictly once, so a `false` re-pinned afterwards always stands. The
556
+ // boot decision cannot wait for the async doc write — the stale value
557
+ // is shadowed out of the first apply below (destructuring omission,
558
+ // not an explicit undefined), and the later watch commit (fullscreen
559
+ // back to undefined) is a no-op for applyFullscreen.
560
+ const bootSettings = scope.get();
561
+ const fullscreenMigration = planFullscreenFactoryMigration(bootSettings.fullscreen, readAppliedMigrations());
562
+ void commitFullscreenFactoryMigration(fullscreenMigration, {
563
+ unset: () => settingsCtx.settings.mutate(tuiSettingsNs, [{ op: 'unset', path: ['fullscreen'] }]),
564
+ });
565
+ if (fullscreenMigration === 'unset') {
566
+ channel.notify(t('settings-fullscreen-migrated'), { color: 'warning' });
567
+ }
568
+ const { fullscreen: staleFullscreen, ...migratedSettings } = bootSettings;
569
+ apply(fullscreenMigration === 'unset' ? migratedSettings : bootSettings);
459
570
  scope.watch(next => {
460
571
  apply(next);
461
572
  if (typeof next.fullscreen === 'boolean' && next.fullscreen !== bootedFullscreen) {
@@ -468,12 +579,109 @@ export async function apply(ctx, config) {
468
579
  // the settings registration above, and the declared selects write `lang`
469
580
  // and `diffLayout` back through the settings service's revision-fenced
470
581
  // mutate (the watch applies both live).
582
+ //
583
+ // Shortcut fields: one text field per customizable action. The draft is
584
+ // one or more ctrl+/alt+ combos (comma-separated); blank restores the
585
+ // default, and a combo another action or a fixed editor binding already
586
+ // owns is refused as invalid so remaps can never silently shadow.
587
+ const shortcutFieldMeta = {
588
+ paste: {
589
+ label: 'Paste shortcut',
590
+ zh: '粘贴快捷键',
591
+ hintEn: d => `Clipboard paste (text, file paths, images). Default: ${d}. Alt+V works where the terminal eats Ctrl+V.`,
592
+ hintZh: d => `剪贴板粘贴(文本、文件路径、图片)。默认 ${d}。终端吞掉 Ctrl+V 时可用 Alt+V。`,
593
+ },
594
+ history: {
595
+ label: 'History search shortcut',
596
+ zh: '历史搜索快捷键',
597
+ hintEn: d => `Open the prompt-history search. Default: ${d}.`,
598
+ hintZh: d => `打开输入历史搜索。默认 ${d}。`,
599
+ },
600
+ editor: {
601
+ label: 'External editor shortcut',
602
+ zh: '外部编辑器快捷键',
603
+ hintEn: d => `Edit the draft in $VISUAL/$EDITOR. Default: ${d}.`,
604
+ hintZh: d => `在 $VISUAL/$EDITOR 外部编辑器中编辑草稿。默认 ${d}。`,
605
+ },
606
+ transcript: {
607
+ label: 'Transcript mode shortcut',
608
+ zh: '转录模式快捷键',
609
+ hintEn: d => `Toggle expanded transcript mode. Default: ${d}.`,
610
+ hintZh: d => `切换展开转录模式。默认 ${d}。`,
611
+ },
612
+ trajectory: {
613
+ label: 'Trajectory scene shortcut',
614
+ zh: '轨迹场景快捷键',
615
+ hintEn: d => `Open the trajectory scene. Default: ${d}.`,
616
+ hintZh: d => `打开轨迹场景。默认 ${d}。`,
617
+ },
618
+ dashboard: {
619
+ label: 'Subagent dashboard shortcut',
620
+ zh: '子代理面板快捷键',
621
+ hintEn: d => `Open the subagent dashboard. Default: ${d}.`,
622
+ hintZh: d => `打开子代理面板。默认 ${d}。`,
623
+ },
624
+ contextPanel: {
625
+ label: 'Loaded-context panel shortcut',
626
+ zh: '加载上下文面板快捷键',
627
+ hintEn: d => `Toggle the startup loaded-context panel. Default: ${d}.`,
628
+ hintZh: d => `切换启动时的已加载上下文面板。默认 ${d}。`,
629
+ },
630
+ showAll: {
631
+ label: 'Show-all shortcut',
632
+ zh: '显示全部消息快捷键',
633
+ hintEn: d => `Toggle show-all-messages. Default: ${d}.`,
634
+ hintZh: d => `切换显示全部消息。默认 ${d}。`,
635
+ },
636
+ redraw: {
637
+ label: 'Redraw shortcut',
638
+ zh: '终端重绘快捷键',
639
+ hintEn: d => `Clear and repaint the terminal. Default: ${d}.`,
640
+ hintZh: d => `清空并重绘终端。默认 ${d}。`,
641
+ },
642
+ todoFold: {
643
+ label: 'Todo fold shortcut',
644
+ zh: '待办折叠快捷键',
645
+ hintEn: d => `Fold/unfold the goal/todo panel. Default: ${d}.`,
646
+ hintZh: d => `折叠/展开目标与待办面板。默认 ${d}。`,
647
+ },
648
+ };
649
+ const shortcutFields = SHORTCUT_ACTIONS.map(action => {
650
+ const meta = shortcutFieldMeta[action.id];
651
+ const defaults = action.defaults.join(', ');
652
+ return {
653
+ path: ['shortcuts', action.id],
654
+ label: meta.label,
655
+ descriptions: { zh: meta.zh },
656
+ hint: meta.hintEn(defaults),
657
+ hintDescriptions: { zh: meta.hintZh(defaults) },
658
+ group: 'shortcuts',
659
+ kind: 'text',
660
+ format(value) {
661
+ return typeof value === 'string' && value.trim() !== '' ? value : effectiveComboString(action.id);
662
+ },
663
+ parse(text) {
664
+ const draft = parseComboDraft(text);
665
+ if (draft === undefined)
666
+ return undefined;
667
+ if (draft.combos.length === 0)
668
+ return { kind: 'clear' };
669
+ if (draftComboConflicts(action.id, draft.combos))
670
+ return undefined;
671
+ return { kind: 'set', value: draft.combos.join(', ') };
672
+ },
673
+ };
674
+ });
471
675
  const settingsSections = getHostSettingsSections(ctx.get('tuiSettingsSections'));
472
676
  if (settingsSections !== undefined) {
473
677
  const unregister = settingsSections.register({
474
678
  ns: 'dsh-tui',
475
679
  title: 'dsh-tui',
476
- groups: [{ id: 'status-bar', title: 'Status bar', descriptions: { zh: '底栏设置' } }],
680
+ groups: [
681
+ { id: 'status-bar', title: 'Status bar', descriptions: { zh: '底栏设置' } },
682
+ { id: 'shortcuts', title: 'Shortcuts', descriptions: { zh: '快捷键' } },
683
+ { id: 'session', title: 'Session', descriptions: { zh: '会话' } },
684
+ ],
477
685
  fields: [
478
686
  {
479
687
  path: ['lang'],
@@ -560,6 +768,27 @@ export async function apply(ctx, config) {
560
768
  { value: 'hidden', label: 'Hidden', descriptions: { zh: '隐藏' } },
561
769
  ],
562
770
  },
771
+ {
772
+ path: ['promptSessionLabel'],
773
+ label: 'Session name chip',
774
+ descriptions: { zh: '会话名标签' },
775
+ hint: 'Show the session name on the prompt top border, right corner. Off by default.',
776
+ hintDescriptions: { zh: '在输入框顶边框右上角显示会话名。默认关闭。' },
777
+ kind: 'boolean',
778
+ },
779
+ {
780
+ path: ['recapOnOpen'],
781
+ label: 'Auto recap on open',
782
+ descriptions: { zh: '打开会话时自动总结' },
783
+ hint: 'On: opening/resuming a session automatically summarizes its recent activity into a dim line at the bottom of the transcript (hover/click to view or apply the suggested title). Off: use /recap manually.',
784
+ hintDescriptions: { zh: '开启:打开/恢复会话时自动把最近活动总结成一行灰字显示在会话底部(可悬停/点击查看或应用建议标题);关闭:手动使用 /recap。' },
785
+ kind: 'boolean',
786
+ format(value) {
787
+ // Unset in settings.yaml: the default is on.
788
+ return value === undefined || value === null ? 'true' : String(value);
789
+ },
790
+ },
791
+ ...shortcutFields,
563
792
  {
564
793
  path: ['statusBar', 'compact'],
565
794
  label: 'Compact status bar',
@@ -782,6 +1011,10 @@ export async function apply(ctx, config) {
782
1011
  let exited = false;
783
1012
  let updateRequested = false;
784
1013
  let updateTargetVersion;
1014
+ // `/restart` flag: same exit funnel as `/update` minus the pnpm step —
1015
+ // write the resume target, restore the terminal, respawn the process with
1016
+ // the original argv, and let the fresh boot attach the same session.
1017
+ let restartRequested = false;
785
1018
  // The profile this process was booted with (`dsh --profile <name>`); dsh
786
1019
  // exposes it nowhere else, and /update must update the installation the
787
1020
  // user is actually running, not a hard-coded one.
@@ -812,6 +1045,25 @@ export async function apply(ctx, config) {
812
1045
  void finishExit(ctx, instance, bootedFullscreen, 'Updating @deepseek-harness-tui/dsh-tui and restarting…', undefined, () => runUpdate(ctx, profile, channel.agentId, updateTargetVersion));
813
1046
  return;
814
1047
  }
1048
+ // `/restart`: same handoff as the update path, no installation step.
1049
+ // The resume target is written unconditionally — the user asked to
1050
+ // restart THIS session, blank or not (mirrors the update contract).
1051
+ if (restartRequested) {
1052
+ beginRestartAttempt(channel.agentId);
1053
+ logRestartEvent('funnel: /restart branch entered');
1054
+ try {
1055
+ writeResumeTarget(channel.agentId);
1056
+ logRestartEvent('funnel: resume target written');
1057
+ }
1058
+ catch (error) {
1059
+ // Resume persistence is best effort and must never block a restart.
1060
+ logRestartEvent('funnel: resume target write failed', {
1061
+ message: error instanceof Error ? error.message : String(error),
1062
+ });
1063
+ }
1064
+ void finishExit(ctx, instance, bootedFullscreen, t('restart-starting'), undefined, () => runRestart(ctx, profile, channel.agentId));
1065
+ return;
1066
+ }
815
1067
  // Judge against the live session behind the channel (channel.agentId),
816
1068
  // not the boot-time agent captured above: /resume, /new and /model swap
817
1069
  // the active agent, so the captured reference can go stale (see
@@ -861,6 +1113,15 @@ export async function apply(ctx, config) {
861
1113
  // the tree is already wrapped below, so they must not nest.
862
1114
  fullscreen: bootedFullscreen,
863
1115
  onExit: () => handleExit(),
1116
+ // `/restart`: respawn this process and resume the session, no update.
1117
+ onRestart: () => {
1118
+ if (exited || restartRequested)
1119
+ return;
1120
+ restartRequested = true;
1121
+ logRestartEvent('command: /restart accepted');
1122
+ channel.notify(t('restart-starting'));
1123
+ handleExit();
1124
+ },
864
1125
  // Only a `dsh --profile <name>` launch has a profile installation for
865
1126
  // `/update` to act on; source checkouts and `--config` overlays get the
866
1127
  // unavailable notice instead.
@@ -926,6 +1187,12 @@ export async function apply(ctx, config) {
926
1187
  const isRecompose = lastBootedFullscreen !== undefined;
927
1188
  lastBootedFullscreen = bootedFullscreen;
928
1189
  logMouseDebug('apply mount', { bootedFullscreen, isRecompose });
1190
+ // /restart handoff diagnosis: the replacement got all the way to a mounted
1191
+ // UI, so any later death is post-boot (and its stderr keeps flowing to the
1192
+ // parent only within the survival window — this line is the durable mark).
1193
+ if (process.env.DSH_TUI_RESTART_CHILD === '1') {
1194
+ logRestartEvent('boot: UI mounted', { fullscreen: bootedFullscreen, isRecompose });
1195
+ }
929
1196
  // Check in the background so registry latency never delays the first frame.
930
1197
  // A failed/offline check is intentionally silent; the manual `/update`
931
1198
  // command remains available regardless of network access.
@@ -977,9 +1244,13 @@ export async function apply(ctx, config) {
977
1244
  async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRoute, meta, configuredPreset) {
978
1245
  // Resume override (issue #67): cordis.yml overrides the target session's
979
1246
  // recorded route only when it pins BOTH halves; undefined halves let the
980
- // session's own request/header records win (issue #30).
1247
+ // session's own request/header records win (issue #30). The recorded route
1248
+ // is ALSO fed back into agentOptions (not just the status line): a resume
1249
+ // whose cordis.yml pins only `provider` would otherwise leave
1250
+ // agentOptions.model undefined, which breaks the `{{model}}` persona
1251
+ // variable for the resumed agent's own assembly and for every subagent it
1252
+ // spawns (dsh-subagent inherits `parent.options.model`).
981
1253
  const resumeRoute = explicitModelRoute(configuredRoute);
982
- const resumeOptions = { provider: resumeRoute?.provider, model: resumeRoute?.model };
983
1254
  if (requestedSessionId !== undefined) {
984
1255
  const resumeId = SessionId(requestedSessionId);
985
1256
  const existing = ctx.agents.get(resumeId);
@@ -996,6 +1267,11 @@ async function resolveAgent(ctx, requestedSessionId, configuredRoute, startupRou
996
1267
  // caller's current preference.
997
1268
  const persisted = await resolvePersistedPreset(ctx, resumeId);
998
1269
  const composed = await composePreset(ctx, persisted);
1270
+ const recorded = await resolvePersistedRoute(ctx, resumeId);
1271
+ const resumeOptions = {
1272
+ provider: resumeRoute?.provider ?? recorded?.provider,
1273
+ model: resumeRoute?.model ?? recorded?.model,
1274
+ };
999
1275
  const resumed = await ctx.agents.resume({
1000
1276
  resumeSessionId: resumeId,
1001
1277
  agentOptions: resumeOptions,
@@ -1195,6 +1471,34 @@ function writeStream(stream, data) {
1195
1471
  }
1196
1472
  });
1197
1473
  }
1474
+ /**
1475
+ * Restart the TUI in place and resume the same session — the `/restart`
1476
+ * tail of `/reload`: the soft reload cannot re-read boot-time-only state
1477
+ * (cordis.yml root config, frozen fullscreen layout, newly built code), so
1478
+ * /restart respawns the process with the original argv through the same
1479
+ * terminal handoff the /update path uses, minus the installation step.
1480
+ * The resume contract is dual-written (env + resume.txt) before this runs.
1481
+ */
1482
+ function runRestart(ctx, profile, sessionId) {
1483
+ logRestartEvent('runRestart: entered, disposing cordis root');
1484
+ disposeRootAndThen(ctx, () => {
1485
+ logRestartEvent('runRestart: root disposed, starting restartTui');
1486
+ void restartTui(sessionId).then(restartCode => {
1487
+ logRestartEvent('runRestart: restartTui resolved', { restartCode });
1488
+ if (restartCode !== 0) {
1489
+ writeHandoffNotice(`\ndsh-tui restart failed to spawn (exit ${restartCode}). Your session is preserved — resume with:\n` +
1490
+ `${resumeCommand(profile, sessionId)}\n\n`);
1491
+ }
1492
+ process.exit(restartCode);
1493
+ }, restartError => {
1494
+ const message = restartError instanceof Error ? restartError.message : String(restartError);
1495
+ logRestartEvent('runRestart: restartTui rejected', { message });
1496
+ writeHandoffNotice(`\ndsh-tui restart failed: ${message}. Your session is preserved — resume with:\n` +
1497
+ `${resumeCommand(profile, sessionId)}\n\n`);
1498
+ process.exit(1);
1499
+ });
1500
+ });
1501
+ }
1198
1502
  function runUpdate(ctx, profile, sessionId, targetVersion) {
1199
1503
  disposeRootAndThen(ctx, () => {
1200
1504
  if (profile === undefined) {
@@ -1243,7 +1547,12 @@ function resumeCommand(profile, sessionId) {
1243
1547
  * reporting failure on a clean exit would mislead wrapper scripts.
1244
1548
  */
1245
1549
  function disposeRootAndThen(ctx, done, fallbackCode = 1) {
1246
- const timer = setTimeout(() => process.exit(fallbackCode), 5000);
1550
+ const timer = setTimeout(() => {
1551
+ // Diagnosis for a stalled disposal: without this line the fallback exit
1552
+ // is indistinguishable from a successful handoff in the field.
1553
+ logRestartEvent('dispose: timeout, taking fallback exit', { fallbackCode });
1554
+ process.exit(fallbackCode);
1555
+ }, 5000);
1247
1556
  timer.unref();
1248
1557
  void withHostRootCapability(() => ctx.root.fiber.dispose()).then(() => {
1249
1558
  clearTimeout(timer);
@@ -19,6 +19,7 @@ import type { Context } from '@deepseek-ai/cordis';
19
19
  import type { AgentSetup } from '@deepseek-ai/dsh-agent';
20
20
  import type { SessionId } from '@deepseek-ai/dsh-session';
21
21
  import type { PromptAssembly } from '@deepseek-ai/dsh-system-prompt';
22
+ import { type ModelRoute } from '../modelRoute.js';
22
23
  /** One roster entry, as returned by `agentPresets.list()`/`resolve()`. */
23
24
  export interface AgentPresetInfo {
24
25
  readonly id: string;
@@ -94,6 +95,23 @@ export declare function runningPresetOf(session: {
94
95
  data: unknown;
95
96
  }[];
96
97
  }): string | undefined;
98
+ /**
99
+ * The route a PERSISTED session actually ran, read from its log: the last
100
+ * `request/header` snapshot. undefined when the log records none (a session
101
+ * that never started a turn) or the artifact is unreadable.
102
+ *
103
+ * Resume feeds this back into `agents.resume({ agentOptions })` so the
104
+ * resumed agent's `options.model` is populated again — a cordis.yml that
105
+ * pins only `provider` (issue #67: a half-pin never merges) leaves
106
+ * agentOptions.model undefined, which breaks the `{{model}}` persona variable
107
+ * for the resumed agent's own assembly AND for every subagent it spawns
108
+ * (dsh-subagent's `resolveChildAgentOptions` inherits `parent.options.model`).
109
+ *
110
+ * @param ctx - The plugin context (persistence lookup).
111
+ * @param sessionId - The persisted session to inspect.
112
+ * @returns The recorded model route, or undefined when unrecorded/unreadable.
113
+ */
114
+ export declare function resolvePersistedRoute(ctx: Context, sessionId: SessionId): Promise<ModelRoute | undefined>;
97
115
  /**
98
116
  * Keep the official Minimal preset's model-facing contract at exactly two
99
117
  * tools. The TUI mounts ask_user_question at the host layer so every other
@@ -1 +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;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAKpE,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;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAM/G;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"}
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;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAEpE,OAAO,EAAsB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAItE,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;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAkB/G;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAM/G;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"}
@@ -16,6 +16,7 @@
16
16
  * before presets existed.
17
17
  */
18
18
  import { resolveSessionPreset } from '@deepseek-ai/dsh-agent-presets';
19
+ import { recordedModelRoute } from '../modelRoute.js';
19
20
  const ASK_USER_TOOL = 'ask_user_question';
20
21
  /**
21
22
  * The mounted preset roster, or undefined when the composition has no
@@ -95,6 +96,36 @@ export async function resolvePersistedPreset(ctx, sessionId) {
95
96
  export function runningPresetOf(session) {
96
97
  return resolveSessionPreset(session);
97
98
  }
99
+ /**
100
+ * The route a PERSISTED session actually ran, read from its log: the last
101
+ * `request/header` snapshot. undefined when the log records none (a session
102
+ * that never started a turn) or the artifact is unreadable.
103
+ *
104
+ * Resume feeds this back into `agents.resume({ agentOptions })` so the
105
+ * resumed agent's `options.model` is populated again — a cordis.yml that
106
+ * pins only `provider` (issue #67: a half-pin never merges) leaves
107
+ * agentOptions.model undefined, which breaks the `{{model}}` persona variable
108
+ * for the resumed agent's own assembly AND for every subagent it spawns
109
+ * (dsh-subagent's `resolveChildAgentOptions` inherits `parent.options.model`).
110
+ *
111
+ * @param ctx - The plugin context (persistence lookup).
112
+ * @param sessionId - The persisted session to inspect.
113
+ * @returns The recorded model route, or undefined when unrecorded/unreadable.
114
+ */
115
+ export async function resolvePersistedRoute(ctx, sessionId) {
116
+ const persistence = ctx.get('sessionPersistence');
117
+ if (persistence === undefined)
118
+ return undefined;
119
+ try {
120
+ const { events } = await persistence.load(sessionId);
121
+ return recordedModelRoute(events);
122
+ }
123
+ catch {
124
+ // A missing/corrupt artifact leaves resume itself to report the failure;
125
+ // the route lookup must not mask it with a second, misleading error.
126
+ return undefined;
127
+ }
128
+ }
98
129
  /**
99
130
  * Keep the official Minimal preset's model-facing contract at exactly two
100
131
  * tools. The TUI mounts ask_user_question at the host layer so every other
@@ -31,6 +31,32 @@ export interface CatalogProviderCandidate {
31
31
  readonly provider: string;
32
32
  readonly displayName: string;
33
33
  }
34
+ /** One OAuth-capable provider a dsh-auth-style plugin mounts (masked state only). */
35
+ export interface OAuthProviderStatus {
36
+ readonly provider: string;
37
+ readonly label: string;
38
+ readonly oauthLabel: string;
39
+ readonly loginLabel: string | undefined;
40
+ readonly signedIn: boolean;
41
+ readonly expiresAt: number | undefined;
42
+ readonly expired: boolean;
43
+ }
44
+ /** One successful OAuth login. */
45
+ export interface OAuthLoginResult {
46
+ readonly provider: string;
47
+ readonly oauthLabel: string;
48
+ readonly expiresAt: number;
49
+ }
50
+ /**
51
+ * The `ctx.dshAuth` api, structural so this tree never imports the plugin:
52
+ * mounting dsh-auth (or anything exporting this shape) lights up the wizard's
53
+ * OAuth branch; absent it, the wizard behaves exactly as before.
54
+ */
55
+ export interface OAuthSetupHost {
56
+ providers(): Promise<readonly OAuthProviderStatus[]>;
57
+ login(provider?: string, signal?: AbortSignal): Promise<OAuthLoginResult>;
58
+ logout(provider: string): Promise<boolean>;
59
+ }
34
60
  /**
35
61
  * Runtime capabilities the wizard needs, implemented by the channel over
36
62
  * `ctx.settings` / `ctx.credentials` / `ctx.llm`. `undefined` from
@@ -66,6 +92,8 @@ export interface ProviderSetupHost {
66
92
  * rejects when the adapter's validation deems it unserviceable.
67
93
  */
68
94
  writeProfile(route: string, profile: Record<string, unknown>): Promise<void>;
95
+ /** The OAuth sign-in surface; absent when no dsh-auth-style plugin is mounted. */
96
+ readonly oauth?: OAuthSetupHost;
69
97
  }
70
98
  export interface ProviderWizardDeps {
71
99
  readonly host: ProviderSetupHost;
@@ -81,7 +109,7 @@ export interface ProviderWizardDeps {
81
109
  readonly working: () => boolean;
82
110
  readonly switchModel: (provider: string, model: string) => Promise<boolean>;
83
111
  }
84
- export type ProviderWizardOutcome = 'added' | 'cancelled' | 'failed';
112
+ export type ProviderWizardOutcome = 'added' | 'signed-out' | 'cancelled' | 'failed';
85
113
  /**
86
114
  * Run the add-provider wizard. Resolves 'cancelled' when the user dismisses
87
115
  * any question (Esc) — nothing has been written at that point by design: