@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
@@ -0,0 +1,210 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The managed plugin dialog (`ctx.tuiDialogs`) — one panel rendering the
4
+ * store's current snapshot in the chat chrome (the slot approval/question
5
+ * panels occupy). Three kinds share one component:
6
+ *
7
+ * - `select` — focus list (↑/↓, windowed), Enter settles the option id
8
+ * - `confirm` — two rows (confirm/cancel), Enter settles the boolean
9
+ * - `input` — single-line text edit, Enter settles the text
10
+ *
11
+ * Esc (and Ctrl+C) always cancels — the plugin's promise resolves with the
12
+ * cancelled value. The panel owns the keyboard through its own useInput,
13
+ * the same contract as ApprovalPanel/AskUserQuestionPanel: Chat's global
14
+ * handler early-returns while a snapshot is pending.
15
+ *
16
+ * Two input-pipeline rules shape every handler below:
17
+ *
18
+ * - BATCHED KEYS: a terminal delivers one stdin chunk as several key events
19
+ * inside a single React batch (Down+Enter arrives together), so state
20
+ * queued by the first event is NOT visible to the second. Every piece of
21
+ * editing state the handlers act on (focus, value, cursor) therefore
22
+ * lives in a ref mutated SYNCHRONOUSLY per event; the useState mirror
23
+ * only exists to re-render.
24
+ * - CODE POINTS: cursor movement and deletion step over whole code points
25
+ * (`[...s]` iteration, same contract as the transcript search box), so an
26
+ * emoji can never be split into a lone surrogate.
27
+ *
28
+ * All text arrives pre-sanitized from TuiDialogRuntime (control chars
29
+ * stripped, cell-width capped); the panel still renders everything through
30
+ * ListItem's single-line truncation.
31
+ */
32
+ import React from 'react';
33
+ import { t } from '../i18n.js';
34
+ import { Box, Text, useInput, useTerminalSize } from '../ui.js';
35
+ import { stringWidth } from '../ink/stringWidth.js';
36
+ import { isPlainReturnInput } from '../utils/modifiers.js';
37
+ import { Pane } from './design-system/Pane.js';
38
+ import { ListItem } from './design-system/ListItem.js';
39
+ import { HintLine } from './design-system/HintLine.js';
40
+ import { listWindow } from './listWindow.js';
41
+ import { INPUT_CELLS } from '../dsh-adapter/dialogs.js';
42
+ import { capCells, flattenInline } from '../dsh-adapter/sanitize.js';
43
+ export function ExtensionDialog({ dialog, onDecide, onCancel }) {
44
+ switch (dialog.kind) {
45
+ case 'select':
46
+ return _jsx(SelectDialog, { dialog: dialog, onDecide: onDecide, onCancel: onCancel });
47
+ case 'confirm':
48
+ return _jsx(ConfirmDialog, { dialog: dialog, onDecide: onDecide, onCancel: onCancel });
49
+ case 'input':
50
+ return _jsx(InputDialog, { dialog: dialog, onDecide: onDecide, onCancel: onCancel });
51
+ }
52
+ }
53
+ function SelectDialog({ dialog, onDecide, onCancel, }) {
54
+ const [focusIndex, setFocusIndex] = React.useState(0);
55
+ // Synchronous source of truth for the handlers (see the module header):
56
+ // Down+Enter in one stdin chunk must move AND read the new focus.
57
+ const focusRef = React.useRef(0);
58
+ const moveFocus = (delta) => {
59
+ const next = (focusRef.current + delta + dialog.options.length) % dialog.options.length;
60
+ focusRef.current = next;
61
+ setFocusIndex(next);
62
+ };
63
+ const { rows: terminalRows } = useTerminalSize();
64
+ useInput((input, key, event) => {
65
+ if (key.escape || (key.ctrl && input === 'c')) {
66
+ onCancel();
67
+ return;
68
+ }
69
+ if (key.upArrow) {
70
+ moveFocus(-1);
71
+ return;
72
+ }
73
+ if (key.downArrow) {
74
+ moveFocus(1);
75
+ return;
76
+ }
77
+ // isPasted lives on the InputEvent, not the key: a bracketed paste that
78
+ // is all line breaks is pasted content, never an Enter press.
79
+ if (isPlainReturnInput(input, { ...key, isPasted: event.isPasted })) {
80
+ const option = dialog.options[focusRef.current];
81
+ if (option !== undefined)
82
+ onDecide(option.id);
83
+ }
84
+ }, { isActive: true });
85
+ // Row budget mirrors the rewind picker: a described option costs 2 rows,
86
+ // a bare one 1; frame rows: Pane 2 + title 2 + footer 1 + slack.
87
+ const { start, end } = listWindow(dialog.options.map(option => (option.description === undefined ? 1 : 2)), focusIndex, Math.max(terminalRows - 10, 2));
88
+ return (_jsxs(Pane, { color: "permission", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "remember", bold: true, children: dialog.title }) }), dialog.options.slice(start, end).map((option, index) => {
89
+ const absoluteIndex = start + index;
90
+ return (_jsx(ListItem, { isFocused: absoluteIndex === focusIndex, description: option.description, showScrollUp: absoluteIndex === start && start > 0, showScrollDown: absoluteIndex === end - 1 && end < dialog.options.length, children: option.label }, option.id));
91
+ })] }), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('hint-select-exit') }) })] }));
92
+ }
93
+ function ConfirmDialog({ dialog, onDecide, onCancel, }) {
94
+ const [focusIndex, setFocusIndex] = React.useState(0);
95
+ // Synchronous source of truth for the handlers (see the module header):
96
+ // Right+Enter in one stdin chunk must settle the NEW row, not the old.
97
+ const focusRef = React.useRef(0);
98
+ const labels = [
99
+ dialog.confirmLabel || t('ext-dialog-yes'),
100
+ dialog.cancelLabel || t('ext-dialog-no'),
101
+ ];
102
+ const moveFocus = (delta) => {
103
+ const next = (focusRef.current + delta + labels.length) % labels.length;
104
+ focusRef.current = next;
105
+ setFocusIndex(next);
106
+ };
107
+ useInput((input, key, event) => {
108
+ if (key.escape || (key.ctrl && input === 'c')) {
109
+ onCancel();
110
+ return;
111
+ }
112
+ if (key.upArrow || key.leftArrow) {
113
+ moveFocus(-1);
114
+ return;
115
+ }
116
+ if (key.downArrow || key.rightArrow) {
117
+ moveFocus(1);
118
+ return;
119
+ }
120
+ // isPasted lives on the InputEvent, not the key: a bracketed paste that
121
+ // is all line breaks must not confirm on the default focus.
122
+ if (isPlainReturnInput(input, { ...key, isPasted: event.isPasted })) {
123
+ onDecide(focusRef.current === 0);
124
+ }
125
+ }, { isActive: true });
126
+ return (_jsxs(Pane, { color: "permission", children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "remember", bold: true, children: dialog.title }), dialog.message !== undefined && _jsx(Text, { dimColor: true, children: dialog.message })] }), labels.map((label, index) => (_jsx(ListItem, { isFocused: index === focusIndex, children: label }, label)))] }), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('hint-select-exit') }) })] }));
127
+ }
128
+ function InputDialog({ dialog, onDecide, onCancel, }) {
129
+ const [value, setValue] = React.useState(dialog.initial);
130
+ const [cursor, setCursor] = React.useState(() => [...dialog.initial].length);
131
+ // Synchronous source of truth for the handlers (see the module header):
132
+ // two Backspaces in one stdin chunk must BOTH delete, each seeing the
133
+ // other's result. The cursor counts CODE POINTS, not UTF-16 units — an
134
+ // emoji is one step and can never be split into a lone surrogate.
135
+ const valueRef = React.useRef(dialog.initial);
136
+ const cursorRef = React.useRef([...dialog.initial].length);
137
+ const applyEdit = (nextValue, nextCursor) => {
138
+ valueRef.current = nextValue;
139
+ cursorRef.current = nextCursor;
140
+ setValue(nextValue);
141
+ setCursor(nextCursor);
142
+ };
143
+ useInput((input, key, event) => {
144
+ if (key.escape || (key.ctrl && input === 'c')) {
145
+ onCancel();
146
+ return;
147
+ }
148
+ // isPasted lives on the InputEvent, not the key: a bracketed paste that
149
+ // is all line breaks is inserted as text, not submitted.
150
+ if (isPlainReturnInput(input, { ...key, isPasted: event.isPasted })) {
151
+ onDecide(valueRef.current);
152
+ return;
153
+ }
154
+ const points = [...valueRef.current];
155
+ const at = cursorRef.current;
156
+ // Single-line editing, same key set as the transcript search bar.
157
+ if (key.backspace) {
158
+ if (at > 0) {
159
+ points.splice(at - 1, 1);
160
+ applyEdit(points.join(''), at - 1);
161
+ }
162
+ return;
163
+ }
164
+ if (key.delete) {
165
+ if (at < points.length) {
166
+ points.splice(at, 1);
167
+ applyEdit(points.join(''), at);
168
+ }
169
+ return;
170
+ }
171
+ if (key.leftArrow) {
172
+ if (at > 0)
173
+ applyEdit(valueRef.current, at - 1);
174
+ return;
175
+ }
176
+ if (key.rightArrow) {
177
+ if (at < points.length)
178
+ applyEdit(valueRef.current, at + 1);
179
+ return;
180
+ }
181
+ if (key.home) {
182
+ applyEdit(valueRef.current, 0);
183
+ return;
184
+ }
185
+ if (key.end) {
186
+ applyEdit(valueRef.current, points.length);
187
+ return;
188
+ }
189
+ if (input && !key.ctrl && !key.meta && !key.super && !key.tab && !key.escape) {
190
+ // A bracketed paste arrives as one chunk and may carry newlines/control
191
+ // chars — this is a single-line panel, so flatten them to spaces. Every
192
+ // edit path holds the value at INPUT_CELLS cells so the resolved answer
193
+ // keeps the documented bound: typing past the cap is ignored, an
194
+ // oversized paste is truncated (never silently unbounded).
195
+ const chunk = event.isPasted ? flattenInline(input) : input;
196
+ const chunkPoints = [...chunk].length;
197
+ const candidate = points.slice(0, at).join('') + chunk + points.slice(at).join('');
198
+ if (stringWidth(candidate) <= INPUT_CELLS) {
199
+ applyEdit(candidate, at + chunkPoints);
200
+ }
201
+ else if (event.isPasted) {
202
+ const capped = capCells(candidate, INPUT_CELLS);
203
+ applyEdit(capped, Math.min(at + chunkPoints, [...capped].length));
204
+ }
205
+ }
206
+ }, { isActive: true });
207
+ const shown = value === '' && dialog.placeholder !== undefined ? dialog.placeholder : value;
208
+ const shownPoints = [...shown];
209
+ return (_jsxs(Pane, { color: "permission", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "remember", bold: true, children: dialog.title }) }), _jsxs(Text, { children: [_jsx(Text, { dimColor: value === '', children: shownPoints.slice(0, cursor).join('') }), _jsx(Text, { inverse: true, children: shownPoints[cursor] ?? ' ' }), _jsx(Text, { children: shownPoints.slice(cursor + 1).join('') })] })] }), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('hint-ext-dialog-input') }) })] }));
210
+ }
@@ -16,5 +16,5 @@ import { modLabel } from '../utils/modifiers.js';
16
16
  */
17
17
  export function HelpMenu({ commands, }) {
18
18
  const chrome = commands.filter(command => !command.skill);
19
- return (_jsxs(Box, { paddingX: 2, flexDirection: "row", gap: 4, children: [_jsxs(Box, { flexDirection: "column", width: 26, flexShrink: 0, children: [_jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-for-commands') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-this-help') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-verbose-output', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-toggle-context', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-search-history', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-interrupt') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-exit') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-redraw', { mod: modLabel }) }) })] }), _jsxs(Box, { flexDirection: "column", width: 24, flexShrink: 0, children: [_jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-clear-input') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-history-nav') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-move-cursor') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-word-jumps', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-complete-command') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-cycle-mode') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-open-editor') }) })] }), _jsxs(Box, { flexDirection: "column", flexShrink: 1, children: [_jsx(Text, { dimColor: true, children: t('help-commands-title') }), chrome.map(command => (_jsx(Box, { children: _jsxs(Text, { dimColor: true, wrap: "truncate-end", children: ["/", command.name, " \u2014 ", localizedDescription(command)] }) }, command.name)))] })] }));
19
+ return (_jsxs(Box, { paddingX: 2, flexDirection: "row", gap: 4, children: [_jsxs(Box, { flexDirection: "column", width: 26, flexShrink: 0, children: [_jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-for-commands') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-this-help') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-verbose-output', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-open-trajectory', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-search-history', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-interrupt') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-exit') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-redraw', { mod: modLabel }) }) })] }), _jsxs(Box, { flexDirection: "column", width: 24, flexShrink: 0, children: [_jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-clear-input') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-history-nav') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-move-cursor') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-word-jumps', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-complete-command') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-cycle-mode') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-open-editor') }) })] }), _jsxs(Box, { flexDirection: "column", flexShrink: 1, children: [_jsx(Text, { dimColor: true, children: t('help-commands-title') }), chrome.map(command => (_jsx(Box, { children: _jsxs(Text, { dimColor: true, wrap: "truncate-end", children: ["/", command.name, " \u2014 ", localizedDescription(command)] }) }, command.name)))] })] }));
20
20
  }
@@ -1,20 +1,15 @@
1
1
  import React from 'react';
2
2
  import type { LoadedContext } from '../dsh-adapter/channel.js';
3
3
  /**
4
- * The startup context panel: a collapsed one-line summary of what a
4
+ * The startup context summary: a one-line inventory of what a
5
5
  * fresh conversation will load for the current agent (system prompt
6
6
  * sections, workspace instruction files, dynamic context, skill catalog,
7
- * tools). Toggle with Ctrl+T (see HelpMenu; the ported ink core has no
8
- * mouse-click handling, so the header is not clickable); the panel renders
9
- * only while the transcript is still empty — the first message's rows take
10
- * over. Renders nothing for an empty snapshot.
7
+ * tools). `/context` renders the existing details as a local report; the
8
+ * summary itself disappears once the transcript has rows. Renders nothing
9
+ * for an empty snapshot.
11
10
  * @param context - the channel's loaded-context snapshot.
12
- * @param open - whether the grouped details are shown.
13
- * @param onToggle - flips `open`; fired by the Ctrl+T keybinding.
14
11
  */
15
- export declare function LoadedContextPanel({ context, open, onToggle, }: {
12
+ export declare function LoadedContextPanel({ context }: {
16
13
  context: LoadedContext;
17
- open: boolean;
18
- onToggle: () => void;
19
14
  }): React.ReactNode;
20
15
  //# sourceMappingURL=LoadedContextPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LoadedContextPanel.d.ts","sourceRoot":"","sources":["../../../src/components/LoadedContextPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,2BAA2B,CAAA;AA+BlF;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,aAAa,CAAA;IACtB,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB,GAAG,KAAK,CAAC,SAAS,CAoElB"}
1
+ {"version":3,"file":"LoadedContextPanel.d.ts","sourceRoot":"","sources":["../../../src/components/LoadedContextPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAG9D;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,aAAa,CAAA;CAAE,GAAG,KAAK,CAAC,SAAS,CAW3F"}
@@ -1,30 +1,19 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { t } from '../i18n.js';
3
3
  import { Box, Text } from '../ui.js';
4
- import { summarizeLoadedContext, truncateContextText } from '../utils/loaded-context.js';
5
- /** One named entry (section or dynamic context) with its full text. */
6
- function Entry({ entry }) {
7
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, dimColor: true, children: entry.name }), _jsx(Text, { dimColor: true, wrap: "wrap", children: truncateContextText(entry.text) })] }));
8
- }
9
- /** A titled group of rows inside the expanded panel. */
10
- function Group({ title, children }) {
11
- return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, color: "subtle", children: title }), _jsx(Box, { flexDirection: "column", paddingLeft: 2, children: children })] }));
12
- }
4
+ import { summarizeLoadedContext } from '../utils/loaded-context.js';
13
5
  /**
14
- * The startup context panel: a collapsed one-line summary of what a
6
+ * The startup context summary: a one-line inventory of what a
15
7
  * fresh conversation will load for the current agent (system prompt
16
8
  * sections, workspace instruction files, dynamic context, skill catalog,
17
- * tools). Toggle with Ctrl+T (see HelpMenu; the ported ink core has no
18
- * mouse-click handling, so the header is not clickable); the panel renders
19
- * only while the transcript is still empty — the first message's rows take
20
- * over. Renders nothing for an empty snapshot.
9
+ * tools). `/context` renders the existing details as a local report; the
10
+ * summary itself disappears once the transcript has rows. Renders nothing
11
+ * for an empty snapshot.
21
12
  * @param context - the channel's loaded-context snapshot.
22
- * @param open - whether the grouped details are shown.
23
- * @param onToggle - flips `open`; fired by the Ctrl+T keybinding.
24
13
  */
25
- export function LoadedContextPanel({ context, open, onToggle, }) {
14
+ export function LoadedContextPanel({ context }) {
26
15
  const summary = summarizeLoadedContext(context);
27
16
  if (summary === '')
28
17
  return null;
29
- return (_jsxs(Box, { flexDirection: "column", marginTop: 1, marginBottom: 1, children: [_jsx(Box, { paddingX: 1, backgroundColor: open ? 'userMessageBackground' : undefined, children: _jsxs(Text, { wrap: "truncate", bold: open, children: [open ? '▼' : '▶', " ", t('context-loaded'), " \u00B7 ", summary, _jsxs(Text, { dimColor: true, children: [" \uFF08Ctrl+T", open ? t('context-panel-collapse') : t('context-panel-expand'), "\uFF09"] })] }) }), open && (_jsxs(Box, { flexDirection: "column", paddingX: 1, paddingTop: 1, children: [context.sections.length > 0 && (_jsx(Group, { title: t('context-panel-sections', { n: context.sections.length }), children: context.sections.map(section => (_jsx(Entry, { entry: section }, section.name))) })), context.files.length > 0 && (_jsx(Group, { title: t('context-panel-files', { n: context.files.length }), children: context.files.map(file => (_jsx(Text, { dimColor: true, children: file.displayPath }, file.displayPath))) })), context.contexts.length > 0 && (_jsx(Group, { title: t('context-panel-runtime', { n: context.contexts.length }), children: context.contexts.map(entry => (_jsx(Entry, { entry: entry }, entry.name))) })), context.skills.length > 0 && (_jsx(Group, { title: t('context-panel-skills', { n: context.skills.length }), children: context.skills.map(skill => (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, dimColor: true, children: skill.name }), _jsx(Text, { dimColor: true, wrap: "wrap", children: skill.description })] }, skill.name))) })), context.tools.length > 0 && (_jsx(Group, { title: t('context-panel-tools', { n: context.tools.length }), children: context.tools.map(tool => (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, dimColor: true, children: tool.name }), _jsx(Text, { dimColor: true, wrap: "wrap", children: truncateContextText(tool.description, 160) })] }, tool.name))) }))] }))] }));
18
+ return (_jsx(Box, { marginTop: 1, marginBottom: 1, paddingX: 1, children: _jsxs(Text, { wrap: "truncate", children: [t('context-loaded'), " \u00B7 ", summary, _jsx(Text, { dimColor: true, children: " \u00B7 /context" })] }) }));
30
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"LogoV2.d.ts","sourceRoot":"","sources":["../../../src/components/LogoV2.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAqDzB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,MAAM,EACN,GAAG,EACH,SAAiB,GAClB,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CAiFlB"}
1
+ {"version":3,"file":"LogoV2.d.ts","sourceRoot":"","sources":["../../../src/components/LogoV2.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAoDzB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,MAAM,EACN,GAAG,EACH,SAAiB,GAClB,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CA+ElB"}
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from 'react';
3
3
  import { t as tr } from '../i18n.js';
4
- import { modLabel } from '../utils/modifiers.js';
5
4
  import { readFileSync } from 'node:fs';
6
5
  import { dirname, join } from 'node:path';
7
6
  import { fileURLToPath } from 'node:url';
@@ -92,5 +91,5 @@ export function LogoV2({ model, effort, cwd, skipIntro = false, }) {
92
91
  const t = settled ? 0 : time;
93
92
  const bigDeepSeek = renderBigText('DEEPSEEK', t, wordmarkRGB, taglineRGB, FLASH, 60);
94
93
  const bigHarness = renderBigText('HARNESS', t, taglineRGB, PALE, FLASH, 60);
95
- return (_jsxs(Box, { ref: ref, flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { flexDirection: "row", gap: 2, width: "100%", alignItems: "center", children: [showWhale && _jsx(WhaleArt, { frameIndex: frameIndex, width: FULL_WHALE_WIDTH }), _jsxs(Box, { flexDirection: "column", flexShrink: 1, children: [_jsxs(Text, { wrap: "truncate-end", children: [sweep('✦ dsh-TUI', t, wordmarkRGB, wordmarkShimmerRGB, 60), _jsx(Text, { dimColor: true, children: ' v' + VERSION })] }), bigDeepSeek.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, `ds-${index}`))), bigHarness.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, `h-${index}`))), _jsxs(Text, { wrap: "truncate-end", children: [model, effort !== undefined && _jsx(Text, { dimColor: true, children: ' · ' + capitalize(effort) + ' effort' })] }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: cwd }), _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { dimColor: true, children: tr('logo-tip-prefix') }), "/model", _jsxs(Text, { dimColor: true, children: [" ", tr('logo-tip-model'), " \u00B7 "] }), "/help", _jsxs(Text, { dimColor: true, children: [" ", tr('logo-tip-help'), " \u00B7 "] }), `${modLabel}t`, _jsxs(Text, { dimColor: true, children: [" ", tr('logo-tip-trace'), " \u00B7 "] }), "Tab", _jsxs(Text, { dimColor: true, children: [" ", tr('logo-tip-tab')] })] })] })] }), _jsx(Box, { marginTop: 1, paddingLeft: showWhale ? WELCOME_PAD : 2, children: _jsx(Text, { children: sweep(tr('logo-tagline'), t, taglineRGB, FLASH, 60) }) })] }));
94
+ return (_jsxs(Box, { ref: ref, flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { flexDirection: "row", gap: 2, width: "100%", alignItems: "center", children: [showWhale && _jsx(WhaleArt, { frameIndex: frameIndex, width: FULL_WHALE_WIDTH }), _jsxs(Box, { flexDirection: "column", flexShrink: 1, children: [_jsxs(Text, { wrap: "truncate-end", children: [sweep('✦ dsh-TUI', t, wordmarkRGB, wordmarkShimmerRGB, 60), _jsx(Text, { dimColor: true, children: ' v' + VERSION })] }), bigDeepSeek.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, `ds-${index}`))), bigHarness.map((row, index) => (_jsx(Text, { wrap: "truncate-end", children: row }, `h-${index}`))), _jsxs(Text, { wrap: "truncate-end", children: [model, effort !== undefined && _jsx(Text, { dimColor: true, children: ' · ' + capitalize(effort) + ' effort' })] }), _jsx(Text, { dimColor: true, wrap: "truncate-end", children: cwd }), _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { dimColor: true, children: tr('logo-tip-prefix') }), "/model", _jsxs(Text, { dimColor: true, children: [" ", tr('logo-tip-model'), " \u00B7 "] }), "/help", _jsxs(Text, { dimColor: true, children: [" ", tr('logo-tip-help'), " \u00B7 "] }), "Tab", _jsxs(Text, { dimColor: true, children: [" ", tr('logo-tip-tab')] })] })] })] }), _jsx(Box, { marginTop: 1, paddingLeft: showWhale ? WELCOME_PAD : 2, children: _jsx(Text, { children: sweep(tr('logo-tagline'), t, taglineRGB, FLASH, 60) }) })] }));
96
95
  }
@@ -2,13 +2,15 @@ import React from 'react';
2
2
  import { type ScrollBoxHandle } from '../ui.js';
3
3
  import type { ChatRow } from '../dsh-adapter/channel.js';
4
4
  import type { DOMElement } from '../ink/dom.js';
5
- export declare function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, model, showAll, onToggleAll, onLoadOlder, thinkingVisible, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, failureHintRowId, failureHint, }: {
5
+ export declare function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, model, diffLayout, showAll, onToggleAll, onLoadOlder, thinkingVisible, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, failureHintRowId, failureHint, }: {
6
6
  rows: readonly ChatRow[];
7
7
  expanded: boolean;
8
8
  expandedRows: ReadonlySet<number>;
9
9
  selectedId: number | null;
10
10
  onToggleRow: (rowId: number) => void;
11
11
  model: string;
12
+ /** Edit/Write diff presentation preference (forwarded to tool cards). */
13
+ diffLayout?: 'auto' | 'split' | 'unified';
12
14
  showAll: boolean;
13
15
  onToggleAll: () => void;
14
16
  /** Restore folded-away older rows from the session log (CC-style "load
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAA8B,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAyC,MAAM,2BAA2B,CAAA;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAuC/C,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,WAAW,EACX,KAAK,EACL,OAAO,EACP,WAAW,EACX,WAAW,EACX,eAAsB,EACtB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,WAAW,GACZ,EAAE;IACD,IAAI,EAAE,SAAS,OAAO,EAAE,CAAA;IACxB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB;2EACuE;IACvE,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAC/D,oDAAoD;IACpD,YAAY,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IACrC,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B;8EAC0E;IAC1E,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,qBAwPA;AAuQD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,MAAM,EACN,GAAG,GACJ,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,KAAK,CAAC,SAAS,CAMlB"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAA8B,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAyC,MAAM,2BAA2B,CAAA;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAuC/C,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,WAAW,EACX,KAAK,EACL,UAAmB,EACnB,OAAO,EACP,WAAW,EACX,WAAW,EACX,eAAsB,EACtB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,WAAW,GACZ,EAAE;IACD,IAAI,EAAE,SAAS,OAAO,EAAE,CAAA;IACxB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;IACzC,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB;2EACuE;IACvE,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAC/D,oDAAoD;IACpD,YAAY,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IACrC,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B;8EAC0E;IAC1E,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,qBAiRA;AA2QD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,MAAM,EACN,GAAG,GACJ,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,KAAK,CAAC,SAAS,CAMlB"}
@@ -37,7 +37,7 @@ const DEFAULT_ROW_HEIGHT = 2;
37
37
  /** Cold-start estimate of the header block above the rows; corrected by the
38
38
  * first layout measurement. */
39
39
  const DEFAULT_HEADER_LINES = 14;
40
- export function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, model, showAll, onToggleAll, onLoadOlder, thinkingVisible = true, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, failureHintRowId, failureHint, }) {
40
+ export function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, model, diffLayout = 'auto', showAll, onToggleAll, onLoadOlder, thinkingVisible = true, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, failureHintRowId, failureHint, }) {
41
41
  const hiddenCount = rows.length - MAX_RENDERED_ROWS;
42
42
  // The thinking filter runs BEFORE virtualization so window indices line up.
43
43
  const visibleRows = (showAll || hiddenCount <= 0
@@ -129,6 +129,21 @@ export function MessageList({ rows, expanded, expandedRows, selectedId, onToggle
129
129
  // transcript mid-stream.
130
130
  if (sticky && visibleRows.length > 0) {
131
131
  start = Math.min(start, visibleRows.length - 1);
132
+ // Blank-band guard: sticky scrollTop tracks the renderer's FRESH Yoga
133
+ // scrollHeight, while these offsets use per-row heights measured one to
134
+ // two commits late. During fast streaming the accurate scrollTop scans
135
+ // deeper through the underestimated offsets than the real viewport does,
136
+ // unmounting rows that are still on screen (visible spacer band). Walk
137
+ // backwards from the tail with the known heights and mount at least one
138
+ // viewport plus overscan of content above it, so the window can never
139
+ // open a gap inside what the user is looking at.
140
+ let covered = viewport + OVERSCAN_LINES;
141
+ let floor = visibleRows.length - 1;
142
+ while (floor > 0 && covered > 0) {
143
+ covered -= heightOf(visibleRows[floor]);
144
+ floor--;
145
+ }
146
+ start = Math.min(start, floor + 1);
132
147
  }
133
148
  if (forceMountRowId !== undefined && forceMountRowId !== null) {
134
149
  const idx = visibleRows.findIndex(row => row.id === forceMountRowId);
@@ -195,7 +210,16 @@ export function MessageList({ rows, expanded, expandedRows, selectedId, onToggle
195
210
  }
196
211
  if (scrollHandle) {
197
212
  if (sticky || (start === 0 && end >= visibleRows.length)) {
198
- scrollHandle.setClampBounds(undefined, undefined);
213
+ // Sticky still needs the MIN clamp: the first wheel-up breaks sticky
214
+ // on the DOM (ScrollBox.scrollBy) several frames before React
215
+ // commits a new mount window, and the drain frames in between paint
216
+ // unmounted spacer rows as a blank band. Clamping to the currently
217
+ // mounted top shows the edge content until React catches up - same
218
+ // behavior as the steady-state scroll path. The MAX clamp stays
219
+ // disabled: sticky follow pushes scrollTop to each frame's new
220
+ // maxScroll, which a stale mounted max would clamp away.
221
+ const min = start > 0 ? Math.max(0, base + topPad - viewport) : undefined;
222
+ scrollHandle.setClampBounds(min, undefined);
199
223
  }
200
224
  else {
201
225
  const min = Math.max(0, base + topPad - viewport);
@@ -232,10 +256,10 @@ export function MessageList({ rows, expanded, expandedRows, selectedId, onToggle
232
256
  // spacing; only the very first row of the whole list has none.
233
257
  const addMargin = margins.get(row.id) === true;
234
258
  const tool = row.tool;
235
- return (_jsx(MemoRow, { rowId: row.id, kind: row.kind, text: row.text, executionTarget: row.executionTarget, streaming: row.streaming === true, durationMs: row.durationMs, time: row.time, addMargin: addMargin, isSelected: selectedId === row.id, isExpanded: expandedRows.has(row.id), expanded: expanded, model: model, background: rowBackground(row.id), toolCallId: tool?.callId, toolName: tool?.name, toolArgsText: tool?.argsText, toolArgsFull: tool?.argsFull, toolStatus: tool?.status, toolResultText: tool?.resultText, toolResultFull: tool?.resultFull, toolErrorText: tool?.errorText, toolFootnote: failureHintRowId === row.id ? failureHint : undefined, toolCallView: tool?.callView, toolResultView: tool?.resultView, toolStartedAt: tool?.startedAt, toolDurationMs: tool?.durationMs, nowSec: tool?.status === 'running' ? nowSec : undefined, onToggleRow: onToggleRow, setRowRef: setRowRef }, row.id));
259
+ return (_jsx(MemoRow, { rowId: row.id, kind: row.kind, text: row.text, executionTarget: row.executionTarget, streaming: row.streaming === true, durationMs: row.durationMs, time: row.time, addMargin: addMargin, isSelected: selectedId === row.id, isExpanded: expandedRows.has(row.id), expanded: expanded, model: model, diffLayout: diffLayout, background: rowBackground(row.id), toolCallId: tool?.callId, toolName: tool?.name, toolArgsText: tool?.argsText, toolArgsFull: tool?.argsFull, toolStatus: tool?.status, toolResultText: tool?.resultText, toolResultFull: tool?.resultFull, toolErrorText: tool?.errorText, toolFootnote: failureHintRowId === row.id ? failureHint : undefined, toolCallView: tool?.callView, toolResultView: tool?.resultView, toolStartedAt: tool?.startedAt, toolDurationMs: tool?.durationMs, nowSec: tool?.status === 'running' ? nowSec : undefined, onToggleRow: onToggleRow, setRowRef: setRowRef }, row.id));
236
260
  }), bottomPad > 0 && _jsx(Box, { height: bottomPad, flexShrink: 0 })] }));
237
261
  }
238
- function TranscriptRow({ rowId, kind, text, executionTarget, streaming, durationMs, time, addMargin, isSelected, isExpanded, expanded, model, background, toolCallId, toolName, toolArgsText, toolArgsFull, toolStatus, toolResultText, toolResultFull, toolErrorText, toolFootnote, toolCallView, toolResultView, toolStartedAt, toolDurationMs, onToggleRow, setRowRef, }) {
262
+ function TranscriptRow({ rowId, kind, text, executionTarget, streaming, durationMs, time, addMargin, isSelected, isExpanded, expanded, model, diffLayout, background, toolCallId, toolName, toolArgsText, toolArgsFull, toolStatus, toolResultText, toolResultFull, toolErrorText, toolFootnote, toolCallView, toolResultView, toolStartedAt, toolDurationMs, onToggleRow, setRowRef, }) {
239
263
  const ref = React.useCallback((el) => {
240
264
  setRowRef(rowId, el);
241
265
  }, [setRowRef, rowId]);
@@ -277,7 +301,7 @@ function TranscriptRow({ rowId, kind, text, executionTarget, streaming, duration
277
301
  startedAt: toolStartedAt,
278
302
  durationMs: toolDurationMs,
279
303
  };
280
- return (_jsx(Box, { flexDirection: "column", ref: ref, children: _jsx(AssistantToolUseMessage, { tool: tool, addMargin: addMargin, verbose: isExpanded || expanded, isSelected: isSelected, isExpanded: isExpanded, footnote: toolFootnote }) }));
304
+ return (_jsx(Box, { flexDirection: "column", ref: ref, children: _jsx(AssistantToolUseMessage, { tool: tool, addMargin: addMargin, verbose: isExpanded || expanded, isSelected: isSelected, isExpanded: isExpanded, footnote: toolFootnote, diffLayout: diffLayout }) }));
281
305
  }
282
306
  case 'notice':
283
307
  return (_jsx(Box, { marginTop: 1, ref: ref, children: _jsx(Divider, { title: ` ${text} ` }) }));
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Error boundary for plugin scenes (dsh-tui-scenes). A scene component is
3
+ * third-party code rendered inside Chat's tree: without a boundary a render
4
+ * error propagates to ink's app-level boundary (src/ink/components/App.tsx)
5
+ * and takes the whole TUI down with it. Catching here collapses the blast
6
+ * radius to the scene itself — the host reports the error to the transcript
7
+ * and closes the scene, landing the user back on the conversation.
8
+ *
9
+ * Boundaries catch render/lifecycle errors only; errors thrown from async
10
+ * handlers and effects remain the scene's own responsibility (see the
11
+ * 场景红线 section in docs/plugins.md).
12
+ */
13
+ import React from 'react';
14
+ type PluginSceneBoundaryProps = {
15
+ /** Scene id, echoed into the error report. */
16
+ readonly id: string;
17
+ /** Called once per caught error; the host reports it and closes the scene. */
18
+ readonly onError: (id: string, error: Error) => void;
19
+ readonly children: React.ReactNode;
20
+ };
21
+ type PluginSceneBoundaryState = {
22
+ readonly crashed: boolean;
23
+ };
24
+ export declare class PluginSceneBoundary extends React.Component<PluginSceneBoundaryProps, PluginSceneBoundaryState> {
25
+ state: PluginSceneBoundaryState;
26
+ static getDerivedStateFromError(): PluginSceneBoundaryState;
27
+ componentDidCatch(error: Error): void;
28
+ render(): React.ReactNode;
29
+ }
30
+ export {};
31
+ //# sourceMappingURL=PluginSceneBoundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PluginSceneBoundary.d.ts","sourceRoot":"","sources":["../../../src/components/PluginSceneBoundary.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,KAAK,wBAAwB,GAAG;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IACpD,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CACnC,CAAA;AAED,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B,CAAA;AAED,qBAAa,mBAAoB,SAAQ,KAAK,CAAC,SAAS,CACtD,wBAAwB,EACxB,wBAAwB,CACzB;IACU,KAAK,EAAE,wBAAwB,CAAqB;IAE7D,MAAM,CAAC,wBAAwB,IAAI,wBAAwB;IAQlD,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAIrC,MAAM,IAAI,KAAK,CAAC,SAAS;CAGnC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Error boundary for plugin scenes (dsh-tui-scenes). A scene component is
3
+ * third-party code rendered inside Chat's tree: without a boundary a render
4
+ * error propagates to ink's app-level boundary (src/ink/components/App.tsx)
5
+ * and takes the whole TUI down with it. Catching here collapses the blast
6
+ * radius to the scene itself — the host reports the error to the transcript
7
+ * and closes the scene, landing the user back on the conversation.
8
+ *
9
+ * Boundaries catch render/lifecycle errors only; errors thrown from async
10
+ * handlers and effects remain the scene's own responsibility (see the
11
+ * 场景红线 section in docs/plugins.md).
12
+ */
13
+ import React from 'react';
14
+ export class PluginSceneBoundary extends React.Component {
15
+ state = { crashed: false };
16
+ static getDerivedStateFromError() {
17
+ // Suppress the scene's next render. The host's onError closes the scene
18
+ // in the same commit turn, so this null fallback normally never paints;
19
+ // it exists only to keep a closed-nowhere crash from remounting the
20
+ // throwing component in a loop.
21
+ return { crashed: true };
22
+ }
23
+ componentDidCatch(error) {
24
+ this.props.onError(this.props.id, error);
25
+ }
26
+ render() {
27
+ return this.state.crashed ? null : this.props.children;
28
+ }
29
+ }
@@ -1,14 +1,26 @@
1
1
  import React from 'react';
2
2
  import type { ChatRow } from '../dsh-adapter/channel.js';
3
+ import type { TuiRewindMode } from '../dsh-adapter/extension-events.js';
3
4
  /**
4
5
  * Double-Esc rewind picker (CC's "Double-tap esc to rewind the code and/or
5
6
  * conversation to a previous point in time"): lists the user's past messages
6
7
  * newest-first; selecting one and confirming rewinds the conversation to
7
8
  * that point (the message comes back into the input for re-editing).
9
+ *
10
+ * The confirm pane has two shapes: the plain one (Enter rewinds), and —
11
+ * when a plugin answered the tui/rewind-prompt decision with extra modes —
12
+ * a choice list whose option zero is always the built-in conversation-only
13
+ * rewind, followed by the plugin's modes (e.g. "also restore files").
8
14
  */
9
- export declare function RewindPicker({ rows, focusIndex, confirmRow, }: {
15
+ export declare function RewindPicker({ rows, focusIndex, confirmRow, modes, modeIndex, busy, }: {
10
16
  rows: readonly ChatRow[];
11
17
  focusIndex: number;
12
18
  confirmRow: ChatRow | null;
19
+ /** Plugin-offered rewind modes (tui/rewind-prompt); null = plain confirm. */
20
+ modes?: readonly TuiRewindMode[] | null;
21
+ /** Focused option in the modes list (0 = conversation-only). */
22
+ modeIndex?: number;
23
+ /** True while the plugin decision is in flight. */
24
+ busy?: boolean;
13
25
  }): React.ReactNode;
14
26
  //# sourceMappingURL=RewindPicker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RewindPicker.d.ts","sourceRoot":"","sources":["../../../src/components/RewindPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAMxD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,UAAU,EACV,UAAU,GACX,EAAE;IACD,IAAI,EAAE,SAAS,OAAO,EAAE,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,OAAO,GAAG,IAAI,CAAA;CAC3B,GAAG,KAAK,CAAC,SAAS,CA+DlB"}
1
+ {"version":3,"file":"RewindPicker.d.ts","sourceRoot":"","sources":["../../../src/components/RewindPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAA;AAMvE;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,UAAU,EACV,UAAU,EACV,KAAY,EACZ,SAAa,EACb,IAAY,GACb,EAAE;IACD,IAAI,EAAE,SAAS,OAAO,EAAE,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,OAAO,GAAG,IAAI,CAAA;IAC1B,6EAA6E;IAC7E,KAAK,CAAC,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CAAA;IACvC,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mDAAmD;IACnD,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,GAAG,KAAK,CAAC,SAAS,CA4GlB"}
@@ -10,9 +10,33 @@ import { listWindow } from './listWindow.js';
10
10
  * conversation to a previous point in time"): lists the user's past messages
11
11
  * newest-first; selecting one and confirming rewinds the conversation to
12
12
  * that point (the message comes back into the input for re-editing).
13
+ *
14
+ * The confirm pane has two shapes: the plain one (Enter rewinds), and —
15
+ * when a plugin answered the tui/rewind-prompt decision with extra modes —
16
+ * a choice list whose option zero is always the built-in conversation-only
17
+ * rewind, followed by the plugin's modes (e.g. "also restore files").
13
18
  */
14
- export function RewindPicker({ rows, focusIndex, confirmRow, }) {
19
+ export function RewindPicker({ rows, focusIndex, confirmRow, modes = null, modeIndex = 0, busy = false, }) {
15
20
  if (confirmRow !== null) {
21
+ if (modes !== null) {
22
+ // Plugin modes: a described choice list (one extra row per
23
+ // description), windowed like the message list below.
24
+ const { rows: terminalRows } = useTerminalSize();
25
+ const rowCosts = [2, ...modes.map(mode => (mode.description === undefined ? 1 : 2))];
26
+ const { start, end } = listWindow(rowCosts, modeIndex, Math.max(terminalRows - 10, 2));
27
+ const options = [
28
+ { key: 'conversation', label: t('rewind-mode-default'), description: t('rewind-confirm-desc') },
29
+ ...modes.map(mode => ({
30
+ key: mode.id,
31
+ label: mode.label,
32
+ ...(mode.description === undefined ? {} : { description: mode.description }),
33
+ })),
34
+ ];
35
+ return (_jsxs(Pane, { color: "permission", children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "remember", bold: true, children: t('rewind-confirm-title') }), _jsx(Text, { dimColor: true, children: preview(confirmRow.text) })] }), options.slice(start, end).map((option, index) => {
36
+ const absoluteIndex = start + index;
37
+ return (_jsx(ListItem, { isFocused: absoluteIndex === modeIndex, description: option.description, showScrollUp: absoluteIndex === start && start > 0, showScrollDown: absoluteIndex === end - 1 && end < options.length, children: option.label }, option.key));
38
+ })] }), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('hint-select-exit') }) })] }));
39
+ }
16
40
  return (_jsx(Pane, { color: "permission", children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "remember", bold: true, children: t('rewind-confirm-title') }) }), _jsx(ListItem, { isFocused: false, description: t('rewind-confirm-desc'), children: preview(confirmRow.text) }), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('hint-rewind-back') }) })] }) }));
17
41
  }
18
42
  const { rows: terminalRows } = useTerminalSize();
@@ -23,7 +47,7 @@ export function RewindPicker({ rows, focusIndex, confirmRow, }) {
23
47
  return (_jsxs(Pane, { color: "permission", children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "remember", bold: true, children: t('rewind-title') }), _jsx(Text, { dimColor: true, children: t('rewind-subtitle') })] }), rows.length === 0 ? (_jsx(ListItem, { isFocused: false, children: t('rewind-empty') })) : (rows.slice(start, end).map((row, index) => {
24
48
  const absoluteIndex = start + index;
25
49
  return (_jsx(ListItem, { isFocused: absoluteIndex === focusIndex, description: absoluteIndex === 0 ? t('rewind-last-message') : undefined, showScrollUp: absoluteIndex === start && start > 0, showScrollDown: absoluteIndex === end - 1 && end < rows.length, children: preview(row.text) }, row.id));
26
- }))] }), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('hint-select-exit') }) })] }));
50
+ })), busy && _jsx(Text, { dimColor: true, children: t('rewind-waiting-plugins') })] }), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('hint-select-exit') }) })] }));
27
51
  }
28
52
  /** One-line preview of a message (newlines flattened, capped). */
29
53
  function preview(text) {
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import type { SkillInfo } from '../dsh-adapter/channel.js';
3
+ /**
4
+ * `/skills` picker (issue #204) in the ModelPicker style: a
5
+ * permission-colored Pane listing the live agent's skill catalog —
6
+ * user-invocable skills lead with `/name`(它们在 / 菜单里也是这个形态),
7
+ * 描述行是「来源 · 简述」。Enter 由 Chat 填回 `/name `,Esc 关闭。
8
+ *
9
+ * 长列表按焦点窗口化(ModelPicker 同款):picker 经 OverlayAbove 浮层挂载后
10
+ * 有 maxHeight 裁剪,全量渲染会让焦点行被裁掉(看不到焦点按 Enter)。
11
+ */
12
+ export declare function SkillsPicker({ skills, focusIndex, }: {
13
+ skills: readonly SkillInfo[];
14
+ focusIndex: number;
15
+ }): React.ReactNode;
16
+ /** `/skills` while the registry snapshot is still in flight (ModelPickerLoading 同款). */
17
+ export declare function SkillsPickerLoading(): React.ReactNode;
18
+ //# sourceMappingURL=SkillsPicker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillsPicker.d.ts","sourceRoot":"","sources":["../../../src/components/SkillsPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AA2B1D;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,UAAU,GACX,EAAE;IACD,MAAM,EAAE,SAAS,SAAS,EAAE,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG,KAAK,CAAC,SAAS,CAyClB;AAED,wFAAwF;AACxF,wBAAgB,mBAAmB,IAAI,KAAK,CAAC,SAAS,CAerD"}