@deepseek-harness-tui/dsh-tui 0.8.0 → 0.8.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 (434) hide show
  1. package/README.md +32 -15
  2. package/cordis.patch.yml +21 -2
  3. package/cordis.yml +12 -1
  4. package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -0
  5. package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -0
  6. package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -0
  7. package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -0
  8. package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -0
  9. package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -0
  10. package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -0
  11. package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -0
  12. package/dsh-ecosystem-spec/registry/README.md +14 -0
  13. package/dsh-ecosystem-spec/registry/contracts/decision-events-v1alpha1.json +13 -0
  14. package/dsh-ecosystem-spec/registry/contracts/scene-v1alpha1.json +13 -0
  15. package/dsh-ecosystem-spec/registry/contracts/settings-section-v1alpha1.json +13 -0
  16. package/dsh-ecosystem-spec/registry/contracts/tui-channel-v1alpha1.json +30 -0
  17. package/dsh-ecosystem-spec/registry/contracts/workspace-provider-v1alpha1.json +6 -0
  18. package/dsh-ecosystem-spec/registry/host-descriptor.tui.example.json +56 -0
  19. package/dsh-ecosystem-spec/registry/permissions-0.1.json +13 -0
  20. package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -0
  21. package/dsh-ecosystem-spec/schemas/conformance-claim.schema.json +15 -0
  22. package/dsh-ecosystem-spec/schemas/effect-ledger-record.schema.json +16 -0
  23. package/dsh-ecosystem-spec/schemas/host-descriptor.schema.json +26 -0
  24. package/lib/types/cc/figures.d.ts +4 -0
  25. package/lib/types/cc/figures.d.ts.map +1 -1
  26. package/lib/types/cc/figures.js +4 -0
  27. package/lib/types/command-trees.d.ts +2 -1
  28. package/lib/types/command-trees.d.ts.map +1 -1
  29. package/lib/types/command-trees.js +1 -1
  30. package/lib/types/commands.d.ts.map +1 -1
  31. package/lib/types/commands.js +2 -0
  32. package/lib/types/components/ExtensionDialog.d.ts +40 -0
  33. package/lib/types/components/ExtensionDialog.d.ts.map +1 -0
  34. package/lib/types/components/ExtensionDialog.js +210 -0
  35. package/lib/types/components/HelpMenu.js +1 -1
  36. package/lib/types/components/LoadedContextPanel.d.ts +5 -5
  37. package/lib/types/components/LoadedContextPanel.js +6 -6
  38. package/lib/types/components/LogoV2.d.ts.map +1 -1
  39. package/lib/types/components/LogoV2.js +16 -8
  40. package/lib/types/components/Markdown.d.ts +13 -1
  41. package/lib/types/components/Markdown.d.ts.map +1 -1
  42. package/lib/types/components/Markdown.js +15 -1
  43. package/lib/types/components/MessageList.d.ts +3 -1
  44. package/lib/types/components/MessageList.d.ts.map +1 -1
  45. package/lib/types/components/MessageList.js +111 -6
  46. package/lib/types/components/PromptInput.d.ts.map +1 -1
  47. package/lib/types/components/PromptInput.js +26 -12
  48. package/lib/types/components/RewindPicker.d.ts +13 -1
  49. package/lib/types/components/RewindPicker.d.ts.map +1 -1
  50. package/lib/types/components/RewindPicker.js +26 -2
  51. package/lib/types/components/StreamingMarkdown.d.ts +2 -8
  52. package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
  53. package/lib/types/components/StreamingMarkdown.js +51 -9
  54. package/lib/types/components/ToolUseLoader.d.ts +8 -3
  55. package/lib/types/components/ToolUseLoader.d.ts.map +1 -1
  56. package/lib/types/components/ToolUseLoader.js +43 -9
  57. package/lib/types/components/activityFrames.d.ts +1 -1
  58. package/lib/types/components/activityFrames.d.ts.map +1 -1
  59. package/lib/types/components/activityFrames.js +4 -1
  60. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +5 -1
  61. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  62. package/lib/types/components/messages/AssistantThinkingMessage.js +26 -3
  63. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  64. package/lib/types/components/messages/AssistantToolUseMessage.js +13 -2
  65. package/lib/types/dsh-adapter/channel.d.ts +61 -11
  66. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  67. package/lib/types/dsh-adapter/channel.js +767 -120
  68. package/lib/types/dsh-adapter/childStderr.d.ts.map +1 -1
  69. package/lib/types/dsh-adapter/childStderr.js +10 -0
  70. package/lib/types/dsh-adapter/command-attribution.d.ts +51 -0
  71. package/lib/types/dsh-adapter/command-attribution.d.ts.map +1 -0
  72. package/lib/types/dsh-adapter/command-attribution.js +93 -0
  73. package/lib/types/dsh-adapter/command-errors.d.ts +42 -0
  74. package/lib/types/dsh-adapter/command-errors.d.ts.map +1 -0
  75. package/lib/types/dsh-adapter/command-errors.js +63 -0
  76. package/lib/types/dsh-adapter/command-trees.d.ts +7 -1
  77. package/lib/types/dsh-adapter/command-trees.d.ts.map +1 -1
  78. package/lib/types/dsh-adapter/command-trees.js +70 -20
  79. package/lib/types/dsh-adapter/component-identity.d.ts +33 -0
  80. package/lib/types/dsh-adapter/component-identity.d.ts.map +1 -0
  81. package/lib/types/dsh-adapter/component-identity.js +108 -0
  82. package/lib/types/dsh-adapter/contract.d.ts +1 -1
  83. package/lib/types/dsh-adapter/contract.js +2 -2
  84. package/lib/types/dsh-adapter/decision-guard.d.ts +84 -0
  85. package/lib/types/dsh-adapter/decision-guard.d.ts.map +1 -0
  86. package/lib/types/dsh-adapter/decision-guard.js +348 -0
  87. package/lib/types/dsh-adapter/dialogs.d.ts +145 -0
  88. package/lib/types/dsh-adapter/dialogs.d.ts.map +1 -0
  89. package/lib/types/dsh-adapter/dialogs.js +316 -0
  90. package/lib/types/dsh-adapter/effect-ledger.d.ts +91 -0
  91. package/lib/types/dsh-adapter/effect-ledger.d.ts.map +1 -0
  92. package/lib/types/dsh-adapter/effect-ledger.js +251 -0
  93. package/lib/types/dsh-adapter/extension-events.d.ts +193 -0
  94. package/lib/types/dsh-adapter/extension-events.d.ts.map +1 -0
  95. package/lib/types/dsh-adapter/extension-events.js +207 -0
  96. package/lib/types/dsh-adapter/extensions.d.ts +32 -0
  97. package/lib/types/dsh-adapter/extensions.d.ts.map +1 -0
  98. package/lib/types/dsh-adapter/extensions.js +42 -0
  99. package/lib/types/dsh-adapter/grants.d.ts +25 -0
  100. package/lib/types/dsh-adapter/grants.d.ts.map +1 -0
  101. package/lib/types/dsh-adapter/grants.js +213 -0
  102. package/lib/types/dsh-adapter/host-access.d.ts +37 -0
  103. package/lib/types/dsh-adapter/host-access.d.ts.map +1 -0
  104. package/lib/types/dsh-adapter/host-access.js +652 -0
  105. package/lib/types/dsh-adapter/host-descriptor.d.ts +24 -0
  106. package/lib/types/dsh-adapter/host-descriptor.d.ts.map +1 -0
  107. package/lib/types/dsh-adapter/host-descriptor.js +169 -0
  108. package/lib/types/dsh-adapter/index.d.ts +4 -0
  109. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  110. package/lib/types/dsh-adapter/index.js +1 -0
  111. package/lib/types/dsh-adapter/message-observer.d.ts +173 -0
  112. package/lib/types/dsh-adapter/message-observer.d.ts.map +1 -0
  113. package/lib/types/dsh-adapter/message-observer.js +553 -0
  114. package/lib/types/dsh-adapter/plugin-host.d.ts +136 -0
  115. package/lib/types/dsh-adapter/plugin-host.d.ts.map +1 -0
  116. package/lib/types/dsh-adapter/plugin-host.js +365 -0
  117. package/lib/types/dsh-adapter/plugin-storage.d.ts +108 -0
  118. package/lib/types/dsh-adapter/plugin-storage.d.ts.map +1 -0
  119. package/lib/types/dsh-adapter/plugin-storage.js +397 -0
  120. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  121. package/lib/types/dsh-adapter/plugin.js +124 -14
  122. package/lib/types/dsh-adapter/plugins-info.d.ts +43 -0
  123. package/lib/types/dsh-adapter/plugins-info.d.ts.map +1 -0
  124. package/lib/types/dsh-adapter/plugins-info.js +276 -0
  125. package/lib/types/dsh-adapter/promptDebug.d.ts +0 -6
  126. package/lib/types/dsh-adapter/promptDebug.d.ts.map +1 -1
  127. package/lib/types/dsh-adapter/promptDebug.js +13 -4
  128. package/lib/types/dsh-adapter/renderers.d.ts +57 -0
  129. package/lib/types/dsh-adapter/renderers.d.ts.map +1 -0
  130. package/lib/types/dsh-adapter/renderers.js +173 -0
  131. package/lib/types/dsh-adapter/sanitize.d.ts +36 -0
  132. package/lib/types/dsh-adapter/sanitize.d.ts.map +1 -0
  133. package/lib/types/dsh-adapter/sanitize.js +65 -0
  134. package/lib/types/dsh-adapter/scenes.d.ts +15 -5
  135. package/lib/types/dsh-adapter/scenes.d.ts.map +1 -1
  136. package/lib/types/dsh-adapter/scenes.js +149 -35
  137. package/lib/types/dsh-adapter/settings-sections.d.ts +7 -3
  138. package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
  139. package/lib/types/dsh-adapter/settings-sections.js +106 -26
  140. package/lib/types/dsh-adapter/shortcuts.d.ts +107 -0
  141. package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -0
  142. package/lib/types/dsh-adapter/shortcuts.js +340 -0
  143. package/lib/types/dsh-adapter/status.d.ts +74 -0
  144. package/lib/types/dsh-adapter/status.d.ts.map +1 -0
  145. package/lib/types/dsh-adapter/status.js +234 -0
  146. package/lib/types/dsh-adapter/workspaces.d.ts +16 -5
  147. package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -1
  148. package/lib/types/dsh-adapter/workspaces.js +287 -170
  149. package/lib/types/extensions.d.ts +13 -0
  150. package/lib/types/extensions.d.ts.map +1 -0
  151. package/lib/types/extensions.js +21 -0
  152. package/lib/types/force-production-react.d.ts +1 -0
  153. package/lib/types/force-production-react.d.ts.map +1 -0
  154. package/lib/types/force-production-react.js +12 -0
  155. package/lib/types/i18n.d.ts +174 -20
  156. package/lib/types/i18n.d.ts.map +1 -1
  157. package/lib/types/i18n.js +56 -6
  158. package/lib/types/index.d.ts +1 -0
  159. package/lib/types/index.d.ts.map +1 -1
  160. package/lib/types/index.js +1 -0
  161. package/lib/types/ink/components/App.d.ts +2 -0
  162. package/lib/types/ink/components/App.d.ts.map +1 -1
  163. package/lib/types/ink/components/App.js +4 -0
  164. package/lib/types/ink/ink.d.ts +31 -3
  165. package/lib/types/ink/ink.d.ts.map +1 -1
  166. package/lib/types/ink/ink.js +90 -5
  167. package/lib/types/ink/log-update.d.ts.map +1 -1
  168. package/lib/types/ink/log-update.js +225 -56
  169. package/lib/types/ink/output.d.ts +35 -2
  170. package/lib/types/ink/output.d.ts.map +1 -1
  171. package/lib/types/ink/output.js +281 -14
  172. package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
  173. package/lib/types/ink/render-node-to-output.js +14 -6
  174. package/lib/types/ink/screen.d.ts +39 -0
  175. package/lib/types/ink/screen.d.ts.map +1 -1
  176. package/lib/types/ink/screen.js +117 -0
  177. package/lib/types/ink/terminal.d.ts.map +1 -1
  178. package/lib/types/ink/terminal.js +26 -6
  179. package/lib/types/ink/wrapAnsi.d.ts +1 -1
  180. package/lib/types/ink/wrapAnsi.d.ts.map +1 -1
  181. package/lib/types/ink/wrapAnsi.js +29 -2
  182. package/lib/types/plugin-host.d.ts +15 -0
  183. package/lib/types/plugin-host.d.ts.map +1 -0
  184. package/lib/types/plugin-host.js +17 -0
  185. package/lib/types/plugin-spec/negotiate.d.ts +11 -0
  186. package/lib/types/plugin-spec/negotiate.d.ts.map +1 -0
  187. package/lib/types/plugin-spec/negotiate.js +97 -0
  188. package/lib/types/plugin-spec/permission-scope.d.ts +32 -0
  189. package/lib/types/plugin-spec/permission-scope.d.ts.map +1 -0
  190. package/lib/types/plugin-spec/permission-scope.js +90 -0
  191. package/lib/types/plugin-spec/registry.d.ts +23 -0
  192. package/lib/types/plugin-spec/registry.d.ts.map +1 -0
  193. package/lib/types/plugin-spec/registry.js +252 -0
  194. package/lib/types/plugin-spec/schema-check.d.ts +17 -0
  195. package/lib/types/plugin-spec/schema-check.d.ts.map +1 -0
  196. package/lib/types/plugin-spec/schema-check.js +165 -0
  197. package/lib/types/plugin-spec/tui-extension.d.ts +16 -0
  198. package/lib/types/plugin-spec/tui-extension.d.ts.map +1 -0
  199. package/lib/types/plugin-spec/tui-extension.js +79 -0
  200. package/lib/types/plugin-spec/types.d.ts +114 -0
  201. package/lib/types/plugin-spec/types.d.ts.map +1 -0
  202. package/lib/types/plugin-spec/types.js +10 -0
  203. package/lib/types/plugin-spec/validate.d.ts +21 -0
  204. package/lib/types/plugin-spec/validate.d.ts.map +1 -0
  205. package/lib/types/plugin-spec/validate.js +138 -0
  206. package/lib/types/scenes.d.ts +2 -1
  207. package/lib/types/scenes.d.ts.map +1 -1
  208. package/lib/types/scenes.js +1 -1
  209. package/lib/types/screens/Chat.d.ts +14 -1
  210. package/lib/types/screens/Chat.d.ts.map +1 -1
  211. package/lib/types/screens/Chat.js +173 -49
  212. package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
  213. package/lib/types/screens/SessionBrowser.js +10 -3
  214. package/lib/types/sessions/view.d.ts +3 -2
  215. package/lib/types/sessions/view.d.ts.map +1 -1
  216. package/lib/types/sessions/view.js +18 -0
  217. package/lib/types/settings-sections.d.ts +2 -1
  218. package/lib/types/settings-sections.d.ts.map +1 -1
  219. package/lib/types/settings-sections.js +1 -1
  220. package/lib/types/theme.d.ts +5 -0
  221. package/lib/types/theme.d.ts.map +1 -1
  222. package/lib/types/theme.js +15 -0
  223. package/lib/types/update.d.ts +20 -0
  224. package/lib/types/update.d.ts.map +1 -1
  225. package/lib/types/update.js +54 -7
  226. package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
  227. package/lib/types/utils/execFileNoThrow.js +3 -0
  228. package/lib/types/utils/loaded-context.d.ts +8 -3
  229. package/lib/types/utils/loaded-context.d.ts.map +1 -1
  230. package/lib/types/utils/loaded-context.js +39 -3
  231. package/lib/types/utils/modifiers.d.ts.map +1 -1
  232. package/lib/types/utils/modifiers.js +3 -2
  233. package/lib/types/working-activity.d.ts +12 -0
  234. package/lib/types/working-activity.d.ts.map +1 -1
  235. package/lib/types/working-activity.js +13 -0
  236. package/lib/types/workspaces.d.ts +2 -1
  237. package/lib/types/workspaces.d.ts.map +1 -1
  238. package/lib/types/workspaces.js +1 -1
  239. package/node_modules/@dsh-std/command/CHANGELOG.md +8 -0
  240. package/node_modules/@dsh-std/command/LICENSE +21 -0
  241. package/node_modules/@dsh-std/command/README.md +26 -0
  242. package/node_modules/@dsh-std/command/README.zh.md +28 -0
  243. package/node_modules/@dsh-std/command/lib/index.d.ts +144 -0
  244. package/node_modules/@dsh-std/command/lib/index.d.ts.map +1 -0
  245. package/node_modules/@dsh-std/command/lib/index.js +252 -0
  246. package/node_modules/@dsh-std/command/lib/index.js.map +1 -0
  247. package/node_modules/@dsh-std/command/package.json +22 -0
  248. package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
  249. package/node_modules/@dsh-std/connection/LICENSE +21 -0
  250. package/node_modules/@dsh-std/connection/README.md +42 -0
  251. package/node_modules/@dsh-std/connection/README.zh.md +42 -0
  252. package/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts +125 -0
  253. package/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts.map +1 -0
  254. package/node_modules/@dsh-std/connection/lib/index.d.ts +89 -0
  255. package/node_modules/@dsh-std/connection/lib/index.d.ts.map +1 -0
  256. package/node_modules/@dsh-std/connection/lib/index.js +158 -0
  257. package/node_modules/@dsh-std/connection/lib/index.js.map +1 -0
  258. package/node_modules/@dsh-std/connection/lib/memory.d.ts +24 -0
  259. package/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -0
  260. package/node_modules/@dsh-std/connection/lib/memory.js +258 -0
  261. package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -0
  262. package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js +226 -0
  263. package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -0
  264. package/node_modules/@dsh-std/connection/package.json +20 -0
  265. package/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  266. package/node_modules/@dsh-std/core/LICENSE +21 -0
  267. package/node_modules/@dsh-std/core/README.md +13 -0
  268. package/node_modules/@dsh-std/core/README.zh.md +13 -0
  269. package/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  270. package/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  271. package/node_modules/@dsh-std/core/lib/index.js +424 -0
  272. package/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  273. package/node_modules/@dsh-std/core/package.json +21 -0
  274. package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -0
  275. package/node_modules/@dsh-std/manifest/LICENSE +21 -0
  276. package/node_modules/@dsh-std/manifest/README.md +5 -0
  277. package/node_modules/@dsh-std/manifest/README.zh.md +5 -0
  278. package/node_modules/@dsh-std/manifest/lib/index.d.ts +182 -0
  279. package/node_modules/@dsh-std/manifest/lib/index.d.ts.map +1 -0
  280. package/node_modules/@dsh-std/manifest/lib/index.js +625 -0
  281. package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -0
  282. package/node_modules/@dsh-std/manifest/package.json +20 -0
  283. package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -0
  284. package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -0
  285. package/node_modules/@dsh-std/messages/LICENSE +21 -0
  286. package/node_modules/@dsh-std/messages/README.md +5 -0
  287. package/node_modules/@dsh-std/messages/README.zh.md +7 -0
  288. package/node_modules/@dsh-std/messages/lib/index.d.ts +50 -0
  289. package/node_modules/@dsh-std/messages/lib/index.d.ts.map +1 -0
  290. package/node_modules/@dsh-std/messages/lib/index.js +151 -0
  291. package/node_modules/@dsh-std/messages/lib/index.js.map +1 -0
  292. package/node_modules/@dsh-std/messages/package.json +20 -0
  293. package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -0
  294. package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -0
  295. package/node_modules/@dsh-std/presentation/LICENSE +21 -0
  296. package/node_modules/@dsh-std/presentation/README.md +27 -0
  297. package/node_modules/@dsh-std/presentation/README.zh.md +29 -0
  298. package/node_modules/@dsh-std/presentation/lib/callback.d.ts +2 -0
  299. package/node_modules/@dsh-std/presentation/lib/callback.js +179 -0
  300. package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -0
  301. package/node_modules/@dsh-std/presentation/lib/index.d.ts +262 -0
  302. package/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -0
  303. package/node_modules/@dsh-std/presentation/lib/index.js +550 -0
  304. package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -0
  305. package/node_modules/@dsh-std/presentation/lib/interaction.d.ts +2 -0
  306. package/node_modules/@dsh-std/presentation/lib/interaction.js +2 -0
  307. package/node_modules/@dsh-std/presentation/lib/operations.d.ts +2 -0
  308. package/node_modules/@dsh-std/presentation/lib/operations.js +2 -0
  309. package/node_modules/@dsh-std/presentation/package.json +25 -0
  310. package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -0
  311. package/node_modules/@dsh-std/storage/LICENSE +21 -0
  312. package/node_modules/@dsh-std/storage/README.md +5 -0
  313. package/node_modules/@dsh-std/storage/README.zh.md +7 -0
  314. package/node_modules/@dsh-std/storage/lib/index.d.ts +48 -0
  315. package/node_modules/@dsh-std/storage/lib/index.d.ts.map +1 -0
  316. package/node_modules/@dsh-std/storage/lib/index.js +104 -0
  317. package/node_modules/@dsh-std/storage/lib/index.js.map +1 -0
  318. package/node_modules/@dsh-std/storage/package.json +20 -0
  319. package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -0
  320. package/package.json +110 -70
  321. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
  322. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -0
  323. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -0
  324. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -0
  325. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts +125 -0
  326. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts.map +1 -0
  327. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.d.ts +89 -0
  328. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.d.ts.map +1 -0
  329. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js +158 -0
  330. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -0
  331. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts +24 -0
  332. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -0
  333. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js +258 -0
  334. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -0
  335. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js +226 -0
  336. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -0
  337. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -0
  338. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  339. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -0
  340. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -0
  341. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -0
  342. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  343. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  344. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js +424 -0
  345. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  346. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -0
  347. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -0
  348. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -0
  349. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -0
  350. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -0
  351. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.d.ts +182 -0
  352. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.d.ts.map +1 -0
  353. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js +625 -0
  354. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -0
  355. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -0
  356. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -0
  357. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -0
  358. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -0
  359. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -0
  360. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -0
  361. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.d.ts +2 -0
  362. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js +179 -0
  363. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -0
  364. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts +262 -0
  365. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -0
  366. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js +550 -0
  367. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -0
  368. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/interaction.d.ts +2 -0
  369. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/interaction.js +2 -0
  370. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/operations.d.ts +2 -0
  371. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/operations.js +2 -0
  372. package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -0
  373. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  374. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -0
  375. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -0
  376. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -0
  377. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  378. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  379. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js +424 -0
  380. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  381. package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -0
  382. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  383. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -0
  384. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -0
  385. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -0
  386. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  387. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  388. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js +424 -0
  389. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  390. package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -0
  391. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  392. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -0
  393. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -0
  394. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -0
  395. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  396. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  397. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js +424 -0
  398. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  399. package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -0
  400. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
  401. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -0
  402. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -0
  403. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -0
  404. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts +125 -0
  405. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts.map +1 -0
  406. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.d.ts +89 -0
  407. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.d.ts.map +1 -0
  408. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js +158 -0
  409. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -0
  410. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts +24 -0
  411. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -0
  412. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js +258 -0
  413. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -0
  414. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js +226 -0
  415. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -0
  416. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -0
  417. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  418. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -0
  419. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -0
  420. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -0
  421. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  422. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  423. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js +424 -0
  424. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  425. package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -0
  426. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
  427. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -0
  428. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -0
  429. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -0
  430. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
  431. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
  432. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js +424 -0
  433. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -0
  434. package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -0
@@ -0,0 +1,21 @@
1
+ /** Semantic validation layered on the official manifest parser/projection. */
2
+ import { createAdmissionCatalog } from './tui-extension.js';
3
+ import type { ContractCoordinate, ContractRegistry, HostDescriptor, PermissionRegistry, PluginManifest, RegistryEntry, SubscriptionRef } from './types.js';
4
+ export interface ContractIndex {
5
+ registry: ContractRegistry;
6
+ permissions: PermissionRegistry;
7
+ facetApiVersions: string[];
8
+ protocols: ReturnType<typeof createAdmissionCatalog>['protocols'];
9
+ manifests: ReturnType<typeof createAdmissionCatalog>['manifests'];
10
+ lookupContract(coordinate: ContractCoordinate): RegistryEntry | undefined;
11
+ resolveContractRef(ref: ContractCoordinate): {
12
+ entry: RegistryEntry | null;
13
+ unregisteredVersion: boolean;
14
+ };
15
+ resolveSubscription(sub: SubscriptionRef): RegistryEntry;
16
+ }
17
+ export declare const groupOf: (apiVersion: string) => string;
18
+ export declare function createContractIndex(registry: ContractRegistry, permissions: PermissionRegistry): ContractIndex;
19
+ export declare function validatePlugin(index: ContractIndex, manifest: PluginManifest): void;
20
+ export declare function validateHost(index: ContractIndex, host: HostDescriptor): void;
21
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/plugin-spec/validate.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAG9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAG3D,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,eAAe,EAChB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,WAAW,EAAE,kBAAkB,CAAA;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,SAAS,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,WAAW,CAAC,CAAA;IACjE,SAAS,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,WAAW,CAAC,CAAA;IACjE,cAAc,CAAC,UAAU,EAAE,kBAAkB,GAAG,aAAa,GAAG,SAAS,CAAA;IACzE,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG;QAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;QAAC,mBAAmB,EAAE,OAAO,CAAA;KAAE,CAAA;IAC1G,mBAAmB,CAAC,GAAG,EAAE,eAAe,GAAG,aAAa,CAAA;CACzD;AAGD,eAAO,MAAM,OAAO,GAAI,YAAY,MAAM,KAAG,MAAwC,CAAA;AAErF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,GAAG,aAAa,CAsC9G;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CA4DnF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CA4B7E"}
@@ -0,0 +1,138 @@
1
+ /** Semantic validation layered on the official manifest parser/projection. */
2
+ import { projectManifest } from '@dsh-std/manifest';
3
+ import { createAdmissionCatalog } from './tui-extension.js';
4
+ import { registryEntries } from './registry.js';
5
+ import { INTERCEPT_PERMISSIONS, normalizePermissionScope } from './permission-scope.js';
6
+ const coordinateKey = (coordinate) => `${coordinate.apiVersion}#${coordinate.kind}`;
7
+ export const groupOf = (apiVersion) => apiVersion.split('/')[0] ?? '';
8
+ export function createContractIndex(registry, permissions) {
9
+ const entries = registryEntries(registry);
10
+ const byCoordinate = new Map(entries.map(entry => [coordinateKey(entry.coordinates), entry]));
11
+ const byName = new Map(entries.map(entry => [entry.name, entry]));
12
+ const { protocols, manifests } = createAdmissionCatalog();
13
+ const resolveContractRef = (ref) => {
14
+ const exact = byCoordinate.get(coordinateKey(ref));
15
+ if (exact !== undefined)
16
+ return { entry: exact, unregisteredVersion: false };
17
+ const sameGroup = entries.filter(entry => groupOf(entry.coordinates.apiVersion) === groupOf(ref.apiVersion));
18
+ if (sameGroup.length === 0)
19
+ throw new Error(`unknown protocol group: ${groupOf(ref.apiVersion)}`);
20
+ if (!sameGroup.some(entry => entry.coordinates.kind === ref.kind)) {
21
+ throw new Error(`unknown protocol kind: ${coordinateKey(ref)}`);
22
+ }
23
+ return { entry: null, unregisteredVersion: true };
24
+ };
25
+ const resolveSubscription = (subscription) => {
26
+ const entry = typeof subscription === 'string'
27
+ ? byName.get(subscription)
28
+ : byCoordinate.get(coordinateKey(subscription));
29
+ if (entry === undefined) {
30
+ throw new Error(`unknown subscription: ${typeof subscription === 'string' ? subscription : coordinateKey(subscription)}`);
31
+ }
32
+ if (entry.kind !== 'event')
33
+ throw new Error(`subscription must reference an event: ${entry.name}`);
34
+ return entry;
35
+ };
36
+ return {
37
+ registry,
38
+ permissions,
39
+ facetApiVersions: [...registry.facetApiVersions],
40
+ protocols,
41
+ manifests,
42
+ lookupContract: coordinate => byCoordinate.get(coordinateKey(coordinate)),
43
+ resolveContractRef,
44
+ resolveSubscription,
45
+ };
46
+ }
47
+ export function validatePlugin(index, manifest) {
48
+ if (!index.facetApiVersions.includes(manifest.facets.host.apiVersion)) {
49
+ throw new Error(`facet apiVersion is not admitted: ${manifest.facets.host.apiVersion}`);
50
+ }
51
+ for (const requirement of manifest.requires.contracts) {
52
+ index.resolveContractRef(requirement);
53
+ if (requirement.optional === true && !requirement.fallback) {
54
+ throw new Error(`optional protocol requires a TUI fallback: ${coordinateKey(requirement)}`);
55
+ }
56
+ }
57
+ for (const subscription of manifest.subscriptions)
58
+ index.resolveSubscription(subscription);
59
+ const knownPermissions = new Set(index.permissions.permissions.map(permission => permission.name));
60
+ const commandIds = new Set(manifest.contributes.commands.map(command => command.id));
61
+ const requiresDecisionEvents = manifest.requires.contracts.some(requirement => requirement.kind === 'DecisionEvents'
62
+ && groupOf(requirement.apiVersion) === groupOf('tui.dsh/v1alpha1'));
63
+ const capabilityForPermission = {
64
+ 'commands.invoke': { apiVersion: 'commands.dsh/v1alpha1', kind: 'Command' },
65
+ 'storage.local.read': { apiVersion: 'storage.dsh/v1alpha1', kind: 'LocalStorage' },
66
+ 'storage.local.write': { apiVersion: 'storage.dsh/v1alpha1', kind: 'LocalStorage' },
67
+ 'messages.observe.read': { apiVersion: 'messages.dsh/v1alpha1', kind: 'MessageObserver' },
68
+ 'session.input.intercept': { apiVersion: 'tui.dsh/v1alpha1', kind: 'DecisionEvents' },
69
+ 'session.rewind.intercept': { apiVersion: 'tui.dsh/v1alpha1', kind: 'DecisionEvents' },
70
+ 'session.switch.intercept': { apiVersion: 'tui.dsh/v1alpha1', kind: 'DecisionEvents' },
71
+ 'session.compact.intercept': { apiVersion: 'tui.dsh/v1alpha1', kind: 'DecisionEvents' },
72
+ };
73
+ for (const permission of manifest.permissions) {
74
+ if (!knownPermissions.has(permission.name)) {
75
+ throw new Error(`permission is not admitted by the TUI profile: ${permission.name}`);
76
+ }
77
+ if (normalizePermissionScope(permission.name, permission.scope, manifest.id) === undefined) {
78
+ throw new Error(`permission scope cannot be enforced: ${permission.name}@${permission.scope}`);
79
+ }
80
+ if (permission.name === 'commands.invoke' && !commandIds.has(permission.scope)) {
81
+ throw new Error(`commands.invoke scope is not a declared command: ${permission.scope}`);
82
+ }
83
+ if (INTERCEPT_PERMISSIONS.has(permission.name) && !requiresDecisionEvents) {
84
+ throw new Error(`${permission.name} requires tui.dsh/v1alpha1#DecisionEvents`);
85
+ }
86
+ const capability = capabilityForPermission[permission.name];
87
+ // An otherwise valid contract reference may use an unregistered version
88
+ // from the same protocol group. Keep that manifest structurally valid so
89
+ // negotiation can return UNKNOWN_PROTOCOL_VERSION rather than letting the
90
+ // permission/capability cross-check mask the version-drift decision.
91
+ if (capability !== undefined && !manifest.requires.contracts.some(requirement => requirement.kind === capability.kind && groupOf(requirement.apiVersion) === groupOf(capability.apiVersion))) {
92
+ throw new Error(`${permission.name} requires ${capability.apiVersion}#${capability.kind}`);
93
+ }
94
+ }
95
+ for (const commandId of commandIds) {
96
+ if (!manifest.permissions.some(permission => permission.name === 'commands.invoke' && permission.scope === commandId)) {
97
+ throw new Error(`declared command is missing commands.invoke permission scope: ${commandId}`);
98
+ }
99
+ }
100
+ const projected = projectManifest(manifest);
101
+ const report = index.manifests.validate(projected, index.protocols);
102
+ const errors = report.issues.filter(issue => issue.severity === 'error');
103
+ if (errors.length > 0)
104
+ throw new Error(errors.map(issue => issue.message).join('; '));
105
+ }
106
+ export function validateHost(index, host) {
107
+ const seen = new Set();
108
+ const knownPermissions = new Set(index.permissions.permissions.map(permission => permission.name));
109
+ for (const contract of host.contracts) {
110
+ const key = coordinateKey(contract);
111
+ if (seen.has(key))
112
+ throw new Error(`host declares duplicate protocol: ${key}`);
113
+ seen.add(key);
114
+ const entry = index.lookupContract(contract);
115
+ const definition = index.protocols.resolve(contract);
116
+ if (entry === undefined || definition === undefined)
117
+ throw new Error(`host declares an unknown protocol: ${key}`);
118
+ definition.validateSupport(Object.hasOwn(contract, 'spec') ? contract.spec : undefined);
119
+ if ('package' in entry) {
120
+ if (contract.definition.source !== 'dsh-std' || contract.definition.package !== entry.package) {
121
+ throw new Error(`host dsh-std definition source mismatch: ${key}`);
122
+ }
123
+ }
124
+ else if (contract.definition.source !== 'tui-profile' || contract.definition.profileHash !== entry.profileHash) {
125
+ throw new Error(`host TUI profile definition hash mismatch: ${key}`);
126
+ }
127
+ const expectedPermissions = [...entry.permissions].sort();
128
+ const actualPermissions = [...contract.permissions].sort();
129
+ if (expectedPermissions.length !== actualPermissions.length
130
+ || expectedPermissions.some((permission, index) => permission !== actualPermissions[index])) {
131
+ throw new Error(`host permission advertisement mismatch: ${key}`);
132
+ }
133
+ for (const permission of contract.permissions) {
134
+ if (!knownPermissions.has(permission))
135
+ throw new Error(`host declares unknown permission: ${permission}`);
136
+ }
137
+ }
138
+ }
@@ -1,3 +1,4 @@
1
- export * from './dsh-adapter/scenes.js';
1
+ export { name, TuiSceneRuntime } from './dsh-adapter/scenes.js';
2
+ export type { TuiSceneProps, TuiSceneDescriptor } from './dsh-adapter/scenes.js';
2
3
  export { default } from './dsh-adapter/scenes.js';
3
4
  //# sourceMappingURL=scenes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scenes.d.ts","sourceRoot":"","sources":["../../src/scenes.ts"],"names":[],"mappings":"AAEA,cAAc,yBAAyB,CAAA;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA"}
1
+ {"version":3,"file":"scenes.d.ts","sourceRoot":"","sources":["../../src/scenes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC/D,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAChF,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA"}
@@ -1,4 +1,4 @@
1
1
  // Re-export shim: the Cordis-backed implementation lives behind the adapter
2
2
  // boundary so UI consumers never import official @deepseek-ai/* packages.
3
- export * from './dsh-adapter/scenes.js';
3
+ export { name, TuiSceneRuntime } from './dsh-adapter/scenes.js';
4
4
  export { default } from './dsh-adapter/scenes.js';
@@ -1,8 +1,11 @@
1
1
  import React from 'react';
2
2
  import { type Channel } from '../dsh-adapter/channel.js';
3
3
  import type { QuestionStore } from '../dsh-adapter/questions.js';
4
+ import { TuiDialogStore } from '../dsh-adapter/dialogs.js';
5
+ import { TuiStatusStore } from '../dsh-adapter/status.js';
6
+ import type { TuiShortcutHost } from '../dsh-adapter/shortcuts.js';
4
7
  import { ApprovalStore } from '../dsh-adapter/approvals.js';
5
- export declare function Chat({ channel, questionStore, approvalStore, onExit, onUpdate, fullscreen, trajectorySeen: trajectorySeenProp, }: {
8
+ export declare function Chat({ channel, questionStore, approvalStore, extensionDialogs, extensionStatus, extensionShortcuts, onExit, onUpdate, fullscreen, trajectorySeen: trajectorySeenProp, }: {
6
9
  channel: Channel;
7
10
  questionStore: QuestionStore;
8
11
  /**
@@ -11,6 +14,16 @@ export declare function Chat({ channel, questionStore, approvalStore, onExit, on
11
14
  * simply never see an approval panel — the question panel keeps its seat.
12
15
  */
13
16
  approvalStore?: ApprovalStore;
17
+ /**
18
+ * The managed plugin dialog queue (tuiDialogs service's store). Optional
19
+ * for the same hosts as approvalStore; absent, plugin dialog requests
20
+ * park unanswered (their `timeoutMs` is the plugin's guard).
21
+ */
22
+ extensionDialogs?: TuiDialogStore;
23
+ /** Plugin status-line contributions (tuiStatus service's store). */
24
+ extensionStatus?: TuiStatusStore;
25
+ /** Host-only keyboard shortcut dispatch path. */
26
+ extensionShortcuts?: TuiShortcutHost;
14
27
  onExit: () => void;
15
28
  /** Update the installed package and restart the current TUI process. */
16
29
  onUpdate?: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/screens/Chat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,EAAqB,KAAK,OAAO,EAAsE,MAAM,2BAA2B,CAAA;AAC/I,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAEhE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AA6H3D,wBAAgB,IAAI,CAAC,EACnB,OAAO,EACP,aAAa,EACb,aAAa,EACb,MAAM,EACN,QAAQ,EACR,UAAkB,EAClB,cAAc,EAAE,kBAAkB,GACnC,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,aAAa,CAAA;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,qBAq9DA"}
1
+ {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/screens/Chat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,EAAqB,KAAK,OAAO,EAAsE,MAAM,2BAA2B,CAAA;AAC/I,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAGlE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAwI3D,wBAAgB,IAAI,CAAC,EACnB,OAAO,EACP,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,QAAQ,EACR,UAAkB,EAClB,cAAc,EAAE,kBAAkB,GACnC,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,aAAa,CAAA;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,cAAc,CAAA;IACjC,oEAAoE;IACpE,eAAe,CAAC,EAAE,cAAc,CAAA;IAChC,iDAAiD;IACjD,kBAAkB,CAAC,EAAE,eAAe,CAAA;IACpC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,qBAwlEA"}
@@ -8,10 +8,13 @@ import { isMod, isPlainReturnInput, modLabel } from '../utils/modifiers.js';
8
8
  import { formatTokens } from '../cc/format.js';
9
9
  import { homeDir } from '../utils/paths.js';
10
10
  import { sessionCwdMatches } from '../dsh-adapter/channel.js';
11
+ import { TuiDialogStore } from '../dsh-adapter/dialogs.js';
12
+ import { TuiStatusStore } from '../dsh-adapter/status.js';
11
13
  import { runProviderWizard } from '../dsh-adapter/providerWizard.js';
12
14
  import { ApprovalStore } from '../dsh-adapter/approvals.js';
13
15
  import { AskUserQuestionPanel } from '../components/questions/AskUserQuestionPanel.js';
14
16
  import { ApprovalPanel } from '../components/approvals/ApprovalPanel.js';
17
+ import { ExtensionDialog } from '../components/ExtensionDialog.js';
15
18
  import { useSearchHighlight } from '../ink/hooks/use-search-highlight.js';
16
19
  import { useTerminalTitle } from '../ink/hooks/use-terminal-title.js';
17
20
  import { useTerminalFocus } from '../ink/hooks/use-terminal-focus.js';
@@ -53,6 +56,7 @@ import { readTrajectorySeen, writeTrajectorySeen } from '../trajectoryPrefs.js';
53
56
  import { LoadingState } from '../components/design-system/LoadingState.js';
54
57
  import { Pane } from '../components/design-system/Pane.js';
55
58
  import { loadHistory } from '../history.js';
59
+ import { formatLoadedContextReport } from '../utils/loaded-context.js';
56
60
  /** Shared empty snapshot for hosts whose channel has no event log. */
57
61
  const NO_EVENTS = [];
58
62
  /** Row kinds the message-selection cursor can land on. */
@@ -121,7 +125,15 @@ function searchableText(row) {
121
125
  * snapshot stays null and the approval panel never mounts.
122
126
  */
123
127
  let fallbackApprovalStore;
124
- 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, }) {
125
137
  // Re-render whenever the channel mutates; rows/status are read fresh below.
126
138
  React.useSyncExternalStore(channel.subscribe, () => channel.version);
127
139
  // Re-render on language switches so the whole UI hot-swaps its strings.
@@ -135,6 +147,27 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
135
147
  // approvalStore share one inert instance that never holds an ask.
136
148
  const approvals = approvalStore ?? (fallbackApprovalStore ??= new ApprovalStore());
137
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
+ return extensionShortcuts.setErrorHandler(combo => {
168
+ channel.notify(t('ext-shortcut-failed', { combo }), { color: 'error', timeoutMs: 4000 });
169
+ });
170
+ }, [extensionShortcuts, channel]);
138
171
  // When a questionnaire batch completes, fold a Q&A summary into the
139
172
  // transcript (the tool card itself is hidden from the message list).
140
173
  const questionOpenRef = React.useRef(questionSnapshot !== null);
@@ -209,6 +242,17 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
209
242
  const [rewindOpen, setRewindOpen] = React.useState(false);
210
243
  const [rewindIndex, setRewindIndex] = React.useState(0);
211
244
  const [rewindConfirm, setRewindConfirm] = React.useState(null);
245
+ /** Plugin rewind modes (tui/rewind-prompt seam): extra choices offered in
246
+ * the confirm pane; null = the plain conversation-only confirm. */
247
+ const [rewindModes, setRewindModes] = React.useState(null);
248
+ const [rewindModeIndex, setRewindModeIndex] = React.useState(0);
249
+ /** True while the tui/rewind-prompt decision is in flight (a plugin may be
250
+ * showing its own dialog); keys except Esc are swallowed meanwhile. */
251
+ const [rewindBusy, setRewindBusy] = React.useState(false);
252
+ /** Monotonic token: only the latest rewind decision may land (a slow
253
+ * plugin answering after the user moved on must not open a confirm for
254
+ * a row they are no longer looking at). */
255
+ const rewindRequestRef = React.useRef(0);
212
256
  /** /btw side-question overlay (CC): pure UI state — the answer never
213
257
  * enters the transcript or the session log. */
214
258
  const [btw, setBtw] = React.useState(null);
@@ -230,15 +274,9 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
230
274
  /**
231
275
  * Close the scene.
232
276
  *
233
- * Leaving the alternate screen makes the terminal restore the main buffer
234
- * itself; Ink then repaints once, because `setAltScreenActive(false)` blanks
235
- * its front frame. In inline mode that costs one frame of scrollback per
236
- * round trip — the same, already-accepted cost as the Ctrl+X external-editor
237
- * handoff, and bounded per OPEN rather than per keystroke. Making it zero
238
- * needs the render core to save and restore the pre-alt front frame, which
239
- * is a separate change to `setAltScreenActive` and deliberately not made
240
- * here. `verify-trace-scene` pins the property that matters meanwhile:
241
- * navigating inside the scene adds nothing at all.
277
+ * Leaving the alternate screen makes the terminal restore the main buffer;
278
+ * Ink restores the matching saved frame and diffs any conversation changes
279
+ * that happened while the scene was open.
242
280
  */
243
281
  const closeScene = React.useCallback(() => {
244
282
  setSceneOpen(false);
@@ -253,16 +291,10 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
253
291
  });
254
292
  setSceneOpen(true);
255
293
  }, []);
256
- /** Startup context panel: expanded by header click or Ctrl+T. */
257
- const [loadedContextOpen, setLoadedContextOpen] = React.useState(false);
258
- /**
259
- * Whether the startup context panel is on screen. Derived once and read by
260
- * BOTH the Ctrl+T handler and the render below: the key's meaning depends on
261
- * the panel being visible, so a second copy of this condition is a place for
262
- * the two to disagree — which is how the key came to advertise one thing and
263
- * do another in the first place.
264
- */
294
+ /** The startup summary gives way to transcript rows after the first local command or message. */
265
295
  const loadedContextVisible = channel.rows.length === 0 && channel.loadedContext !== undefined;
296
+ /** Startup context panel: collapsed by default, toggled with Ctrl+P. */
297
+ const [loadedContextOpen, setLoadedContextOpen] = React.useState(false);
266
298
  /** `/` transcript search (less-style incsearch, ported from CC's REPL). */
267
299
  const [searchOpen, setSearchOpen] = React.useState(false);
268
300
  const [searchQuery, setSearchQuery] = React.useState('');
@@ -542,7 +574,8 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
542
574
  case 'lang': {
543
575
  // `/lang` shows the current UI language, `/lang en|zh` switches
544
576
  // (hot-swap, persisted to ~/.dsh-tui/lang.json). Precedence on next
545
- // launch: DSH_TUI_LANG > cordis.yml `lang` > the persisted choice.
577
+ // launch: DSH_TUI_LANG > settings.yaml `dsh-tui.lang` > cordis.yml
578
+ // `lang` > the persisted choice.
546
579
  const parts = rawInput.trim().split(/\s+/).filter(Boolean);
547
580
  if (parts[0] === 'status') {
548
581
  setHelpOpen(false);
@@ -558,6 +591,16 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
558
591
  if (isLang(parts[0])) {
559
592
  const ok = writeLangPref(parts[0]);
560
593
  setLang(parts[0]);
594
+ // Mirror into the dsh-tui settings namespace when it is served,
595
+ // so /settings and the next boot see the same last-write-wins
596
+ // choice (best effort; lang.json stays the fallback).
597
+ const settingsHost = channel.settingsHost();
598
+ const tuiView = settingsHost?.listNamespaces().find(entry => entry.ns === 'dsh-tui');
599
+ if (settingsHost !== undefined && tuiView !== undefined) {
600
+ void settingsHost
601
+ .write('dsh-tui', [{ op: 'set', path: ['lang'], value: parts[0] }], tuiView.revision)
602
+ .catch(() => { });
603
+ }
561
604
  channel.notify(ok ? t('lang-switched', { lang: parts[0] }) : t('lang-switch-failed', { lang: parts[0] }), { color: ok ? 'success' : 'error' });
562
605
  }
563
606
  else {
@@ -635,6 +678,16 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
635
678
  setHelpOpen(false);
636
679
  openScene();
637
680
  return true;
681
+ case 'context': {
682
+ setHelpOpen(false);
683
+ const context = channel.loadedContext;
684
+ if (context === undefined) {
685
+ channel.notify(t('context-unavailable'), { color: 'warning' });
686
+ return true;
687
+ }
688
+ channel.pushLocal('/context', formatLoadedContextReport(context));
689
+ return true;
690
+ }
638
691
  case 'help':
639
692
  setHelpOpen(true);
640
693
  return true;
@@ -841,6 +894,13 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
841
894
  setHelpOpen(false);
842
895
  channel.pushLocal('/doctor', channel.doctorInfo());
843
896
  return true;
897
+ case 'plugins':
898
+ // Plugin diagnostics (C-070): trust banner first, then descriptor /
899
+ // grant matrix / ledger tail — or validate+negotiate for
900
+ // `/plugins check <path>` (rawInput carries the subcommand).
901
+ setHelpOpen(false);
902
+ channel.pushLocal('/plugins', channel.pluginsInfo(rawInput));
903
+ return true;
844
904
  case 'export': {
845
905
  const target = channel.exportSession();
846
906
  channel.notify(target === null
@@ -1048,11 +1108,32 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1048
1108
  }
1049
1109
  setRewindIndex(0);
1050
1110
  setRewindConfirm(null);
1111
+ setRewindModes(null);
1112
+ setRewindBusy(false);
1113
+ rewindRequestRef.current += 1;
1051
1114
  setRewindOpen(true);
1052
1115
  };
1116
+ /**
1117
+ * Enter on a rewind candidate: ask the plugins first (tui/rewind-prompt).
1118
+ * A veto keeps the list open; offered modes turn the confirm pane into a
1119
+ * choice list; "no opinion" lands on the plain confirm as before.
1120
+ */
1121
+ const requestRewindConfirm = async (row) => {
1122
+ const token = ++rewindRequestRef.current;
1123
+ setRewindBusy(true);
1124
+ const decision = await channel.promptRewind(row);
1125
+ if (token !== rewindRequestRef.current)
1126
+ return;
1127
+ setRewindBusy(false);
1128
+ if (decision === 'cancel')
1129
+ return;
1130
+ setRewindConfirm(row);
1131
+ setRewindModes(decision?.modes ?? null);
1132
+ setRewindModeIndex(0);
1133
+ };
1053
1134
  /** Execute the confirmed rewind; the message comes back into the input. */
1054
- const performRewind = async (row) => {
1055
- const text = await channel.rewindTo(row);
1135
+ const performRewind = async (row, mode = null) => {
1136
+ const text = await channel.rewindTo(row, mode);
1056
1137
  if (text !== null) {
1057
1138
  // CC puts the restored message back in the prompt for re-editing.
1058
1139
  setHistoryFill(text);
@@ -1241,10 +1322,11 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1241
1322
  // turn was in flight — closing the view and killing the turn in one key.
1242
1323
  if (sceneOpen || channel.pluginScene !== undefined)
1243
1324
  return;
1244
- // The questionnaire / approval panel owns the keyboard while one is
1245
- // pending (the panel's own useInput handles ↑/↓/Space/Tab/Enter/Esc;
1246
- // the prompt input is unmounted, so nothing else should see these keys).
1247
- if (questionSnapshot !== null || approvalSnapshot !== null)
1325
+ // The questionnaire / approval panel / managed plugin dialog owns the
1326
+ // keyboard while one is pending (the panel's own useInput handles
1327
+ // ↑/↓/Space/Tab/Enter/Esc; the prompt input is unmounted, so nothing
1328
+ // else should see these keys).
1329
+ if (questionSnapshot !== null || approvalSnapshot !== null || dialogSnapshot !== null)
1248
1330
  return;
1249
1331
  const returnCandidate = isPlainReturnInput(input, key);
1250
1332
  const returnNow = Date.now();
@@ -1662,7 +1744,40 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1662
1744
  return;
1663
1745
  }
1664
1746
  if (rewindOpen) {
1747
+ // While the plugin decision is in flight the picker is read-only;
1748
+ // Esc abandons the wait (the stale answer is dropped by the token).
1749
+ if (rewindBusy) {
1750
+ if (key.escape) {
1751
+ rewindRequestRef.current += 1;
1752
+ setRewindBusy(false);
1753
+ }
1754
+ return;
1755
+ }
1665
1756
  if (rewindConfirm !== null) {
1757
+ if (rewindModes !== null) {
1758
+ // Plugin offered modes: the confirm pane is a choice list —
1759
+ // option 0 is always the built-in conversation-only rewind.
1760
+ const optionCount = rewindModes.length + 1;
1761
+ if (key.upArrow) {
1762
+ setRewindModeIndex(index => (index <= 0 ? optionCount - 1 : index - 1));
1763
+ }
1764
+ else if (key.downArrow) {
1765
+ setRewindModeIndex(index => (index >= optionCount - 1 ? 0 : index + 1));
1766
+ }
1767
+ else if (plainReturn) {
1768
+ const row = rewindConfirm;
1769
+ const mode = rewindModeIndex === 0 ? null : (rewindModes[rewindModeIndex - 1]?.id ?? null);
1770
+ setRewindOpen(false);
1771
+ setRewindConfirm(null);
1772
+ setRewindModes(null);
1773
+ void performRewind(row, mode);
1774
+ }
1775
+ else if (key.escape) {
1776
+ setRewindConfirm(null);
1777
+ setRewindModes(null);
1778
+ }
1779
+ return;
1780
+ }
1666
1781
  // Confirmation state: Enter rewinds, Esc backs out to the list.
1667
1782
  if (plainReturn) {
1668
1783
  const row = rewindConfirm;
@@ -1684,37 +1799,27 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1684
1799
  const row = rewindRows[rewindIndex];
1685
1800
  // oxlint-disable-next-line typescript/no-unnecessary-condition -- runtime guard: out-of-range index on an empty list
1686
1801
  if (row)
1687
- setRewindConfirm(row);
1802
+ void requestRewindConfirm(row);
1688
1803
  }
1689
1804
  else if (key.escape) {
1690
1805
  setRewindOpen(false);
1691
1806
  setRewindConfirm(null);
1807
+ setRewindModes(null);
1692
1808
  }
1693
1809
  return;
1694
1810
  }
1695
1811
  if (isMod(key) && input === 't') {
1696
- // Ctrl+T means "expand what is in front of you", and the two things it
1697
- // can expand never share the screen.
1698
- //
1699
- // The startup loaded-context panel renders only while the transcript is
1700
- // empty (see the render below) — and that is exactly the window where
1701
- // the trajectory has nothing in it yet, since the trajectory is folded
1702
- // from the session's own events. So the panel wins while it is up, and
1703
- // the scene takes over for the rest of the session.
1704
- //
1705
- // Claiming the key outright for the scene was wrong even though the
1706
- // panel binding looked dead: the panel prints its own `(Ctrl+T 展开)`
1707
- // hint, so the key still had a visible promise attached to it, and the
1708
- // scene it opened instead was necessarily empty at that moment. That
1709
- // left the panel reachable only by clicking its header, which is not a
1710
- // keyboard path at all.
1711
- if (loadedContextVisible) {
1712
- setLoadedContextOpen(previous => !previous);
1713
- return;
1714
- }
1812
+ // Ctrl+T opens the trajectory scene at any point in the session.
1715
1813
  openScene();
1716
1814
  return;
1717
1815
  }
1816
+ if (isMod(key) && input === 'p' && loadedContextVisible) {
1817
+ // Ctrl+P toggles the startup loaded-context panel while it is on
1818
+ // screen (transcript still empty); once rows take over and the
1819
+ // panel disappears the key has nothing left to do.
1820
+ setLoadedContextOpen(previous => !previous);
1821
+ return;
1822
+ }
1718
1823
  if (isMod(key) && input === 'r' && !helpOpen) {
1719
1824
  setHistoryQuery('');
1720
1825
  setHistoryCursor(0);
@@ -1760,6 +1865,16 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1760
1865
  else if (isMod(key) && input === 'o') {
1761
1866
  // Leaving transcript mode (Ctrl+O) — search was already handled above.
1762
1867
  setExpanded(previous => !previous);
1868
+ // The toggle rewrites every thinking row's layout at once. The
1869
+ // ordinary scroll-based diff pushes rows into terminal scrollback on
1870
+ // each expand and nothing removes them on collapse — rapid toggling
1871
+ // drifts the virtual↔scrollback mapping until writes misland
1872
+ // (garbled transcript, duplicated rows). Re-anchor the next frame:
1873
+ // in-place viewport repaint, nothing added to scrollback. Lookup
1874
+ // falls back to the only live instance for embedders whose stdout
1875
+ // isn't process.stdout (test harnesses).
1876
+ const ink = instances.get(process.stdout) ?? instances.values().next().value;
1877
+ ink?.reanchorViewport();
1763
1878
  }
1764
1879
  else if (input === '/' && !key.ctrl && !key.meta && !key.super) {
1765
1880
  // `/` in transcript mode (Ctrl+O expanded, CC's REPL semantics:
@@ -1803,6 +1918,15 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1803
1918
  else if (plainReturn && showPill) {
1804
1919
  handle?.scrollToBottom();
1805
1920
  }
1921
+ else if (extensionShortcuts !== undefined && extensionShortcuts.dispatch(input, key)) {
1922
+ // Plugin shortcut (tuiShortcuts seam): matched only after every
1923
+ // built-in global binding above declined — locals always win, and the
1924
+ // registry additionally refuses the prompt editor's own combos at
1925
+ // registration, so a plugin can never shadow anything. The handler
1926
+ // runs fire-and-forget; its errors arrive via the onError hook
1927
+ // (wired to the toast below).
1928
+ event.stopImmediatePropagation();
1929
+ }
1806
1930
  });
1807
1931
  // Working-activity line (spinner slot): context-pressure prefix shares the
1808
1932
  // StatusLine thresholds (amber ≥ 80, red ≥ 95).
@@ -1883,7 +2007,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1883
2007
  seekRow(lastUser.id);
1884
2008
  else
1885
2009
  handle?.scrollToBottom();
1886
- } })), _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, 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 &&
2010
+ } })), _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, diffLayout: channel.diffLayout, thinkingFold: channel.thinkingFold, 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 &&
1887
2011
  (channel.activityEnabled &&
1888
2012
  channel.workingActivity !== undefined &&
1889
2013
  channel.workingActivity.line !== '' &&
@@ -1892,7 +2016,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1892
2016
  // the animated chars/4 estimate, matching the classic
1893
2017
  // spinner's counter (the suffix used raw chars before,
1894
2018
  // inflating the reading next to a real upload number).
1895
- 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: () => {
2019
+ 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: () => {
1896
2020
  void setClipboard(btw.answer ?? '').then(raw => { if (raw)
1897
2021
  process.stdout.write(raw); });
1898
2022
  channel.notify(t('copied-chars', { n: (btw.answer ?? '').length }), { timeoutMs: 1500 });
@@ -1902,7 +2026,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
1902
2026
  band: wakeBand,
1903
2027
  hint: trajectorySeen ? undefined : `${modLabel}t`,
1904
2028
  tick: Math.floor(wakeTime / 120),
1905
- } }), 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 }) })), searchOpen && _jsx(TranscriptSearchBar, { query: searchQuery, cursorOffset: searchCursor, count: searchCount, current: searchCurrent })] }))] })] }));
2029
+ } }), 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 })] }))] })] }));
1906
2030
  }
1907
2031
  /**
1908
2032
  * The pinned prompt header shown above the ScrollBox while the user has
@@ -1 +1 @@
1
- {"version":3,"file":"SessionBrowser.d.ts","sourceRoot":"","sources":["../../../src/screens/SessionBrowser.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAsBzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAoDxD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,IAAI,EACJ,WAAW,EACX,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CAselB"}
1
+ {"version":3,"file":"SessionBrowser.d.ts","sourceRoot":"","sources":["../../../src/screens/SessionBrowser.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAsBzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAoDxD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,IAAI,EACJ,WAAW,EACX,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CA4elB"}