@dxos/plugin-assistant 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (611) hide show
  1. package/PLUGIN.mdl +3 -28
  2. package/dist/lib/AssistantPlugin.mjs +2 -0
  3. package/dist/lib/AssistantPlugin.node.mjs +55 -0
  4. package/dist/lib/AssistantPlugin.node.mjs.map +1 -0
  5. package/dist/lib/AssistantPlugin.workerd.mjs +43 -0
  6. package/dist/lib/AssistantPlugin.workerd.mjs.map +1 -0
  7. package/dist/lib/capabilities.mjs +24 -0
  8. package/dist/lib/capabilities.mjs.map +1 -0
  9. package/dist/lib/chunk-AgentArticle.mjs +52 -0
  10. package/dist/lib/chunk-AgentArticle.mjs.map +1 -0
  11. package/dist/lib/chunk-AgentProperties.mjs +35 -0
  12. package/dist/lib/chunk-AgentProperties.mjs.map +1 -0
  13. package/dist/lib/chunk-AssistantPlugin.mjs +88 -0
  14. package/dist/lib/chunk-AssistantPlugin.mjs.map +1 -0
  15. package/dist/lib/chunk-AssistantSettings.mjs +285 -0
  16. package/dist/lib/chunk-AssistantSettings.mjs.map +1 -0
  17. package/dist/lib/chunk-ChatArticle.mjs +121 -0
  18. package/dist/lib/chunk-ChatArticle.mjs.map +1 -0
  19. package/dist/lib/chunk-ChatCompanion.mjs +116 -0
  20. package/dist/lib/chunk-ChatCompanion.mjs.map +1 -0
  21. package/dist/lib/chunk-ChatDialog.mjs +73 -0
  22. package/dist/lib/chunk-ChatDialog.mjs.map +1 -0
  23. package/dist/lib/chunk-IntegrationPrompt.mjs +73 -0
  24. package/dist/lib/chunk-IntegrationPrompt.mjs.map +1 -0
  25. package/dist/lib/chunk-SpaceHomePrompt.mjs +104 -0
  26. package/dist/lib/chunk-SpaceHomePrompt.mjs.map +1 -0
  27. package/dist/lib/chunk-SpaceHomeSuggestions.mjs +60 -0
  28. package/dist/lib/chunk-SpaceHomeSuggestions.mjs.map +1 -0
  29. package/dist/lib/chunk-TracePanel.mjs +127 -0
  30. package/dist/lib/chunk-TracePanel.mjs.map +1 -0
  31. package/dist/lib/chunk-TracePanel2.mjs +7 -0
  32. package/dist/lib/chunk-TracePanel2.mjs.map +1 -0
  33. package/dist/lib/chunk-TriggerStatus.mjs +72 -0
  34. package/dist/lib/chunk-TriggerStatus.mjs.map +1 -0
  35. package/dist/lib/chunk-agent-hydrator.mjs +22 -0
  36. package/dist/lib/chunk-agent-hydrator.mjs.map +1 -0
  37. package/dist/lib/chunk-agent-service.mjs +21 -0
  38. package/dist/lib/chunk-agent-service.mjs.map +1 -0
  39. package/dist/lib/{neutral/ai-context-LIKJYMIN.mjs → chunk-ai-context.mjs} +8 -12
  40. package/dist/lib/chunk-ai-context.mjs.map +1 -0
  41. package/dist/lib/chunk-ai-service.mjs +27 -0
  42. package/dist/lib/chunk-ai-service.mjs.map +1 -0
  43. package/dist/lib/chunk-app-graph-builder.mjs +179 -0
  44. package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
  45. package/dist/lib/chunk-automation-templates.mjs +99 -0
  46. package/dist/lib/chunk-automation-templates.mjs.map +1 -0
  47. package/dist/lib/chunk-companion-chat-provisioner.mjs +123 -0
  48. package/dist/lib/chunk-companion-chat-provisioner.mjs.map +1 -0
  49. package/dist/lib/chunk-connector.mjs +60 -0
  50. package/dist/lib/chunk-connector.mjs.map +1 -0
  51. package/dist/lib/chunk-constants.mjs +9 -0
  52. package/dist/lib/chunk-constants.mjs.map +1 -0
  53. package/dist/lib/chunk-context.mjs +7 -0
  54. package/dist/lib/chunk-context.mjs.map +1 -0
  55. package/dist/lib/chunk-create-chat.mjs +53 -0
  56. package/dist/lib/chunk-create-chat.mjs.map +1 -0
  57. package/dist/lib/chunk-create-object.mjs +70 -0
  58. package/dist/lib/chunk-create-object.mjs.map +1 -0
  59. package/dist/lib/chunk-edge-model-resolver.mjs +64 -0
  60. package/dist/lib/chunk-edge-model-resolver.mjs.map +1 -0
  61. package/dist/lib/chunk-ensure-companion-chat.mjs +49 -0
  62. package/dist/lib/chunk-ensure-companion-chat.mjs.map +1 -0
  63. package/dist/lib/chunk-extensions.mjs +78 -0
  64. package/dist/lib/chunk-extensions.mjs.map +1 -0
  65. package/dist/lib/chunk-fork-chat.mjs +83 -0
  66. package/dist/lib/chunk-fork-chat.mjs.map +1 -0
  67. package/dist/lib/chunk-generate-home-suggestions.mjs +71 -0
  68. package/dist/lib/chunk-generate-home-suggestions.mjs.map +1 -0
  69. package/dist/lib/chunk-local-model-resolver.mjs +25 -0
  70. package/dist/lib/chunk-local-model-resolver.mjs.map +1 -0
  71. package/dist/lib/chunk-markdown-extension.mjs +27 -0
  72. package/dist/lib/chunk-markdown-extension.mjs.map +1 -0
  73. package/dist/lib/{neutral/chunk-L7AR4VTA.mjs → chunk-meta.mjs} +20 -25
  74. package/dist/lib/chunk-meta.mjs.map +1 -0
  75. package/dist/lib/chunk-operation-handler.mjs +13 -0
  76. package/dist/lib/chunk-operation-handler.mjs.map +1 -0
  77. package/dist/lib/chunk-paths.mjs +8 -0
  78. package/dist/lib/chunk-paths.mjs.map +1 -0
  79. package/dist/lib/chunk-processor.mjs +432 -0
  80. package/dist/lib/chunk-processor.mjs.map +1 -0
  81. package/dist/lib/chunk-react-surface.mjs +177 -0
  82. package/dist/lib/chunk-react-surface.mjs.map +1 -0
  83. package/dist/lib/chunk-run-prompt-in-new-chat.mjs +96 -0
  84. package/dist/lib/chunk-run-prompt-in-new-chat.mjs.map +1 -0
  85. package/dist/lib/chunk-set-current-chat.mjs +43 -0
  86. package/dist/lib/chunk-set-current-chat.mjs.map +1 -0
  87. package/dist/lib/chunk-settings.mjs +23 -0
  88. package/dist/lib/chunk-settings.mjs.map +1 -0
  89. package/dist/lib/chunk-skill-definition.mjs +42 -0
  90. package/dist/lib/chunk-skill-definition.mjs.map +1 -0
  91. package/dist/lib/chunk-skills.mjs +19 -0
  92. package/dist/lib/chunk-skills.mjs.map +1 -0
  93. package/dist/lib/chunk-state.mjs +32 -0
  94. package/dist/lib/chunk-state.mjs.map +1 -0
  95. package/dist/lib/chunk-toggle-trace-panel-debug.mjs +18 -0
  96. package/dist/lib/chunk-toggle-trace-panel-debug.mjs.map +1 -0
  97. package/dist/lib/chunk-toolkit.mjs +12 -0
  98. package/dist/lib/chunk-toolkit.mjs.map +1 -0
  99. package/dist/lib/chunk-types.mjs +332 -0
  100. package/dist/lib/chunk-types.mjs.map +1 -0
  101. package/dist/lib/chunk-update-chat-name.mjs +63 -0
  102. package/dist/lib/chunk-update-chat-name.mjs.map +1 -0
  103. package/dist/lib/components.mjs +2616 -0
  104. package/dist/lib/components.mjs.map +1 -0
  105. package/dist/lib/containers.mjs +17 -0
  106. package/dist/lib/containers.mjs.map +1 -0
  107. package/dist/lib/execution-graph.mjs +961 -0
  108. package/dist/lib/execution-graph.mjs.map +1 -0
  109. package/dist/lib/extensions.mjs +2 -0
  110. package/dist/lib/hooks.mjs +674 -0
  111. package/dist/lib/hooks.mjs.map +1 -0
  112. package/dist/lib/index.mjs +5 -0
  113. package/dist/lib/meta.mjs +2 -0
  114. package/dist/lib/operations.mjs +7 -0
  115. package/dist/lib/operations.mjs.map +1 -0
  116. package/dist/lib/plugin.mjs +9 -0
  117. package/dist/lib/plugin.mjs.map +1 -0
  118. package/dist/lib/plugin.workerd.mjs +2 -0
  119. package/dist/lib/skills.mjs +2 -0
  120. package/dist/lib/testing.mjs +2 -0
  121. package/dist/lib/translations.mjs +207 -0
  122. package/dist/lib/translations.mjs.map +1 -0
  123. package/dist/lib/types.mjs +2 -0
  124. package/dist/types/src/AssistantPlugin.d.ts.map +1 -1
  125. package/dist/types/src/AssistantPlugin.node.d.ts.map +1 -1
  126. package/dist/types/src/AssistantPlugin.workerd.d.ts.map +1 -1
  127. package/dist/types/src/capabilities/AssistantSurfaces.d.ts +22 -0
  128. package/dist/types/src/capabilities/AssistantSurfaces.d.ts.map +1 -0
  129. package/dist/types/src/capabilities/agent-hydrator.d.ts +1 -1
  130. package/dist/types/src/capabilities/agent-service.d.ts +1 -1
  131. package/dist/types/src/capabilities/agent-service.d.ts.map +1 -1
  132. package/dist/types/src/capabilities/ai-context.d.ts +1 -1
  133. package/dist/types/src/capabilities/ai-service.d.ts +1 -1
  134. package/dist/types/src/capabilities/app-graph-builder.d.ts +12 -1
  135. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  136. package/dist/types/src/capabilities/automation-templates.d.ts +1 -1
  137. package/dist/types/src/capabilities/companion-chat-provisioner.d.ts +1 -1
  138. package/dist/types/src/capabilities/connector.d.ts +1 -1
  139. package/dist/types/src/capabilities/create-object.d.ts +1 -1
  140. package/dist/types/src/capabilities/edge-model-resolver.d.ts +1 -1
  141. package/dist/types/src/capabilities/edge-model-resolver.d.ts.map +1 -1
  142. package/dist/types/src/capabilities/index.d.ts +0 -2
  143. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  144. package/dist/types/src/capabilities/local-model-resolver.d.ts +1 -1
  145. package/dist/types/src/capabilities/local-model-resolver.d.ts.map +1 -1
  146. package/dist/types/src/capabilities/markdown-extension.d.ts +1 -1
  147. package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
  148. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  149. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  150. package/dist/types/src/capabilities/settings.d.ts +1 -1
  151. package/dist/types/src/capabilities/skill-definition.d.ts.map +1 -1
  152. package/dist/types/src/capabilities/standalone-chats-query.test.d.ts +2 -0
  153. package/dist/types/src/capabilities/standalone-chats-query.test.d.ts.map +1 -0
  154. package/dist/types/src/capabilities/state.d.ts +1 -1
  155. package/dist/types/src/capabilities/toolkit.d.ts +1 -1
  156. package/dist/types/src/components/AgentProperties/AgentProperties.d.ts +4 -1
  157. package/dist/types/src/components/AgentProperties/AgentProperties.d.ts.map +1 -1
  158. package/dist/types/src/components/AgentProperties/AgentProperties.stories.d.ts.map +1 -1
  159. package/dist/types/src/components/Chat/Chat.d.ts +21 -8
  160. package/dist/types/src/components/Chat/Chat.d.ts.map +1 -1
  161. package/dist/types/src/components/Chat/{Chat.stories.d.ts → Error.stories.d.ts} +1 -1
  162. package/dist/types/src/components/Chat/Error.stories.d.ts.map +1 -0
  163. package/dist/types/src/components/Chat/context.d.ts +8 -0
  164. package/dist/types/src/components/Chat/context.d.ts.map +1 -1
  165. package/dist/types/src/components/Chat/events.d.ts +5 -0
  166. package/dist/types/src/components/Chat/events.d.ts.map +1 -1
  167. package/dist/types/src/components/Chat/thread.d.ts +42 -0
  168. package/dist/types/src/components/Chat/thread.d.ts.map +1 -0
  169. package/dist/types/src/components/Chat/thread.test.d.ts +2 -0
  170. package/dist/types/src/components/Chat/thread.test.d.ts.map +1 -0
  171. package/dist/types/src/components/ChatPrompt/ChatActions.d.ts.map +1 -1
  172. package/dist/types/src/components/ChatPrompt/ChatOptions.stories.d.ts.map +1 -1
  173. package/dist/types/src/components/ChatPrompt/ChatPrompt.d.ts +5 -3
  174. package/dist/types/src/components/ChatPrompt/ChatPrompt.d.ts.map +1 -1
  175. package/dist/types/src/components/ChatPrompt/index.d.ts +0 -1
  176. package/dist/types/src/components/ChatPrompt/index.d.ts.map +1 -1
  177. package/dist/types/src/components/ChatThread/Anchor.stories.d.ts.map +1 -1
  178. package/dist/types/src/components/ChatThread/ChatThread.d.ts +8 -3
  179. package/dist/types/src/components/ChatThread/ChatThread.d.ts.map +1 -1
  180. package/dist/types/src/components/ChatThread/ChatThread.stories.d.ts +30 -2
  181. package/dist/types/src/components/ChatThread/ChatThread.stories.d.ts.map +1 -1
  182. package/dist/types/src/components/ChatThread/Link.d.ts.map +1 -1
  183. package/dist/types/src/components/ChatThread/index.d.ts +1 -0
  184. package/dist/types/src/components/ChatThread/index.d.ts.map +1 -1
  185. package/dist/types/src/components/ChatThread/registry.d.ts.map +1 -1
  186. package/dist/types/src/components/ChatThread/sync/index.d.ts +3 -0
  187. package/dist/types/src/components/ChatThread/sync/index.d.ts.map +1 -0
  188. package/dist/types/src/components/ChatThread/{sync.d.ts → sync/sync.d.ts} +46 -2
  189. package/dist/types/src/components/ChatThread/sync/sync.d.ts.map +1 -0
  190. package/dist/types/src/components/ChatThread/sync/sync.test.d.ts.map +1 -0
  191. package/dist/types/src/components/ChatThread/sync/tool-widget-state.d.ts.map +1 -0
  192. package/dist/types/src/components/ChatThread/sync/tool-widget-state.test.d.ts.map +1 -0
  193. package/dist/types/src/components/ChatThread/widgets/BranchWidget.d.ts +15 -0
  194. package/dist/types/src/components/ChatThread/widgets/BranchWidget.d.ts.map +1 -0
  195. package/dist/types/src/components/ChatThread/widgets/BranchWidget.stories.d.ts +21 -0
  196. package/dist/types/src/components/ChatThread/widgets/BranchWidget.stories.d.ts.map +1 -0
  197. package/dist/types/src/components/ChatThread/widgets/BranchWidget.test.d.ts +2 -0
  198. package/dist/types/src/components/ChatThread/widgets/BranchWidget.test.d.ts.map +1 -0
  199. package/dist/types/src/components/ChatThread/widgets/ReferenceWidget.d.ts.map +1 -1
  200. package/dist/types/src/components/ChatThread/widgets/SuggestionWidget.d.ts.map +1 -1
  201. package/dist/types/src/components/ChatThread/widgets/ToolWidget.d.ts +1 -2
  202. package/dist/types/src/components/ChatThread/widgets/ToolWidget.d.ts.map +1 -1
  203. package/dist/types/src/components/ChatThread/widgets/defaults.d.ts +6 -0
  204. package/dist/types/src/components/ChatThread/widgets/defaults.d.ts.map +1 -1
  205. package/dist/types/src/components/ChatThread/widgets/format-time.d.ts +2 -0
  206. package/dist/types/src/components/ChatThread/widgets/format-time.d.ts.map +1 -0
  207. package/dist/types/src/components/ChatThread/widgets/index.d.ts +4 -1
  208. package/dist/types/src/components/ChatThread/widgets/index.d.ts.map +1 -1
  209. package/dist/types/src/components/ChatThread/widgets/is-tool-message.d.ts +3 -0
  210. package/dist/types/src/components/ChatThread/widgets/is-tool-message.d.ts.map +1 -0
  211. package/dist/types/src/components/ConnectorAuthMenu/ConnectorAuthMenu.d.ts +16 -0
  212. package/dist/types/src/components/ConnectorAuthMenu/ConnectorAuthMenu.d.ts.map +1 -0
  213. package/dist/types/src/components/ConnectorAuthMenu/ConnectorAuthMenu.stories.d.ts +210 -0
  214. package/dist/types/src/components/ConnectorAuthMenu/ConnectorAuthMenu.stories.d.ts.map +1 -0
  215. package/dist/types/src/components/ConnectorAuthMenu/index.d.ts +2 -0
  216. package/dist/types/src/components/ConnectorAuthMenu/index.d.ts.map +1 -0
  217. package/dist/types/src/components/ProcessTree/ProcessTree.d.ts +1 -1
  218. package/dist/types/src/components/ProcessTree/ProcessTree.d.ts.map +1 -1
  219. package/dist/types/src/components/TaskList/TaskList.d.ts +9 -11
  220. package/dist/types/src/components/TaskList/TaskList.d.ts.map +1 -1
  221. package/dist/types/src/components/TaskList/TaskList.stories.d.ts +3 -4
  222. package/dist/types/src/components/TaskList/TaskList.stories.d.ts.map +1 -1
  223. package/dist/types/src/components/ToolBlock/ToolBlock.d.ts +1 -2
  224. package/dist/types/src/components/ToolBlock/ToolBlock.d.ts.map +1 -1
  225. package/dist/types/src/components/ToolBlock/index.d.ts +1 -0
  226. package/dist/types/src/components/ToolBlock/index.d.ts.map +1 -1
  227. package/dist/types/src/components/ToolBlock/is-tool-message.d.ts +3 -0
  228. package/dist/types/src/components/ToolBlock/is-tool-message.d.ts.map +1 -0
  229. package/dist/types/src/components/Toolbox/Toolbox.d.ts +1 -1
  230. package/dist/types/src/components/Toolbox/Toolbox.d.ts.map +1 -1
  231. package/dist/types/src/components/index.d.ts +1 -0
  232. package/dist/types/src/components/index.d.ts.map +1 -1
  233. package/dist/types/src/containers/AgentArticle/AgentArticle.d.ts +5 -2
  234. package/dist/types/src/containers/AgentArticle/AgentArticle.d.ts.map +1 -1
  235. package/dist/types/src/containers/AgentArticle/AgentArticle.stories.d.ts.map +1 -1
  236. package/dist/types/src/containers/AgentProperties/AgentProperties.d.ts +4 -1
  237. package/dist/types/src/containers/AgentProperties/AgentProperties.d.ts.map +1 -1
  238. package/dist/types/src/containers/AssistantSettings/AssistantSettings.d.ts +4 -1
  239. package/dist/types/src/containers/AssistantSettings/AssistantSettings.d.ts.map +1 -1
  240. package/dist/types/src/containers/AssistantSettings/AssistantSettings.stories.d.ts +4 -1
  241. package/dist/types/src/containers/AssistantSettings/AssistantSettings.stories.d.ts.map +1 -1
  242. package/dist/types/src/containers/AssistantSettings/OllamaModels.d.ts +4 -6
  243. package/dist/types/src/containers/AssistantSettings/OllamaModels.d.ts.map +1 -1
  244. package/dist/types/src/containers/ChatArticle/ChatArticle.d.ts.map +1 -1
  245. package/dist/types/src/containers/ChatArticle/ChatArticle.stories.d.ts +22 -1
  246. package/dist/types/src/containers/ChatArticle/ChatArticle.stories.d.ts.map +1 -1
  247. package/dist/types/src/containers/ChatCompanion/ChatCompanion.d.ts.map +1 -1
  248. package/dist/types/src/containers/ChatDialog/ChatDialog.d.ts +4 -1
  249. package/dist/types/src/containers/ChatDialog/ChatDialog.d.ts.map +1 -1
  250. package/dist/types/src/containers/IntegrationPrompt/IntegrationPrompt.d.ts +4 -7
  251. package/dist/types/src/containers/IntegrationPrompt/IntegrationPrompt.d.ts.map +1 -1
  252. package/dist/types/src/containers/SpaceHomePrompt/SpaceHomePrompt.d.ts +4 -9
  253. package/dist/types/src/containers/SpaceHomePrompt/SpaceHomePrompt.d.ts.map +1 -1
  254. package/dist/types/src/containers/SpaceHomeSuggestions/SpaceHomeSuggestions.d.ts +5 -7
  255. package/dist/types/src/containers/SpaceHomeSuggestions/SpaceHomeSuggestions.d.ts.map +1 -1
  256. package/dist/types/src/containers/TracePanel/TracePanel.d.ts +1 -1
  257. package/dist/types/src/containers/TracePanel/TracePanel.d.ts.map +1 -1
  258. package/dist/types/src/containers/TracePanel/TracePanel.stories.d.ts.map +1 -1
  259. package/dist/types/src/containers/TriggerStatus/TriggerStatus.d.ts +15 -1
  260. package/dist/types/src/containers/TriggerStatus/TriggerStatus.d.ts.map +1 -1
  261. package/dist/types/src/containers/index.d.ts +0 -1
  262. package/dist/types/src/containers/index.d.ts.map +1 -1
  263. package/dist/types/src/execution-graph/execution-graph.d.ts +12 -1
  264. package/dist/types/src/execution-graph/execution-graph.d.ts.map +1 -1
  265. package/dist/types/src/execution-graph/index.d.ts +1 -1
  266. package/dist/types/src/execution-graph/index.d.ts.map +1 -1
  267. package/dist/types/src/execution-graph/pending-block-status.d.ts.map +1 -1
  268. package/dist/types/src/execution-graph/span-tree.d.ts +17 -0
  269. package/dist/types/src/execution-graph/span-tree.d.ts.map +1 -1
  270. package/dist/types/src/feed-logger.d.ts +1 -1
  271. package/dist/types/src/feed-logger.d.ts.map +1 -1
  272. package/dist/types/src/hooks/index.d.ts +1 -1
  273. package/dist/types/src/hooks/index.d.ts.map +1 -1
  274. package/dist/types/src/hooks/useChatProcessor.d.ts.map +1 -1
  275. package/dist/types/src/hooks/useChatToolbarActions.d.ts.map +1 -1
  276. package/dist/types/src/hooks/useContextObjects.d.ts +1 -1
  277. package/dist/types/src/hooks/useContextObjects.d.ts.map +1 -1
  278. package/dist/types/src/hooks/useSelectionContext.d.ts +13 -0
  279. package/dist/types/src/hooks/useSelectionContext.d.ts.map +1 -0
  280. package/dist/types/src/hooks/useSelectionContext.test.d.ts +2 -0
  281. package/dist/types/src/hooks/useSelectionContext.test.d.ts.map +1 -0
  282. package/dist/types/src/hooks/useTraceMessages.d.ts.map +1 -1
  283. package/dist/types/src/operations/index.d.ts.map +1 -1
  284. package/dist/types/src/processor/index.d.ts +1 -0
  285. package/dist/types/src/processor/index.d.ts.map +1 -1
  286. package/dist/types/src/processor/processor.d.ts +5 -2
  287. package/dist/types/src/processor/processor.d.ts.map +1 -1
  288. package/dist/types/src/processor/prompt.d.ts +18 -0
  289. package/dist/types/src/processor/prompt.d.ts.map +1 -0
  290. package/dist/types/src/processor/prompt.test.d.ts +2 -0
  291. package/dist/types/src/processor/prompt.test.d.ts.map +1 -0
  292. package/dist/types/src/processor/streaming.node.test.d.ts +2 -0
  293. package/dist/types/src/processor/streaming.node.test.d.ts.map +1 -0
  294. package/dist/types/src/skills/assistant/skill.d.ts.map +1 -1
  295. package/dist/types/src/templates/scaffold.d.ts +1 -1
  296. package/dist/types/src/templates/scaffold.d.ts.map +1 -1
  297. package/dist/types/src/translations.d.ts.map +1 -1
  298. package/dist/types/src/types/AssistantCapabilities.d.ts +1 -1
  299. package/dist/types/src/types/AssistantCapabilities.d.ts.map +1 -1
  300. package/dist/types/src/types/AssistantOperation.d.ts +2 -13
  301. package/dist/types/src/types/AssistantOperation.d.ts.map +1 -1
  302. package/dist/types/src/types/ChatSurface.d.ts +2 -2
  303. package/dist/types/src/types/ChatSurface.d.ts.map +1 -1
  304. package/dist/types/src/types/Ollama.d.ts +1 -1
  305. package/dist/types/src/types/Ollama.d.ts.map +1 -1
  306. package/dist/types/tsconfig.tsbuildinfo +1 -1
  307. package/dx.config.ts +1 -0
  308. package/package.json +106 -105
  309. package/src/AssistantPlugin.node.ts +1 -2
  310. package/src/AssistantPlugin.test.ts +60 -62
  311. package/src/AssistantPlugin.ts +1 -10
  312. package/src/AssistantPlugin.workerd.ts +1 -2
  313. package/src/capabilities/AssistantSurfaces.tsx +86 -0
  314. package/src/capabilities/agent-service.ts +1 -1
  315. package/src/capabilities/app-graph-builder.ts +31 -17
  316. package/src/capabilities/companion-chat-provisioner.ts +12 -11
  317. package/src/capabilities/connector.ts +3 -3
  318. package/src/capabilities/edge-model-resolver.ts +5 -2
  319. package/src/capabilities/index.ts +0 -2
  320. package/src/capabilities/react-surface.ts +135 -0
  321. package/src/capabilities/skill-definition.ts +4 -0
  322. package/src/capabilities/standalone-chats-query.test.ts +51 -0
  323. package/src/capabilities/state.ts +1 -1
  324. package/src/components/AgentProperties/AgentProperties.stories.tsx +6 -7
  325. package/src/components/AgentProperties/AgentProperties.tsx +37 -30
  326. package/src/components/Chat/Chat.tsx +275 -59
  327. package/src/components/Chat/{Chat.stories.tsx → Error.stories.tsx} +1 -1
  328. package/src/components/Chat/context.ts +8 -0
  329. package/src/components/Chat/events.ts +5 -0
  330. package/src/components/Chat/thread.test.ts +127 -0
  331. package/src/components/Chat/thread.ts +87 -0
  332. package/src/components/ChatPrompt/ChatActions.tsx +8 -8
  333. package/src/components/ChatPrompt/ChatMcpErrors.tsx +2 -2
  334. package/src/components/ChatPrompt/ChatOptions.stories.tsx +2 -1
  335. package/src/components/ChatPrompt/ChatOptions.tsx +5 -5
  336. package/src/components/ChatPrompt/ChatPrompt.tsx +33 -6
  337. package/src/components/ChatPrompt/index.ts +0 -1
  338. package/src/components/ChatThread/Anchor.stories.tsx +2 -1
  339. package/src/components/ChatThread/ChatThread.stories.tsx +99 -4
  340. package/src/components/ChatThread/ChatThread.tsx +34 -6
  341. package/src/components/ChatThread/Link.tsx +1 -0
  342. package/src/components/ChatThread/index.ts +2 -0
  343. package/src/components/ChatThread/registry.tsx +28 -4
  344. package/src/components/ChatThread/sync/index.ts +6 -0
  345. package/src/components/ChatThread/{sync.test.ts → sync/sync.test.ts} +167 -7
  346. package/src/components/ChatThread/{sync.ts → sync/sync.ts} +97 -3
  347. package/src/components/ChatThread/{tool-widget-state.ts → sync/tool-widget-state.ts} +1 -3
  348. package/src/components/ChatThread/widgets/BranchWidget.stories.tsx +83 -0
  349. package/src/components/ChatThread/widgets/BranchWidget.test.ts +55 -0
  350. package/src/components/ChatThread/widgets/BranchWidget.tsx +61 -0
  351. package/src/components/ChatThread/widgets/FallbackWidget.tsx +2 -2
  352. package/src/components/ChatThread/widgets/ReasoningWidget.ts +1 -1
  353. package/src/components/ChatThread/widgets/ReferenceWidget.ts +1 -6
  354. package/src/components/ChatThread/widgets/SuggestionWidget.ts +12 -3
  355. package/src/components/ChatThread/widgets/SummaryWidget.tsx +1 -1
  356. package/src/components/ChatThread/widgets/ToolWidget.tsx +15 -9
  357. package/src/components/ChatThread/widgets/defaults.ts +7 -1
  358. package/src/components/ChatThread/widgets/format-time.ts +45 -0
  359. package/src/components/ChatThread/widgets/index.ts +4 -1
  360. package/src/components/ChatThread/widgets/is-tool-message.ts +13 -0
  361. package/src/components/ConnectorAuthMenu/ConnectorAuthMenu.stories.tsx +177 -0
  362. package/src/components/ConnectorAuthMenu/ConnectorAuthMenu.tsx +82 -0
  363. package/src/components/ConnectorAuthMenu/index.ts +5 -0
  364. package/src/components/ProcessTree/ProcessTree.stories.tsx +1 -1
  365. package/src/components/TaskList/TaskList.stories.tsx +19 -26
  366. package/src/components/TaskList/TaskList.tsx +32 -104
  367. package/src/components/ToolBlock/ToolBlock.tsx +1 -5
  368. package/src/components/ToolBlock/index.ts +1 -0
  369. package/src/components/ToolBlock/is-tool-message.ts +13 -0
  370. package/src/components/Toolbox/Toolbox.tsx +1 -1
  371. package/src/components/index.ts +1 -0
  372. package/src/containers/AgentArticle/AgentArticle.stories.tsx +18 -11
  373. package/src/containers/AgentArticle/AgentArticle.tsx +27 -151
  374. package/src/containers/AgentProperties/AgentProperties.tsx +21 -17
  375. package/src/containers/AssistantSettings/AssistantSettings.tsx +2 -0
  376. package/src/containers/AssistantSettings/OllamaModels.tsx +6 -4
  377. package/src/containers/ChatArticle/ChatArticle.stories.tsx +200 -27
  378. package/src/containers/ChatArticle/ChatArticle.tsx +25 -5
  379. package/src/containers/ChatCompanion/ChatCompanion.tsx +45 -10
  380. package/src/containers/ChatDialog/ChatDialog.tsx +4 -1
  381. package/src/containers/IntegrationPrompt/IntegrationPrompt.tsx +9 -6
  382. package/src/containers/SpaceHomePrompt/SpaceHomePrompt.tsx +2 -0
  383. package/src/containers/SpaceHomeSuggestions/SpaceHomeSuggestions.tsx +40 -39
  384. package/src/containers/TracePanel/TracePanel.stories.tsx +9 -4
  385. package/src/containers/TracePanel/TracePanel.tsx +22 -6
  386. package/src/containers/TriggerStatus/TriggerStatus.tsx +9 -16
  387. package/src/containers/index.ts +0 -1
  388. package/src/execution-graph/SPEC.md +60 -2
  389. package/src/execution-graph/execution-graph.ts +15 -2
  390. package/src/execution-graph/index.ts +1 -0
  391. package/src/execution-graph/pending-block-status.ts +3 -2
  392. package/src/execution-graph/span-tree.test.ts +87 -1
  393. package/src/execution-graph/span-tree.ts +95 -0
  394. package/src/feed-logger.ts +6 -6
  395. package/src/hooks/index.ts +1 -1
  396. package/src/hooks/useChatProcessor.ts +2 -1
  397. package/src/hooks/useChatToolbarActions.ts +22 -19
  398. package/src/hooks/useContextObjects.ts +9 -3
  399. package/src/hooks/useSelectionContext.test.ts +93 -0
  400. package/src/hooks/useSelectionContext.ts +72 -0
  401. package/src/hooks/useSkillRegistry.ts +1 -1
  402. package/src/hooks/useTraceMessages.ts +5 -3
  403. package/src/operations/create-chat.ts +2 -2
  404. package/src/operations/fork-chat.ts +2 -2
  405. package/src/operations/generate-home-suggestions.test.ts +2 -2
  406. package/src/operations/index.ts +0 -1
  407. package/src/operations/prompt.node.test.ts +1 -1
  408. package/src/paths.ts +3 -3
  409. package/src/processor/index.ts +1 -0
  410. package/src/processor/processor.node.test.ts +1 -1
  411. package/src/processor/processor.ts +33 -5
  412. package/src/processor/prompt.test.ts +37 -0
  413. package/src/processor/prompt.ts +42 -0
  414. package/src/processor/streaming.node.test.ts +196 -0
  415. package/src/skills/assistant/skill.node.test.ts +2 -2
  416. package/src/skills/assistant/skill.ts +3 -5
  417. package/src/templates/routine-templates.test.ts +1 -2
  418. package/src/templates/scaffold.ts +3 -3
  419. package/src/testing/data/trace-timeline-multiple.dx.json +1 -1
  420. package/src/testing/data/trace-timeline-remote.dx.json +1 -1
  421. package/src/testing/data/trace-timeline.dx.json +1 -2
  422. package/src/testing/trace-timeline.node.test.ts +3 -3
  423. package/src/translations.ts +11 -10
  424. package/src/types/AssistantCapabilities.ts +1 -1
  425. package/src/types/AssistantOperation.ts +8 -31
  426. package/src/types/ChatSurface.ts +3 -3
  427. package/src/types/Ollama.ts +1 -1
  428. package/dist/lib/neutral/AgentArticle-GV6EEW3I.mjs +0 -161
  429. package/dist/lib/neutral/AgentArticle-GV6EEW3I.mjs.map +0 -7
  430. package/dist/lib/neutral/AgentProperties-LFTEYJ54.mjs +0 -40
  431. package/dist/lib/neutral/AgentProperties-LFTEYJ54.mjs.map +0 -7
  432. package/dist/lib/neutral/AssistantPlugin.mjs +0 -10
  433. package/dist/lib/neutral/AssistantPlugin.mjs.map +0 -7
  434. package/dist/lib/neutral/AssistantPlugin.node.mjs +0 -72
  435. package/dist/lib/neutral/AssistantPlugin.node.mjs.map +0 -7
  436. package/dist/lib/neutral/AssistantPlugin.workerd.mjs +0 -13
  437. package/dist/lib/neutral/AssistantPlugin.workerd.mjs.map +0 -7
  438. package/dist/lib/neutral/AssistantSettings-3N5M5VCN.mjs +0 -302
  439. package/dist/lib/neutral/AssistantSettings-3N5M5VCN.mjs.map +0 -7
  440. package/dist/lib/neutral/ChatArticle-OO7GGEFW.mjs +0 -8
  441. package/dist/lib/neutral/ChatArticle-OO7GGEFW.mjs.map +0 -7
  442. package/dist/lib/neutral/ChatCompanion-GIFJRY6I.mjs +0 -128
  443. package/dist/lib/neutral/ChatCompanion-GIFJRY6I.mjs.map +0 -7
  444. package/dist/lib/neutral/ChatDialog-5MXN4MXS.mjs +0 -74
  445. package/dist/lib/neutral/ChatDialog-5MXN4MXS.mjs.map +0 -7
  446. package/dist/lib/neutral/IntegrationPrompt-2HJQFYJE.mjs +0 -72
  447. package/dist/lib/neutral/IntegrationPrompt-2HJQFYJE.mjs.map +0 -7
  448. package/dist/lib/neutral/PlanArticle-VPK2IYWU.mjs +0 -34
  449. package/dist/lib/neutral/PlanArticle-VPK2IYWU.mjs.map +0 -7
  450. package/dist/lib/neutral/SpaceHomePrompt-ISAB76LD.mjs +0 -114
  451. package/dist/lib/neutral/SpaceHomePrompt-ISAB76LD.mjs.map +0 -7
  452. package/dist/lib/neutral/SpaceHomeSuggestions-IDH77QQR.mjs +0 -63
  453. package/dist/lib/neutral/SpaceHomeSuggestions-IDH77QQR.mjs.map +0 -7
  454. package/dist/lib/neutral/TracePanel-JKNWADJ4.mjs +0 -12
  455. package/dist/lib/neutral/TracePanel-JKNWADJ4.mjs.map +0 -7
  456. package/dist/lib/neutral/TriggerStatus-FURRBHYA.mjs +0 -95
  457. package/dist/lib/neutral/TriggerStatus-FURRBHYA.mjs.map +0 -7
  458. package/dist/lib/neutral/agent-hydrator-OBO3RHLO.mjs +0 -23
  459. package/dist/lib/neutral/agent-hydrator-OBO3RHLO.mjs.map +0 -7
  460. package/dist/lib/neutral/agent-service-XFJ4VQMT.mjs +0 -32
  461. package/dist/lib/neutral/agent-service-XFJ4VQMT.mjs.map +0 -7
  462. package/dist/lib/neutral/ai-context-LIKJYMIN.mjs.map +0 -7
  463. package/dist/lib/neutral/ai-service-DM6YXWUC.mjs +0 -44
  464. package/dist/lib/neutral/ai-service-DM6YXWUC.mjs.map +0 -7
  465. package/dist/lib/neutral/app-graph-builder-OPVOEQY7.mjs +0 -249
  466. package/dist/lib/neutral/app-graph-builder-OPVOEQY7.mjs.map +0 -7
  467. package/dist/lib/neutral/automation-templates-MADJLXGJ.mjs +0 -97
  468. package/dist/lib/neutral/automation-templates-MADJLXGJ.mjs.map +0 -7
  469. package/dist/lib/neutral/capabilities/index.mjs +0 -47
  470. package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
  471. package/dist/lib/neutral/chunk-5IHQ52KJ.mjs +0 -9
  472. package/dist/lib/neutral/chunk-5IHQ52KJ.mjs.map +0 -7
  473. package/dist/lib/neutral/chunk-6Q4OBGIK.mjs +0 -420
  474. package/dist/lib/neutral/chunk-6Q4OBGIK.mjs.map +0 -7
  475. package/dist/lib/neutral/chunk-BXI2R4OO.mjs +0 -410
  476. package/dist/lib/neutral/chunk-BXI2R4OO.mjs.map +0 -7
  477. package/dist/lib/neutral/chunk-CMPLPDYE.mjs +0 -30
  478. package/dist/lib/neutral/chunk-CMPLPDYE.mjs.map +0 -7
  479. package/dist/lib/neutral/chunk-GPHT3HYS.mjs +0 -8
  480. package/dist/lib/neutral/chunk-GPHT3HYS.mjs.map +0 -7
  481. package/dist/lib/neutral/chunk-HKLSFB5I.mjs +0 -90
  482. package/dist/lib/neutral/chunk-HKLSFB5I.mjs.map +0 -7
  483. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  484. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  485. package/dist/lib/neutral/chunk-L7AR4VTA.mjs.map +0 -7
  486. package/dist/lib/neutral/chunk-LS72HWMM.mjs +0 -42
  487. package/dist/lib/neutral/chunk-LS72HWMM.mjs.map +0 -7
  488. package/dist/lib/neutral/chunk-OZWZGIV2.mjs +0 -12
  489. package/dist/lib/neutral/chunk-OZWZGIV2.mjs.map +0 -7
  490. package/dist/lib/neutral/chunk-QOKLFHUS.mjs +0 -13
  491. package/dist/lib/neutral/chunk-QOKLFHUS.mjs.map +0 -7
  492. package/dist/lib/neutral/chunk-SCTHQVIJ.mjs +0 -155
  493. package/dist/lib/neutral/chunk-SCTHQVIJ.mjs.map +0 -7
  494. package/dist/lib/neutral/chunk-U4LTLBAX.mjs +0 -56
  495. package/dist/lib/neutral/chunk-U4LTLBAX.mjs.map +0 -7
  496. package/dist/lib/neutral/chunk-UPKFUZ6V.mjs +0 -115
  497. package/dist/lib/neutral/chunk-UPKFUZ6V.mjs.map +0 -7
  498. package/dist/lib/neutral/chunk-V2Y4XE3O.mjs +0 -12
  499. package/dist/lib/neutral/chunk-V2Y4XE3O.mjs.map +0 -7
  500. package/dist/lib/neutral/chunk-VTK5R4H3.mjs +0 -9
  501. package/dist/lib/neutral/chunk-VTK5R4H3.mjs.map +0 -7
  502. package/dist/lib/neutral/chunk-XVGEJWJX.mjs +0 -133
  503. package/dist/lib/neutral/chunk-XVGEJWJX.mjs.map +0 -7
  504. package/dist/lib/neutral/companion-chat-provisioner-IQV5VIVE.mjs +0 -126
  505. package/dist/lib/neutral/companion-chat-provisioner-IQV5VIVE.mjs.map +0 -7
  506. package/dist/lib/neutral/components/index.mjs +0 -2527
  507. package/dist/lib/neutral/components/index.mjs.map +0 -7
  508. package/dist/lib/neutral/connector-ITLLTBPZ.mjs +0 -70
  509. package/dist/lib/neutral/connector-ITLLTBPZ.mjs.map +0 -7
  510. package/dist/lib/neutral/containers/index.mjs +0 -31
  511. package/dist/lib/neutral/containers/index.mjs.map +0 -7
  512. package/dist/lib/neutral/create-chat-YGVZZYGP.mjs +0 -56
  513. package/dist/lib/neutral/create-chat-YGVZZYGP.mjs.map +0 -7
  514. package/dist/lib/neutral/create-object-5PAEJ6KM.mjs +0 -76
  515. package/dist/lib/neutral/create-object-5PAEJ6KM.mjs.map +0 -7
  516. package/dist/lib/neutral/edge-model-resolver-WDJWDZTT.mjs +0 -55
  517. package/dist/lib/neutral/edge-model-resolver-WDJWDZTT.mjs.map +0 -7
  518. package/dist/lib/neutral/ensure-companion-chat-AMOF3C66.mjs +0 -58
  519. package/dist/lib/neutral/ensure-companion-chat-AMOF3C66.mjs.map +0 -7
  520. package/dist/lib/neutral/execution-graph/index.mjs +0 -977
  521. package/dist/lib/neutral/execution-graph/index.mjs.map +0 -7
  522. package/dist/lib/neutral/extensions/index.mjs +0 -8
  523. package/dist/lib/neutral/extensions/index.mjs.map +0 -7
  524. package/dist/lib/neutral/fork-chat-RMAAYYQF.mjs +0 -92
  525. package/dist/lib/neutral/fork-chat-RMAAYYQF.mjs.map +0 -7
  526. package/dist/lib/neutral/generate-home-suggestions-6MM2XWPV.mjs +0 -93
  527. package/dist/lib/neutral/generate-home-suggestions-6MM2XWPV.mjs.map +0 -7
  528. package/dist/lib/neutral/hooks/index.mjs +0 -877
  529. package/dist/lib/neutral/hooks/index.mjs.map +0 -7
  530. package/dist/lib/neutral/index.mjs +0 -42
  531. package/dist/lib/neutral/index.mjs.map +0 -7
  532. package/dist/lib/neutral/local-model-resolver-I2BENFFS.mjs +0 -24
  533. package/dist/lib/neutral/local-model-resolver-I2BENFFS.mjs.map +0 -7
  534. package/dist/lib/neutral/markdown-extension-R4TKDTIF.mjs +0 -41
  535. package/dist/lib/neutral/markdown-extension-R4TKDTIF.mjs.map +0 -7
  536. package/dist/lib/neutral/meta.json +0 -1
  537. package/dist/lib/neutral/meta.mjs +0 -12
  538. package/dist/lib/neutral/meta.mjs.map +0 -7
  539. package/dist/lib/neutral/migrations-7DEMVBOG.mjs +0 -28
  540. package/dist/lib/neutral/migrations-7DEMVBOG.mjs.map +0 -7
  541. package/dist/lib/neutral/navigation-resolver-PYGP2DAW.mjs +0 -18
  542. package/dist/lib/neutral/navigation-resolver-PYGP2DAW.mjs.map +0 -7
  543. package/dist/lib/neutral/operation-handler-2LEN45GP.mjs +0 -8
  544. package/dist/lib/neutral/operation-handler-2LEN45GP.mjs.map +0 -7
  545. package/dist/lib/neutral/operations/index.mjs +0 -8
  546. package/dist/lib/neutral/operations/index.mjs.map +0 -7
  547. package/dist/lib/neutral/plugin.mjs +0 -16
  548. package/dist/lib/neutral/plugin.mjs.map +0 -7
  549. package/dist/lib/neutral/plugin.workerd.mjs +0 -13
  550. package/dist/lib/neutral/plugin.workerd.mjs.map +0 -7
  551. package/dist/lib/neutral/react-surface-HEJEK44F.mjs +0 -171
  552. package/dist/lib/neutral/react-surface-HEJEK44F.mjs.map +0 -7
  553. package/dist/lib/neutral/resolve-navigation-targets-PBQ3OLUE.mjs +0 -28
  554. package/dist/lib/neutral/resolve-navigation-targets-PBQ3OLUE.mjs.map +0 -7
  555. package/dist/lib/neutral/run-prompt-in-new-chat-RNUJE2FM.mjs +0 -102
  556. package/dist/lib/neutral/run-prompt-in-new-chat-RNUJE2FM.mjs.map +0 -7
  557. package/dist/lib/neutral/set-current-chat-VWBPSIMZ.mjs +0 -48
  558. package/dist/lib/neutral/set-current-chat-VWBPSIMZ.mjs.map +0 -7
  559. package/dist/lib/neutral/settings-7Q3RITIT.mjs +0 -28
  560. package/dist/lib/neutral/settings-7Q3RITIT.mjs.map +0 -7
  561. package/dist/lib/neutral/skill-definition-553MQRTR.mjs +0 -8
  562. package/dist/lib/neutral/skill-definition-553MQRTR.mjs.map +0 -7
  563. package/dist/lib/neutral/skills/index.mjs +0 -8
  564. package/dist/lib/neutral/skills/index.mjs.map +0 -7
  565. package/dist/lib/neutral/state-4LGAKSSD.mjs +0 -34
  566. package/dist/lib/neutral/state-4LGAKSSD.mjs.map +0 -7
  567. package/dist/lib/neutral/testing.mjs +0 -8
  568. package/dist/lib/neutral/testing.mjs.map +0 -7
  569. package/dist/lib/neutral/toggle-trace-panel-debug-JGTB6KVJ.mjs +0 -21
  570. package/dist/lib/neutral/toggle-trace-panel-debug-JGTB6KVJ.mjs.map +0 -7
  571. package/dist/lib/neutral/toolkit-ETWLG5NT.mjs +0 -8
  572. package/dist/lib/neutral/toolkit-ETWLG5NT.mjs.map +0 -7
  573. package/dist/lib/neutral/translations.mjs +0 -217
  574. package/dist/lib/neutral/translations.mjs.map +0 -7
  575. package/dist/lib/neutral/types/index.mjs +0 -24
  576. package/dist/lib/neutral/types/index.mjs.map +0 -7
  577. package/dist/lib/neutral/update-chat-name-IJJELRR6.mjs +0 -61
  578. package/dist/lib/neutral/update-chat-name-IJJELRR6.mjs.map +0 -7
  579. package/dist/types/src/capabilities/migrations.d.ts +0 -5
  580. package/dist/types/src/capabilities/migrations.d.ts.map +0 -1
  581. package/dist/types/src/capabilities/navigation-resolver.d.ts +0 -5
  582. package/dist/types/src/capabilities/navigation-resolver.d.ts.map +0 -1
  583. package/dist/types/src/components/Chat/Chat.stories.d.ts.map +0 -1
  584. package/dist/types/src/components/ChatPrompt/ChatStatusIndicator.d.ts +0 -10
  585. package/dist/types/src/components/ChatPrompt/ChatStatusIndicator.d.ts.map +0 -1
  586. package/dist/types/src/components/ChatThread/sync.d.ts.map +0 -1
  587. package/dist/types/src/components/ChatThread/sync.test.d.ts.map +0 -1
  588. package/dist/types/src/components/ChatThread/tool-widget-state.d.ts.map +0 -1
  589. package/dist/types/src/components/ChatThread/tool-widget-state.test.d.ts.map +0 -1
  590. package/dist/types/src/containers/PlanArticle/PlanArticle.d.ts +0 -6
  591. package/dist/types/src/containers/PlanArticle/PlanArticle.d.ts.map +0 -1
  592. package/dist/types/src/containers/PlanArticle/index.d.ts +0 -2
  593. package/dist/types/src/containers/PlanArticle/index.d.ts.map +0 -1
  594. package/dist/types/src/hooks/useFlush.d.ts +0 -6
  595. package/dist/types/src/hooks/useFlush.d.ts.map +0 -1
  596. package/dist/types/src/operations/resolve-navigation-targets.d.ts +0 -5
  597. package/dist/types/src/operations/resolve-navigation-targets.d.ts.map +0 -1
  598. package/src/AssistantPlugin.conversations.json +0 -1
  599. package/src/capabilities/migrations.ts +0 -28
  600. package/src/capabilities/navigation-resolver.ts +0 -20
  601. package/src/capabilities/react-surface.tsx +0 -177
  602. package/src/components/ChatPrompt/ChatStatusIndicator.tsx +0 -42
  603. package/src/components/ChatThread/DEBUG.md +0 -64
  604. package/src/containers/PlanArticle/PlanArticle.tsx +0 -37
  605. package/src/containers/PlanArticle/index.ts +0 -5
  606. package/src/hooks/useFlush.ts +0 -35
  607. package/src/operations/resolve-navigation-targets.ts +0 -44
  608. /package/dist/types/src/components/ChatThread/{sync.test.d.ts → sync/sync.test.d.ts} +0 -0
  609. /package/dist/types/src/components/ChatThread/{tool-widget-state.d.ts → sync/tool-widget-state.d.ts} +0 -0
  610. /package/dist/types/src/components/ChatThread/{tool-widget-state.test.d.ts → sync/tool-widget-state.test.d.ts} +0 -0
  611. /package/src/components/ChatThread/{tool-widget-state.test.ts → sync/tool-widget-state.test.ts} +0 -0
@@ -4,8 +4,8 @@
4
4
 
5
5
  import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
6
6
 
7
+ import { Identity } from '@dxos/halo';
7
8
  import { PublicKey } from '@dxos/keys';
8
- import { type Identity } from '@dxos/react-client/halo';
9
9
  import { type ThemedClassName, setRef } from '@dxos/react-ui';
10
10
  import { MarkdownStream, type MarkdownStreamController, type MarkdownStreamProps } from '@dxos/react-ui-markdown';
11
11
  import { type Message } from '@dxos/types';
@@ -14,7 +14,7 @@ import { keyToFallback } from '@dxos/util';
14
14
  import { type Assistant } from '../../types';
15
15
  import { type ChatEvent } from '../Chat';
16
16
  import { componentRegistry, createBlockRenderer } from './registry';
17
- import { MessageSyncer } from './sync';
17
+ import { type MessageSpan, MessageSyncer } from './sync';
18
18
 
19
19
  const defaultOptions: MarkdownStreamProps['options'] = {
20
20
  autoScroll: true,
@@ -25,11 +25,13 @@ const defaultOptions: MarkdownStreamProps['options'] = {
25
25
 
26
26
  export type ChatThreadProps = ThemedClassName<
27
27
  {
28
- identity?: Identity;
28
+ identity?: Identity.Info;
29
29
  messages?: Message.Message[];
30
30
  error?: Error;
31
31
  viewType?: Assistant.ChatView;
32
32
  onEvent?: (event: ChatEvent) => void;
33
+ /** Publishes the syncer's per-message document spans after each update (minimap, prompt nav). */
34
+ onSpans?: (spans: MessageSpan[]) => void;
33
35
  } & Pick<MarkdownStreamProps, 'options' | 'debug' | 'extensions' | 'footer'>
34
36
  >;
35
37
 
@@ -46,6 +48,7 @@ export const ChatThread = forwardRef<MarkdownStreamController | null, ChatThread
46
48
  extensions,
47
49
  viewType,
48
50
  onEvent,
51
+ onSpans,
49
52
  },
50
53
  forwardedRef,
51
54
  ) => {
@@ -59,7 +62,9 @@ export const ChatThread = forwardRef<MarkdownStreamController | null, ChatThread
59
62
  );
60
63
 
61
64
  const userHue = useMemo(
62
- () => identity?.profile?.data?.hue || keyToFallback(identity?.identityKey ?? PublicKey.random()).hue,
65
+ () =>
66
+ identity?.data?.hue ||
67
+ keyToFallback(identity?.identityKey ? PublicKey.fromHex(identity.identityKey) : PublicKey.random()).hue,
63
68
  [identity],
64
69
  );
65
70
 
@@ -77,18 +82,41 @@ export const ChatThread = forwardRef<MarkdownStreamController | null, ChatThread
77
82
  initializedRef.current = true;
78
83
  }, [controller, error]);
79
84
 
85
+ // Widget callbacks are routed through the syncer's context, so they must be referentially stable
86
+ // — rebuilding the syncer replaces the document.
87
+ const onEventRef = useRef(onEvent);
88
+ useEffect(() => {
89
+ onEventRef.current = onEvent;
90
+ }, [onEvent]);
91
+ const handleRewind = useCallback((id: string) => onEventRef.current?.({ type: 'rewind', id }), []);
92
+
80
93
  // Update document.
81
94
  const renderer = useMemo(() => createBlockRenderer(viewType), [viewType]);
82
- const syncer = useMemo(() => controller && new MessageSyncer(controller, renderer), [controller, renderer]);
95
+ const syncer = useMemo(
96
+ () => controller && new MessageSyncer(controller, renderer, { onRewind: handleRewind }),
97
+ [controller, renderer, handleRewind],
98
+ );
83
99
  useEffect(() => {
84
100
  if (!syncer) {
85
101
  return;
86
102
  }
87
103
 
104
+ // Publish the context every pass: widget props read it from a CodeMirror state field, and
105
+ // `setContext` dispatches through `viewRef.current?` — a no-op before the view exists, so doing this
106
+ // once on mount silently loses it and every widget callback (e.g. rewind) dies on the optional call.
107
+ controller?.setContext(syncer.context);
108
+
109
+ // Publish the context every pass: widget props read it from a CodeMirror state field, and
110
+ // `setContext` dispatches through `viewRef.current?` — a no-op before the view exists, so doing this
111
+ // once on mount silently loses it and every widget callback (e.g. rewind) dies on the optional call.
112
+ controller?.setContext(syncer.context);
113
+
88
114
  if (syncer.update(messages)) {
89
115
  controller?.scrollToBottom('instant');
90
116
  }
91
- }, [controller, syncer, messages]);
117
+ // Spans are valid synchronously after `update` (offsets are computed during the walk).
118
+ onSpans?.(syncer.getSpans());
119
+ }, [controller, syncer, messages, onSpans]);
92
120
 
93
121
  // Event adapter.
94
122
  const handleEvent = useCallback<NonNullable<MarkdownStreamProps['onEvent']>>(
@@ -14,6 +14,7 @@ export type ObjectLinkProps = {
14
14
  dxn: URI.URI;
15
15
  };
16
16
 
17
+ // TODO(burdon): Document.
17
18
  export const ObjectLink = ({ space, dxn }: ObjectLinkProps) => {
18
19
  const ref = useMemo(() => space.db.makeRef(dxn), [space, dxn]);
19
20
 
@@ -2,4 +2,6 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ export type { MessageSpan } from './sync';
6
+
5
7
  export * from './ChatThread';
@@ -9,9 +9,9 @@ import { ContentBlock, type Message } from '@dxos/types';
9
9
  import { AnchorWidget, type XmlWidgetRegistry, getXmlTextChild } from '@dxos/ui-editor';
10
10
 
11
11
  import { type Assistant } from '../../types';
12
- import { type BlockRenderer, type MessageThreadContext } from './sync';
13
- import { applyToolBlockToWidgetState } from './tool-widget-state';
12
+ import { type BlockRenderer, type MessageThreadContext, applyToolBlockToWidgetState } from './sync';
14
13
  import {
14
+ BranchWidget,
15
15
  FallbackWidget,
16
16
  ReasoningWidget,
17
17
  ReferenceWidget,
@@ -88,8 +88,9 @@ export const componentRegistry: XmlWidgetRegistry = {
88
88
  return options?.length ? new SelectWidget(options) : null;
89
89
  },
90
90
  },
91
+ // Inline so a run of suggestions flows onto one wrapped line instead of one block per line.
91
92
  'suggestion': {
92
- block: true,
93
+ block: false,
93
94
  factory: ({ children }) => {
94
95
  const text = getXmlTextChild(children);
95
96
  return text ? new SuggestionWidget(text) : null;
@@ -115,6 +116,10 @@ export const componentRegistry: XmlWidgetRegistry = {
115
116
  // React Widgets (portaled outside of the editor)
116
117
  //
117
118
 
119
+ 'branch': {
120
+ block: true,
121
+ Component: BranchWidget,
122
+ },
118
123
  'summary': {
119
124
  block: true,
120
125
  Component: SummaryWidget,
@@ -168,8 +173,16 @@ export function createBlockRenderer(viewType: Assistant.ChatView | undefined): B
168
173
  if (!isBlockVisible(viewType, message, block)) {
169
174
  return;
170
175
  }
176
+
171
177
  let str = blockToMarkdownImpl(context, message, block);
172
178
  if (str && !block.pending) {
179
+ // Suggestions are inline widgets meant to flow: keeping them on one line lets a run of them wrap
180
+ // as chips instead of stacking one per line. A trailing space separates adjacent tags so the
181
+ // inline parser sees them as distinct.
182
+ if (block._tag === 'suggestion') {
183
+ return (str += ' ');
184
+ }
185
+
173
186
  // Use a blank line as the block separator so each rendered block parses as its own
174
187
  // markdown block. A single newline lets CommonMark absorb a following `<prompt>` (an
175
188
  // HTML type-7 tag, which can't interrupt an open paragraph) into the previous
@@ -208,7 +221,11 @@ const blockToMarkdownImpl = (context: MessageThreadContext, message: Message.Mes
208
221
  if (block.disposition === 'synthetic') {
209
222
  return renderXMLBlock('synthetic', { content: block.text, pending: block.pending });
210
223
  } else {
211
- return `\n<prompt>${block.text}</prompt>`;
224
+ // Built by explicit concatenation, not an indented template: `trim` dedents by the minimum
225
+ // indent across all lines, and a multi-line prompt contributes lines at zero indent — so the
226
+ // source file's indentation survived into the document, where 4+ spaces is an indented code
227
+ // block and neither the prompt nor the toolbar parsed as an element any more.
228
+ return `\n<prompt>${block.text}</prompt>\n${renderBranchToolbar(message)}\n`;
212
229
  }
213
230
  } else {
214
231
  const text = block.text.trim();
@@ -291,6 +308,13 @@ const blockToMarkdownImpl = (context: MessageThreadContext, message: Message.Mes
291
308
  }
292
309
  };
293
310
 
311
+ /**
312
+ * Mini toolbar below a user prompt: branch (soft fork) plus when the prompt was sent.
313
+ * `messageId` rather than `id` because a tag's `id` attribute would shadow the widget's own id.
314
+ */
315
+ const renderBranchToolbar = (message: Message.Message) =>
316
+ `<branch messageId="${escapeXmlAttribute(message.id)}" created="${escapeXmlAttribute(message.created)}" />`;
317
+
294
318
  /**
295
319
  * Escape text embedded in generated XML so the mixed XML parser does not treat `&`, `<`, `>` as markup.
296
320
  */
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './sync';
6
+ export { applyToolBlockToWidgetState } from './tool-widget-state';
@@ -5,7 +5,7 @@
5
5
  // @vitest-environment jsdom
6
6
 
7
7
  import { EditorView } from '@codemirror/view';
8
- import { describe, it } from '@effect/vitest';
8
+ import { describe, expect, it } from '@effect/vitest';
9
9
  import * as Effect from 'effect/Effect';
10
10
 
11
11
  import { Obj } from '@dxos/echo';
@@ -14,8 +14,8 @@ import { type ContentBlock, type Message } from '@dxos/types';
14
14
 
15
15
  import { createMessage } from '#testing';
16
16
 
17
- import { createBlockRenderer } from './registry';
18
- import { type BlockRenderer, MessageSyncer, type MessageThreadContext, type TextModel } from './sync';
17
+ import { createBlockRenderer } from '../registry';
18
+ import { type BlockRenderer, MessageSyncer, type MessageThreadContext, type TextModel } from '../sync/sync';
19
19
 
20
20
  class TestDocument implements TextModel {
21
21
  private readonly _view = new EditorView({ extensions: [] });
@@ -56,13 +56,13 @@ describe('reducers', () => {
56
56
  ];
57
57
 
58
58
  syncer.update(messages);
59
- expect(doc.content).toEqual('\n<prompt>Hello</prompt>\nHi there!\n');
59
+ expect(normalize(doc.content)).toEqual('\n<prompt>Hello</prompt>\n<branch />\n\nHi there!\n');
60
60
 
61
61
  Obj.update(messages[1], (obj) => {
62
62
  obj.blocks.push({ _tag: 'text', text: 'How can I help?' });
63
63
  });
64
64
  syncer.update(messages);
65
- expect(doc.content).toEqual('\n<prompt>Hello</prompt>\nHi there!\nHow can I help?\n');
65
+ expect(normalize(doc.content)).toEqual('\n<prompt>Hello</prompt>\n<branch />\n\nHi there!\nHow can I help?\n');
66
66
  }),
67
67
  );
68
68
 
@@ -78,7 +78,7 @@ describe('reducers', () => {
78
78
  ];
79
79
 
80
80
  syncer.update(messages);
81
- expect(doc.content).toEqual('\n<prompt>Hello</prompt>\nHi there!');
81
+ expect(normalize(doc.content)).toEqual('\n<prompt>Hello</prompt>\n<branch />\n\nHi there!');
82
82
 
83
83
  Obj.update(messages[1], (obj) => {
84
84
  const block = obj.blocks[0] as Mutable<ContentBlock.Text>;
@@ -91,7 +91,43 @@ describe('reducers', () => {
91
91
  obj.blocks.push({ _tag: 'text', text: 'How can I help?' });
92
92
  });
93
93
  syncer.update(messages);
94
- expect(doc.content).toEqual('\n<prompt>Hello</prompt>\nHi there! How are you?\nHow can I help?\n');
94
+ expect(normalize(doc.content)).toEqual(
95
+ '\n<prompt>Hello</prompt>\n<branch />\n\nHi there! How are you?\nHow can I help?\n',
96
+ );
97
+ }),
98
+ );
99
+
100
+ it.effect(
101
+ 'tracks per-message document ranges',
102
+ Effect.fn(function* ({ expect }) {
103
+ const doc = new TestDocument();
104
+ const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
105
+
106
+ const messages = [
107
+ createMessage('user', [{ _tag: 'text', text: 'Hello' }]),
108
+ createMessage('assistant', [{ _tag: 'text', text: 'Hi there!' }]),
109
+ ];
110
+
111
+ syncer.update(messages);
112
+ const spans = syncer.getSpans();
113
+ expect(spans.map((range) => range.id)).toEqual([messages[0].id, messages[1].id]);
114
+ // Ranges tile the document contiguously and slice back to each message's rendered content.
115
+ expect(spans[0].from).toEqual(0);
116
+ expect(spans[1].from).toEqual(spans[0].to);
117
+ expect(spans[1].to).toEqual(doc.length);
118
+ expect(doc.content.slice(spans[0].from, spans[0].to)).toContain('<prompt>Hello</prompt>');
119
+ expect(doc.content.slice(spans[1].from, spans[1].to)).toContain('Hi there!');
120
+
121
+ // Appending to the last message extends its range through the append path.
122
+ Obj.update(messages[1], (obj) => {
123
+ obj.blocks.push({ _tag: 'text', text: 'How can I help?' });
124
+ });
125
+ syncer.update(messages);
126
+ const extended = syncer.getSpans();
127
+ expect(extended).toHaveLength(2);
128
+ expect(extended[0].to).toEqual(spans[0].to);
129
+ expect(extended[1].to).toEqual(doc.length);
130
+ expect(doc.content.slice(extended[1].from, extended[1].to)).toContain('How can I help?');
95
131
  }),
96
132
  );
97
133
 
@@ -255,3 +291,127 @@ describe('reducers', () => {
255
291
  }),
256
292
  );
257
293
  });
294
+
295
+ describe('MessageSyncer tool widget rehydration', () => {
296
+ it.effect(
297
+ 'restores tool widget state after reset replaces the document',
298
+ Effect.fnUntraced(function* (_) {
299
+ const updates: { id: string; value: any }[] = [];
300
+ class RecordingDocument extends TestDocument {
301
+ override updateWidget(id: string, value: any) {
302
+ updates.push({ id, value });
303
+ }
304
+ }
305
+
306
+ const document = new RecordingDocument();
307
+ const syncer = new MessageSyncer(document, createBlockRenderer('thinking'));
308
+ const messages = [
309
+ createMessage('assistant', [
310
+ { _tag: 'toolCall', toolCallId: 'abc', name: 'search', input: '{}', providerExecuted: false },
311
+ ]),
312
+ createMessage('user', [
313
+ { _tag: 'toolResult', toolCallId: 'abc', name: 'search', result: 'ok', providerExecuted: false },
314
+ ]),
315
+ ] as Message.Message[];
316
+
317
+ syncer.reset(messages);
318
+ // `reset` rehydrates in a promise continuation after `setContent`.
319
+ yield* Effect.promise(() => Promise.resolve());
320
+ yield* Effect.promise(() => Promise.resolve());
321
+
322
+ // Reduce the dispatches the way the widget state store does: each is either a value or a
323
+ // function of the previous state, applied in arrival order.
324
+ const forTool = updates.filter((update) => update.id === 'abc');
325
+ expect(forTool.length).toBeGreaterThan(0);
326
+ const state = forTool.reduce<{ blocks: ContentBlock.Any[] }>(
327
+ (previous, { value }) => (typeof value === 'function' ? value(previous) : value),
328
+ { blocks: [] },
329
+ );
330
+ expect(state.blocks.map((block) => block._tag)).toEqual(['toolCall', 'toolResult']);
331
+ }),
332
+ );
333
+
334
+ // Regression: the prompt was built with an indented `trim` template, which dedents by the minimum
335
+ // indent across all lines — so a multi-line prompt, contributing lines at zero indent, left the source
336
+ // file's indentation in the document. At 4+ spaces CommonMark reads an indented code block, so neither
337
+ // the prompt nor the toolbar parsed as an element and the turn rendered as raw text.
338
+ it.effect(
339
+ 'a multi-line prompt emits unindented markup',
340
+ Effect.fn(function* ({ expect }) {
341
+ const doc = new TestDocument();
342
+ const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
343
+
344
+ const prompt = createMessage('user', [{ _tag: 'text', text: 'this is a list:\n- foo\n- bar' }]);
345
+ syncer.update([prompt]);
346
+
347
+ const indented = doc.content.split('\n').filter((line) => /^\s+\S/.test(line));
348
+ expect(indented).toEqual([]);
349
+ expect(normalize(doc.content)).toContain('<prompt>this is a list:\n- foo\n- bar</prompt>\n<branch />');
350
+ }),
351
+ );
352
+
353
+ // Regression: `update` streams a suffix, so an append-only path leaves removed turns on screen. A
354
+ // rewind shrinks the thread, which has to fall back to a full reset.
355
+ it.effect(
356
+ 'a shrinking message list replaces the document',
357
+ Effect.fn(function* ({ expect }) {
358
+ const doc = new TestDocument();
359
+ const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
360
+
361
+ const prompt = createMessage('user', [{ _tag: 'text', text: 'Hello' }]);
362
+ const reply = createMessage('assistant', [{ _tag: 'text', text: 'Hi there!' }]);
363
+ syncer.update([prompt, reply]);
364
+ expect(doc.content).toContain('Hi there!');
365
+
366
+ // The rewind case: same first message, fewer turns.
367
+ const replaced = syncer.update([prompt]);
368
+ expect(replaced).toBe(true);
369
+ expect(doc.content).not.toContain('Hi there!');
370
+ expect(doc.content).toContain('Hello');
371
+ }),
372
+ );
373
+
374
+ it.effect(
375
+ 'a message list diverging mid-thread replaces the document',
376
+ Effect.fn(function* ({ expect }) {
377
+ const doc = new TestDocument();
378
+ const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
379
+
380
+ const prompt = createMessage('user', [{ _tag: 'text', text: 'Hello' }]);
381
+ const abandoned = createMessage('assistant', [{ _tag: 'text', text: 'Abandoned.' }]);
382
+ syncer.update([prompt, abandoned]);
383
+
384
+ // Same length, different second turn — the branch changed underneath us.
385
+ const retry = createMessage('assistant', [{ _tag: 'text', text: 'Retry.' }]);
386
+ expect(syncer.update([prompt, retry])).toBe(true);
387
+ expect(doc.content).not.toContain('Abandoned.');
388
+ expect(doc.content).toContain('Retry.');
389
+ }),
390
+ );
391
+
392
+ // Regression: widget callbacks reach the thread through the syncer's context, which the host has to
393
+ // publish to the editor via `setContext`. Nothing did, so a widget received `context: undefined` and
394
+ // the rewind button silently no-oped.
395
+ it.effect(
396
+ 'exposes a context routing widget callbacks to the handlers',
397
+ Effect.fn(function* ({ expect }) {
398
+ const rewound: string[] = [];
399
+ const syncer = new MessageSyncer(new TestDocument(), createBlockRenderer('thinking'), {
400
+ onRewind: (id) => rewound.push(id),
401
+ });
402
+
403
+ expect(syncer.context).toBeDefined();
404
+ syncer.context.rewind('msg-1');
405
+ expect(rewound).toEqual(['msg-1']);
406
+ }),
407
+ );
408
+ });
409
+
410
+ /**
411
+ * Canonicalizes the rendered document for comparison:
412
+ * - the branch toolbar's attributes, since `messageId` is a fresh ULID and `created` a wall-clock
413
+ * timestamp, so neither is stable across runs;
414
+ * - the run of leading newlines, which is presentational padding above the first block and is tuned
415
+ * independently — these tests are about the block sequence and the incremental append path.
416
+ */
417
+ const normalize = (content: string) => content.replace(/<branch\b[^>]*\/>/g, '<branch />').replace(/^\n+/, '\n');
@@ -14,6 +14,17 @@ import { rehydrateToolWidgetsFromMessages } from './tool-widget-state';
14
14
  */
15
15
  export type TextModel = Pick<MarkdownStreamController, 'length' | 'setContent' | 'append' | 'updateWidget'>;
16
16
 
17
+ /**
18
+ * Document offset range occupied by a message's rendered blocks. Positions are in the same
19
+ * space as the CodeMirror document (i.e. what {@link MarkdownStreamController.scrollTo} and
20
+ * {@link MarkdownStreamController.getVisibleRange} operate on).
21
+ */
22
+ export type MessageSpan = {
23
+ id: string;
24
+ from: number;
25
+ to: number;
26
+ };
27
+
17
28
  /**
18
29
  * Renders a block to markdown.
19
30
  *
@@ -29,11 +40,26 @@ export type BlockRenderer = (
29
40
  block: ContentBlock.Any,
30
41
  ) => string | undefined;
31
42
 
43
+ /**
44
+ * Callbacks a widget can invoke through {@link MessageThreadContext}.
45
+ *
46
+ * React widgets are portaled by `MarkdownStream` without its `onEvent`, so interactive widgets reach
47
+ * the thread through the context they already receive in their props.
48
+ */
49
+ export type MessageThreadHandlers = {
50
+ /** Soft-fork the thread from the given message. */
51
+ onRewind?: (messageId: string) => void;
52
+ };
53
+
32
54
  /**
33
55
  * Thread context passed to renderer.
56
+ * This enables the renderer to "stream" content into the widget state.
34
57
  */
35
58
  export class MessageThreadContext implements Pick<MarkdownStreamController, 'updateWidget'> {
36
- constructor(private readonly _widgetState?: XmlWidgetStateManager) {}
59
+ constructor(
60
+ private readonly _widgetState?: XmlWidgetStateManager,
61
+ private readonly _handlers: MessageThreadHandlers = {},
62
+ ) {}
37
63
 
38
64
  updateWidget<T>(id: string, value: StateDispatch<T>) {
39
65
  this._widgetState?.updateWidget(id, value);
@@ -43,6 +69,10 @@ export class MessageThreadContext implements Pick<MarkdownStreamController, 'upd
43
69
  getObjectLabel(_id: URI.URI) {
44
70
  return 'Object';
45
71
  }
72
+
73
+ rewind(messageId: string) {
74
+ this._handlers.onRewind?.(messageId);
75
+ }
46
76
  }
47
77
 
48
78
  /**
@@ -61,30 +91,60 @@ export class MessageThreadContext implements Pick<MarkdownStreamController, 'upd
61
91
  */
62
92
  export class MessageSyncer {
63
93
  private _threadId?: string;
94
+
95
+ /**
96
+ * Ids of the messages rendered so far, in document order. `update` streams a suffix, so it needs to
97
+ * know when the incoming list no longer extends what is on screen — a rewind drops turns, and an
98
+ * append-only path would leave them rendered.
99
+ */
100
+ private _renderedIds: string[] = [];
101
+
102
+ /** Cumulative block index (across all completed blocks in all messages). */
64
103
  private _completed = 0;
104
+
105
+ /** Chars of the in-flight block (at index `_completed`) already appended. */
65
106
  private _trailing = 0;
66
107
 
108
+ /** Document offset at the `_completed` boundary (length of all fully-appended blocks). */
109
+ private _completedOffset = 0;
110
+
111
+ /** Per-message document offset ranges, keyed by message id in document order. */
112
+ private readonly _spans = new Map<string, { from: number; to: number }>();
113
+
67
114
  private readonly _context: MessageThreadContext;
68
115
 
69
116
  constructor(
70
117
  private readonly _document: TextModel,
71
118
  private readonly _renderer: BlockRenderer,
119
+ handlers: MessageThreadHandlers = {},
72
120
  ) {
73
- this._context = new MessageThreadContext(this._document);
121
+ this._context = new MessageThreadContext(this._document, handlers);
74
122
  }
75
123
 
76
124
  get context() {
77
125
  return this._context;
78
126
  }
79
127
 
128
+ /**
129
+ * Per-message document offset spans, in document order. Valid synchronously after
130
+ * {@link reset} or {@link update} (the offsets are derived from the same rendered buffer
131
+ * that is dispatched to the document).
132
+ */
133
+ getSpans(): MessageSpan[] {
134
+ return Array.from(this._spans, ([id, { from, to }]) => ({ id, from, to }));
135
+ }
136
+
80
137
  /**
81
138
  * Replace the document with the rendering of `messages`. Use on mount, on thread switch,
82
139
  * and from {@link update} when it detects an identity change in `messages[0]`.
83
140
  */
84
141
  reset(messages: Message.Message[] = []): void {
85
142
  this._threadId = messages[0]?.id;
143
+ this._renderedIds = messages.map((message) => message.id);
86
144
  this._completed = 0;
87
145
  this._trailing = 0;
146
+ this._completedOffset = 0;
147
+ this._spans.clear();
88
148
  const buffer = this._walk(messages);
89
149
  // Match the pre-rewrite behaviour: rendering from a steady state (initial mount with
90
150
  // non-empty messages, or thread switch) lands the entire content via `setContent` — which
@@ -97,16 +157,30 @@ export class MessageSyncer {
97
157
  });
98
158
  }
99
159
 
160
+ /**
161
+ * Whether `messages` still begins with everything already rendered, making this an append.
162
+ *
163
+ * A rewind removes turns from the middle or end of the thread, and the streaming path can only add
164
+ * text — so anything other than an extension has to go through {@link reset}.
165
+ */
166
+ #extendsRendered(messages: Message.Message[]): boolean {
167
+ if (messages.length < this._renderedIds.length) {
168
+ return false;
169
+ }
170
+ return this._renderedIds.every((id, index) => messages[index]?.id === id);
171
+ }
172
+
100
173
  /**
101
174
  * Stream the suffix of the rendered messages into the document.
102
175
  * Returns `true` if the document was replaced (initial mount or thread switch), `false`
103
176
  * if the call was a streaming append (or a no-op).
104
177
  */
105
178
  update(messages: Message.Message[]): boolean {
106
- if (messages[0]?.id !== this._threadId) {
179
+ if (messages[0]?.id !== this._threadId || !this.#extendsRendered(messages)) {
107
180
  this.reset(messages);
108
181
  return true;
109
182
  }
183
+ this._renderedIds = messages.map((message) => message.id);
110
184
  const buffer = this._walk(messages);
111
185
  if (buffer.length > 0) {
112
186
  void this._document.append(buffer);
@@ -122,6 +196,9 @@ export class MessageSyncer {
122
196
  _walk(messages: Message.Message[]): string {
123
197
  let buffer = '';
124
198
  let index = 0;
199
+ // Absolute document offset at the `_completed` boundary; blocks before it were rendered on
200
+ // earlier calls and their offsets are already baked into `_completedOffset` (and `_ranges`).
201
+ let offset = this._completedOffset;
125
202
  outer: for (const message of messages) {
126
203
  for (const block of message.blocks) {
127
204
  if (index < this._completed) {
@@ -132,6 +209,11 @@ export class MessageSyncer {
132
209
  if (rendered.length > this._trailing) {
133
210
  buffer += rendered.slice(this._trailing);
134
211
  }
212
+ // The document never shrinks (see the `_trailing` guard below), so span/offset accounting
213
+ // must track the document, not a renderer output that regressed below what was appended.
214
+ const renderedLength = Math.max(rendered.length, this._trailing);
215
+ // The block occupies `[offset, offset + renderedLength)`; extend the message's range.
216
+ this._saveRange(message.id, offset, offset + renderedLength);
135
217
  if (block.pending) {
136
218
  // Stay on this block; record how far we've appended so the next call can resume.
137
219
  // `Math.max`-style guard against a non-monotonic renderer output without shrinking the doc.
@@ -142,9 +224,21 @@ export class MessageSyncer {
142
224
  }
143
225
  this._completed = index + 1;
144
226
  this._trailing = 0;
227
+ offset += renderedLength;
228
+ this._completedOffset = offset;
145
229
  index++;
146
230
  }
147
231
  }
148
232
  return buffer;
149
233
  }
234
+
235
+ /** Record (or extend) the offset range of a message. `from` is preserved; `to` never regresses. */
236
+ private _saveRange(id: string, from: number, to: number): void {
237
+ const existing = this._spans.get(id);
238
+ if (existing) {
239
+ existing.to = Math.max(existing.to, to);
240
+ } else {
241
+ this._spans.set(id, { from, to });
242
+ }
243
+ }
150
244
  }
@@ -23,15 +23,13 @@ export const applyToolBlockToWidgetState = (context: ToolWidgetStateSink, block:
23
23
  });
24
24
  break;
25
25
  }
26
+
26
27
  case 'toolResult': {
27
28
  context.updateWidget<{ blocks: ContentBlock.Any[] }>(block.toolCallId, ({ blocks = [] } = { blocks: [] }) => ({
28
29
  blocks: [...blocks, block],
29
30
  }));
30
31
  break;
31
32
  }
32
- default: {
33
- break;
34
- }
35
33
  }
36
34
  };
37
35