@deepseek-harness-tui/dsh-tui 0.7.3 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/README.md +15 -7
  2. package/bin/dsh-tui.js +19 -3
  3. package/cordis.patch.yml +43 -11
  4. package/cordis.yml +20 -1
  5. package/ecosystem-spec/registry/contracts/decision-events-v1alpha1.json +13 -0
  6. package/ecosystem-spec/registry/host-descriptor.tui.example.json +56 -0
  7. package/ecosystem-spec/registry/permissions-0.1.json +13 -0
  8. package/ecosystem-spec/registry/registry-0.15.json +57 -0
  9. package/ecosystem-spec/schemas/conformance-claim.schema.json +15 -0
  10. package/ecosystem-spec/schemas/effect-ledger-record.schema.json +16 -0
  11. package/ecosystem-spec/schemas/host-descriptor.schema.json +26 -0
  12. package/lib/types/cc/figures.d.ts +4 -0
  13. package/lib/types/cc/figures.d.ts.map +1 -1
  14. package/lib/types/cc/figures.js +4 -0
  15. package/lib/types/commands.d.ts.map +1 -1
  16. package/lib/types/commands.js +4 -1
  17. package/lib/types/components/ExtensionDialog.d.ts +40 -0
  18. package/lib/types/components/ExtensionDialog.d.ts.map +1 -0
  19. package/lib/types/components/ExtensionDialog.js +210 -0
  20. package/lib/types/components/HelpMenu.js +1 -1
  21. package/lib/types/components/LoadedContextPanel.d.ts +5 -10
  22. package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
  23. package/lib/types/components/LoadedContextPanel.js +7 -18
  24. package/lib/types/components/LogoV2.d.ts.map +1 -1
  25. package/lib/types/components/LogoV2.js +1 -2
  26. package/lib/types/components/MessageList.d.ts +3 -1
  27. package/lib/types/components/MessageList.d.ts.map +1 -1
  28. package/lib/types/components/MessageList.js +29 -5
  29. package/lib/types/components/PluginSceneBoundary.d.ts +31 -0
  30. package/lib/types/components/PluginSceneBoundary.d.ts.map +1 -0
  31. package/lib/types/components/PluginSceneBoundary.js +29 -0
  32. package/lib/types/components/RewindPicker.d.ts +13 -1
  33. package/lib/types/components/RewindPicker.d.ts.map +1 -1
  34. package/lib/types/components/RewindPicker.js +26 -2
  35. package/lib/types/components/SkillsPicker.d.ts +18 -0
  36. package/lib/types/components/SkillsPicker.d.ts.map +1 -0
  37. package/lib/types/components/SkillsPicker.js +50 -0
  38. package/lib/types/components/SplitDiffView.d.ts +28 -0
  39. package/lib/types/components/SplitDiffView.d.ts.map +1 -0
  40. package/lib/types/components/SplitDiffView.js +417 -0
  41. package/lib/types/components/ToolUseLoader.d.ts +8 -3
  42. package/lib/types/components/ToolUseLoader.d.ts.map +1 -1
  43. package/lib/types/components/ToolUseLoader.js +43 -9
  44. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +3 -1
  45. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  46. package/lib/types/components/messages/AssistantToolUseMessage.js +17 -7
  47. package/lib/types/dsh-adapter/channel.d.ts +98 -7
  48. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  49. package/lib/types/dsh-adapter/channel.js +623 -26
  50. package/lib/types/dsh-adapter/command-attribution.d.ts +51 -0
  51. package/lib/types/dsh-adapter/command-attribution.d.ts.map +1 -0
  52. package/lib/types/dsh-adapter/command-attribution.js +93 -0
  53. package/lib/types/dsh-adapter/command-errors.d.ts +42 -0
  54. package/lib/types/dsh-adapter/command-errors.d.ts.map +1 -0
  55. package/lib/types/dsh-adapter/command-errors.js +63 -0
  56. package/lib/types/dsh-adapter/component-identity.d.ts +28 -0
  57. package/lib/types/dsh-adapter/component-identity.d.ts.map +1 -0
  58. package/lib/types/dsh-adapter/component-identity.js +108 -0
  59. package/lib/types/dsh-adapter/contract.d.ts +2 -2
  60. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  61. package/lib/types/dsh-adapter/contract.js +3 -2
  62. package/lib/types/dsh-adapter/decision-guard.d.ts +84 -0
  63. package/lib/types/dsh-adapter/decision-guard.d.ts.map +1 -0
  64. package/lib/types/dsh-adapter/decision-guard.js +354 -0
  65. package/lib/types/dsh-adapter/dialogs.d.ts +146 -0
  66. package/lib/types/dsh-adapter/dialogs.d.ts.map +1 -0
  67. package/lib/types/dsh-adapter/dialogs.js +262 -0
  68. package/lib/types/dsh-adapter/effect-ledger.d.ts +99 -0
  69. package/lib/types/dsh-adapter/effect-ledger.d.ts.map +1 -0
  70. package/lib/types/dsh-adapter/effect-ledger.js +231 -0
  71. package/lib/types/dsh-adapter/extension-events.d.ts +193 -0
  72. package/lib/types/dsh-adapter/extension-events.d.ts.map +1 -0
  73. package/lib/types/dsh-adapter/extension-events.js +169 -0
  74. package/lib/types/dsh-adapter/extensions.d.ts +32 -0
  75. package/lib/types/dsh-adapter/extensions.d.ts.map +1 -0
  76. package/lib/types/dsh-adapter/extensions.js +42 -0
  77. package/lib/types/dsh-adapter/grants.d.ts +25 -0
  78. package/lib/types/dsh-adapter/grants.d.ts.map +1 -0
  79. package/lib/types/dsh-adapter/grants.js +184 -0
  80. package/lib/types/dsh-adapter/host-descriptor.d.ts +24 -0
  81. package/lib/types/dsh-adapter/host-descriptor.d.ts.map +1 -0
  82. package/lib/types/dsh-adapter/host-descriptor.js +146 -0
  83. package/lib/types/dsh-adapter/index.d.ts +4 -0
  84. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  85. package/lib/types/dsh-adapter/index.js +1 -0
  86. package/lib/types/dsh-adapter/message-observer.d.ts +178 -0
  87. package/lib/types/dsh-adapter/message-observer.d.ts.map +1 -0
  88. package/lib/types/dsh-adapter/message-observer.js +509 -0
  89. package/lib/types/dsh-adapter/plugin-host.d.ts +103 -0
  90. package/lib/types/dsh-adapter/plugin-host.d.ts.map +1 -0
  91. package/lib/types/dsh-adapter/plugin-host.js +270 -0
  92. package/lib/types/dsh-adapter/plugin-storage.d.ts +113 -0
  93. package/lib/types/dsh-adapter/plugin-storage.d.ts.map +1 -0
  94. package/lib/types/dsh-adapter/plugin-storage.js +385 -0
  95. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  96. package/lib/types/dsh-adapter/plugin.js +106 -1
  97. package/lib/types/dsh-adapter/plugins-info.d.ts +43 -0
  98. package/lib/types/dsh-adapter/plugins-info.d.ts.map +1 -0
  99. package/lib/types/dsh-adapter/plugins-info.js +276 -0
  100. package/lib/types/dsh-adapter/promptDebug.d.ts +10 -0
  101. package/lib/types/dsh-adapter/promptDebug.d.ts.map +1 -0
  102. package/lib/types/dsh-adapter/promptDebug.js +148 -0
  103. package/lib/types/dsh-adapter/renderers.d.ts +65 -0
  104. package/lib/types/dsh-adapter/renderers.d.ts.map +1 -0
  105. package/lib/types/dsh-adapter/renderers.js +138 -0
  106. package/lib/types/dsh-adapter/sanitize.d.ts +36 -0
  107. package/lib/types/dsh-adapter/sanitize.d.ts.map +1 -0
  108. package/lib/types/dsh-adapter/sanitize.js +65 -0
  109. package/lib/types/dsh-adapter/scenes.d.ts +81 -0
  110. package/lib/types/dsh-adapter/scenes.d.ts.map +1 -0
  111. package/lib/types/dsh-adapter/scenes.js +93 -0
  112. package/lib/types/dsh-adapter/settings-sections.d.ts +116 -0
  113. package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -0
  114. package/lib/types/dsh-adapter/settings-sections.js +63 -0
  115. package/lib/types/dsh-adapter/settingsEditor.d.ts +128 -0
  116. package/lib/types/dsh-adapter/settingsEditor.d.ts.map +1 -0
  117. package/lib/types/dsh-adapter/settingsEditor.js +244 -0
  118. package/lib/types/dsh-adapter/shortcuts.d.ts +109 -0
  119. package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -0
  120. package/lib/types/dsh-adapter/shortcuts.js +268 -0
  121. package/lib/types/dsh-adapter/status.d.ts +75 -0
  122. package/lib/types/dsh-adapter/status.d.ts.map +1 -0
  123. package/lib/types/dsh-adapter/status.js +168 -0
  124. package/lib/types/extensions.d.ts +8 -0
  125. package/lib/types/extensions.d.ts.map +1 -0
  126. package/lib/types/extensions.js +15 -0
  127. package/lib/types/i18n.d.ts +299 -26
  128. package/lib/types/i18n.d.ts.map +1 -1
  129. package/lib/types/i18n.js +89 -8
  130. package/lib/types/ink/ink.d.ts +11 -0
  131. package/lib/types/ink/ink.d.ts.map +1 -1
  132. package/lib/types/ink/ink.js +33 -0
  133. package/lib/types/ink/log-update.d.ts.map +1 -1
  134. package/lib/types/ink/log-update.js +101 -51
  135. package/lib/types/ink/output.d.ts +7 -0
  136. package/lib/types/ink/output.d.ts.map +1 -1
  137. package/lib/types/ink/output.js +125 -4
  138. package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
  139. package/lib/types/ink/render-node-to-output.js +14 -6
  140. package/lib/types/ink/terminal.d.ts.map +1 -1
  141. package/lib/types/ink/terminal.js +18 -6
  142. package/lib/types/jsx-runtime.d.ts +2 -0
  143. package/lib/types/jsx-runtime.d.ts.map +1 -0
  144. package/lib/types/jsx-runtime.js +13 -0
  145. package/lib/types/modelRoute.d.ts +10 -2
  146. package/lib/types/modelRoute.d.ts.map +1 -1
  147. package/lib/types/modelRoute.js +33 -4
  148. package/lib/types/plugin-host.d.ts +13 -0
  149. package/lib/types/plugin-host.d.ts.map +1 -0
  150. package/lib/types/plugin-host.js +17 -0
  151. package/lib/types/plugin-spec/negotiate.d.ts +11 -0
  152. package/lib/types/plugin-spec/negotiate.d.ts.map +1 -0
  153. package/lib/types/plugin-spec/negotiate.js +97 -0
  154. package/lib/types/plugin-spec/permission-scope.d.ts +32 -0
  155. package/lib/types/plugin-spec/permission-scope.d.ts.map +1 -0
  156. package/lib/types/plugin-spec/permission-scope.js +90 -0
  157. package/lib/types/plugin-spec/registry.d.ts +23 -0
  158. package/lib/types/plugin-spec/registry.d.ts.map +1 -0
  159. package/lib/types/plugin-spec/registry.js +157 -0
  160. package/lib/types/plugin-spec/schema-check.d.ts +17 -0
  161. package/lib/types/plugin-spec/schema-check.d.ts.map +1 -0
  162. package/lib/types/plugin-spec/schema-check.js +165 -0
  163. package/lib/types/plugin-spec/tui-extension.d.ts +16 -0
  164. package/lib/types/plugin-spec/tui-extension.d.ts.map +1 -0
  165. package/lib/types/plugin-spec/tui-extension.js +77 -0
  166. package/lib/types/plugin-spec/types.d.ts +114 -0
  167. package/lib/types/plugin-spec/types.d.ts.map +1 -0
  168. package/lib/types/plugin-spec/types.js +10 -0
  169. package/lib/types/plugin-spec/validate.d.ts +21 -0
  170. package/lib/types/plugin-spec/validate.d.ts.map +1 -0
  171. package/lib/types/plugin-spec/validate.js +119 -0
  172. package/lib/types/scenes.d.ts +3 -0
  173. package/lib/types/scenes.d.ts.map +1 -0
  174. package/lib/types/scenes.js +4 -0
  175. package/lib/types/screens/Chat.d.ts +14 -1
  176. package/lib/types/screens/Chat.d.ts.map +1 -1
  177. package/lib/types/screens/Chat.js +247 -48
  178. package/lib/types/screens/Settings.d.ts +20 -0
  179. package/lib/types/screens/Settings.d.ts.map +1 -0
  180. package/lib/types/screens/Settings.js +333 -0
  181. package/lib/types/screens/StatusLine.js +1 -1
  182. package/lib/types/settings-sections.d.ts +3 -0
  183. package/lib/types/settings-sections.d.ts.map +1 -0
  184. package/lib/types/settings-sections.js +4 -0
  185. package/lib/types/theme.d.ts +17 -0
  186. package/lib/types/theme.d.ts.map +1 -1
  187. package/lib/types/theme.js +51 -0
  188. package/lib/types/update.d.ts +20 -0
  189. package/lib/types/update.d.ts.map +1 -1
  190. package/lib/types/update.js +54 -7
  191. package/lib/types/utils/loaded-context.d.ts +8 -3
  192. package/lib/types/utils/loaded-context.d.ts.map +1 -1
  193. package/lib/types/utils/loaded-context.js +39 -3
  194. package/lib/types/utils/modifiers.d.ts.map +1 -1
  195. package/lib/types/utils/modifiers.js +3 -2
  196. package/lib/types/working-activity.d.ts +12 -0
  197. package/lib/types/working-activity.d.ts.map +1 -1
  198. package/lib/types/working-activity.js +13 -0
  199. package/node_modules/@dsh-std/command/LICENSE +21 -0
  200. package/node_modules/@dsh-std/command/README.md +26 -0
  201. package/node_modules/@dsh-std/command/README.zh.md +28 -0
  202. package/node_modules/@dsh-std/command/lib/index.d.ts +144 -0
  203. package/node_modules/@dsh-std/command/lib/index.d.ts.map +1 -0
  204. package/node_modules/@dsh-std/command/lib/index.js +252 -0
  205. package/node_modules/@dsh-std/command/lib/index.js.map +1 -0
  206. package/node_modules/@dsh-std/command/package.json +22 -0
  207. package/node_modules/@dsh-std/connection/LICENSE +21 -0
  208. package/node_modules/@dsh-std/connection/README.md +42 -0
  209. package/node_modules/@dsh-std/connection/README.zh.md +42 -0
  210. package/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts +125 -0
  211. package/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts.map +1 -0
  212. package/node_modules/@dsh-std/connection/lib/index.d.ts +89 -0
  213. package/node_modules/@dsh-std/connection/lib/index.d.ts.map +1 -0
  214. package/node_modules/@dsh-std/connection/lib/index.js +158 -0
  215. package/node_modules/@dsh-std/connection/lib/index.js.map +1 -0
  216. package/node_modules/@dsh-std/connection/lib/memory.d.ts +24 -0
  217. package/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -0
  218. package/node_modules/@dsh-std/connection/lib/memory.js +257 -0
  219. package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -0
  220. package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js +226 -0
  221. package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -0
  222. package/node_modules/@dsh-std/connection/package.json +20 -0
  223. package/node_modules/@dsh-std/core/LICENSE +21 -0
  224. package/node_modules/@dsh-std/core/README.md +13 -0
  225. package/node_modules/@dsh-std/core/README.zh.md +13 -0
  226. package/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  227. package/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  228. package/node_modules/@dsh-std/core/lib/index.js +424 -0
  229. package/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  230. package/node_modules/@dsh-std/core/package.json +21 -0
  231. package/node_modules/@dsh-std/manifest/LICENSE +21 -0
  232. package/node_modules/@dsh-std/manifest/README.md +5 -0
  233. package/node_modules/@dsh-std/manifest/README.zh.md +5 -0
  234. package/node_modules/@dsh-std/manifest/lib/index.d.ts +182 -0
  235. package/node_modules/@dsh-std/manifest/lib/index.d.ts.map +1 -0
  236. package/node_modules/@dsh-std/manifest/lib/index.js +625 -0
  237. package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -0
  238. package/node_modules/@dsh-std/manifest/package.json +20 -0
  239. package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -0
  240. package/node_modules/@dsh-std/messages/LICENSE +21 -0
  241. package/node_modules/@dsh-std/messages/README.md +5 -0
  242. package/node_modules/@dsh-std/messages/README.zh.md +7 -0
  243. package/node_modules/@dsh-std/messages/lib/index.d.ts +50 -0
  244. package/node_modules/@dsh-std/messages/lib/index.d.ts.map +1 -0
  245. package/node_modules/@dsh-std/messages/lib/index.js +151 -0
  246. package/node_modules/@dsh-std/messages/lib/index.js.map +1 -0
  247. package/node_modules/@dsh-std/messages/package.json +20 -0
  248. package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -0
  249. package/node_modules/@dsh-std/presentation/LICENSE +21 -0
  250. package/node_modules/@dsh-std/presentation/README.md +26 -0
  251. package/node_modules/@dsh-std/presentation/README.zh.md +28 -0
  252. package/node_modules/@dsh-std/presentation/lib/index.d.ts +219 -0
  253. package/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -0
  254. package/node_modules/@dsh-std/presentation/lib/index.js +547 -0
  255. package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -0
  256. package/node_modules/@dsh-std/presentation/lib/interaction.d.ts +2 -0
  257. package/node_modules/@dsh-std/presentation/lib/interaction.js +2 -0
  258. package/node_modules/@dsh-std/presentation/lib/operations.d.ts +2 -0
  259. package/node_modules/@dsh-std/presentation/lib/operations.js +2 -0
  260. package/node_modules/@dsh-std/presentation/package.json +21 -0
  261. package/node_modules/@dsh-std/storage/LICENSE +21 -0
  262. package/node_modules/@dsh-std/storage/README.md +5 -0
  263. package/node_modules/@dsh-std/storage/README.zh.md +7 -0
  264. package/node_modules/@dsh-std/storage/lib/index.d.ts +48 -0
  265. package/node_modules/@dsh-std/storage/lib/index.d.ts.map +1 -0
  266. package/node_modules/@dsh-std/storage/lib/index.js +104 -0
  267. package/node_modules/@dsh-std/storage/lib/index.js.map +1 -0
  268. package/node_modules/@dsh-std/storage/package.json +20 -0
  269. package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -0
  270. package/package.json +118 -67
  271. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -0
  272. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -0
  273. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -0
  274. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts +125 -0
  275. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts.map +1 -0
  276. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.d.ts +89 -0
  277. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.d.ts.map +1 -0
  278. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js +158 -0
  279. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -0
  280. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts +24 -0
  281. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -0
  282. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js +257 -0
  283. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -0
  284. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js +226 -0
  285. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -0
  286. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -0
  287. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -0
  288. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -0
  289. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -0
  290. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  291. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  292. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js +424 -0
  293. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  294. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -0
  295. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -0
  296. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -0
  297. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -0
  298. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.d.ts +182 -0
  299. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.d.ts.map +1 -0
  300. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js +625 -0
  301. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -0
  302. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -0
  303. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -0
  304. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -0
  305. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +26 -0
  306. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +28 -0
  307. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts +219 -0
  308. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -0
  309. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js +547 -0
  310. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -0
  311. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/interaction.d.ts +2 -0
  312. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/interaction.js +2 -0
  313. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/operations.d.ts +2 -0
  314. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/operations.js +2 -0
  315. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +21 -0
  316. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -0
  317. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -0
  318. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -0
  319. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  320. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  321. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js +424 -0
  322. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  323. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -0
  324. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -0
  325. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -0
  326. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -0
  327. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  328. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  329. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js +424 -0
  330. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  331. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -0
  332. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -0
  333. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -0
  334. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -0
  335. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  336. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  337. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js +424 -0
  338. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  339. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -0
  340. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -0
  341. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -0
  342. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -0
  343. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts +125 -0
  344. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts.map +1 -0
  345. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.d.ts +89 -0
  346. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.d.ts.map +1 -0
  347. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js +158 -0
  348. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -0
  349. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts +24 -0
  350. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -0
  351. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js +257 -0
  352. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -0
  353. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js +226 -0
  354. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -0
  355. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -0
  356. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -0
  357. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -0
  358. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -0
  359. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  360. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  361. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js +424 -0
  362. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  363. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -0
  364. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -0
  365. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -0
  366. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -0
  367. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  368. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  369. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js +424 -0
  370. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  371. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -0
@@ -2,15 +2,19 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from 'react';
3
3
  import { t, getLang, setLang, isLang, writeLangPref, subscribeLang } from '../i18n.js';
4
4
  import { AlternateScreen, Box, Text, useInput, ScrollBox, useTheme, useTerminalSize } from '../ui.js';
5
+ import * as tuiKit from '../ui.js';
5
6
  import { POINTER } from '../cc/figures.js';
6
7
  import { isMod, isPlainReturnInput, modLabel } from '../utils/modifiers.js';
7
8
  import { formatTokens } from '../cc/format.js';
8
9
  import { homeDir } from '../utils/paths.js';
9
10
  import { sessionCwdMatches } from '../dsh-adapter/channel.js';
11
+ import { TuiDialogStore } from '../dsh-adapter/dialogs.js';
12
+ import { TuiStatusStore } from '../dsh-adapter/status.js';
10
13
  import { runProviderWizard } from '../dsh-adapter/providerWizard.js';
11
14
  import { ApprovalStore } from '../dsh-adapter/approvals.js';
12
15
  import { AskUserQuestionPanel } from '../components/questions/AskUserQuestionPanel.js';
13
16
  import { ApprovalPanel } from '../components/approvals/ApprovalPanel.js';
17
+ import { ExtensionDialog } from '../components/ExtensionDialog.js';
14
18
  import { useSearchHighlight } from '../ink/hooks/use-search-highlight.js';
15
19
  import { useTerminalTitle } from '../ink/hooks/use-terminal-title.js';
16
20
  import { useTerminalFocus } from '../ink/hooks/use-terminal-focus.js';
@@ -26,7 +30,10 @@ import { StatusLine } from './StatusLine.js';
26
30
  import { WorkingSpinner, useThinkingStatus } from '../components/WorkingSpinner.js';
27
31
  import { ActivityLine, contextPressurePct } from '../components/ActivityLine.js';
28
32
  import { ModelPicker } from '../components/ModelPicker.js';
33
+ import { PluginSceneBoundary } from '../components/PluginSceneBoundary.js';
34
+ import { SkillsPicker, SkillsPickerLoading } from '../components/SkillsPicker.js';
29
35
  import { SessionBrowser } from './SessionBrowser.js';
36
+ import { Settings } from './Settings.js';
30
37
  import { WorkspacePicker } from '../components/WorkspacePicker.js';
31
38
  import { WorkspaceFlowPicker } from '../components/WorkspaceFlowPicker.js';
32
39
  import { ActivityPicker } from '../components/ActivityPicker.js';
@@ -49,6 +56,7 @@ import { readTrajectorySeen, writeTrajectorySeen } from '../trajectoryPrefs.js';
49
56
  import { LoadingState } from '../components/design-system/LoadingState.js';
50
57
  import { Pane } from '../components/design-system/Pane.js';
51
58
  import { loadHistory } from '../history.js';
59
+ import { formatLoadedContextReport } from '../utils/loaded-context.js';
52
60
  /** Shared empty snapshot for hosts whose channel has no event log. */
53
61
  const NO_EVENTS = [];
54
62
  /** Row kinds the message-selection cursor can land on. */
@@ -117,7 +125,15 @@ function searchableText(row) {
117
125
  * snapshot stays null and the approval panel never mounts.
118
126
  */
119
127
  let fallbackApprovalStore;
120
- export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate, fullscreen = false, trajectorySeen: trajectorySeenProp, }) {
128
+ /**
129
+ * Shared inert extension stores for hosts that render Chat without the
130
+ * dsh-tui-extensions row (headless verify scripts, bare embeds). Never
131
+ * written, so the dialog panel and the plugin status line never mount and
132
+ * no shortcut ever matches.
133
+ */
134
+ let fallbackDialogStore;
135
+ let fallbackStatusStore;
136
+ export function Chat({ channel, questionStore, approvalStore, extensionDialogs, extensionStatus, extensionShortcuts, onExit, onUpdate, fullscreen = false, trajectorySeen: trajectorySeenProp, }) {
121
137
  // Re-render whenever the channel mutates; rows/status are read fresh below.
122
138
  React.useSyncExternalStore(channel.subscribe, () => channel.version);
123
139
  // Re-render on language switches so the whole UI hot-swaps its strings.
@@ -131,6 +147,30 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
131
147
  // approvalStore share one inert instance that never holds an ask.
132
148
  const approvals = approvalStore ?? (fallbackApprovalStore ??= new ApprovalStore());
133
149
  const approvalSnapshot = React.useSyncExternalStore(listener => approvals.subscribe(listener), () => approvals.getSnapshot());
150
+ // The pending managed plugin dialog (tuiDialogs seam): a plugin's
151
+ // select/confirm/input request parks here until the panel settles it.
152
+ // Priority sits right below the approval panel (a gated tool outranks a
153
+ // plugin's question) and above the questionnaire. Hosts without the
154
+ // extensions row share one inert store that never holds a dialog.
155
+ const dialogs = extensionDialogs ?? (fallbackDialogStore ??= new TuiDialogStore());
156
+ const dialogSnapshot = React.useSyncExternalStore(listener => dialogs.subscribe(listener), () => dialogs.getSnapshot());
157
+ // Plugin status-line contributions (tuiStatus seam): keyed texts joined
158
+ // into one line above the prompt.
159
+ const statusContributions = extensionStatus ?? (fallbackStatusStore ??= new TuiStatusStore());
160
+ const statusEntries = React.useSyncExternalStore(listener => statusContributions.subscribe(listener), () => statusContributions.getSnapshot());
161
+ // Shortcut handler failures surface as toasts (the registry also logs
162
+ // them); the hook is re-pointed on every mount so a stale closure never
163
+ // outlives its channel.
164
+ React.useEffect(() => {
165
+ if (extensionShortcuts === undefined)
166
+ return;
167
+ extensionShortcuts.onError = combo => {
168
+ channel.notify(t('ext-shortcut-failed', { combo }), { color: 'error', timeoutMs: 4000 });
169
+ };
170
+ return () => {
171
+ extensionShortcuts.onError = undefined;
172
+ };
173
+ }, [extensionShortcuts, channel]);
134
174
  // When a questionnaire batch completes, fold a Q&A summary into the
135
175
  // transcript (the tool card itself is hidden from the message list).
136
176
  const questionOpenRef = React.useRef(questionSnapshot !== null);
@@ -152,9 +192,17 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
152
192
  const [modelPickerOpen, setModelPickerOpen] = React.useState(false);
153
193
  const [models, setModels] = React.useState([]);
154
194
  const [modelIndex, setModelIndex] = React.useState(0);
195
+ /** `/skills` 技能目录(issue #204):null = 注册表快照在途。 */
196
+ const [skillsPickerOpen, setSkillsPickerOpen] = React.useState(false);
197
+ const [skillsList, setSkillsList] = React.useState(null);
198
+ const [skillsIndex, setSkillsIndex] = React.useState(0);
155
199
  /** `/resume` opens the session browser, a screen rather than a panel. It
156
200
  * owns its own selection, filters and keyboard — Chat only opens it. */
157
201
  const [browserOpen, setBrowserOpen] = React.useState(false);
202
+ /** `/settings` opens the plugin settings screen (issue #165) — like the
203
+ * browser, a screen rather than a panel: it owns its own focus, staged
204
+ * drafts and keyboard; Chat only opens it. */
205
+ const [settingsOpen, setSettingsOpen] = React.useState(false);
158
206
  const [workspacePickerOpen, setWorkspacePickerOpen] = React.useState(false);
159
207
  const [workspaceTargets, setWorkspaceTargets] = React.useState([]);
160
208
  const [workspaceIndex, setWorkspaceIndex] = React.useState(0);
@@ -197,6 +245,17 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
197
245
  const [rewindOpen, setRewindOpen] = React.useState(false);
198
246
  const [rewindIndex, setRewindIndex] = React.useState(0);
199
247
  const [rewindConfirm, setRewindConfirm] = React.useState(null);
248
+ /** Plugin rewind modes (tui/rewind-prompt seam): extra choices offered in
249
+ * the confirm pane; null = the plain conversation-only confirm. */
250
+ const [rewindModes, setRewindModes] = React.useState(null);
251
+ const [rewindModeIndex, setRewindModeIndex] = React.useState(0);
252
+ /** True while the tui/rewind-prompt decision is in flight (a plugin may be
253
+ * showing its own dialog); keys except Esc are swallowed meanwhile. */
254
+ const [rewindBusy, setRewindBusy] = React.useState(false);
255
+ /** Monotonic token: only the latest rewind decision may land (a slow
256
+ * plugin answering after the user moved on must not open a confirm for
257
+ * a row they are no longer looking at). */
258
+ const rewindRequestRef = React.useRef(0);
200
259
  /** /btw side-question overlay (CC): pure UI state — the answer never
201
260
  * enters the transcript or the session log. */
202
261
  const [btw, setBtw] = React.useState(null);
@@ -241,15 +300,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
241
300
  });
242
301
  setSceneOpen(true);
243
302
  }, []);
244
- /** Startup context panel: expanded by header click or Ctrl+T. */
245
- const [loadedContextOpen, setLoadedContextOpen] = React.useState(false);
246
- /**
247
- * Whether the startup context panel is on screen. Derived once and read by
248
- * BOTH the Ctrl+T handler and the render below: the key's meaning depends on
249
- * the panel being visible, so a second copy of this condition is a place for
250
- * the two to disagree — which is how the key came to advertise one thing and
251
- * do another in the first place.
252
- */
303
+ /** The startup summary gives way to transcript rows after the first local command or message. */
253
304
  const loadedContextVisible = channel.rows.length === 0 && channel.loadedContext !== undefined;
254
305
  /** `/` transcript search (less-style incsearch, ported from CC's REPL). */
255
306
  const [searchOpen, setSearchOpen] = React.useState(false);
@@ -623,6 +674,16 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
623
674
  setHelpOpen(false);
624
675
  openScene();
625
676
  return true;
677
+ case 'context': {
678
+ setHelpOpen(false);
679
+ const context = channel.loadedContext;
680
+ if (context === undefined) {
681
+ channel.notify(t('context-unavailable'), { color: 'warning' });
682
+ return true;
683
+ }
684
+ channel.pushLocal('/context', formatLoadedContextReport(context));
685
+ return true;
686
+ }
626
687
  case 'help':
627
688
  setHelpOpen(true);
628
689
  return true;
@@ -635,6 +696,23 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
635
696
  setModelIndex(index >= 0 ? index : 0);
636
697
  });
637
698
  return true;
699
+ case 'skills':
700
+ // issue #204: 列出当前 agent 的完整技能目录(名称 + 来源 + 简述),
701
+ // Enter 把可直调技能以 `/name ` 填回输入行(completion-only 分发的
702
+ // 同一路径)。注册表读取走 channel(快照 scoped 到 live agent)。
703
+ setHelpOpen(false);
704
+ setSkillsList(null);
705
+ setSkillsIndex(0);
706
+ setSkillsPickerOpen(true);
707
+ void channel.listSkills().then((list) => {
708
+ if (list === undefined) {
709
+ setSkillsPickerOpen(false);
710
+ channel.notify(t('skills-load-failed'), { color: 'error' });
711
+ return;
712
+ }
713
+ setSkillsList(list);
714
+ });
715
+ return true;
638
716
  case 'provider': {
639
717
  // Interactive add-provider wizard (/provider): drives the shared
640
718
  // question panel, persists profile + key via the channel's settings/
@@ -788,6 +866,13 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
788
866
  channel.pushLocal('/cost', lines);
789
867
  return true;
790
868
  }
869
+ case 'settings': {
870
+ // Plugin settings screen (issue #165): opens immediately; the screen
871
+ // reads sections + namespaces from the channel itself.
872
+ setHelpOpen(false);
873
+ setSettingsOpen(true);
874
+ return true;
875
+ }
791
876
  case 'config': {
792
877
  const userHome = process.env.USERPROFILE ?? '';
793
878
  const lines = [
@@ -805,6 +890,13 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
805
890
  setHelpOpen(false);
806
891
  channel.pushLocal('/doctor', channel.doctorInfo());
807
892
  return true;
893
+ case 'plugins':
894
+ // Plugin diagnostics (C-070): trust banner first, then descriptor /
895
+ // grant matrix / ledger tail — or validate+negotiate for
896
+ // `/plugins check <path>` (rawInput carries the subcommand).
897
+ setHelpOpen(false);
898
+ channel.pushLocal('/plugins', channel.pluginsInfo(rawInput));
899
+ return true;
808
900
  case 'export': {
809
901
  const target = channel.exportSession();
810
902
  channel.notify(target === null
@@ -888,13 +980,6 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
888
980
  setHelpOpen(false);
889
981
  channel.pushLocal('/mcp', channel.mcpStatus());
890
982
  return true;
891
- case 'memory':
892
- setHelpOpen(false);
893
- channel.pushLocal('/memory', [
894
- t('memory-none'),
895
- t('memory-hint'),
896
- ]);
897
- return true;
898
983
  case 'update':
899
984
  setHelpOpen(false);
900
985
  if (onUpdate === undefined) {
@@ -1019,11 +1104,32 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1019
1104
  }
1020
1105
  setRewindIndex(0);
1021
1106
  setRewindConfirm(null);
1107
+ setRewindModes(null);
1108
+ setRewindBusy(false);
1109
+ rewindRequestRef.current += 1;
1022
1110
  setRewindOpen(true);
1023
1111
  };
1112
+ /**
1113
+ * Enter on a rewind candidate: ask the plugins first (tui/rewind-prompt).
1114
+ * A veto keeps the list open; offered modes turn the confirm pane into a
1115
+ * choice list; "no opinion" lands on the plain confirm as before.
1116
+ */
1117
+ const requestRewindConfirm = async (row) => {
1118
+ const token = ++rewindRequestRef.current;
1119
+ setRewindBusy(true);
1120
+ const decision = await channel.promptRewind(row);
1121
+ if (token !== rewindRequestRef.current)
1122
+ return;
1123
+ setRewindBusy(false);
1124
+ if (decision === 'cancel')
1125
+ return;
1126
+ setRewindConfirm(row);
1127
+ setRewindModes(decision?.modes ?? null);
1128
+ setRewindModeIndex(0);
1129
+ };
1024
1130
  /** Execute the confirmed rewind; the message comes back into the input. */
1025
- const performRewind = async (row) => {
1026
- const text = await channel.rewindTo(row);
1131
+ const performRewind = async (row, mode = null) => {
1132
+ const text = await channel.rewindTo(row, mode);
1027
1133
  if (text !== null) {
1028
1134
  // CC puts the restored message back in the prompt for re-editing.
1029
1135
  setHistoryFill(text);
@@ -1202,10 +1308,21 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1202
1308
  // search box, which Chat would otherwise route into the prompt.
1203
1309
  if (browserOpen)
1204
1310
  return;
1205
- // The questionnaire / approval panel owns the keyboard while one is
1206
- // pending (the panel's own useInput handles ↑/↓/Space/Tab/Enter/Esc;
1207
- // the prompt input is unmounted, so nothing else should see these keys).
1208
- if (questionSnapshot !== null || approvalSnapshot !== null)
1311
+ // Same for the settings screen: plain letters (s save / d discard) and
1312
+ // the field draft editor belong to it alone.
1313
+ if (settingsOpen)
1314
+ return;
1315
+ // A plugin scene (dsh-tui-scenes) or the trajectory scene owns the whole
1316
+ // screen while open: every key belongs to it. Unguarded, an Esc meant to
1317
+ // CLOSE the scene also reached the chat:cancel branch below whenever a
1318
+ // turn was in flight — closing the view and killing the turn in one key.
1319
+ if (sceneOpen || channel.pluginScene !== undefined)
1320
+ return;
1321
+ // The questionnaire / approval panel / managed plugin dialog owns the
1322
+ // keyboard while one is pending (the panel's own useInput handles
1323
+ // ↑/↓/Space/Tab/Enter/Esc; the prompt input is unmounted, so nothing
1324
+ // else should see these keys).
1325
+ if (questionSnapshot !== null || approvalSnapshot !== null || dialogSnapshot !== null)
1209
1326
  return;
1210
1327
  const returnCandidate = isPlainReturnInput(input, key);
1211
1328
  const returnNow = Date.now();
@@ -1457,6 +1574,30 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1457
1574
  }
1458
1575
  return;
1459
1576
  }
1577
+ if (skillsPickerOpen) {
1578
+ const list = skillsList ?? [];
1579
+ if (key.upArrow) {
1580
+ if (list.length > 0)
1581
+ setSkillsIndex(index => (index <= 0 ? list.length - 1 : index - 1));
1582
+ }
1583
+ else if (key.downArrow) {
1584
+ if (list.length > 0)
1585
+ setSkillsIndex(index => (index >= list.length - 1 ? 0 : index + 1));
1586
+ }
1587
+ else if (plainReturn) {
1588
+ const skill = list[skillsIndex];
1589
+ setSkillsPickerOpen(false);
1590
+ // 可直调技能 Enter 填入 `/name `——与 / 菜单选中技能同一条
1591
+ // completion-only 分发路径;模型专用技能(userInvocable=false)只关闭。
1592
+ // oxlint-disable-next-line typescript/no-unnecessary-condition -- runtime guard: out-of-range index on an empty list
1593
+ if (skill?.userInvocable)
1594
+ setHistoryFill(`/${skill.name} `);
1595
+ }
1596
+ else if (key.escape) {
1597
+ setSkillsPickerOpen(false);
1598
+ }
1599
+ return;
1600
+ }
1460
1601
  if (activityPickerOpen) {
1461
1602
  if (key.upArrow) {
1462
1603
  setActivityIndex(index => (index <= 0 ? PRESET_NAMES.length - 1 : index - 1));
@@ -1599,7 +1740,40 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1599
1740
  return;
1600
1741
  }
1601
1742
  if (rewindOpen) {
1743
+ // While the plugin decision is in flight the picker is read-only;
1744
+ // Esc abandons the wait (the stale answer is dropped by the token).
1745
+ if (rewindBusy) {
1746
+ if (key.escape) {
1747
+ rewindRequestRef.current += 1;
1748
+ setRewindBusy(false);
1749
+ }
1750
+ return;
1751
+ }
1602
1752
  if (rewindConfirm !== null) {
1753
+ if (rewindModes !== null) {
1754
+ // Plugin offered modes: the confirm pane is a choice list —
1755
+ // option 0 is always the built-in conversation-only rewind.
1756
+ const optionCount = rewindModes.length + 1;
1757
+ if (key.upArrow) {
1758
+ setRewindModeIndex(index => (index <= 0 ? optionCount - 1 : index - 1));
1759
+ }
1760
+ else if (key.downArrow) {
1761
+ setRewindModeIndex(index => (index >= optionCount - 1 ? 0 : index + 1));
1762
+ }
1763
+ else if (plainReturn) {
1764
+ const row = rewindConfirm;
1765
+ const mode = rewindModeIndex === 0 ? null : (rewindModes[rewindModeIndex - 1]?.id ?? null);
1766
+ setRewindOpen(false);
1767
+ setRewindConfirm(null);
1768
+ setRewindModes(null);
1769
+ void performRewind(row, mode);
1770
+ }
1771
+ else if (key.escape) {
1772
+ setRewindConfirm(null);
1773
+ setRewindModes(null);
1774
+ }
1775
+ return;
1776
+ }
1603
1777
  // Confirmation state: Enter rewinds, Esc backs out to the list.
1604
1778
  if (plainReturn) {
1605
1779
  const row = rewindConfirm;
@@ -1621,34 +1795,17 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1621
1795
  const row = rewindRows[rewindIndex];
1622
1796
  // oxlint-disable-next-line typescript/no-unnecessary-condition -- runtime guard: out-of-range index on an empty list
1623
1797
  if (row)
1624
- setRewindConfirm(row);
1798
+ void requestRewindConfirm(row);
1625
1799
  }
1626
1800
  else if (key.escape) {
1627
1801
  setRewindOpen(false);
1628
1802
  setRewindConfirm(null);
1803
+ setRewindModes(null);
1629
1804
  }
1630
1805
  return;
1631
1806
  }
1632
1807
  if (isMod(key) && input === 't') {
1633
- // Ctrl+T means "expand what is in front of you", and the two things it
1634
- // can expand never share the screen.
1635
- //
1636
- // The startup loaded-context panel renders only while the transcript is
1637
- // empty (see the render below) — and that is exactly the window where
1638
- // the trajectory has nothing in it yet, since the trajectory is folded
1639
- // from the session's own events. So the panel wins while it is up, and
1640
- // the scene takes over for the rest of the session.
1641
- //
1642
- // Claiming the key outright for the scene was wrong even though the
1643
- // panel binding looked dead: the panel prints its own `(Ctrl+T 展开)`
1644
- // hint, so the key still had a visible promise attached to it, and the
1645
- // scene it opened instead was necessarily empty at that moment. That
1646
- // left the panel reachable only by clicking its header, which is not a
1647
- // keyboard path at all.
1648
- if (loadedContextVisible) {
1649
- setLoadedContextOpen(previous => !previous);
1650
- return;
1651
- }
1808
+ // Ctrl+T has one stable meaning; loaded-context details live at /context.
1652
1809
  openScene();
1653
1810
  return;
1654
1811
  }
@@ -1740,10 +1897,45 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1740
1897
  else if (plainReturn && showPill) {
1741
1898
  handle?.scrollToBottom();
1742
1899
  }
1900
+ else if (extensionShortcuts !== undefined && extensionShortcuts.dispatch(input, key)) {
1901
+ // Plugin shortcut (tuiShortcuts seam): matched only after every
1902
+ // built-in global binding above declined — locals always win, and the
1903
+ // registry additionally refuses the prompt editor's own combos at
1904
+ // registration, so a plugin can never shadow anything. The handler
1905
+ // runs fire-and-forget; its errors arrive via the onError hook
1906
+ // (wired to the toast below).
1907
+ event.stopImmediatePropagation();
1908
+ }
1743
1909
  });
1744
1910
  // Working-activity line (spinner slot): context-pressure prefix shares the
1745
1911
  // StatusLine thresholds (amber ≥ 80, red ≥ 95).
1746
1912
  const activityWarnPct = contextPressurePct(channel.lastUsage, channel.contextWindow);
1913
+ // A plugin scene (dsh-tui-scenes) takes the whole terminal the same way
1914
+ // the trajectory scene does, and sits at the TOP of this return chain:
1915
+ // an open() landing while the session browser or the trajectory scene is
1916
+ // up must still take the screen (and the keyboard, via the useInput guard
1917
+ // above), not queue silently behind them. Closing the plugin scene lands
1918
+ // back on whatever screen was up before, so these early returns read as a
1919
+ // stack. The component comes from the registry, so its identity is stable
1920
+ // across renders and its hook state survives re-renders; it receives the
1921
+ // TUI's own React + ui kit because a plugin importing its own React copy
1922
+ // would die on the first hook call under this reconciler.
1923
+ // The scene is third-party code, so it renders inside a boundary: a render
1924
+ // crash reports to the transcript and closes the scene instead of taking
1925
+ // the whole TUI down through ink's app-level boundary.
1926
+ const pluginScene = channel.pluginScene;
1927
+ if (pluginScene !== undefined) {
1928
+ const node = (_jsx(PluginSceneBoundary, { id: pluginScene.id, onError: (id, error) => {
1929
+ channel.notify(t('plugin-scene-crashed', { id, err: error.message }), { color: 'error' });
1930
+ channel.closePluginScene();
1931
+ }, children: React.createElement(pluginScene.component, {
1932
+ React,
1933
+ ui: tuiKit,
1934
+ channel,
1935
+ close: () => channel.closePluginScene(),
1936
+ }) }));
1937
+ return fullscreen ? node : _jsx(AlternateScreen, { children: node });
1938
+ }
1747
1939
  // The browser is a screen, not an overlay: it REPLACES the conversation
1748
1940
  // rather than floating above it. Rendering it as an early return (after
1749
1941
  // every hook above has run) is what makes that literal — there is no
@@ -1754,8 +1946,15 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1754
1946
  // hosts are already in it and must not nest a second one.
1755
1947
  return fullscreen ? browser : _jsx(AlternateScreen, { children: browser });
1756
1948
  }
1949
+ // The settings screen follows the browser's rule exactly: it REPLACES the
1950
+ // conversation (an early return after every hook above has run), so there
1951
+ // is no transcript underneath to be repainted or bled through.
1952
+ if (settingsOpen) {
1953
+ const screen = _jsx(Settings, { channel: channel, onClose: () => setSettingsOpen(false) });
1954
+ return fullscreen ? screen : _jsx(AlternateScreen, { children: screen });
1955
+ }
1757
1956
  /** Prompt input is inert while a modal dialog owns the keyboard. */
1758
- const promptSelectionActive = selectionActive || modelPickerOpen || workspacePickerOpen || workspaceFlow !== null || activityPickerOpen ||
1957
+ const promptSelectionActive = selectionActive || modelPickerOpen || skillsPickerOpen || workspacePickerOpen || workspaceFlow !== null || activityPickerOpen ||
1759
1958
  effortSliderOpen || presetPickerOpen || themePickerOpen || thinkingOpen || historyOpen || rewindOpen || searchOpen ||
1760
1959
  btw !== null;
1761
1960
  // The trajectory scene replaces the conversation for as long as it is open.
@@ -1776,7 +1975,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1776
1975
  // 常驻、只移除其普通子节点,blit 解毒不触发,被覆盖的转录行会在
1777
1976
  // blit-skip 后留空(Esc 关 picker 一片空白的根因)。
1778
1977
  const dialogOverlayOpen = thinkingOpen || (workspacePickerOpen && workspaceTargets.length > 0) || workspaceFlow !== null ||
1779
- modelPickerOpen ||
1978
+ modelPickerOpen || skillsPickerOpen ||
1780
1979
  activityPickerOpen || (effortSliderOpen && effortOptions.length > 1) ||
1781
1980
  (presetPickerOpen && presetOptions.length > 0) || themePickerOpen || historyOpen ||
1782
1981
  rewindOpen || searchOpen;
@@ -1787,7 +1986,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1787
1986
  seekRow(lastUser.id);
1788
1987
  else
1789
1988
  handle?.scrollToBottom();
1790
- } })), _jsxs(ScrollBox, { ref: setHandle, flexDirection: "column", flexGrow: 1, flexShrink: 1, stickyScroll: true, children: [_jsx(LogoHeader, { model: channel.model, effort: channel.reasoningEffort, cwd: channel.displayCwd }), loadedContextVisible && (_jsx(LoadedContextPanel, { context: channel.loadedContext, open: loadedContextOpen, onToggle: () => { setLoadedContextOpen(previous => !previous); } })), _jsx(MessageList, { rows: channel.rows, failureHintRowId: failureHintRowId, failureHint: t('traj-hint-failure', { key: `${modLabel}t` }), expanded: expanded, expandedRows: expandedRows, selectedId: selectionActive ? selectedId : null, onToggleRow: toggleRowExpanded, model: channel.model, showAll: showAllMessages, thinkingVisible: thinkingVisible, onToggleAll: () => { setShowAllMessages(previous => !previous); }, onLoadOlder: () => channel.loadOlder(), registerRowRef: registerRowRef, scrollHandle: handle, forceMountRowId: forceMountRowId, newSinceRowId: isSticky ? null : lastSeenRowIdRef.current, onUnseenCount: setUnseenCount })] }), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [showPill && (_jsx(NewMessagesPill, { count: unseenCount, onClick: () => handle?.scrollToBottom() })), channel.working &&
1989
+ } })), _jsxs(ScrollBox, { ref: setHandle, flexDirection: "column", flexGrow: 1, flexShrink: 1, stickyScroll: true, children: [_jsx(LogoHeader, { model: channel.model, effort: channel.reasoningEffort, cwd: channel.displayCwd }), loadedContextVisible && (_jsx(LoadedContextPanel, { context: channel.loadedContext })), _jsx(MessageList, { rows: channel.rows, failureHintRowId: failureHintRowId, failureHint: t('traj-hint-failure', { key: `${modLabel}t` }), expanded: expanded, expandedRows: expandedRows, selectedId: selectionActive ? selectedId : null, onToggleRow: toggleRowExpanded, model: channel.model, diffLayout: channel.diffLayout, showAll: showAllMessages, thinkingVisible: thinkingVisible, onToggleAll: () => { setShowAllMessages(previous => !previous); }, onLoadOlder: () => channel.loadOlder(), registerRowRef: registerRowRef, scrollHandle: handle, forceMountRowId: forceMountRowId, newSinceRowId: isSticky ? null : lastSeenRowIdRef.current, onUnseenCount: setUnseenCount })] }), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [showPill && (_jsx(NewMessagesPill, { count: unseenCount, onClick: () => handle?.scrollToBottom() })), channel.working &&
1791
1990
  (channel.activityEnabled &&
1792
1991
  channel.workingActivity !== undefined &&
1793
1992
  channel.workingActivity.line !== '' &&
@@ -1796,7 +1995,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1796
1995
  // the animated chars/4 estimate, matching the classic
1797
1996
  // spinner's counter (the suffix used raw chars before,
1798
1997
  // inflating the reading next to a real upload number).
1799
- suffix: `${lastUploadTokens > 0 ? ` · ↑ ${formatTokens(lastUploadTokens)}` : ''} · ↓ ${formatTokens(Math.round(channel.responseChars / 4))} tokens` }) })) : (_jsx(WorkingSpinner, { mode: channel.spinnerMode, hasActiveTools: channel.activeToolCount > 0, responseLengthRef: responseLengthRef, uploadTokensRef: uploadTokensRef, loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, thinkingStatus: thinkingStatus }))), _jsx(GoalTodoPanel, { channel: channel }), approvalSnapshot !== null ? (_jsx(ApprovalPanel, { approval: approvalSnapshot, onDecide: outcome => approvals.decide(outcome) }, approvalSnapshot.key)) : btw !== null ? (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(BtwPanel, { question: btw.question, answer: btw.answer, error: btw.error, streaming: !btw.done, onClose: closeBtw, onCopy: () => {
1998
+ suffix: `${lastUploadTokens > 0 ? ` · ↑ ${formatTokens(lastUploadTokens)}` : ''} · ↓ ${formatTokens(Math.round(channel.responseChars / 4))} tokens` }) })) : (_jsx(WorkingSpinner, { mode: channel.spinnerMode, hasActiveTools: channel.activeToolCount > 0, responseLengthRef: responseLengthRef, uploadTokensRef: uploadTokensRef, loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, thinkingStatus: thinkingStatus }))), _jsx(GoalTodoPanel, { channel: channel }), statusEntries.length > 0 && (_jsx(Text, { dimColor: true, wrap: "truncate", children: statusEntries.map(entry => entry.text).join(' · ') })), approvalSnapshot !== null ? (_jsx(ApprovalPanel, { approval: approvalSnapshot, onDecide: outcome => approvals.decide(outcome) }, approvalSnapshot.key)) : dialogSnapshot !== null ? (_jsx(ExtensionDialog, { dialog: dialogSnapshot, onDecide: value => dialogs.decide(dialogSnapshot.key, value), onCancel: () => dialogs.cancel(dialogSnapshot.key) }, dialogSnapshot.key)) : btw !== null ? (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(BtwPanel, { question: btw.question, answer: btw.answer, error: btw.error, streaming: !btw.done, onClose: closeBtw, onCopy: () => {
1800
1999
  void setClipboard(btw.answer ?? '').then(raw => { if (raw)
1801
2000
  process.stdout.write(raw); });
1802
2001
  channel.notify(t('copied-chars', { n: (btw.answer ?? '').length }), { timeoutMs: 1500 });
@@ -1806,7 +2005,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1806
2005
  band: wakeBand,
1807
2006
  hint: trajectorySeen ? undefined : `${modLabel}t`,
1808
2007
  tick: Math.floor(wakeTime / 120),
1809
- } }), dialogOverlayOpen && (_jsxs(OverlayAbove, { maxHeight: Math.max(terminalRows - 8, 8), children: [thinkingOpen && (_jsx(ThinkingToggle, { currentValue: thinkingVisible, focusIndex: thinkingFocus, confirmationPending: thinkingConfirm })), workspacePickerOpen && workspaceTargets.length > 0 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(WorkspacePicker, { targets: workspaceTargets, focusIndex: workspaceIndex, currentCwd: channel.cwd }) })), workspaceFlow !== null && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(WorkspaceFlowPicker, { title: workspaceFlow.title, choices: workspaceFlow.choices, focusIndex: workspaceFlowIndex, busy: workspaceFlowBusy, input: workspaceFlowInput }) })), modelPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: models.length === 0 ? (_jsx(ModelPickerLoading, {})) : (_jsx(ModelPicker, { models: models, focusIndex: modelIndex, currentModel: `${channel.provider}/${channel.model}` })) })), activityPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(ActivityPicker, { focusIndex: activityIndex, currentPreset: channel.activityFrames }) })), effortSliderOpen && effortOptions.length > 1 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(EffortSlider, { options: effortOptions, focusIndex: effortIndex, currentId: channel.reasoningEffort }) })), presetPickerOpen && presetOptions.length > 0 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(PresetPicker, { presets: presetOptions, focusIndex: presetIndex, currentPreset: channel.agentPreset }) })), themePickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(ThemePicker, { focusIndex: themeIndex, currentTheme: themeName }) })), historyOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(HistorySearchDialog, { query: historyQuery, cursorOffset: historyCursor, matches: historyMatches, focusIndex: historyFocus }) })), rewindOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(RewindPicker, { rows: rewindRows, focusIndex: rewindIndex, confirmRow: rewindConfirm }) })), searchOpen && _jsx(TranscriptSearchBar, { query: searchQuery, cursorOffset: searchCursor, count: searchCount, current: searchCurrent })] }))] })] }));
2008
+ } }), dialogOverlayOpen && (_jsxs(OverlayAbove, { maxHeight: Math.max(terminalRows - 8, 8), children: [thinkingOpen && (_jsx(ThinkingToggle, { currentValue: thinkingVisible, focusIndex: thinkingFocus, confirmationPending: thinkingConfirm })), workspacePickerOpen && workspaceTargets.length > 0 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(WorkspacePicker, { targets: workspaceTargets, focusIndex: workspaceIndex, currentCwd: channel.cwd }) })), workspaceFlow !== null && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(WorkspaceFlowPicker, { title: workspaceFlow.title, choices: workspaceFlow.choices, focusIndex: workspaceFlowIndex, busy: workspaceFlowBusy, input: workspaceFlowInput }) })), modelPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: models.length === 0 ? (_jsx(ModelPickerLoading, {})) : (_jsx(ModelPicker, { models: models, focusIndex: modelIndex, currentModel: `${channel.provider}/${channel.model}` })) })), skillsPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: skillsList === null ? (_jsx(SkillsPickerLoading, {})) : (_jsx(SkillsPicker, { skills: skillsList, focusIndex: skillsIndex })) })), activityPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(ActivityPicker, { focusIndex: activityIndex, currentPreset: channel.activityFrames }) })), effortSliderOpen && effortOptions.length > 1 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(EffortSlider, { options: effortOptions, focusIndex: effortIndex, currentId: channel.reasoningEffort }) })), presetPickerOpen && presetOptions.length > 0 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(PresetPicker, { presets: presetOptions, focusIndex: presetIndex, currentPreset: channel.agentPreset }) })), themePickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(ThemePicker, { focusIndex: themeIndex, currentTheme: themeName }) })), historyOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(HistorySearchDialog, { query: historyQuery, cursorOffset: historyCursor, matches: historyMatches, focusIndex: historyFocus }) })), rewindOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(RewindPicker, { rows: rewindRows, focusIndex: rewindIndex, confirmRow: rewindConfirm, modes: rewindModes, modeIndex: rewindModeIndex, busy: rewindBusy }) })), searchOpen && _jsx(TranscriptSearchBar, { query: searchQuery, cursorOffset: searchCursor, count: searchCount, current: searchCurrent })] }))] })] }));
1810
2009
  }
1811
2010
  /**
1812
2011
  * The pinned prompt header shown above the ScrollBox while the user has
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import type { Channel } from '../dsh-adapter/channel.js';
3
+ /**
4
+ * The settings screen — `/settings` as a screen of its own (issue #165).
5
+ *
6
+ * The TUI owns only presentation here: plugin-declared sections from the
7
+ * `tuiSettingsSections` seam render as editable forms; every write goes back
8
+ * through the dsh settings service (revision-fenced `mutate` path ops) or the
9
+ * credentials seam (secret fields, blank-until-typed). Namespaces no plugin
10
+ * declared a section for stay read-only with a YAML hint — the same fallback
11
+ * the web front door gives namespaces without a card.
12
+ *
13
+ * Edits are staged, never settled live: typing changes a draft, and only the
14
+ * explicit save writes the durable document (see settingsEditor.ts for why).
15
+ */
16
+ export declare function Settings({ channel, onClose, }: {
17
+ channel: Channel;
18
+ onClose: () => void;
19
+ }): React.ReactNode;
20
+ //# sourceMappingURL=Settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Settings.d.ts","sourceRoot":"","sources":["../../../src/screens/Settings.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAUzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AA2CxD;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CA0VlB"}