@dxos/plugin-assistant 0.8.4-main.9be5663bfe → 0.8.4-main.abd8ff62ef

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 (483) hide show
  1. package/dist/lib/browser/AssistantSettings-GG52BLKS.mjs +40 -0
  2. package/dist/lib/browser/AssistantSettings-GG52BLKS.mjs.map +7 -0
  3. package/dist/lib/browser/blueprints/index.mjs +26 -3
  4. package/dist/lib/browser/blueprints/index.mjs.map +4 -4
  5. package/dist/lib/browser/{chunk-ATHYBVGN.mjs → chunk-DVOOFAWU.mjs} +4 -5
  6. package/dist/lib/browser/chunk-DVOOFAWU.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-M55MBYG7.mjs +932 -0
  8. package/dist/lib/browser/chunk-M55MBYG7.mjs.map +7 -0
  9. package/dist/lib/browser/{chunk-RUV2WOQH.mjs → chunk-SEMCG4ZK.mjs} +58 -17
  10. package/dist/lib/browser/chunk-SEMCG4ZK.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-VK53MITK.mjs +2300 -0
  12. package/dist/lib/browser/chunk-VK53MITK.mjs.map +7 -0
  13. package/dist/lib/browser/cli/index.mjs +73 -0
  14. package/dist/lib/browser/cli/index.mjs.map +7 -0
  15. package/dist/lib/browser/components/index.mjs +20 -0
  16. package/dist/lib/browser/components/index.mjs.map +7 -0
  17. package/dist/lib/browser/{create-chat-LBZHGVSN.mjs → create-chat-E2ZLVTLP.mjs} +4 -13
  18. package/dist/lib/browser/create-chat-E2ZLVTLP.mjs.map +7 -0
  19. package/dist/lib/browser/{ensure-companion-chat-FR4AWZ2P.mjs → ensure-companion-chat-7GDMXSQW.mjs} +4 -4
  20. package/dist/lib/browser/ensure-companion-chat-7GDMXSQW.mjs.map +7 -0
  21. package/dist/lib/browser/hooks/index.mjs +39 -0
  22. package/dist/lib/browser/hooks/index.mjs.map +7 -0
  23. package/dist/lib/browser/index.mjs +43 -3233
  24. package/dist/lib/browser/index.mjs.map +4 -4
  25. package/dist/lib/browser/meta.json +1 -1
  26. package/dist/lib/browser/{on-create-space-54RNX5JI.mjs → on-create-space-4J3KTNAJ.mjs} +3 -3
  27. package/dist/lib/browser/{on-create-space-54RNX5JI.mjs.map → on-create-space-4J3KTNAJ.mjs.map} +1 -1
  28. package/dist/lib/browser/operations/index.mjs +3 -3
  29. package/dist/lib/browser/operations/index.mjs.map +3 -3
  30. package/dist/lib/browser/{resolve-navigation-targets-NZOD66NY.mjs → resolve-navigation-targets-3ZPQE6SZ.mjs} +3 -3
  31. package/dist/lib/browser/{resolve-navigation-targets-NZOD66NY.mjs.map → resolve-navigation-targets-3ZPQE6SZ.mjs.map} +1 -1
  32. package/dist/lib/browser/{run-prompt-in-new-chat-4YQ37XIS.mjs → run-prompt-in-new-chat-AA3KPBDN.mjs} +9 -39
  33. package/dist/lib/browser/run-prompt-in-new-chat-AA3KPBDN.mjs.map +7 -0
  34. package/dist/lib/browser/{set-current-chat-WJI3WAVM.mjs → set-current-chat-P4VHI3YF.mjs} +4 -4
  35. package/dist/lib/browser/set-current-chat-P4VHI3YF.mjs.map +7 -0
  36. package/dist/lib/browser/translations.mjs +172 -0
  37. package/dist/lib/browser/translations.mjs.map +7 -0
  38. package/dist/lib/browser/types/index.mjs +1 -3
  39. package/dist/lib/browser/{update-chat-name-3Y36KFAS.mjs → update-chat-name-VWKNUON7.mjs} +7 -22
  40. package/dist/lib/browser/update-chat-name-VWKNUON7.mjs.map +7 -0
  41. package/dist/lib/node-esm/AssistantSettings-23A5IMHS.mjs +41 -0
  42. package/dist/lib/node-esm/AssistantSettings-23A5IMHS.mjs.map +7 -0
  43. package/dist/lib/node-esm/blueprints/index.mjs +26 -3
  44. package/dist/lib/node-esm/blueprints/index.mjs.map +4 -4
  45. package/dist/lib/node-esm/chunk-FWC3ZGPH.mjs +933 -0
  46. package/dist/lib/node-esm/chunk-FWC3ZGPH.mjs.map +7 -0
  47. package/dist/lib/node-esm/chunk-JKEB3NFZ.mjs +2302 -0
  48. package/dist/lib/node-esm/chunk-JKEB3NFZ.mjs.map +7 -0
  49. package/dist/lib/node-esm/{chunk-PXAJSTGZ.mjs → chunk-MBDVPB4V.mjs} +4 -5
  50. package/dist/lib/node-esm/chunk-MBDVPB4V.mjs.map +7 -0
  51. package/dist/lib/node-esm/{chunk-PY4X6FJT.mjs → chunk-XAFVSEUJ.mjs} +58 -17
  52. package/dist/lib/node-esm/chunk-XAFVSEUJ.mjs.map +7 -0
  53. package/dist/lib/node-esm/cli/index.mjs +74 -0
  54. package/dist/lib/node-esm/cli/index.mjs.map +7 -0
  55. package/dist/lib/node-esm/components/index.mjs +21 -0
  56. package/dist/lib/node-esm/components/index.mjs.map +7 -0
  57. package/dist/lib/node-esm/{create-chat-3BEG4R6J.mjs → create-chat-UQQ3542N.mjs} +4 -13
  58. package/dist/lib/node-esm/create-chat-UQQ3542N.mjs.map +7 -0
  59. package/dist/lib/node-esm/{ensure-companion-chat-BLP7NT32.mjs → ensure-companion-chat-LVCPD4DJ.mjs} +4 -4
  60. package/dist/lib/node-esm/ensure-companion-chat-LVCPD4DJ.mjs.map +7 -0
  61. package/dist/lib/node-esm/hooks/index.mjs +40 -0
  62. package/dist/lib/node-esm/hooks/index.mjs.map +7 -0
  63. package/dist/lib/node-esm/index.mjs +43 -3233
  64. package/dist/lib/node-esm/index.mjs.map +4 -4
  65. package/dist/lib/node-esm/meta.json +1 -1
  66. package/dist/lib/node-esm/{on-create-space-YRPZ6HZY.mjs → on-create-space-M63UBTTT.mjs} +3 -3
  67. package/dist/lib/node-esm/{on-create-space-YRPZ6HZY.mjs.map → on-create-space-M63UBTTT.mjs.map} +1 -1
  68. package/dist/lib/node-esm/operations/index.mjs +3 -3
  69. package/dist/lib/node-esm/operations/index.mjs.map +3 -3
  70. package/dist/lib/node-esm/{resolve-navigation-targets-3PPK7XLH.mjs → resolve-navigation-targets-HO77CAFT.mjs} +3 -3
  71. package/dist/lib/node-esm/{resolve-navigation-targets-3PPK7XLH.mjs.map → resolve-navigation-targets-HO77CAFT.mjs.map} +1 -1
  72. package/dist/lib/node-esm/{run-prompt-in-new-chat-2IJBSDTM.mjs → run-prompt-in-new-chat-RIRYYYPK.mjs} +9 -39
  73. package/dist/lib/node-esm/run-prompt-in-new-chat-RIRYYYPK.mjs.map +7 -0
  74. package/dist/lib/node-esm/{set-current-chat-KBMMZULR.mjs → set-current-chat-Z7GJ52VX.mjs} +4 -4
  75. package/dist/lib/node-esm/set-current-chat-Z7GJ52VX.mjs.map +7 -0
  76. package/dist/lib/node-esm/translations.mjs +173 -0
  77. package/dist/lib/node-esm/translations.mjs.map +7 -0
  78. package/dist/lib/node-esm/types/index.mjs +1 -3
  79. package/dist/lib/node-esm/{update-chat-name-HM2P4NSI.mjs → update-chat-name-GV4HX32Z.mjs} +7 -22
  80. package/dist/lib/node-esm/update-chat-name-GV4HX32Z.mjs.map +7 -0
  81. package/dist/types/src/AssistantPlugin.d.ts +1 -0
  82. package/dist/types/src/AssistantPlugin.d.ts.map +1 -1
  83. package/dist/types/src/AssistantPlugin.node.d.ts +4 -0
  84. package/dist/types/src/AssistantPlugin.node.d.ts.map +1 -0
  85. package/dist/types/src/AssistantPlugin.test.d.ts +2 -0
  86. package/dist/types/src/AssistantPlugin.test.d.ts.map +1 -0
  87. package/dist/types/src/blueprints/assistant/blueprint.d.ts +2 -2
  88. package/dist/types/src/blueprints/assistant/blueprint.d.ts.map +1 -1
  89. package/dist/types/src/capabilities/ai-service.d.ts.map +1 -1
  90. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  91. package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -1
  92. package/dist/types/src/capabilities/companion-chat-provisioner.d.ts.map +1 -1
  93. package/dist/types/src/capabilities/edge-model-resolver.d.ts.map +1 -1
  94. package/dist/types/src/capabilities/index.d.ts +5 -17
  95. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  96. package/dist/types/src/capabilities/local-model-resolver.d.ts +6 -3
  97. package/dist/types/src/capabilities/local-model-resolver.d.ts.map +1 -1
  98. package/dist/types/src/capabilities/markdown.d.ts +1 -1
  99. package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
  100. package/dist/types/src/capabilities/migrations.d.ts +1 -1
  101. package/dist/types/src/capabilities/migrations.d.ts.map +1 -1
  102. package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
  103. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -1
  104. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  105. package/dist/types/src/capabilities/settings.d.ts +1 -13
  106. package/dist/types/src/capabilities/settings.d.ts.map +1 -1
  107. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  108. package/dist/types/src/capabilities/toolkit.d.ts.map +1 -1
  109. package/dist/types/src/cli/index.d.ts +2 -0
  110. package/dist/types/src/cli/index.d.ts.map +1 -0
  111. package/dist/types/src/cli/plugin.d.ts +10 -0
  112. package/dist/types/src/cli/plugin.d.ts.map +1 -0
  113. package/dist/types/src/components/AssistantSettings/AssistantSettings.d.ts +1 -1
  114. package/dist/types/src/components/AssistantSettings/AssistantSettings.d.ts.map +1 -1
  115. package/dist/types/src/components/AssistantSettings/AssistantSettings.stories.d.ts +1 -539
  116. package/dist/types/src/components/AssistantSettings/AssistantSettings.stories.d.ts.map +1 -1
  117. package/dist/types/src/components/Chat/Chat.d.ts +32 -42
  118. package/dist/types/src/components/Chat/Chat.d.ts.map +1 -1
  119. package/dist/types/src/components/Chat/context.d.ts +29 -0
  120. package/dist/types/src/components/Chat/context.d.ts.map +1 -0
  121. package/dist/types/src/components/ChatPrompt/ChatActions.d.ts.map +1 -1
  122. package/dist/types/src/components/ChatPrompt/ChatMcpErrors.d.ts +12 -0
  123. package/dist/types/src/components/ChatPrompt/ChatMcpErrors.d.ts.map +1 -0
  124. package/dist/types/src/components/ChatPrompt/ChatOptions.d.ts +6 -2
  125. package/dist/types/src/components/ChatPrompt/ChatOptions.d.ts.map +1 -1
  126. package/dist/types/src/components/ChatPrompt/ChatOptions.stories.d.ts +19 -0
  127. package/dist/types/src/components/ChatPrompt/ChatOptions.stories.d.ts.map +1 -0
  128. package/dist/types/src/components/ChatPrompt/ChatPresets.d.ts.map +1 -1
  129. package/dist/types/src/components/ChatPrompt/ChatPrompt.d.ts +28 -0
  130. package/dist/types/src/components/ChatPrompt/ChatPrompt.d.ts.map +1 -0
  131. package/dist/types/src/components/ChatPrompt/ChatReferences.d.ts.map +1 -1
  132. package/dist/types/src/components/ChatPrompt/ChatStatus.d.ts +20 -0
  133. package/dist/types/src/components/ChatPrompt/ChatStatus.d.ts.map +1 -0
  134. package/dist/types/src/components/ChatPrompt/ChatStatusIndicator.d.ts.map +1 -1
  135. package/dist/types/src/components/ChatPrompt/index.d.ts +3 -0
  136. package/dist/types/src/components/ChatPrompt/index.d.ts.map +1 -1
  137. package/dist/types/src/components/ChatThread/Anchor.stories.d.ts +14 -0
  138. package/dist/types/src/components/ChatThread/Anchor.stories.d.ts.map +1 -0
  139. package/dist/types/src/components/ChatThread/ChatThread.d.ts +6 -3
  140. package/dist/types/src/components/ChatThread/ChatThread.d.ts.map +1 -1
  141. package/dist/types/src/components/ChatThread/ChatThread.stories.d.ts +4 -541
  142. package/dist/types/src/components/ChatThread/ChatThread.stories.d.ts.map +1 -1
  143. package/dist/types/src/components/ChatThread/Link.d.ts.map +1 -1
  144. package/dist/types/src/components/ChatThread/MarkdownStream.stories.d.ts +9 -540
  145. package/dist/types/src/components/ChatThread/MarkdownStream.stories.d.ts.map +1 -1
  146. package/dist/types/src/components/ChatThread/registry.d.ts +18 -0
  147. package/dist/types/src/components/ChatThread/registry.d.ts.map +1 -1
  148. package/dist/types/src/components/ChatThread/sync.d.ts +40 -14
  149. package/dist/types/src/components/ChatThread/sync.d.ts.map +1 -1
  150. package/dist/types/src/components/ChatThread/tool-widget-state.d.ts.map +1 -1
  151. package/dist/types/src/components/ChatThread/widgets/FallbackWidget.d.ts +4 -4
  152. package/dist/types/src/components/ChatThread/widgets/FallbackWidget.d.ts.map +1 -1
  153. package/dist/types/src/components/ChatThread/widgets/ReasoningWidget.d.ts.map +1 -1
  154. package/dist/types/src/components/ChatThread/widgets/ReasoningWidget.stories.d.ts.map +1 -1
  155. package/dist/types/src/components/ChatThread/widgets/ReferenceWidget.d.ts.map +1 -1
  156. package/dist/types/src/components/ChatThread/widgets/SelectWidget.d.ts.map +1 -1
  157. package/dist/types/src/components/ChatThread/widgets/StatsWidget.d.ts.map +1 -1
  158. package/dist/types/src/components/ChatThread/widgets/StatusWidget.d.ts.map +1 -1
  159. package/dist/types/src/components/ChatThread/widgets/SuggestionWidget.d.ts.map +1 -1
  160. package/dist/types/src/components/ChatThread/widgets/SummaryWidget.d.ts.map +1 -1
  161. package/dist/types/src/components/ChatThread/widgets/ToolWidget.d.ts.map +1 -1
  162. package/dist/types/src/components/ChatThread/widgets/ToolWidget.stories.d.ts +1 -539
  163. package/dist/types/src/components/ChatThread/widgets/ToolWidget.stories.d.ts.map +1 -1
  164. package/dist/types/src/components/ChatThread/widgets/defaults.d.ts +5 -0
  165. package/dist/types/src/components/ChatThread/widgets/defaults.d.ts.map +1 -0
  166. package/dist/types/src/components/ChatThread/widgets/index.d.ts +1 -2
  167. package/dist/types/src/components/ChatThread/widgets/index.d.ts.map +1 -1
  168. package/dist/types/src/components/ProcessTree/ProcessTree.d.ts +2 -1
  169. package/dist/types/src/components/ProcessTree/ProcessTree.d.ts.map +1 -1
  170. package/dist/types/src/components/ProcessTree/ProcessTree.stories.d.ts +0 -1
  171. package/dist/types/src/components/ProcessTree/ProcessTree.stories.d.ts.map +1 -1
  172. package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts +2 -2
  173. package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts.map +1 -1
  174. package/dist/types/src/components/TemplateEditor/TemplateEditor.stories.d.ts +1 -539
  175. package/dist/types/src/components/TemplateEditor/TemplateEditor.stories.d.ts.map +1 -1
  176. package/dist/types/src/components/TemplateEditor/TemplateForm.d.ts +3 -3
  177. package/dist/types/src/components/TemplateEditor/TemplateForm.d.ts.map +1 -1
  178. package/dist/types/src/components/TemplateEditor/TemplateForm.stories.d.ts +1 -539
  179. package/dist/types/src/components/TemplateEditor/TemplateForm.stories.d.ts.map +1 -1
  180. package/dist/types/src/components/TemplateEditor/extensions/handlebars-extension.d.ts.map +1 -1
  181. package/dist/types/src/components/TemplateEditor/extensions/xml-extension.d.ts.map +1 -1
  182. package/dist/types/src/components/ToolBlock/ToolBlock.d.ts +4 -4
  183. package/dist/types/src/components/ToolBlock/ToolBlock.d.ts.map +1 -1
  184. package/dist/types/src/components/Toolbox/Toolbox.d.ts +3 -3
  185. package/dist/types/src/components/Toolbox/Toolbox.d.ts.map +1 -1
  186. package/dist/types/src/components/Toolbox/Toolbox.stories.d.ts +1 -539
  187. package/dist/types/src/components/Toolbox/Toolbox.stories.d.ts.map +1 -1
  188. package/dist/types/src/containers/AgentArticle/AgentArticle.d.ts +2 -2
  189. package/dist/types/src/containers/AgentArticle/AgentArticle.d.ts.map +1 -1
  190. package/dist/types/src/containers/AgentArticle/AgentArticle.stories.d.ts +7 -540
  191. package/dist/types/src/containers/AgentArticle/AgentArticle.stories.d.ts.map +1 -1
  192. package/dist/types/src/containers/AgentProperties/AgentProperties.d.ts +1 -1
  193. package/dist/types/src/containers/AgentProperties/AgentProperties.d.ts.map +1 -1
  194. package/dist/types/src/containers/AgentProperties/AgentProperties.stories.d.ts +1 -539
  195. package/dist/types/src/containers/AgentProperties/AgentProperties.stories.d.ts.map +1 -1
  196. package/dist/types/src/containers/BlueprintArticle/BlueprintArticle.d.ts +1 -1
  197. package/dist/types/src/containers/BlueprintArticle/BlueprintArticle.d.ts.map +1 -1
  198. package/dist/types/src/containers/ChatCompanion/ChatCompanion.d.ts +1 -1
  199. package/dist/types/src/containers/ChatContainer/ChatContainer.d.ts.map +1 -1
  200. package/dist/types/src/containers/ChatDialog/ChatDialog.d.ts.map +1 -1
  201. package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts +6 -0
  202. package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts.map +1 -0
  203. package/dist/types/src/containers/RoutineArticle/index.d.ts +2 -0
  204. package/dist/types/src/containers/RoutineArticle/index.d.ts.map +1 -0
  205. package/dist/types/src/containers/RoutineList/RoutineList.d.ts +6 -0
  206. package/dist/types/src/containers/RoutineList/RoutineList.d.ts.map +1 -0
  207. package/dist/types/src/containers/RoutineList/RoutineList.stories.d.ts +21 -0
  208. package/dist/types/src/containers/RoutineList/RoutineList.stories.d.ts.map +1 -0
  209. package/dist/types/src/containers/RoutineList/index.d.ts +2 -0
  210. package/dist/types/src/containers/RoutineList/index.d.ts.map +1 -0
  211. package/dist/types/src/containers/TracePanel/TracePanel.d.ts +6 -4
  212. package/dist/types/src/containers/TracePanel/TracePanel.d.ts.map +1 -1
  213. package/dist/types/src/containers/TracePanel/TracePanel.stories.d.ts +13 -0
  214. package/dist/types/src/containers/TracePanel/TracePanel.stories.d.ts.map +1 -0
  215. package/dist/types/src/containers/TracePanel/dxn-extractor.d.ts +1 -1
  216. package/dist/types/src/containers/TracePanel/dxn-extractor.d.ts.map +1 -1
  217. package/dist/types/src/containers/TracePanel/execution-graph.d.ts +97 -0
  218. package/dist/types/src/containers/TracePanel/execution-graph.d.ts.map +1 -0
  219. package/dist/types/src/containers/TracePanel/execution-graph.test.d.ts +2 -0
  220. package/dist/types/src/containers/TracePanel/execution-graph.test.d.ts.map +1 -0
  221. package/dist/types/src/containers/TracePanel/index.d.ts.map +1 -1
  222. package/dist/types/src/containers/TracePanel/testing/index.d.ts +3 -0
  223. package/dist/types/src/containers/TracePanel/testing/index.d.ts.map +1 -0
  224. package/dist/types/src/containers/TracePanel/testing/simulated-agent.d.ts +14 -0
  225. package/dist/types/src/containers/TracePanel/testing/simulated-agent.d.ts.map +1 -0
  226. package/dist/types/src/containers/TracePanel/testing/snapshot-playback.d.ts +12 -0
  227. package/dist/types/src/containers/TracePanel/testing/snapshot-playback.d.ts.map +1 -0
  228. package/dist/types/src/containers/TriggerStatus/TriggerStatus.d.ts +3 -2
  229. package/dist/types/src/containers/TriggerStatus/TriggerStatus.d.ts.map +1 -1
  230. package/dist/types/src/containers/TriggerStatus/index.d.ts +1 -1
  231. package/dist/types/src/containers/TriggerStatus/index.d.ts.map +1 -1
  232. package/dist/types/src/containers/index.d.ts +2 -2
  233. package/dist/types/src/containers/index.d.ts.map +1 -1
  234. package/dist/types/src/extensions/prompt-extension.d.ts.map +1 -1
  235. package/dist/types/src/hooks/index.d.ts +2 -0
  236. package/dist/types/src/hooks/index.d.ts.map +1 -1
  237. package/dist/types/src/hooks/useBlueprintRegistry.d.ts +1 -1
  238. package/dist/types/src/hooks/useBlueprintRegistry.d.ts.map +1 -1
  239. package/dist/types/src/hooks/useChatKeymap.d.ts +12 -0
  240. package/dist/types/src/hooks/useChatKeymap.d.ts.map +1 -0
  241. package/dist/types/src/hooks/useChatProcessor.d.ts +1 -1
  242. package/dist/types/src/hooks/useChatProcessor.d.ts.map +1 -1
  243. package/dist/types/src/hooks/useChatServices.d.ts.map +1 -1
  244. package/dist/types/src/hooks/useChatToolbarActions.d.ts.map +1 -1
  245. package/dist/types/src/hooks/useContextBinder.d.ts.map +1 -1
  246. package/dist/types/src/hooks/useContextObjects.d.ts.map +1 -1
  247. package/dist/types/src/hooks/useDebug.d.ts +10 -0
  248. package/dist/types/src/hooks/useDebug.d.ts.map +1 -0
  249. package/dist/types/src/hooks/useFilteredTypes.d.ts.map +1 -1
  250. package/dist/types/src/hooks/useFlush.d.ts +1 -1
  251. package/dist/types/src/hooks/useFlush.d.ts.map +1 -1
  252. package/dist/types/src/hooks/usePresets.d.ts.map +1 -1
  253. package/dist/types/src/hooks/useReferencesProvider.d.ts.map +1 -1
  254. package/dist/types/src/index.d.ts +3 -5
  255. package/dist/types/src/index.d.ts.map +1 -1
  256. package/dist/types/src/operations/create-chat.d.ts +1 -1
  257. package/dist/types/src/operations/create-chat.d.ts.map +1 -1
  258. package/dist/types/src/operations/definitions.d.ts +24 -19
  259. package/dist/types/src/operations/definitions.d.ts.map +1 -1
  260. package/dist/types/src/operations/ensure-companion-chat.d.ts +1 -1
  261. package/dist/types/src/operations/ensure-companion-chat.d.ts.map +1 -1
  262. package/dist/types/src/operations/index.d.ts +1 -1
  263. package/dist/types/src/operations/index.d.ts.map +1 -1
  264. package/dist/types/src/operations/on-create-space.d.ts +1 -1
  265. package/dist/types/src/operations/on-create-space.d.ts.map +1 -1
  266. package/dist/types/src/operations/prompt.test.d.ts +2 -0
  267. package/dist/types/src/operations/prompt.test.d.ts.map +1 -0
  268. package/dist/types/src/operations/resolve-navigation-targets.d.ts +1 -1
  269. package/dist/types/src/operations/resolve-navigation-targets.d.ts.map +1 -1
  270. package/dist/types/src/operations/run-prompt-in-new-chat.d.ts +1 -1
  271. package/dist/types/src/operations/run-prompt-in-new-chat.d.ts.map +1 -1
  272. package/dist/types/src/operations/set-current-chat.d.ts +1 -1
  273. package/dist/types/src/operations/set-current-chat.d.ts.map +1 -1
  274. package/dist/types/src/operations/update-chat-name.d.ts +1 -1
  275. package/dist/types/src/operations/update-chat-name.d.ts.map +1 -1
  276. package/dist/types/src/processor/presets.d.ts +1 -1
  277. package/dist/types/src/processor/presets.d.ts.map +1 -1
  278. package/dist/types/src/processor/processor.d.ts +25 -7
  279. package/dist/types/src/processor/processor.d.ts.map +1 -1
  280. package/dist/types/src/queue-logger.d.ts.map +1 -1
  281. package/dist/types/src/testing/index.d.ts +1 -0
  282. package/dist/types/src/testing/index.d.ts.map +1 -1
  283. package/dist/types/src/testing/test-generator.d.ts.map +1 -1
  284. package/dist/types/src/testing/test-generator.test.d.ts +2 -0
  285. package/dist/types/src/testing/test-generator.test.d.ts.map +1 -0
  286. package/dist/types/src/testing/test-services.d.ts.map +1 -1
  287. package/dist/types/src/testing/test-trace.d.ts +5 -0
  288. package/dist/types/src/testing/test-trace.d.ts.map +1 -0
  289. package/dist/types/src/testing/trace-timeline.test.d.ts +2 -0
  290. package/dist/types/src/testing/trace-timeline.test.d.ts.map +1 -0
  291. package/dist/types/src/translations.d.ts +2 -539
  292. package/dist/types/src/translations.d.ts.map +1 -1
  293. package/dist/types/src/types/Assistant.d.ts +22 -6
  294. package/dist/types/src/types/Assistant.d.ts.map +1 -1
  295. package/dist/types/src/types/Settings.d.ts +22 -6
  296. package/dist/types/src/types/Settings.d.ts.map +1 -1
  297. package/dist/types/src/types/capabilities.d.ts +1 -13
  298. package/dist/types/src/types/capabilities.d.ts.map +1 -1
  299. package/dist/types/src/types/events.d.ts.map +1 -1
  300. package/dist/types/src/types/index.d.ts +0 -1
  301. package/dist/types/src/types/index.d.ts.map +1 -1
  302. package/dist/types/src/types/service.d.ts +1 -1
  303. package/dist/types/src/types/service.d.ts.map +1 -1
  304. package/dist/types/tsconfig.tsbuildinfo +1 -1
  305. package/package.json +113 -99
  306. package/src/AssistantPlugin.node.ts +125 -0
  307. package/src/AssistantPlugin.test.ts +35 -0
  308. package/src/AssistantPlugin.tsx +22 -16
  309. package/src/blueprints/assistant/blueprint.test.ts +3 -3
  310. package/src/blueprints/assistant/blueprint.ts +3 -3
  311. package/src/capabilities/app-graph-builder.ts +5 -61
  312. package/src/capabilities/blueprint-definition.ts +2 -4
  313. package/src/capabilities/index.ts +2 -1
  314. package/src/capabilities/local-model-resolver.ts +14 -4
  315. package/src/capabilities/markdown.ts +1 -1
  316. package/src/capabilities/migrations.ts +1 -7
  317. package/src/capabilities/operation-handler.ts +1 -1
  318. package/src/capabilities/react-surface.tsx +38 -28
  319. package/src/capabilities/toolkit.ts +2 -2
  320. package/src/{components/Typewriter → cli}/index.ts +1 -1
  321. package/src/cli/plugin.ts +83 -0
  322. package/src/components/AssistantSettings/AssistantSettings.stories.tsx +3 -2
  323. package/src/components/AssistantSettings/AssistantSettings.tsx +22 -111
  324. package/src/components/Chat/Chat.tsx +82 -286
  325. package/src/components/Chat/context.ts +39 -0
  326. package/src/components/ChatPrompt/ChatActions.tsx +10 -10
  327. package/src/components/ChatPrompt/ChatMcpErrors.tsx +50 -0
  328. package/src/components/ChatPrompt/ChatOptions.stories.tsx +136 -0
  329. package/src/components/ChatPrompt/ChatOptions.tsx +229 -37
  330. package/src/components/ChatPrompt/ChatPrompt.tsx +182 -0
  331. package/src/components/ChatPrompt/ChatReferences.tsx +1 -1
  332. package/src/components/ChatPrompt/ChatStatus.tsx +123 -0
  333. package/src/components/ChatPrompt/index.ts +3 -0
  334. package/src/components/ChatThread/Anchor.stories.tsx +95 -0
  335. package/src/components/ChatThread/ChatThread.stories.tsx +39 -29
  336. package/src/components/ChatThread/ChatThread.tsx +36 -21
  337. package/src/components/ChatThread/DEBUG.md +41 -0
  338. package/src/components/ChatThread/MarkdownStream.stories.tsx +43 -5
  339. package/src/components/ChatThread/registry.tsx +72 -24
  340. package/src/components/ChatThread/sync.test.ts +175 -15
  341. package/src/components/ChatThread/sync.ts +87 -102
  342. package/src/components/ChatThread/testing/reasoning.md +25 -0
  343. package/src/components/ChatThread/widgets/FallbackWidget.tsx +2 -2
  344. package/src/components/ChatThread/widgets/ReasoningWidget.stories.tsx +1 -1
  345. package/src/components/ChatThread/widgets/ReasoningWidget.ts +6 -6
  346. package/src/components/ChatThread/widgets/ReferenceWidget.ts +3 -1
  347. package/src/components/ChatThread/widgets/SelectWidget.ts +3 -1
  348. package/src/components/ChatThread/widgets/StatsWidget.ts +3 -1
  349. package/src/components/ChatThread/widgets/StatusWidget.ts +3 -3
  350. package/src/components/ChatThread/widgets/SuggestionWidget.ts +1 -1
  351. package/src/components/ChatThread/widgets/SummaryWidget.tsx +3 -2
  352. package/src/components/ChatThread/widgets/ToolWidget.stories.tsx +3 -2
  353. package/src/components/ChatThread/widgets/ToolWidget.tsx +2 -2
  354. package/src/components/ChatThread/widgets/defaults.ts +8 -0
  355. package/src/components/ChatThread/widgets/index.ts +1 -2
  356. package/src/components/ProcessTree/ProcessTree.stories.tsx +12 -38
  357. package/src/components/ProcessTree/ProcessTree.tsx +70 -37
  358. package/src/components/TemplateEditor/TemplateEditor.stories.tsx +3 -2
  359. package/src/components/TemplateEditor/TemplateEditor.tsx +5 -5
  360. package/src/components/TemplateEditor/TemplateForm.stories.tsx +4 -3
  361. package/src/components/TemplateEditor/TemplateForm.tsx +3 -3
  362. package/src/components/TemplateEditor/extensions/handlebars-extension.ts +1 -1
  363. package/src/components/ToolBlock/ToolBlock.tsx +2 -2
  364. package/src/components/Toolbox/Toolbox.stories.tsx +2 -1
  365. package/src/components/Toolbox/Toolbox.tsx +2 -2
  366. package/src/containers/AgentArticle/AgentArticle.stories.tsx +40 -25
  367. package/src/containers/AgentArticle/AgentArticle.tsx +96 -53
  368. package/src/containers/AgentProperties/AgentProperties.stories.tsx +14 -4
  369. package/src/containers/AgentProperties/AgentProperties.tsx +46 -88
  370. package/src/containers/BlueprintArticle/BlueprintArticle.tsx +1 -1
  371. package/src/containers/ChatCompanion/ChatCompanion.tsx +1 -1
  372. package/src/containers/ChatContainer/ChatContainer.tsx +16 -6
  373. package/src/containers/ChatDialog/ChatDialog.tsx +3 -9
  374. package/src/containers/{PromptArticle/PromptArticle.tsx → RoutineArticle/RoutineArticle.tsx} +4 -4
  375. package/src/containers/RoutineArticle/index.ts +5 -0
  376. package/src/containers/{PromptList/PromptList.stories.tsx → RoutineList/RoutineList.stories.tsx} +11 -10
  377. package/src/containers/{PromptList/PromptList.tsx → RoutineList/RoutineList.tsx} +6 -5
  378. package/src/containers/RoutineList/index.ts +5 -0
  379. package/src/containers/TracePanel/TracePanel.stories.tsx +278 -0
  380. package/src/containers/TracePanel/TracePanel.tsx +95 -318
  381. package/src/containers/TracePanel/dxn-extractor.test.ts +7 -7
  382. package/src/containers/TracePanel/dxn-extractor.ts +4 -4
  383. package/src/containers/TracePanel/execution-graph.test.ts +382 -0
  384. package/src/containers/TracePanel/execution-graph.ts +579 -0
  385. package/src/containers/TracePanel/testing/index.ts +6 -0
  386. package/src/containers/TracePanel/testing/simulated-agent.ts +114 -0
  387. package/src/containers/TracePanel/testing/snapshot-playback.ts +45 -0
  388. package/src/containers/TriggerStatus/TriggerStatus.tsx +19 -34
  389. package/src/containers/TriggerStatus/index.ts +1 -1
  390. package/src/containers/index.ts +2 -2
  391. package/src/hooks/index.ts +2 -0
  392. package/src/hooks/useBlueprintRegistry.ts +1 -1
  393. package/src/hooks/useChatKeymap.ts +52 -0
  394. package/src/hooks/useChatProcessor.ts +11 -11
  395. package/src/hooks/useDebug.ts +38 -0
  396. package/src/index.ts +8 -6
  397. package/src/operations/create-chat.ts +1 -2
  398. package/src/operations/definitions.ts +3 -4
  399. package/src/operations/ensure-companion-chat.ts +1 -1
  400. package/src/operations/index.ts +1 -1
  401. package/src/operations/on-create-space.ts +1 -1
  402. package/src/operations/prompt.test.ts +77 -0
  403. package/src/operations/resolve-navigation-targets.ts +1 -1
  404. package/src/operations/run-prompt-in-new-chat.ts +2 -3
  405. package/src/operations/set-current-chat.ts +1 -1
  406. package/src/operations/update-chat-name.ts +2 -2
  407. package/src/processor/presets.ts +9 -1
  408. package/src/processor/processor.test.ts +4 -4
  409. package/src/processor/processor.ts +43 -27
  410. package/src/queue-logger.ts +19 -8
  411. package/src/testing/data/trace-timeline.dx.json +4657 -0
  412. package/src/testing/index.ts +1 -0
  413. package/src/testing/test-generator.test.ts +81 -0
  414. package/src/testing/test-generator.ts +46 -40
  415. package/src/testing/test-trace.ts +20 -0
  416. package/src/testing/trace-timeline.conversations.json +1 -0
  417. package/src/testing/trace-timeline.test.ts +249 -0
  418. package/src/translations.ts +49 -34
  419. package/src/types/Assistant.ts +11 -0
  420. package/src/types/Settings.ts +63 -8
  421. package/src/types/index.ts +0 -1
  422. package/src/types/service.ts +1 -1
  423. package/dist/lib/browser/AssistantSettings-7QMO3LGF.mjs +0 -97
  424. package/dist/lib/browser/AssistantSettings-7QMO3LGF.mjs.map +0 -7
  425. package/dist/lib/browser/chunk-ATHYBVGN.mjs.map +0 -7
  426. package/dist/lib/browser/chunk-EZRS3J25.mjs +0 -30
  427. package/dist/lib/browser/chunk-EZRS3J25.mjs.map +0 -7
  428. package/dist/lib/browser/chunk-RUV2WOQH.mjs.map +0 -7
  429. package/dist/lib/browser/create-chat-LBZHGVSN.mjs.map +0 -7
  430. package/dist/lib/browser/ensure-companion-chat-FR4AWZ2P.mjs.map +0 -7
  431. package/dist/lib/browser/run-prompt-in-new-chat-4YQ37XIS.mjs.map +0 -7
  432. package/dist/lib/browser/set-current-chat-WJI3WAVM.mjs.map +0 -7
  433. package/dist/lib/browser/update-chat-name-3Y36KFAS.mjs.map +0 -7
  434. package/dist/lib/node-esm/AssistantSettings-UVUTKO7E.mjs +0 -98
  435. package/dist/lib/node-esm/AssistantSettings-UVUTKO7E.mjs.map +0 -7
  436. package/dist/lib/node-esm/chunk-NZIKC7AN.mjs +0 -32
  437. package/dist/lib/node-esm/chunk-NZIKC7AN.mjs.map +0 -7
  438. package/dist/lib/node-esm/chunk-PXAJSTGZ.mjs.map +0 -7
  439. package/dist/lib/node-esm/chunk-PY4X6FJT.mjs.map +0 -7
  440. package/dist/lib/node-esm/create-chat-3BEG4R6J.mjs.map +0 -7
  441. package/dist/lib/node-esm/ensure-companion-chat-BLP7NT32.mjs.map +0 -7
  442. package/dist/lib/node-esm/run-prompt-in-new-chat-2IJBSDTM.mjs.map +0 -7
  443. package/dist/lib/node-esm/set-current-chat-KBMMZULR.mjs.map +0 -7
  444. package/dist/lib/node-esm/update-chat-name-HM2P4NSI.mjs.map +0 -7
  445. package/dist/types/src/components/ChatProgress/ChatProgress.d.ts +0 -10
  446. package/dist/types/src/components/ChatProgress/ChatProgress.d.ts.map +0 -1
  447. package/dist/types/src/components/ChatProgress/index.d.ts +0 -2
  448. package/dist/types/src/components/ChatProgress/index.d.ts.map +0 -1
  449. package/dist/types/src/components/ChatThread/widgets/PromptWidget.d.ts +0 -14
  450. package/dist/types/src/components/ChatThread/widgets/PromptWidget.d.ts.map +0 -1
  451. package/dist/types/src/components/Typewriter/AssistantToolbar.d.ts +0 -12
  452. package/dist/types/src/components/Typewriter/AssistantToolbar.d.ts.map +0 -1
  453. package/dist/types/src/components/Typewriter/Typewriter.d.ts +0 -11
  454. package/dist/types/src/components/Typewriter/Typewriter.d.ts.map +0 -1
  455. package/dist/types/src/components/Typewriter/Typewriter.stories.d.ts +0 -7
  456. package/dist/types/src/components/Typewriter/Typewriter.stories.d.ts.map +0 -1
  457. package/dist/types/src/components/Typewriter/assistant-extension.d.ts +0 -5
  458. package/dist/types/src/components/Typewriter/assistant-extension.d.ts.map +0 -1
  459. package/dist/types/src/components/Typewriter/index.d.ts +0 -2
  460. package/dist/types/src/components/Typewriter/index.d.ts.map +0 -1
  461. package/dist/types/src/containers/PromptArticle/PromptArticle.d.ts +0 -6
  462. package/dist/types/src/containers/PromptArticle/PromptArticle.d.ts.map +0 -1
  463. package/dist/types/src/containers/PromptArticle/index.d.ts +0 -2
  464. package/dist/types/src/containers/PromptArticle/index.d.ts.map +0 -1
  465. package/dist/types/src/containers/PromptList/PromptList.d.ts +0 -6
  466. package/dist/types/src/containers/PromptList/PromptList.d.ts.map +0 -1
  467. package/dist/types/src/containers/PromptList/PromptList.stories.d.ts +0 -559
  468. package/dist/types/src/containers/PromptList/PromptList.stories.d.ts.map +0 -1
  469. package/dist/types/src/containers/PromptList/index.d.ts +0 -2
  470. package/dist/types/src/containers/PromptList/index.d.ts.map +0 -1
  471. package/dist/types/src/types/defs.d.ts +0 -2
  472. package/dist/types/src/types/defs.d.ts.map +0 -1
  473. package/src/blueprints/assistant/blueprint.conversations.json +0 -1
  474. package/src/components/ChatProgress/ChatProgress.tsx +0 -56
  475. package/src/components/ChatProgress/index.ts +0 -5
  476. package/src/components/ChatThread/widgets/PromptWidget.ts +0 -28
  477. package/src/components/Typewriter/AssistantToolbar.tsx +0 -161
  478. package/src/components/Typewriter/Typewriter.stories.tsx +0 -86
  479. package/src/components/Typewriter/Typewriter.tsx +0 -50
  480. package/src/components/Typewriter/assistant-extension.tsx +0 -141
  481. package/src/containers/PromptArticle/index.ts +0 -5
  482. package/src/containers/PromptList/index.ts +0 -5
  483. package/src/types/defs.ts +0 -5
@@ -8,11 +8,11 @@ import { log } from '@dxos/log';
8
8
  import { ContentBlock, type Message } from '@dxos/types';
9
9
  import { type XmlWidgetRegistry, getXmlTextChild } from '@dxos/ui-editor';
10
10
 
11
+ import { type Assistant } from '../../types';
11
12
  import { type BlockRenderer, type MessageThreadContext } from './sync';
12
13
  import { applyToolBlockToWidgetState } from './tool-widget-state';
13
14
  import {
14
15
  FallbackWidget,
15
- PromptWidget,
16
16
  ReasoningWidget,
17
17
  ReferenceWidget,
18
18
  SelectWidget,
@@ -25,17 +25,36 @@ import {
25
25
 
26
26
  /**
27
27
  * Custom XML tags registry.
28
+ *
29
+ * NOTE: `<prompt>` has no widget — it is rendered via mark + line decorations
30
+ * (`xmlBlockDecoration`) in MarkdownStream so the prompt text remains part of the document
31
+ * and can be highlighted by `xmlFormatting`. It is still listed here so the markdown block
32
+ * parser (`xmlBlockParsers`) knows to keep `<prompt>...</prompt>` as a single HTMLBlock
33
+ * — otherwise an unregistered prompt opens a Paragraph that lazy-continues into the
34
+ * following lines and breaks parsing of subsequent multi-line tags (e.g. a `<reasoning>`
35
+ * block whose content contains an ordered list).
28
36
  */
29
37
  export const componentRegistry: XmlWidgetRegistry = {
30
38
  //
31
- // DOM Widgets
39
+ // Block-only (no widget — see note above).
32
40
  //
33
41
 
34
42
  prompt: {
35
43
  block: true,
36
- factory: ({ children }) => {
44
+ },
45
+
46
+ //
47
+ // DOM Widgets
48
+ //
49
+
50
+ synthetic: {
51
+ block: true,
52
+ factory: ({ children, range }) => {
37
53
  const text = getXmlTextChild(children);
38
- return text ? new PromptWidget(text) : null;
54
+ // TODO(dmaretskyi): Synthetic blocks are "user"-turn messages generated by the system, i.e. and event from a trigger, an email-encoded to JSON, etc.
55
+ // They are meant to start agent, to process the event without looking like user-authored prompt.
56
+ // Create a new widget type for them.
57
+ return text ? new ReasoningWidget(text, range.from) : null;
39
58
  },
40
59
  },
41
60
  reasoning: {
@@ -123,17 +142,47 @@ export const componentRegistry: XmlWidgetRegistry = {
123
142
  /**
124
143
  * Convert block to markdown.
125
144
  */
126
- export const blockToMarkdown: BlockRenderer = (
127
- context: MessageThreadContext,
145
+ export const blockToMarkdown: BlockRenderer = createBlockRenderer('normal');
146
+
147
+ /**
148
+ * Create a {@link BlockRenderer} that filters blocks based on the chat view type.
149
+ *
150
+ * - `summary`: only user prompts.
151
+ * - `normal`: user prompts + assistant text + tool calls + summary/select/suggestion/reference + status. Hides reasoning.
152
+ * - `thinking`: same as normal plus reasoning.
153
+ * - `debug`: renders every block (raw fallbacks visible).
154
+ */
155
+ export function createBlockRenderer(viewType: Assistant.ChatView | undefined): BlockRenderer {
156
+ return (context, message, block) => {
157
+ if (!isBlockVisible(viewType, message, block)) {
158
+ return;
159
+ }
160
+ let str = blockToMarkdownImpl(context, message, block);
161
+ if (str && !block.pending) {
162
+ return (str += '\n');
163
+ }
164
+ return str;
165
+ };
166
+ }
167
+
168
+ const isBlockVisible = (
169
+ viewType: Assistant.ChatView | undefined,
128
170
  message: Message.Message,
129
171
  block: ContentBlock.Any,
130
- ) => {
131
- let str = blockToMarkdownImpl(context, message, block);
132
- if (str && !block.pending) {
133
- return (str += '\n');
172
+ ): boolean => {
173
+ switch (viewType) {
174
+ case 'debug':
175
+ return true;
176
+ case 'normal':
177
+ return block._tag !== 'reasoning';
178
+ case 'summary':
179
+ // Show only conversational text (user prompts + assistant replies); hide reasoning,
180
+ // tool calls, status, stats, and synthetic system messages.
181
+ return block._tag === 'text' && (block as ContentBlock.Text).disposition !== 'synthetic';
182
+ case 'thinking':
183
+ default:
184
+ return true;
134
185
  }
135
-
136
- return str;
137
186
  };
138
187
 
139
188
  const blockToMarkdownImpl = (context: MessageThreadContext, message: Message.Message, block: ContentBlock.Any) => {
@@ -141,7 +190,11 @@ const blockToMarkdownImpl = (context: MessageThreadContext, message: Message.Mes
141
190
  switch (block._tag) {
142
191
  case 'text': {
143
192
  if (message.sender.role === 'user') {
144
- return `<prompt>${block.text}</prompt>`;
193
+ if (block.disposition === 'synthetic') {
194
+ return renderXMLBlock('synthetic', { content: block.text, pending: block.pending });
195
+ } else {
196
+ return `<prompt>${block.text}</prompt>`;
197
+ }
145
198
  } else {
146
199
  const text = block.text.trim();
147
200
  if (text.length > 0) {
@@ -217,18 +270,13 @@ const blockToMarkdownImpl = (context: MessageThreadContext, message: Message.Mes
217
270
  const escapeXmlTextContent = (raw: string): string =>
218
271
  raw.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
219
272
 
220
- /**
221
- * Strip actual list-marker prefixes without removing meaningful leading content.
222
- */
223
- const stripBulletLikeLinePrefixes = (raw: string): string =>
224
- raw
225
- .split(/\r?\n/)
226
- .map((line) => line.replace(/^\s*(?:[-*+•]|\d+[.)]\s)/, ''))
227
- .join('\n');
228
-
229
273
  const renderXMLBlock = (tag: string, opts: { content?: string; pending?: boolean; attributes?: string }) => {
230
- // Replace paragraph breaks so that markdown parser does not split the content into multiple paragraphs.
231
- const content = escapeXmlTextContent(stripBulletLikeLinePrefixes((opts.content ?? '').replace(/\n\n/g, ' ').trim()));
274
+ // Replace paragraph breaks so that the markdown parser does not split the content into multiple paragraphs.
275
+ // NOTE: do not strip leading list-marker prefixes (`-`, `*`, `1. `, ...) per line — the streaming
276
+ // tag's range is replaced atomically by the XML widget so the inner markdown is never user-visible,
277
+ // and stripping can collapse a line to empty mid-stream (e.g. when only `1. ` has arrived), breaking
278
+ // the prefix-extension contract that `MessageSyncer` relies on for incremental appends.
279
+ const content = escapeXmlTextContent((opts.content ?? '').replace(/\n\n/g, ' ').trim());
232
280
 
233
281
  if (opts.pending) {
234
282
  return `<${tag}${opts.attributes ? ` ${opts.attributes}` : ''}>${content}`;
@@ -1,21 +1,21 @@
1
- // @vitest-environment jsdom
2
-
3
1
  //
4
2
  // Copyright 2025 DXOS.org
5
3
  //
6
4
 
5
+ // @vitest-environment jsdom
6
+
7
7
  import { EditorView } from '@codemirror/view';
8
8
  import { describe, it } from '@effect/vitest';
9
9
  import * as Effect from 'effect/Effect';
10
10
 
11
11
  import { Obj } from '@dxos/echo';
12
12
  import { type Mutable } from '@dxos/echo/internal';
13
- import { type ContentBlock } from '@dxos/types';
13
+ import { type ContentBlock, type Message } from '@dxos/types';
14
14
 
15
15
  import { createMessage } from '#testing';
16
16
 
17
- import { blockToMarkdown } from './registry';
18
- import { MessageSyncer, type TextModel } from './sync';
17
+ import { createBlockRenderer } from './registry';
18
+ import { type BlockRenderer, MessageSyncer, type MessageThreadContext, type TextModel } from './sync';
19
19
 
20
20
  class TestDocument implements TextModel {
21
21
  private readonly _view = new EditorView({ extensions: [] });
@@ -48,20 +48,20 @@ describe('reducers', () => {
48
48
  'basic sync',
49
49
  Effect.fn(function* ({ expect }) {
50
50
  const doc = new TestDocument();
51
- const syncer = new MessageSyncer(doc, blockToMarkdown);
51
+ const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
52
52
 
53
53
  const messages = [
54
54
  createMessage('user', [{ _tag: 'text', text: 'Hello' }]),
55
55
  createMessage('assistant', [{ _tag: 'text', text: 'Hi there!' }]),
56
56
  ];
57
57
 
58
- syncer.append(messages);
58
+ syncer.update(messages);
59
59
  expect(doc.content).toEqual(['<prompt>Hello</prompt>', 'Hi there!', ''].join('\n'));
60
60
 
61
- Obj.change(messages[1], (obj) => {
61
+ Obj.update(messages[1], (obj) => {
62
62
  obj.blocks.push({ _tag: 'text', text: 'How can I help?' });
63
63
  });
64
- syncer.append(messages);
64
+ syncer.update(messages);
65
65
  expect(doc.content).toEqual(['<prompt>Hello</prompt>', 'Hi there!', 'How can I help?', ''].join('\n'));
66
66
  }),
67
67
  );
@@ -70,30 +70,190 @@ describe('reducers', () => {
70
70
  'sync with partial updates',
71
71
  Effect.fn(function* ({ expect }) {
72
72
  const doc = new TestDocument();
73
- const syncer = new MessageSyncer(doc, blockToMarkdown);
73
+ const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
74
74
 
75
75
  const messages = [
76
76
  createMessage('user', [{ _tag: 'text', text: 'Hello' }]),
77
77
  createMessage('assistant', [{ _tag: 'text', text: 'Hi there!', pending: true }]),
78
78
  ];
79
79
 
80
- syncer.append(messages);
80
+ syncer.update(messages);
81
81
  expect(doc.content).toEqual(['<prompt>Hello</prompt>', 'Hi there!'].join('\n'));
82
82
 
83
- Obj.change(messages[1], (obj) => {
83
+ Obj.update(messages[1], (obj) => {
84
84
  const block = obj.blocks[0] as Mutable<ContentBlock.Text>;
85
85
  block.text = 'Hi there! How are you?';
86
86
  block.pending = false;
87
87
  });
88
- syncer.append(messages);
88
+ syncer.update(messages);
89
89
 
90
- Obj.change(messages[1], (obj) => {
90
+ Obj.update(messages[1], (obj) => {
91
91
  obj.blocks.push({ _tag: 'text', text: 'How can I help?' });
92
92
  });
93
- syncer.append(messages);
93
+ syncer.update(messages);
94
94
  expect(doc.content).toEqual(
95
95
  ['<prompt>Hello</prompt>', 'Hi there! How are you?', 'How can I help?', ''].join('\n'),
96
96
  );
97
97
  }),
98
98
  );
99
+
100
+ // Regression: streaming reasoning text that passes through a bare list-marker state
101
+ // (e.g. `"…\n1. "`) used to make `stripBulletLikeLinePrefixes` collapse the line to empty,
102
+ // breaking the prefix-diff invariant in `MessageSyncer` and producing a duplicate `<reasoning>`
103
+ // opening tag in the document.
104
+ it.effect(
105
+ 'streaming reasoning with list-marker transitions does not duplicate opening tag',
106
+ Effect.fn(function* ({ expect }) {
107
+ const doc = new TestDocument();
108
+ const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
109
+
110
+ const setReasoning = (message: Message.Message, text: string, pending: boolean) => {
111
+ Obj.update(message, (message) => {
112
+ const block = message.blocks[0] as Mutable<ContentBlock.Reasoning>;
113
+ block.reasoningText = text;
114
+ block.pending = pending;
115
+ });
116
+ };
117
+
118
+ const messages = [createMessage('assistant', [{ _tag: 'reasoning', reasoningText: 'abc\n1', pending: true }])];
119
+
120
+ // Tick 1: `"abc\n1"` — `\d+[.)]\s` regex does not match (no dot/space yet).
121
+ syncer.update(messages);
122
+
123
+ // Tick 2: `"abc\n1."` — still no match (no trailing whitespace).
124
+ setReasoning(messages[0], 'abc\n1.', true);
125
+ syncer.update(messages);
126
+
127
+ // Tick 3: `"abc\n1. "` — line `"1. "` matches and is stripped to empty.
128
+ setReasoning(messages[0], 'abc\n1. ', true);
129
+ syncer.update(messages);
130
+
131
+ // Tick 4: `"abc\n1. foo"` — list item with content.
132
+ setReasoning(messages[0], 'abc\n1. foo', true);
133
+ syncer.update(messages);
134
+
135
+ // Tick 5: finalize.
136
+ setReasoning(messages[0], 'abc\n1. foo', false);
137
+ syncer.update(messages);
138
+
139
+ const openTagCount = (doc.content.match(/<reasoning>/g) ?? []).length;
140
+ const closeTagCount = (doc.content.match(/<\/reasoning>/g) ?? []).length;
141
+ expect(openTagCount).toBe(1);
142
+ expect(closeTagCount).toBe(1);
143
+ }),
144
+ );
145
+
146
+ // Regression: prompt "respond with your name inside an xml tag" produces a streamed
147
+ // reasoning block followed by a text block containing a non-registered XML tag
148
+ // (`<name>Claude</name>`). The text block must appear in the document AFTER the
149
+ // closed reasoning block — the bug symptom is the reasoning tag rendering with no
150
+ // follow-up response visible.
151
+ it.effect(
152
+ 'reasoning block followed by text containing a non-registered xml tag',
153
+ Effect.fn(function* ({ expect }) {
154
+ const doc = new TestDocument();
155
+ const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
156
+
157
+ const setReasoning = (message: Message.Message, text: string, pending: boolean) => {
158
+ Obj.update(message, (message) => {
159
+ const block = message.blocks[0] as Mutable<ContentBlock.Reasoning>;
160
+ block.reasoningText = text;
161
+ block.pending = pending;
162
+ });
163
+ };
164
+
165
+ const setText = (message: Message.Message, text: string, pending: boolean) => {
166
+ Obj.update(message, (message) => {
167
+ const block = message.blocks[1] as Mutable<ContentBlock.Text>;
168
+ block.text = text;
169
+ block.pending = pending;
170
+ });
171
+ };
172
+
173
+ // Tick 1: reasoning starts streaming.
174
+ const messages = [createMessage('assistant', [{ _tag: 'reasoning', reasoningText: 'Thinking', pending: true }])];
175
+ syncer.update(messages);
176
+
177
+ // Tick 2: reasoning grows.
178
+ setReasoning(messages[0], 'Thinking about the answer', true);
179
+ syncer.update(messages);
180
+
181
+ // Tick 3: reasoning closes.
182
+ setReasoning(messages[0], 'Thinking about the answer', false);
183
+ syncer.update(messages);
184
+
185
+ // Tick 4: text block appears, pending and empty (model has started emitting but text is still '').
186
+ Obj.update(messages[0], (message) => {
187
+ message.blocks.push({ _tag: 'text', text: '', pending: true });
188
+ });
189
+ syncer.update(messages);
190
+
191
+ // Tick 5: partial text — opening tag only.
192
+ setText(messages[0], '<name>', true);
193
+ syncer.update(messages);
194
+
195
+ // Tick 6: full text streamed.
196
+ setText(messages[0], '<name>Claude</name>', true);
197
+ syncer.update(messages);
198
+
199
+ // Tick 7: text finalised.
200
+ setText(messages[0], '<name>Claude</name>', false);
201
+ syncer.update(messages);
202
+
203
+ // Both the closed reasoning tag and the response text must be present.
204
+ expect(doc.content).toContain('<reasoning>Thinking about the answer</reasoning>');
205
+ expect(doc.content).toContain('<name>Claude</name>');
206
+
207
+ const openReasoning = (doc.content.match(/<reasoning>/g) ?? []).length;
208
+ const closeReasoning = (doc.content.match(/<\/reasoning>/g) ?? []).length;
209
+ expect(openReasoning).toBe(1);
210
+ expect(closeReasoning).toBe(1);
211
+ }),
212
+ );
213
+
214
+ // Direct test of `MessageSyncer`'s tolerance for non-monotonic renderer output —
215
+ // any renderer that produces a shorter string for the same streaming block (e.g., due
216
+ // to whitespace normalisation or future transforms) must not produce duplicate output.
217
+ it.effect(
218
+ 'non-monotonic renderer output does not duplicate previously-emitted content',
219
+ Effect.fn(function* ({ expect }) {
220
+ const doc = new TestDocument();
221
+
222
+ const renderer: BlockRenderer = (_ctx: MessageThreadContext, _msg: Message.Message, block: ContentBlock.Any) => {
223
+ if (block._tag !== 'reasoning') {
224
+ return undefined;
225
+ }
226
+ const text = block.reasoningText ?? '';
227
+ // Simulate a non-monotonic transform: collapse a line that is a sole digit+dot+space.
228
+ const normalised = text
229
+ .split(/\r?\n/)
230
+ .map((line) => line.replace(/^\s*\d+[.)]\s$/, ''))
231
+ .join('\n')
232
+ .trim();
233
+ return block.pending ? `<reasoning>${normalised}` : `<reasoning>${normalised}</reasoning>\n`;
234
+ };
235
+
236
+ const syncer = new MessageSyncer(doc, renderer);
237
+
238
+ const messages = [createMessage('assistant', [{ _tag: 'reasoning', reasoningText: 'abc\n1.', pending: true }])];
239
+
240
+ syncer.update(messages);
241
+ Obj.update(messages[0], (obj) => {
242
+ const block = obj.blocks[0] as Mutable<ContentBlock.Reasoning>;
243
+ block.reasoningText = 'abc\n1. ';
244
+ });
245
+ syncer.update(messages);
246
+ Obj.update(messages[0], (obj) => {
247
+ const block = obj.blocks[0] as Mutable<ContentBlock.Reasoning>;
248
+ block.reasoningText = 'abc\n1. tail';
249
+ block.pending = false;
250
+ });
251
+ syncer.update(messages);
252
+
253
+ const openTagCount = (doc.content.match(/<reasoning>/g) ?? []).length;
254
+ const closeTagCount = (doc.content.match(/<\/reasoning>/g) ?? []).length;
255
+ expect(openTagCount).toBe(1);
256
+ expect(closeTagCount).toBe(1);
257
+ }),
258
+ );
99
259
  });
@@ -3,8 +3,7 @@
3
3
  //
4
4
 
5
5
  import { type DXN } from '@dxos/echo';
6
- import { log } from '@dxos/log';
7
- import { type MarkdownStreamController } from '@dxos/react-ui-components';
6
+ import { type MarkdownStreamController } from '@dxos/react-ui-markdown';
8
7
  import { type ContentBlock, type Message } from '@dxos/types';
9
8
  import { type StateDispatch, type XmlWidgetStateManager } from '@dxos/ui-editor';
10
9
 
@@ -15,6 +14,21 @@ import { rehydrateToolWidgetsFromMessages } from './tool-widget-state';
15
14
  */
16
15
  export type TextModel = Pick<MarkdownStreamController, 'length' | 'setContent' | 'append' | 'updateWidget'>;
17
16
 
17
+ /**
18
+ * Renders a block to markdown.
19
+ *
20
+ * Contract: for any block whose lifetime spans multiple invocations (i.e. a streaming block
21
+ * with `pending: true` whose content grows over time, transitioning to `pending: false`), the
22
+ * sequence of returned strings must be monotonically extending — each subsequent value must be
23
+ * a string-extension of the previous. The {@link MessageSyncer} relies on this invariant to
24
+ * compute appendable deltas without diffing.
25
+ */
26
+ export type BlockRenderer = (
27
+ context: MessageThreadContext,
28
+ message: Message.Message,
29
+ block: ContentBlock.Any,
30
+ ) => string | undefined;
31
+
18
32
  /**
19
33
  * Thread context passed to renderer.
20
34
  */
@@ -25,30 +39,30 @@ export class MessageThreadContext implements Pick<MarkdownStreamController, 'upd
25
39
  this._widgetState?.updateWidget(id, value);
26
40
  }
27
41
 
28
- // TODO(burdon): Resolve from hypergraph.
42
+ // TODO(burdon): Resolve name from hypergraph.
29
43
  getObjectLabel(_id: DXN) {
30
44
  return 'Object';
31
45
  }
32
46
  }
33
47
 
34
- /**
35
- * Renders a block to markdown.
36
- */
37
- export type BlockRenderer = (
38
- context: MessageThreadContext,
39
- message: Message.Message,
40
- block: ContentBlock.Any,
41
- ) => string | undefined;
42
-
43
48
  /**
44
49
  * Syncs messages with the editor.
50
+ *
51
+ * Reflects the AI streaming contract:
52
+ * - Messages and their blocks are appended in order.
53
+ * - Only the last block in `messages` may be `pending`; all earlier blocks are finalized.
54
+ * - The renderer's output for a streaming block grows monotonically (see {@link BlockRenderer}).
55
+ * - The document is read-only outside this syncer.
56
+ *
57
+ * Under those rules the syncer needs only:
58
+ * - `_completed`: the flat-block index past which everything has been fully appended.
59
+ * - `_trailing`: chars of the in-flight block (at index `_completed`) already appended.
60
+ * - `_threadId`: identity sentinel; if `messages[0]?.id` changes, the document is replaced.
45
61
  */
46
62
  export class MessageSyncer {
47
- #syncEpoch = 0;
48
- private _initialMessageId?: string;
49
- private _currentMessageIndex = 0;
50
- private _currentBlockIndex = 0;
51
- private _currentBlockContent?: string;
63
+ private _threadId?: string;
64
+ private _completed = 0;
65
+ private _trailing = 0;
52
66
 
53
67
  private readonly _context: MessageThreadContext;
54
68
 
@@ -63,103 +77,74 @@ export class MessageSyncer {
63
77
  return this._context;
64
78
  }
65
79
 
66
- reset() {
67
- log('reset');
68
- this.#syncEpoch++;
69
- this._initialMessageId = undefined;
70
- this._currentMessageIndex = 0;
71
- this._currentBlockIndex = 0;
72
- this._currentBlockContent = undefined;
73
- void this._document.setContent('');
80
+ /**
81
+ * Replace the document with the rendering of `messages`. Use on mount, on thread switch,
82
+ * and from {@link update} when it detects an identity change in `messages[0]`.
83
+ */
84
+ reset(messages: Message.Message[] = []): void {
85
+ this._threadId = messages[0]?.id;
86
+ this._completed = 0;
87
+ this._trailing = 0;
88
+ const buffer = this._walk(messages);
89
+ // Match the pre-rewrite behaviour: rendering from a steady state (initial mount with
90
+ // non-empty messages, or thread switch) lands the entire content via `setContent` — which
91
+ // uses `wireBypass`, so the editor jumps straight to the final text and `update()` returns
92
+ // `true` so the caller can scroll to the bottom. Live streaming partials that arrive
93
+ // *after* this initial render flow through `update()`'s incremental path → `_document.append`
94
+ // → wire's drip filter, preserving the char-by-char typewriter for incoming text.
95
+ void this._document.setContent(buffer).then(() => {
96
+ rehydrateToolWidgetsFromMessages(this._context, messages);
97
+ });
74
98
  }
75
99
 
76
100
  /**
77
- * Syncs messages with the editor.
101
+ * Stream the suffix of the rendered messages into the document.
102
+ * Returns `true` if the document was replaced (initial mount or thread switch), `false`
103
+ * if the call was a streaming append (or a no-op).
78
104
  */
79
- append(messages: Message.Message[], flush = false): boolean {
80
- // TODO(dmaretskyi): MarkdownStream currently does not support streaming XML tags, so we need to remove pending non-text blocks.
81
- // messages = messages.map((message) => ({
82
- // ...message,
83
- // blocks: message.blocks.filter((block) => !block.pending || block._tag === 'text'),
84
- // }));
85
-
86
- // Check if new set of messages.
87
- if (this._initialMessageId !== messages[0]?.id) {
88
- this.reset();
89
- this._initialMessageId = messages[0]?.id;
90
- }
91
-
92
- if (this._document.length === 0 && flush) {
93
- const buffer: string[] = [];
94
- this.processBlocks(messages, (content) => buffer.push(content));
95
- const content = buffer.join('');
96
- // `setContent` dispatches `xmlTagResetEffect`, which clears widget props accumulated during
97
- // `processBlocks`; re-apply tool state after the document is replaced.
98
- const epoch = this.#syncEpoch;
99
- void this._document
100
- .setContent(content)
101
- .then(() => {
102
- if (epoch !== this.#syncEpoch) {
103
- return;
104
- }
105
- rehydrateToolWidgetsFromMessages(this._context, messages);
106
- })
107
- .catch((error) => {
108
- log.warn('failed to replace thread content before widget rehydration', { error });
109
- });
110
-
105
+ update(messages: Message.Message[]): boolean {
106
+ if (messages[0]?.id !== this._threadId) {
107
+ this.reset(messages);
111
108
  return true;
112
- } else {
113
- this.processBlocks(messages, (content) => {
114
- void this._document.append(content);
115
- });
116
-
117
- return false;
118
109
  }
110
+ const buffer = this._walk(messages);
111
+ if (buffer.length > 0) {
112
+ void this._document.append(buffer);
113
+ }
114
+ return false;
119
115
  }
120
116
 
121
- private processBlocks(messages: Message.Message[], append: (content: string) => void) {
122
- // console.log('sync', {
123
- // doc: this._model.view?.state.doc.length,
124
- // messages: messages.map((message) => message.blocks.length),
125
- // currentMessageIndex: this._currentMessageIndex,
126
- // currentBlockIndex: this._currentBlockIndex,
127
- // currentBlockContent: this._currentBlockContent,
128
- // });
129
-
130
- let i = this._currentMessageIndex;
131
- for (const message of messages.slice(this._currentMessageIndex)) {
132
- if (i > this._currentMessageIndex) {
133
- this._currentBlockIndex = 0;
134
- }
135
-
136
- this._currentMessageIndex = i;
137
- let j = this._currentBlockIndex;
138
- for (const block of message.blocks.slice(this._currentBlockIndex)) {
139
- this._currentBlockIndex = j;
140
- const currentBlockContent = this._renderer(this._context, message, block);
141
- if (currentBlockContent) {
142
- let content: string = '';
143
- if (this._currentBlockContent && currentBlockContent.startsWith(this._currentBlockContent)) {
144
- content = currentBlockContent.slice(this._currentBlockContent.length);
145
- } else {
146
- content = currentBlockContent;
147
- }
148
-
149
- // console.log('append', { message: i, block: j, content });
150
- this._currentBlockContent = currentBlockContent;
151
- append(content);
117
+ /**
118
+ * Walk flat blocks starting at `_completed`, advancing the cursors and returning the chars
119
+ * to append. Blocks before `_completed` are skipped — their renderer is never re-invoked,
120
+ * which preserves single-shot side effects (e.g. tool widget state mutation).
121
+ */
122
+ _walk(messages: Message.Message[]): string {
123
+ let buffer = '';
124
+ let index = 0;
125
+ outer: for (const message of messages) {
126
+ for (const block of message.blocks) {
127
+ if (index < this._completed) {
128
+ index++;
129
+ continue;
130
+ }
131
+ const rendered = this._renderer(this._context, message, block) ?? '';
132
+ if (rendered.length > this._trailing) {
133
+ buffer += rendered.slice(this._trailing);
152
134
  }
153
-
154
135
  if (block.pending) {
155
- return;
156
- } else {
157
- this._currentBlockContent = undefined;
158
- this._currentBlockIndex++;
136
+ // Stay on this block; record how far we've appended so the next call can resume.
137
+ // `Math.max`-style guard against a non-monotonic renderer output without shrinking the doc.
138
+ if (rendered.length > this._trailing) {
139
+ this._trailing = rendered.length;
140
+ }
141
+ break outer;
159
142
  }
160
- j++;
143
+ this._completed = index + 1;
144
+ this._trailing = 0;
145
+ index++;
161
146
  }
162
- i++;
163
147
  }
148
+ return buffer;
164
149
  }
165
150
  }
@@ -0,0 +1,25 @@
1
+ <prompt>How should I structure a CLI tool with subcommands?</prompt>
2
+
3
+ <reasoning>
4
+ The user is asking about CLI subcommand structure. Let me think through what they likely care about:
5
+
6
+ 1. Discoverability — every subcommand needs help text and a flat top-level listing.
7
+ 2. Composability — subcommands should be invokable individually for scripting.
8
+ 3. Shared concerns — auth, config, logging should not be duplicated per command.
9
+
10
+ A few patterns worth considering:
11
+
12
+ - A single binary that dispatches to subcommand handlers (like `git`, `kubectl`).
13
+ - A plugin model where subcommands live in separate binaries on the PATH (like `git-foo`).
14
+ - A library that each subcommand wraps as a thin executable.
15
+
16
+ The plugin model wins for very large surfaces but adds packaging cost. For a tool with under ~30 subcommands the dispatcher pattern stays clearer.
17
+ </reasoning>
18
+
19
+ For a CLI with a moderate set of subcommands, the dispatcher pattern is usually the right default:
20
+
21
+ 1. One binary, one entry point.
22
+ 2. Subcommands registered as handlers off a shared root.
23
+ 3. Cross-cutting concerns (auth, config, logging) wired in at the root and inherited.
24
+
25
+ If you grow past ~30 subcommands or want third-party extensions, switch to a plugin model where binaries named `<tool>-<subcommand>` are discovered on the `PATH`.
@@ -5,7 +5,7 @@
5
5
  import React from 'react';
6
6
 
7
7
  import { TogglePanel } from '@dxos/react-ui-components';
8
- import { Json } from '@dxos/react-ui-syntax-highlighter';
8
+ import { JsonHighlighter } from '@dxos/react-ui-syntax-highlighter';
9
9
  import { type XmlWidgetProps } from '@dxos/ui-editor';
10
10
 
11
11
  import { type MessageThreadContext } from '../sync';
@@ -16,7 +16,7 @@ export const FallbackWidget = ({ _tag, ...props }: XmlWidgetProps<MessageThreadC
16
16
  <TogglePanel.Header classNames='bg-group-surface'>{_tag}</TogglePanel.Header>
17
17
  <TogglePanel.Content classNames='bg-modal-surface'>
18
18
  <TogglePanel.Viewport>
19
- <Json.Data classNames='p-2! text-sm' data={props} />
19
+ <JsonHighlighter classNames='p-2! text-sm' data={props} />
20
20
  </TogglePanel.Viewport>
21
21
  </TogglePanel.Content>
22
22
  </TogglePanel.Root>