@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,553 @@
1
+ /**
2
+ * messages.observe contract surface (C-042,
3
+ * `messages.dsh/v1alpha1#MessageObserver`): the host event broker, mounted
4
+ * by the dsh-tui-plugin-host row as `ctx.tuiMessageObserver`.
5
+ *
6
+ * Mapping (deliberately narrow):
7
+ *
8
+ * - `user/message` → `message.received` (the user's prompt)
9
+ * - `assistant/message` → `message.sent` (the assembled step reply)
10
+ * - EVERYTHING ELSE (assistant/chunk streaming, tool/*, turn/*, mode
11
+ * events, …) produces NO envelope — observation starts conservative.
12
+ *
13
+ * Envelope rules (the pinned `@dsh-std/messages` v0.15 definition):
14
+ *
15
+ * - `scope` = `session:<sessionId>`; `sequence` = the session event's own
16
+ * `seq` (monotonic within scope, gaps allowed — unmapped events simply
17
+ * leave holes); `eventId` = `<sessionId>:<seq>` with schema-unsafe
18
+ * characters flattened to `_`.
19
+ * - privacyClass is ALWAYS `sensitive` for now (conservative and
20
+ * irreversible-safe; finer classification is a future, documented step).
21
+ * - Content carries the text/image subset (MCP ContentBlock): text runs
22
+ * join (a pure-text message keeps the single trimmed block); session
23
+ * image blocks are `{type:'image', attachment}` REFERENCES resolved via
24
+ * the attachments service into base64 `data` with a 192 KiB budget —
25
+ * an unreadable/oversize image is dropped and marks `truncated`.
26
+ * `summary` is the sanitized first 200 cells of the joined text;
27
+ * `truncated` marks summary, content, or image-drop truncation.
28
+ * - EVERY produced envelope passes the official pinned validator before delivery;
29
+ * a malformed envelope is dropped with a warning, never delivered.
30
+ *
31
+ * Scope isolation (C-042): `subscribe` requires an exact `scope` string
32
+ * and an envelope is delivered ONLY to subscriptions of the same scope —
33
+ * a plugin moving between sessions subscribes per scope and never
34
+ * receives another session's sensitive content.
35
+ *
36
+ * Grant gating (`messages.observe.read`, default deny):
37
+ *
38
+ * - SUBSCRIBE time: a denied plugin gets a no-op disposer + a warning
39
+ * naming plugin and grant (fast fail, as-if-unsubscribed).
40
+ * - DELIVER time: every publish re-checks each subscription; a revoked
41
+ * grant RELEASES the subscription (contract cleanup rule) with one
42
+ * warning.
43
+ *
44
+ * Delivery semantics: at-most-once, no replay; envelope builds serialize
45
+ * broker-wide (image reads are async — delivery order stays the publish
46
+ * order, so sequence stays monotonic); callbacks of ONE subscription run
47
+ * serially (per-subscription promise chain); a throwing listener is
48
+ * isolated (warn, name the plugin, keep delivering to the rest). The host
49
+ * MUST NOT persist payload through this contract — the broker keeps no
50
+ * history.
51
+ *
52
+ * privacyClass: sensitive — envelope content is never logged.
53
+ */
54
+ import { Service } from '@deepseek-ai/cordis';
55
+ import { validateMessageEvent } from '@dsh-std/messages';
56
+ import { check } from '../plugin-spec/schema-check.js';
57
+ import { cleanScalarText } from './sanitize.js';
58
+ import { activationContext, assertCallerContext, bindCallerEffect, compositionRoot, concreteService } from './host-access.js';
59
+ import { readGrantStore } from './grants.js';
60
+ import { declaresObserverScope, declaresPermission, requireComponentIdentity, requiresContract, } from './component-identity.js';
61
+ import { normalizePermissionScope, scopeCovers, SESSION_SCOPE_MAX_CHARS, } from '../plugin-spec/permission-scope.js';
62
+ /** Summary bound (cells; schema maxLength 1024 chars — 200 cells ≤ 1024). */
63
+ export const OBSERVE_SUMMARY_CELLS = 200;
64
+ /** Content text bound (chars; schema maxLength 262144). */
65
+ export const OBSERVE_CONTENT_MAX_CHARS = 262144;
66
+ /** Scope bound (schema maxLength 256). */
67
+ export const OBSERVE_SCOPE_MAX_CHARS = SESSION_SCOPE_MAX_CHARS;
68
+ /** messageId bound (schema maxLength 256). */
69
+ export const OBSERVE_ID_MAX_CHARS = 256;
70
+ /** Raw image byte budget per block (192 KiB → ≤262144 base64 chars). */
71
+ export const OBSERVE_IMAGE_MAX_BYTES = 192 * 1024;
72
+ /** Base64 length bound implied by OBSERVE_IMAGE_MAX_BYTES. */
73
+ export const OBSERVE_IMAGE_BASE64_MAX_CHARS = 262144;
74
+ /** Per-callback budget; timeout closes the subscription deterministically. */
75
+ export const OBSERVE_CALLBACK_TIMEOUT_MS = 1500;
76
+ /** Bound queued callbacks per subscription so a stalled listener cannot grow
77
+ * an unbounded Promise chain before its timeout closes the subscription. */
78
+ export const OBSERVE_CALLBACK_QUEUE_LIMIT = 32;
79
+ /** Attachment reads are part of the broker build chain and therefore need an
80
+ * independent bound; a wedged reader must not stall every later envelope. */
81
+ export const OBSERVE_IMAGE_READ_TIMEOUT_MS = 1500;
82
+ /** The envelope schema's mimeType pattern (image blocks). */
83
+ const OBSERVE_MIME_PATTERN = /^[A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+$/;
84
+ function deepFreeze(value) {
85
+ if (value === null || typeof value !== 'object' || Object.isFrozen(value))
86
+ return value;
87
+ Object.freeze(value);
88
+ for (const child of Object.values(value))
89
+ deepFreeze(child);
90
+ return value;
91
+ }
92
+ function freezeEnvelope(envelope) {
93
+ return deepFreeze(structuredClone(envelope));
94
+ }
95
+ /** Session events are untrusted at this boundary. Never coerce arbitrary
96
+ * objects through `String()` because a hostile `toString` can fabricate
97
+ * message text (or throw) before the envelope validator sees it. */
98
+ function sourceBlockType(value) {
99
+ if (value === null || typeof value !== 'object')
100
+ return undefined;
101
+ try {
102
+ const type = value.type;
103
+ return type === 'text' || type === 'image' ? type : undefined;
104
+ }
105
+ catch {
106
+ return undefined;
107
+ }
108
+ }
109
+ function sourceText(value) {
110
+ try {
111
+ const text = value.text;
112
+ return typeof text === 'string' ? text : undefined;
113
+ }
114
+ catch {
115
+ return undefined;
116
+ }
117
+ }
118
+ async function runWithBudget(task, timeoutMs) {
119
+ let timer;
120
+ const work = Promise.resolve()
121
+ .then(task)
122
+ .then(() => ({ kind: 'fulfilled' }), error => ({ kind: 'rejected', error }));
123
+ const timeout = new Promise(resolve => {
124
+ timer = setTimeout(() => resolve({ kind: 'timeout' }), timeoutMs);
125
+ });
126
+ try {
127
+ return await Promise.race([work, timeout]);
128
+ }
129
+ finally {
130
+ if (timer !== undefined)
131
+ clearTimeout(timer);
132
+ }
133
+ }
134
+ /** Match a requested observer scope against the concrete scope of an
135
+ * envelope. `session:*` is an explicit, grantable parent scope; all other
136
+ * scopes remain exact. Keeping this relation in the broker means a wildcard
137
+ * declaration cannot accidentally become global unless both the manifest and
138
+ * the current grant cover it. */
139
+ function observerScopeCovers(subscriptionScope, envelopeScope) {
140
+ const declared = normalizePermissionScope('messages.observe.read', subscriptionScope, 'host');
141
+ const actual = normalizePermissionScope('messages.observe.read', envelopeScope, 'host');
142
+ return declared !== undefined && actual !== undefined && scopeCovers(declared, actual);
143
+ }
144
+ /**
145
+ * `ctx.tuiMessageObserver` — the messages.observe broker. The channel
146
+ * publishes mapped session events; plugins subscribe with their own
147
+ * context. When the vendored envelope schema is unavailable (packaging
148
+ * accident) the broker fails CLOSED: subscriptions are accepted but nothing
149
+ * is ever delivered (a host that cannot self-check must not emit).
150
+ */
151
+ export class TuiMessageObserverRuntime extends Service {
152
+ constructor(ctx, options = {}) {
153
+ super(ctx, 'tuiMessageObserver');
154
+ const state = {
155
+ hostContext: compositionRoot(ctx),
156
+ grantsOption: options.grants,
157
+ fallbackGrants: readGrantStore(),
158
+ ledgerOption: options.ledger,
159
+ subscriptions: new Set(),
160
+ validateEnvelope: validateMessageEvent,
161
+ validatorUnavailable: false,
162
+ validatorWarned: false,
163
+ buildChain: Promise.resolve(),
164
+ };
165
+ const runtime = this;
166
+ const host = Object.freeze({
167
+ publish: (session, event) => {
168
+ try {
169
+ runtime.#publishGuarded(session, event);
170
+ }
171
+ catch (error) {
172
+ runtime.ctx.logger.warn('dsh-tui: messages.observe publish failed (event dropped)');
173
+ }
174
+ },
175
+ });
176
+ hostMessageObservers.set(runtime, host);
177
+ if (Object.hasOwn(options, 'validateEnvelope')) {
178
+ state.validatorUnavailable = options.validateEnvelope === undefined;
179
+ state.validateEnvelope = options.validateEnvelope ?? (() => { throw new Error('standard envelope validator unavailable'); });
180
+ }
181
+ else if (Object.hasOwn(options, 'envelopeSchema')) {
182
+ const schema = options.envelopeSchema;
183
+ state.validatorUnavailable = schema === undefined;
184
+ state.validateEnvelope = schema === undefined
185
+ ? (() => { throw new Error('vendored envelope schema unavailable'); })
186
+ : (value) => check(value, schema, schema);
187
+ }
188
+ observerStates.set(this, state);
189
+ }
190
+ /** Grants: the plugin-host row's store when mounted, else a private read.
191
+ * Resolved PER CALL — sibling services mounted later by the same apply()
192
+ * are not visible to constructors (cordis), so a constructor-time probe
193
+ * would silently stick to the fallback. */
194
+ grants() {
195
+ const state = observerStateFor(this);
196
+ return state.grantsOption ?? state.hostContext.get('tuiPluginHost')?.grants ?? state.fallbackGrants;
197
+ }
198
+ /** Optional observability; a bare mount (tests) simply records nothing. */
199
+ ledger() {
200
+ const state = observerStateFor(this);
201
+ return state.ledgerOption ?? state.hostContext.get('tuiEffectLedger');
202
+ }
203
+ /**
204
+ * Subscribe to observation envelopes for ONE scope. Identity = the verified
205
+ * Component bound to the PASSED activation (the same identity rule as
206
+ * storage); the scope
207
+ * is required and matched exactly — a plugin moving between sessions
208
+ * subscribes per scope and never receives another scope's sensitive
209
+ * content (C-042 isolation). A denied subscription fast-fails: no-op
210
+ * disposer + warning. The subscription releases when the caller's context
211
+ * unloads.
212
+ */
213
+ subscribe(pluginCtx, listener, options) {
214
+ const caller = activationContext(pluginCtx);
215
+ if (caller === undefined)
216
+ throw new Error('dsh-tui: messages.observe.subscribe requires a live activation context');
217
+ assertCallerContext(this.ctx, caller, 'messages.observe.subscribe', this);
218
+ const identity = requireComponentIdentity(caller);
219
+ const plugin = identity.componentId;
220
+ if (!requiresContract(identity, 'messages.dsh/v1alpha1', 'MessageObserver')) {
221
+ observerStateFor(this).hostContext.logger.warn(`dsh-tui: messages.observe subscription from Component "${plugin}" denied — ` +
222
+ 'the messages.dsh/v1alpha1#MessageObserver contract was not required');
223
+ return () => false;
224
+ }
225
+ const scope = typeof options?.scope === 'string' ? options.scope : '';
226
+ if (scope === '' || scope.length > OBSERVE_SCOPE_MAX_CHARS) {
227
+ observerStateFor(this).hostContext.logger.warn(`dsh-tui: messages.observe subscription from plugin "${plugin}" refused — options.scope must be a ` +
228
+ `non-empty string of at most ${OBSERVE_SCOPE_MAX_CHARS} characters (e.g. "session:<id>")`);
229
+ return () => false;
230
+ }
231
+ if (typeof listener !== 'function'
232
+ || !declaresObserverScope(identity, scope)
233
+ || !declaresPermission(identity, 'messages.observe.read', scope)
234
+ || !this.grants().allows({ componentId: identity.componentId, activationId: identity.activationId }, 'messages.observe.read', scope)) {
235
+ observerStateFor(this).hostContext.logger.warn(`dsh-tui: messages.observe subscription from Component "${plugin}" denied — ` +
236
+ 'the scope is not statically declared or the current grant does not cover it; the listener was NOT registered');
237
+ this.ledger()?.record({
238
+ operation: 'bind',
239
+ resource: { kind: 'permission', id: 'messages.observe.read' },
240
+ result: 'failed',
241
+ errorCode: 'PERMISSION_NOT_GRANTED',
242
+ }, caller);
243
+ return () => false;
244
+ }
245
+ const subscription = {
246
+ plugin,
247
+ identity,
248
+ ownerContext: caller,
249
+ scope,
250
+ listener,
251
+ chain: Promise.resolve(),
252
+ pendingCallbacks: 0,
253
+ closed: false,
254
+ };
255
+ observerStateFor(this).subscriptions.add(subscription);
256
+ this.ledger()?.record({ operation: 'bind', resource: { kind: 'subscription', id: plugin }, result: 'applied' }, caller);
257
+ const release = () => {
258
+ if (subscription.closed)
259
+ return false;
260
+ this.drop(subscription);
261
+ return true;
262
+ };
263
+ subscription.stopGrantWatch = this.grants().onChange?.(() => {
264
+ if (!this.grants().allows({ componentId: identity.componentId, activationId: identity.activationId }, 'messages.observe.read', scope))
265
+ release();
266
+ });
267
+ bindCallerEffect(caller, release);
268
+ return release;
269
+ }
270
+ #publishGuarded(session, event) {
271
+ const state = observerStateFor(this);
272
+ if (state.subscriptions.size === 0)
273
+ return;
274
+ const record = event;
275
+ const kind = record.type === 'user/message'
276
+ ? 'message.received'
277
+ : record.type === 'assistant/message'
278
+ ? 'message.sent'
279
+ : undefined;
280
+ if (kind === undefined)
281
+ return;
282
+ if (typeof record.seq !== 'number' || !Number.isInteger(record.seq) || record.seq < 0)
283
+ return;
284
+ const sessionId = session?.id;
285
+ if (typeof sessionId !== 'string' || sessionId === '') {
286
+ observerStateFor(this).hostContext.logger.warn('dsh-tui: messages.observe publish skipped — the session carries no string id');
287
+ return;
288
+ }
289
+ const data = (record.data ?? {});
290
+ const message = (kind === 'message.sent' ? data.message : data);
291
+ const scope = `session:${sessionId}`;
292
+ // Never truncate a session identity into the schema's scope bound: two
293
+ // distinct long ids can otherwise collapse into one subscription scope.
294
+ if (scope.length > OBSERVE_SCOPE_MAX_CHARS) {
295
+ observerStateFor(this).hostContext.logger.warn(`dsh-tui: messages.observe publish skipped — the session scope exceeds ${OBSERVE_SCOPE_MAX_CHARS} characters`);
296
+ return;
297
+ }
298
+ // C-042 isolation: match subscriptions BEFORE building anything — a
299
+ // subscription for another scope must never see this scope's content.
300
+ const matched = [...state.subscriptions].filter(subscription => !subscription.closed && observerScopeCovers(subscription.scope, scope));
301
+ if (matched.length === 0)
302
+ return;
303
+ // Builds serialize broker-wide so delivery order stays the publish
304
+ // order even though image reads are async (sequence stays monotonic).
305
+ state.buildChain = state.buildChain.then(() => this.buildAndDeliver(kind, sessionId, scope, record.seq, message, matched));
306
+ }
307
+ async buildAndDeliver(kind, sessionId, scope, sequence, message, matched) {
308
+ const state = observerStateFor(this);
309
+ try {
310
+ const text = this.textOf(message?.content);
311
+ const { blocks, truncated: contentTruncated } = await this.contentOf(message?.content);
312
+ const summary = cleanScalarText(text, OBSERVE_SUMMARY_CELLS);
313
+ // Exact truncation detection: the capped clean differs from the
314
+ // uncapped clean (cells ≠ chars, so length comparison would lie).
315
+ const summaryTruncated = summary !== cleanScalarText(text, Number.MAX_SAFE_INTEGER);
316
+ const envelope = {
317
+ eventType: 'messages.observe',
318
+ eventVersion: '0.15',
319
+ eventId: `${sessionId}:${sequence}`.replace(/[^A-Za-z0-9._:-]/g, '_'),
320
+ scope,
321
+ sequence,
322
+ // Conservative-by-default: every envelope is sensitive until a
323
+ // documented finer classification exists.
324
+ privacyClass: 'sensitive',
325
+ summary,
326
+ payload: {
327
+ kind,
328
+ ...(typeof message?.id === 'string' && message.id.length > 0 && message.id.length <= OBSERVE_ID_MAX_CHARS
329
+ ? { messageId: message.id }
330
+ : {}),
331
+ author: kind === 'message.received' ? 'user' : 'assistant',
332
+ content: blocks,
333
+ ...(summaryTruncated || contentTruncated ? { truncated: true } : {}),
334
+ },
335
+ };
336
+ // Self-check EVERY envelope with the pinned @dsh-std/messages validator.
337
+ if (state.validatorUnavailable) {
338
+ if (!state.validatorWarned) {
339
+ state.validatorWarned = true;
340
+ observerStateFor(this).hostContext.logger.warn('dsh-tui: standard message envelope validator unavailable — delivery is fail-closed');
341
+ }
342
+ return;
343
+ }
344
+ try {
345
+ state.validateEnvelope(envelope);
346
+ }
347
+ catch (error) {
348
+ observerStateFor(this).hostContext.logger.warn('dsh-tui: messages.observe envelope failed the standard validator and was dropped');
349
+ return;
350
+ }
351
+ for (const subscription of matched) {
352
+ if (subscription.closed)
353
+ continue;
354
+ // Deliver-time grant re-check: a revoked grant RELEASES the
355
+ // subscription (contract cleanup rule), with one warning.
356
+ if (!this.grants().allows({ componentId: subscription.identity.componentId, activationId: subscription.identity.activationId }, 'messages.observe.read', scope)) {
357
+ observerStateFor(this).hostContext.logger.warn(`dsh-tui: messages.observe subscription of plugin "${subscription.plugin}" released — the grant was revoked`);
358
+ this.drop(subscription);
359
+ continue;
360
+ }
361
+ if (subscription.pendingCallbacks >= OBSERVE_CALLBACK_QUEUE_LIMIT) {
362
+ observerStateFor(this).hostContext.logger.warn(`dsh-tui: messages.observe listener of Component "${subscription.plugin}" reached its ` +
363
+ `${OBSERVE_CALLBACK_QUEUE_LIMIT}-callback queue limit; this envelope was skipped`);
364
+ continue;
365
+ }
366
+ subscription.pendingCallbacks += 1;
367
+ const run = subscription.chain.then(async () => {
368
+ if (subscription.closed)
369
+ return;
370
+ // Re-check at the actual callback boundary as well as at enqueue
371
+ // time. A grant may be revoked while an earlier callback is still
372
+ // running; queued envelopes must then be skipped rather than
373
+ // delivered from the stale pre-revocation snapshot.
374
+ if (!this.grants().allows({ componentId: subscription.identity.componentId, activationId: subscription.identity.activationId }, 'messages.observe.read', scope)) {
375
+ observerStateFor(this).hostContext.logger.warn(`dsh-tui: messages.observe subscription of plugin "${subscription.plugin}" released — the grant was revoked`);
376
+ this.drop(subscription);
377
+ return;
378
+ }
379
+ const isolated = freezeEnvelope(envelope);
380
+ const result = await runWithBudget(() => subscription.listener(isolated), OBSERVE_CALLBACK_TIMEOUT_MS);
381
+ if (result.kind === 'timeout') {
382
+ observerStateFor(this).hostContext.logger.warn(`dsh-tui: messages.observe listener of Component "${subscription.plugin}" exceeded ` +
383
+ `${OBSERVE_CALLBACK_TIMEOUT_MS}ms and the subscription was closed`);
384
+ this.drop(subscription);
385
+ }
386
+ else if (result.kind === 'rejected') {
387
+ observerStateFor(this).hostContext.logger.warn(`dsh-tui: messages.observe listener of Component "${subscription.plugin}" failed; delivery continues`);
388
+ }
389
+ });
390
+ subscription.chain = run.catch(error => {
391
+ observerStateFor(this).hostContext.logger.warn('dsh-tui: messages.observe delivery failed');
392
+ }).finally(() => { subscription.pendingCallbacks -= 1; });
393
+ }
394
+ }
395
+ catch (error) {
396
+ observerStateFor(this).hostContext.logger.warn('dsh-tui: messages.observe publish failed (event dropped)');
397
+ }
398
+ }
399
+ /** Release a subscription exactly once (disposer, ctx unload, revoke). */
400
+ drop(subscription) {
401
+ if (subscription.closed)
402
+ return;
403
+ subscription.closed = true;
404
+ subscription.stopGrantWatch?.();
405
+ subscription.stopGrantWatch = undefined;
406
+ observerStateFor(this).subscriptions.delete(subscription);
407
+ this.ledger()?.record({ operation: 'release', resource: { kind: 'subscription', id: subscription.plugin }, result: 'applied' }, subscription.ownerContext);
408
+ }
409
+ /** Join the text blocks of a session message's content (text-only view). */
410
+ textOf(content) {
411
+ if (!Array.isArray(content))
412
+ return '';
413
+ let text = '';
414
+ for (const block of content) {
415
+ if (sourceBlockType(block) !== 'text')
416
+ continue;
417
+ const value = sourceText(block);
418
+ if (value !== undefined)
419
+ text += value;
420
+ }
421
+ return text.trim();
422
+ }
423
+ /**
424
+ * Map session content blocks to envelope blocks in order (text/image
425
+ * subset). Consecutive text runs join into one block (capped at
426
+ * OBSERVE_CONTENT_MAX_CHARS, pure-text messages keep the exact legacy
427
+ * shape: a single trimmed block); image blocks resolve through the
428
+ * attachments service (soft-probe) with a byte budget. A failed or
429
+ * oversize image becomes NO block plus the truncation mark; zero
430
+ * surviving blocks collapse to a single empty text block (schema
431
+ * minItems 1).
432
+ */
433
+ async contentOf(content) {
434
+ const blocks = [];
435
+ let pendingText = '';
436
+ let truncated = false;
437
+ const appendText = (value) => {
438
+ const remaining = OBSERVE_CONTENT_MAX_CHARS - pendingText.length;
439
+ if (remaining <= 0) {
440
+ truncated = true;
441
+ return;
442
+ }
443
+ if (value.length > remaining) {
444
+ pendingText += value.slice(0, remaining);
445
+ truncated = true;
446
+ return;
447
+ }
448
+ pendingText += value;
449
+ };
450
+ const flushText = () => {
451
+ const run = pendingText.trim();
452
+ pendingText = '';
453
+ if (run === '')
454
+ return;
455
+ blocks.push({ type: 'text', text: run });
456
+ };
457
+ if (Array.isArray(content)) {
458
+ for (const raw of content) {
459
+ const type = sourceBlockType(raw);
460
+ if (type === 'text') {
461
+ const text = sourceText(raw);
462
+ if (text === undefined) {
463
+ // A declared text block with a non-string body is malformed source
464
+ // data, not the literal string "[object Object]".
465
+ truncated = true;
466
+ continue;
467
+ }
468
+ appendText(text);
469
+ continue;
470
+ }
471
+ if (type === 'image') {
472
+ const image = await this.imageBlockOf(raw);
473
+ if (image === undefined) {
474
+ truncated = true;
475
+ continue;
476
+ }
477
+ flushText();
478
+ blocks.push(image);
479
+ continue;
480
+ }
481
+ // Unknown block types are outside the text/image subset: dropped.
482
+ }
483
+ }
484
+ flushText();
485
+ if (blocks.length === 0)
486
+ blocks.push({ type: 'text', text: '' });
487
+ return { blocks, truncated };
488
+ }
489
+ /** Resolve a session image block (`{type:'image', attachment}` — a
490
+ * REFERENCE, never inline data) to an envelope image block; undefined =
491
+ * drop (unreadable, oversize, bad media type, no attachment store). */
492
+ async imageBlockOf(block) {
493
+ try {
494
+ if (block === null || typeof block !== 'object')
495
+ return undefined;
496
+ const attachment = block.attachment;
497
+ if (attachment === null || attachment === undefined || typeof attachment !== 'object')
498
+ return undefined;
499
+ const mediaType = attachment.mediaType;
500
+ if (typeof mediaType !== 'string' || !OBSERVE_MIME_PATTERN.test(mediaType))
501
+ return undefined;
502
+ const bytes = attachment.bytes;
503
+ if (typeof bytes !== 'number' || !Number.isFinite(bytes) || bytes < 0 || bytes > OBSERVE_IMAGE_MAX_BYTES)
504
+ return undefined;
505
+ const reader = observerStateFor(this).hostContext.get('attachments');
506
+ if (typeof reader?.readImage !== 'function')
507
+ return undefined;
508
+ // A failing read drops ONLY this image (the envelope survives with the
509
+ // truncation mark) — one corrupt attachment must not nuke the message.
510
+ let timer;
511
+ const read = Promise.resolve().then(() => reader.readImage(attachment));
512
+ const timeout = new Promise(resolve => {
513
+ timer = setTimeout(() => resolve(undefined), OBSERVE_IMAGE_READ_TIMEOUT_MS);
514
+ });
515
+ const stored = await Promise.race([read, timeout]);
516
+ if (timer !== undefined)
517
+ clearTimeout(timer);
518
+ // `read` has an attached rejection handler through the race's promise
519
+ // chain; late completion after a timeout is deliberately ignored.
520
+ const data = stored?.data;
521
+ if (!(data instanceof Uint8Array) || data.byteLength > OBSERVE_IMAGE_MAX_BYTES)
522
+ return undefined;
523
+ const base64 = Buffer.from(data).toString('base64');
524
+ if (base64.length > OBSERVE_IMAGE_BASE64_MAX_CHARS)
525
+ return undefined;
526
+ return { type: 'image', data: base64, mimeType: mediaType };
527
+ }
528
+ catch {
529
+ // Source content and attachment service output are untrusted here.
530
+ // Drop only this block and let the enclosing envelope carry truncated.
531
+ return undefined;
532
+ }
533
+ }
534
+ }
535
+ /** Host-only ingress accessor; deliberately omitted from `./plugin-host`. */
536
+ const hostMessageObservers = new WeakMap();
537
+ export function getHostMessageObserver(runtime) {
538
+ if (runtime === undefined)
539
+ return undefined;
540
+ try {
541
+ return hostMessageObservers.get(concreteService(runtime));
542
+ }
543
+ catch {
544
+ return undefined;
545
+ }
546
+ }
547
+ const observerStates = new WeakMap();
548
+ function observerStateFor(runtime) {
549
+ const state = observerStates.get(concreteService(runtime));
550
+ if (state === undefined)
551
+ throw new Error('tuiMessageObserver host state is unavailable');
552
+ return state;
553
+ }