@dxos/plugin-automation 0.7.4 → 0.7.5-labs.071a3e2

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 (280) hide show
  1. package/dist/lib/browser/AutomationPanel-YPD3AGQN.mjs +8 -0
  2. package/dist/lib/browser/ChatContainer-ODZECATM.mjs +12 -0
  3. package/dist/lib/browser/ai-client-UJLNYP7B.mjs +22 -0
  4. package/dist/lib/browser/ai-client-UJLNYP7B.mjs.map +7 -0
  5. package/dist/lib/browser/app-graph-builder-3H5TCRG4.mjs +162 -0
  6. package/dist/lib/browser/app-graph-builder-3H5TCRG4.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-43WRHV2L.mjs +150 -0
  8. package/dist/lib/browser/chunk-43WRHV2L.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-BQHXJZ4K.mjs +15 -0
  10. package/dist/lib/browser/chunk-BQHXJZ4K.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-DL7XA62G.mjs +1531 -0
  12. package/dist/lib/browser/chunk-DL7XA62G.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-X5KMOH3I.mjs → chunk-DQ7ZSYJJ.mjs} +4 -4
  14. package/dist/lib/browser/chunk-DQ7ZSYJJ.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-PQGFC2ZO.mjs +284 -0
  16. package/dist/lib/browser/chunk-PQGFC2ZO.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-Z54KIF6H.mjs +242 -0
  18. package/dist/lib/browser/chunk-Z54KIF6H.mjs.map +7 -0
  19. package/dist/lib/browser/index.mjs +152 -252
  20. package/dist/lib/browser/index.mjs.map +4 -4
  21. package/dist/lib/browser/intent-resolver-5YVZJFS3.mjs +29 -0
  22. package/dist/lib/browser/intent-resolver-5YVZJFS3.mjs.map +7 -0
  23. package/dist/lib/browser/meta.json +1 -1
  24. package/dist/lib/browser/react-surface-WRHRCEV5.mjs +50 -0
  25. package/dist/lib/browser/react-surface-WRHRCEV5.mjs.map +7 -0
  26. package/dist/lib/browser/types/index.mjs +12 -3
  27. package/dist/lib/node/{meta.cjs → AutomationPanel-CO26O75P.cjs} +7 -11
  28. package/dist/lib/node/AutomationPanel-CO26O75P.cjs.map +7 -0
  29. package/dist/lib/node/ChatContainer-5URBEXQD.cjs +33 -0
  30. package/dist/lib/node/ChatContainer-5URBEXQD.cjs.map +7 -0
  31. package/dist/lib/node/ai-client-AOB6TLNW.cjs +38 -0
  32. package/dist/lib/node/ai-client-AOB6TLNW.cjs.map +7 -0
  33. package/dist/lib/node/app-graph-builder-CDEQJEHY.cjs +178 -0
  34. package/dist/lib/node/app-graph-builder-CDEQJEHY.cjs.map +7 -0
  35. package/dist/lib/node/chunk-AWZVJZ2I.cjs +34 -0
  36. package/dist/lib/node/chunk-AWZVJZ2I.cjs.map +7 -0
  37. package/dist/lib/node/chunk-D2QQXWOY.cjs +302 -0
  38. package/dist/lib/node/chunk-D2QQXWOY.cjs.map +7 -0
  39. package/dist/lib/node/chunk-H3RSMGJG.cjs +173 -0
  40. package/dist/lib/node/chunk-H3RSMGJG.cjs.map +7 -0
  41. package/dist/lib/node/chunk-NH7STAX6.cjs +1515 -0
  42. package/dist/lib/node/chunk-NH7STAX6.cjs.map +7 -0
  43. package/dist/lib/node/chunk-OCW5GAVZ.cjs +266 -0
  44. package/dist/lib/node/chunk-OCW5GAVZ.cjs.map +7 -0
  45. package/dist/lib/node/{chunk-DTJ7XVO2.cjs → chunk-TQEDPRY5.cjs} +8 -8
  46. package/dist/lib/node/chunk-TQEDPRY5.cjs.map +7 -0
  47. package/dist/lib/node/index.cjs +169 -282
  48. package/dist/lib/node/index.cjs.map +4 -4
  49. package/dist/lib/node/intent-resolver-MJFZT5IU.cjs +44 -0
  50. package/dist/lib/node/intent-resolver-MJFZT5IU.cjs.map +7 -0
  51. package/dist/lib/node/meta.json +1 -1
  52. package/dist/lib/node/react-surface-HDAVE6NU.cjs +70 -0
  53. package/dist/lib/node/react-surface-HDAVE6NU.cjs.map +7 -0
  54. package/dist/lib/node/types/index.cjs +16 -7
  55. package/dist/lib/node/types/index.cjs.map +2 -2
  56. package/dist/lib/node-esm/AutomationPanel-VQZUKPK2.mjs +9 -0
  57. package/dist/lib/node-esm/AutomationPanel-VQZUKPK2.mjs.map +7 -0
  58. package/dist/lib/node-esm/ChatContainer-23QIVDG5.mjs +13 -0
  59. package/dist/lib/node-esm/ChatContainer-23QIVDG5.mjs.map +7 -0
  60. package/dist/lib/node-esm/ai-client-RUCCJ7JZ.mjs +23 -0
  61. package/dist/lib/node-esm/ai-client-RUCCJ7JZ.mjs.map +7 -0
  62. package/dist/lib/node-esm/app-graph-builder-GR3URVNX.mjs +163 -0
  63. package/dist/lib/node-esm/app-graph-builder-GR3URVNX.mjs.map +7 -0
  64. package/dist/lib/node-esm/chunk-7JO77AAS.mjs +151 -0
  65. package/dist/lib/node-esm/chunk-7JO77AAS.mjs.map +7 -0
  66. package/dist/lib/node-esm/{chunk-HNOBZHWK.mjs → chunk-JFHI22MF.mjs} +4 -4
  67. package/dist/lib/node-esm/chunk-JFHI22MF.mjs.map +7 -0
  68. package/dist/lib/node-esm/chunk-JJFWFS6P.mjs +1532 -0
  69. package/dist/lib/node-esm/chunk-JJFWFS6P.mjs.map +7 -0
  70. package/dist/lib/node-esm/chunk-LSSWQIQD.mjs +16 -0
  71. package/dist/lib/node-esm/chunk-LSSWQIQD.mjs.map +7 -0
  72. package/dist/lib/node-esm/chunk-NSVQZ3EH.mjs +243 -0
  73. package/dist/lib/node-esm/chunk-NSVQZ3EH.mjs.map +7 -0
  74. package/dist/lib/node-esm/chunk-VN2AFV25.mjs +285 -0
  75. package/dist/lib/node-esm/chunk-VN2AFV25.mjs.map +7 -0
  76. package/dist/lib/node-esm/index.mjs +152 -252
  77. package/dist/lib/node-esm/index.mjs.map +4 -4
  78. package/dist/lib/node-esm/intent-resolver-FCKNRTKQ.mjs +30 -0
  79. package/dist/lib/node-esm/intent-resolver-FCKNRTKQ.mjs.map +7 -0
  80. package/dist/lib/node-esm/meta.json +1 -1
  81. package/dist/lib/node-esm/react-surface-FZ5OFRDE.mjs +51 -0
  82. package/dist/lib/node-esm/react-surface-FZ5OFRDE.mjs.map +7 -0
  83. package/dist/lib/node-esm/types/index.mjs +12 -3
  84. package/dist/types/src/AutomationPlugin.d.ts +1 -3
  85. package/dist/types/src/AutomationPlugin.d.ts.map +1 -1
  86. package/dist/types/src/artifacts.stories.d.ts +16 -0
  87. package/dist/types/src/artifacts.stories.d.ts.map +1 -0
  88. package/dist/types/src/capabilities/ai-client.d.ts +5 -0
  89. package/dist/types/src/capabilities/ai-client.d.ts.map +1 -0
  90. package/dist/types/src/capabilities/app-graph-builder.d.ts +180 -0
  91. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  92. package/dist/types/src/capabilities/capabilities.d.ts +5 -0
  93. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
  94. package/dist/types/src/capabilities/index.d.ts +182 -0
  95. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  96. package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
  97. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
  98. package/dist/types/src/capabilities/react-surface.d.ts +4 -0
  99. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  100. package/dist/types/src/components/AutomationPanel/AutomationPanel.d.ts +1 -1
  101. package/dist/types/src/components/AutomationPanel/AutomationPanel.d.ts.map +1 -1
  102. package/dist/types/src/components/AutomationPanel/AutomationPanel.stories.d.ts.map +1 -1
  103. package/dist/types/src/components/ChatContainer/ChatContainer.d.ts +7 -0
  104. package/dist/types/src/components/ChatContainer/ChatContainer.d.ts.map +1 -0
  105. package/dist/types/src/components/ChatContainer/index.d.ts +4 -0
  106. package/dist/types/src/components/ChatContainer/index.d.ts.map +1 -0
  107. package/dist/types/src/components/MarkdownViewer/MarkdownViewer.d.ts +14 -0
  108. package/dist/types/src/components/MarkdownViewer/MarkdownViewer.d.ts.map +1 -0
  109. package/dist/types/src/components/MarkdownViewer/MarkdownViewer.stories.d.ts +8 -0
  110. package/dist/types/src/components/MarkdownViewer/MarkdownViewer.stories.d.ts.map +1 -0
  111. package/dist/types/src/components/MarkdownViewer/index.d.ts +2 -0
  112. package/dist/types/src/components/MarkdownViewer/index.d.ts.map +1 -0
  113. package/dist/types/src/components/ServiceRegistry/ServiceRegistry.d.ts +6 -0
  114. package/dist/types/src/components/ServiceRegistry/ServiceRegistry.d.ts.map +1 -0
  115. package/dist/types/src/components/ServiceRegistry/ServiceRegistry.stories.d.ts +8 -0
  116. package/dist/types/src/components/ServiceRegistry/ServiceRegistry.stories.d.ts.map +1 -0
  117. package/dist/types/src/components/ServiceRegistry/index.d.ts +2 -0
  118. package/dist/types/src/components/ServiceRegistry/index.d.ts.map +1 -0
  119. package/dist/types/src/components/Thread/ScrollContainer.d.ts +15 -0
  120. package/dist/types/src/components/Thread/ScrollContainer.d.ts.map +1 -0
  121. package/dist/types/src/components/Thread/StatusLine.d.ts +11 -0
  122. package/dist/types/src/components/Thread/StatusLine.d.ts.map +1 -0
  123. package/dist/types/src/components/Thread/StatusLine.stories.d.ts +9 -0
  124. package/dist/types/src/components/Thread/StatusLine.stories.d.ts.map +1 -0
  125. package/dist/types/src/components/Thread/Tabbed.d.ts +9 -0
  126. package/dist/types/src/components/Thread/Tabbed.d.ts.map +1 -0
  127. package/dist/types/src/components/Thread/Tabbed.stories.d.ts +8 -0
  128. package/dist/types/src/components/Thread/Tabbed.stories.d.ts.map +1 -0
  129. package/dist/types/src/components/Thread/Thread.d.ts +11 -0
  130. package/dist/types/src/components/Thread/Thread.d.ts.map +1 -0
  131. package/dist/types/src/components/Thread/Thread.stories.d.ts +10 -0
  132. package/dist/types/src/components/Thread/Thread.stories.d.ts.map +1 -0
  133. package/dist/types/src/components/Thread/ThreadMessage.d.ts +12 -0
  134. package/dist/types/src/components/Thread/ThreadMessage.d.ts.map +1 -0
  135. package/dist/types/src/components/Thread/ToggleContainer.d.ts +13 -0
  136. package/dist/types/src/components/Thread/ToggleContainer.d.ts.map +1 -0
  137. package/dist/types/src/components/Thread/ToggleContainer.stories.d.ts +9 -0
  138. package/dist/types/src/components/Thread/ToggleContainer.stories.d.ts.map +1 -0
  139. package/dist/types/src/components/Thread/index.d.ts +2 -0
  140. package/dist/types/src/components/Thread/index.d.ts.map +1 -0
  141. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts +1 -2
  142. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -1
  143. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts.map +1 -1
  144. package/dist/types/src/components/index.d.ts +12 -2
  145. package/dist/types/src/components/index.d.ts.map +1 -1
  146. package/dist/types/src/hooks/email.d.ts.map +1 -1
  147. package/dist/types/src/hooks/index.d.ts +4 -0
  148. package/dist/types/src/hooks/index.d.ts.map +1 -1
  149. package/dist/types/src/hooks/invocation-handler.d.ts.map +1 -1
  150. package/dist/types/src/hooks/processor.d.ts +70 -0
  151. package/dist/types/src/hooks/processor.d.ts.map +1 -0
  152. package/dist/types/src/hooks/processor.test.d.ts +2 -0
  153. package/dist/types/src/hooks/processor.test.d.ts.map +1 -0
  154. package/dist/types/src/hooks/useChatProcessor.d.ts +7 -0
  155. package/dist/types/src/hooks/useChatProcessor.d.ts.map +1 -0
  156. package/dist/types/src/hooks/useMessageQueue.d.ts +41 -0
  157. package/dist/types/src/hooks/useMessageQueue.d.ts.map +1 -0
  158. package/dist/types/src/hooks/useServices.d.ts +7 -0
  159. package/dist/types/src/hooks/useServices.d.ts.map +1 -0
  160. package/dist/types/src/index.d.ts +1 -2
  161. package/dist/types/src/index.d.ts.map +1 -1
  162. package/dist/types/src/meta.d.ts +1 -2
  163. package/dist/types/src/meta.d.ts.map +1 -1
  164. package/dist/types/src/testing/index.d.ts +2 -1
  165. package/dist/types/src/testing/index.d.ts.map +1 -1
  166. package/dist/types/src/testing/{testing.d.ts → test-functions.d.ts} +3 -1
  167. package/dist/types/src/testing/test-functions.d.ts.map +1 -0
  168. package/dist/types/src/testing/test-services.d.ts +5 -0
  169. package/dist/types/src/testing/test-services.d.ts.map +1 -0
  170. package/dist/types/src/tools/function.d.ts +5 -0
  171. package/dist/types/src/tools/function.d.ts.map +1 -0
  172. package/dist/types/src/tools/index.d.ts +3 -0
  173. package/dist/types/src/tools/index.d.ts.map +1 -0
  174. package/dist/types/src/tools/openapi.d.ts +10 -0
  175. package/dist/types/src/tools/openapi.d.ts.map +1 -0
  176. package/dist/types/src/tools/openapi.test.d.ts +2 -0
  177. package/dist/types/src/tools/openapi.test.d.ts.map +1 -0
  178. package/dist/types/src/translations.d.ts +81 -2
  179. package/dist/types/src/translations.d.ts.map +1 -1
  180. package/dist/types/src/types/index.d.ts +1 -0
  181. package/dist/types/src/types/index.d.ts.map +1 -1
  182. package/dist/types/src/types/registry.d.ts +10 -0
  183. package/dist/types/src/types/registry.d.ts.map +1 -0
  184. package/dist/types/src/types/schema.d.ts +189 -39
  185. package/dist/types/src/types/schema.d.ts.map +1 -1
  186. package/dist/types/src/types/types.d.ts +16 -5
  187. package/dist/types/src/types/types.d.ts.map +1 -1
  188. package/dist/types/tsconfig.tsbuildinfo +1 -0
  189. package/package.json +54 -48
  190. package/src/AutomationPlugin.tsx +77 -194
  191. package/src/artifacts.stories.tsx +241 -0
  192. package/src/capabilities/ai-client.ts +19 -0
  193. package/src/capabilities/app-graph-builder.ts +156 -0
  194. package/src/capabilities/capabilities.ts +12 -0
  195. package/src/capabilities/index.ts +12 -0
  196. package/src/capabilities/intent-resolver.ts +27 -0
  197. package/src/capabilities/react-surface.tsx +36 -0
  198. package/src/components/AutomationPanel/AutomationPanel.stories.tsx +1 -2
  199. package/src/components/AutomationPanel/AutomationPanel.tsx +61 -39
  200. package/src/components/ChatContainer/ChatContainer.tsx +52 -0
  201. package/src/components/ChatContainer/index.ts +8 -0
  202. package/src/components/MarkdownViewer/MarkdownViewer.stories.tsx +56 -0
  203. package/src/components/MarkdownViewer/MarkdownViewer.tsx +79 -0
  204. package/src/components/MarkdownViewer/index.ts +5 -0
  205. package/src/components/PromptEditor/PromptEditor.stories.tsx +3 -3
  206. package/src/components/ServiceRegistry/ServiceRegistry.stories.tsx +49 -0
  207. package/src/components/ServiceRegistry/ServiceRegistry.tsx +75 -0
  208. package/src/components/ServiceRegistry/index.ts +5 -0
  209. package/src/components/Thread/ScrollContainer.tsx +92 -0
  210. package/src/components/Thread/StatusLine.stories.tsx +52 -0
  211. package/src/components/Thread/StatusLine.tsx +76 -0
  212. package/src/components/Thread/Tabbed.stories.tsx +52 -0
  213. package/src/components/Thread/Tabbed.tsx +72 -0
  214. package/src/components/Thread/Thread.stories.tsx +190 -0
  215. package/src/components/Thread/Thread.tsx +156 -0
  216. package/src/components/Thread/ThreadMessage.tsx +203 -0
  217. package/src/components/Thread/ToggleContainer.stories.tsx +111 -0
  218. package/src/components/Thread/ToggleContainer.tsx +103 -0
  219. package/src/components/Thread/index.ts +5 -0
  220. package/src/components/TriggerEditor/TriggerEditor.stories.tsx +1 -2
  221. package/src/components/TriggerEditor/TriggerEditor.tsx +81 -16
  222. package/src/components/index.ts +9 -1
  223. package/src/hooks/email.ts +2 -2
  224. package/src/hooks/index.ts +5 -0
  225. package/src/hooks/invocation-handler.ts +2 -2
  226. package/src/hooks/processor.test.ts +15 -0
  227. package/src/hooks/processor.ts +210 -0
  228. package/src/hooks/useChatProcessor.tsx +86 -0
  229. package/src/hooks/useMessageQueue.ts +23 -0
  230. package/src/hooks/useServices.ts +28 -0
  231. package/src/index.ts +1 -4
  232. package/src/meta.ts +3 -2
  233. package/src/testing/index.ts +2 -1
  234. package/src/testing/{testing.ts → test-functions.ts} +9 -2
  235. package/src/testing/test-services.ts +131 -0
  236. package/src/tools/function.ts +47 -0
  237. package/src/tools/index.ts +6 -0
  238. package/src/tools/openapi.test.ts +227 -0
  239. package/src/tools/openapi.ts +331 -0
  240. package/src/translations.ts +17 -2
  241. package/src/types/index.ts +1 -0
  242. package/src/types/registry.ts +26 -0
  243. package/src/types/schema.ts +96 -2
  244. package/src/types/types.ts +15 -21
  245. package/dist/lib/browser/AssistantPanel-N3QSALKY.mjs +0 -341
  246. package/dist/lib/browser/AssistantPanel-N3QSALKY.mjs.map +0 -7
  247. package/dist/lib/browser/AutomationPanel-AQMN2CQR.mjs +0 -153
  248. package/dist/lib/browser/AutomationPanel-AQMN2CQR.mjs.map +0 -7
  249. package/dist/lib/browser/chunk-7KB4UMXO.mjs +0 -49
  250. package/dist/lib/browser/chunk-7KB4UMXO.mjs.map +0 -7
  251. package/dist/lib/browser/chunk-X5KMOH3I.mjs.map +0 -7
  252. package/dist/lib/browser/meta.mjs +0 -9
  253. package/dist/lib/node/AssistantPanel-RIA4TI3B.cjs +0 -361
  254. package/dist/lib/node/AssistantPanel-RIA4TI3B.cjs.map +0 -7
  255. package/dist/lib/node/AutomationPanel-HZS5WKI5.cjs +0 -173
  256. package/dist/lib/node/AutomationPanel-HZS5WKI5.cjs.map +0 -7
  257. package/dist/lib/node/chunk-CUCUWUAF.cjs +0 -73
  258. package/dist/lib/node/chunk-CUCUWUAF.cjs.map +0 -7
  259. package/dist/lib/node/chunk-DTJ7XVO2.cjs.map +0 -7
  260. package/dist/lib/node/meta.cjs.map +0 -7
  261. package/dist/lib/node-esm/AssistantPanel-72YH43CH.mjs +0 -342
  262. package/dist/lib/node-esm/AssistantPanel-72YH43CH.mjs.map +0 -7
  263. package/dist/lib/node-esm/AutomationPanel-JUHOWQWW.mjs +0 -154
  264. package/dist/lib/node-esm/AutomationPanel-JUHOWQWW.mjs.map +0 -7
  265. package/dist/lib/node-esm/chunk-23LY7DYS.mjs +0 -51
  266. package/dist/lib/node-esm/chunk-23LY7DYS.mjs.map +0 -7
  267. package/dist/lib/node-esm/chunk-HNOBZHWK.mjs.map +0 -7
  268. package/dist/lib/node-esm/meta.mjs +0 -10
  269. package/dist/types/src/components/AssistantPanel/AssistantPanel.d.ts +0 -8
  270. package/dist/types/src/components/AssistantPanel/AssistantPanel.d.ts.map +0 -1
  271. package/dist/types/src/components/AssistantPanel/index.d.ts +0 -3
  272. package/dist/types/src/components/AssistantPanel/index.d.ts.map +0 -1
  273. package/dist/types/src/components/AssistantPanel/system-instructions.d.ts +0 -6
  274. package/dist/types/src/components/AssistantPanel/system-instructions.d.ts.map +0 -1
  275. package/dist/types/src/testing/testing.d.ts.map +0 -1
  276. package/src/components/AssistantPanel/AssistantPanel.tsx +0 -230
  277. package/src/components/AssistantPanel/index.ts +0 -7
  278. package/src/components/AssistantPanel/system-instructions.ts +0 -166
  279. /package/dist/lib/browser/{meta.mjs.map → AutomationPanel-YPD3AGQN.mjs.map} +0 -0
  280. /package/dist/lib/{node-esm/meta.mjs.map → browser/ChatContainer-ODZECATM.mjs.map} +0 -0
@@ -0,0 +1,156 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
6
+ import { ClientCapabilities } from '@dxos/plugin-client';
7
+ import { createExtension, toSignal } from '@dxos/plugin-graph';
8
+ import { memoizeQuery } from '@dxos/plugin-space';
9
+ import { getTypename, parseId, SpaceState } from '@dxos/react-client/echo';
10
+
11
+ import { AUTOMATION_PLUGIN } from '../meta';
12
+
13
+ export default (context: PluginsContext) => {
14
+ const resolve = (typename: string) =>
15
+ context.requestCapabilities(Capabilities.Metadata).find(({ id }) => id === typename)?.metadata ?? {};
16
+
17
+ return contributes(Capabilities.AppGraphBuilder, [
18
+ createExtension({
19
+ id: `${AUTOMATION_PLUGIN}/service-registry`,
20
+ resolver: ({ id }) => {
21
+ if (!id.endsWith('~service-registry')) {
22
+ return;
23
+ }
24
+
25
+ const type = 'orphan-settings-for-subject';
26
+ const icon = 'ph--plugs--regular';
27
+
28
+ const client = context.requestCapability(ClientCapabilities.Client);
29
+ const [subjectId] = id.split('~');
30
+ const { spaceId } = parseId(subjectId);
31
+ const spaces = toSignal(
32
+ (onChange) => client.spaces.subscribe(() => onChange()).unsubscribe,
33
+ () => client.spaces.get(),
34
+ );
35
+ const space = spaces?.find((space) => space.id === spaceId && space.state.get() === SpaceState.SPACE_READY);
36
+ return {
37
+ id,
38
+ type,
39
+ data: null,
40
+ properties: {
41
+ icon,
42
+ label: ['service registry label', { ns: AUTOMATION_PLUGIN }],
43
+ object: null,
44
+ space,
45
+ },
46
+ };
47
+ },
48
+ }),
49
+ createExtension({
50
+ id: `${AUTOMATION_PLUGIN}/automation-for-subject`,
51
+ resolver: ({ id }) => {
52
+ if (!id.endsWith('~automation')) {
53
+ return;
54
+ }
55
+
56
+ const type = 'orphan-settings-for-subject';
57
+ const icon = 'ph--magic-wand--regular';
58
+
59
+ const client = context.requestCapability(ClientCapabilities.Client);
60
+ const [subjectId] = id.split('~');
61
+ const { spaceId, objectId } = parseId(subjectId);
62
+ const spaces = toSignal(
63
+ (onChange) => client.spaces.subscribe(() => onChange()).unsubscribe,
64
+ () => client.spaces.get(),
65
+ );
66
+ const space = spaces?.find((space) => space.id === spaceId && space.state.get() === SpaceState.SPACE_READY);
67
+ if (!objectId) {
68
+ // TODO(burdon): Ref SPACE_PLUGIN ns.
69
+ const label = space
70
+ ? space.properties.name || ['unnamed space label', { ns: AUTOMATION_PLUGIN }]
71
+ : ['unnamed object settings label', { ns: AUTOMATION_PLUGIN }];
72
+
73
+ // TODO(wittjosiah): Support comments for arbitrary subjects.
74
+ // This is to ensure that the comments panel is not stuck on an old object.
75
+ return {
76
+ id,
77
+ type,
78
+ data: null,
79
+ properties: {
80
+ icon,
81
+ label,
82
+ showResolvedThreads: false,
83
+ object: null,
84
+ space,
85
+ },
86
+ };
87
+ }
88
+
89
+ const [object] = memoizeQuery(space, { id: objectId });
90
+ if (!object || !subjectId) {
91
+ return;
92
+ }
93
+
94
+ const meta = resolve(getTypename(object) ?? '');
95
+ const label = meta.label?.(object) ||
96
+ object.name ||
97
+ meta.placeholder || ['unnamed object settings label', { ns: AUTOMATION_PLUGIN }];
98
+
99
+ return {
100
+ id,
101
+ type,
102
+ data: null,
103
+ properties: {
104
+ icon,
105
+ label,
106
+ object,
107
+ },
108
+ };
109
+ },
110
+ }),
111
+ createExtension({
112
+ id: `${AUTOMATION_PLUGIN}/assistant-for-subject`,
113
+ resolver: ({ id }) => {
114
+ if (!id.endsWith('~assistant')) {
115
+ return;
116
+ }
117
+
118
+ const client = context.requestCapability(ClientCapabilities.Client);
119
+ const [subjectId] = id.split('~');
120
+ const { spaceId, objectId } = parseId(subjectId);
121
+ const spaces = toSignal(
122
+ (onChange) => client.spaces.subscribe(() => onChange()).unsubscribe,
123
+ () => client.spaces.get(),
124
+ );
125
+ const space = spaces?.find((space) => space.id === spaceId && space.state.get() === SpaceState.SPACE_READY);
126
+ if (!objectId) {
127
+ // TODO(wittjosiah): Support assistant for arbitrary subjects.
128
+ // This is to ensure that the assistant panel is not stuck on an old object.
129
+ return {
130
+ id,
131
+ type: 'orphan-automation-for-subject',
132
+ data: null,
133
+ properties: {
134
+ icon: 'ph--atom--regular',
135
+ label: ['assistant panel label', { ns: AUTOMATION_PLUGIN }],
136
+ object: null,
137
+ space,
138
+ },
139
+ };
140
+ }
141
+
142
+ const [object] = memoizeQuery(space, { id: objectId });
143
+ return {
144
+ id,
145
+ type: 'orphan-automation-for-subject',
146
+ data: null,
147
+ properties: {
148
+ icon: 'ph--atom--regular',
149
+ label: ['assistant panel label', { ns: AUTOMATION_PLUGIN }],
150
+ object,
151
+ },
152
+ };
153
+ },
154
+ }),
155
+ ]);
156
+ };
@@ -0,0 +1,12 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { defineCapability } from '@dxos/app-framework';
6
+ import { type AIServiceClientImpl } from '@dxos/assistant';
7
+
8
+ import { AUTOMATION_PLUGIN } from '../meta';
9
+
10
+ export namespace AutomationCapabilities {
11
+ export const AiClient = defineCapability<AIServiceClientImpl>(`${AUTOMATION_PLUGIN}/capability/ai-client`);
12
+ }
@@ -0,0 +1,12 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { lazy } from '@dxos/app-framework';
6
+
7
+ export const AiClient = lazy(() => import('./ai-client'));
8
+ export const AppGraphBuilder = lazy(() => import('./app-graph-builder'));
9
+ export const IntentResolver = lazy(() => import('./intent-resolver'));
10
+ export const ReactSurface = lazy(() => import('./react-surface'));
11
+
12
+ export * from './capabilities';
@@ -0,0 +1,27 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Capabilities, contributes, createResolver } from '@dxos/app-framework';
6
+ import { ObjectId } from '@dxos/echo-schema';
7
+ import { create, makeRef } from '@dxos/live-object';
8
+
9
+ import { AutomationAction, AIChatType } from '../types';
10
+
11
+ export default () =>
12
+ contributes(
13
+ Capabilities.IntentResolver,
14
+ createResolver({
15
+ intent: AutomationAction.Create,
16
+ resolve: ({ name }) => ({
17
+ data: {
18
+ object: create(AIChatType, {
19
+ name,
20
+ // TODO(burdon): ???
21
+ // new DXN(DXN.kind.QUEUE, [QueueSubspaceTags.DATA, SpaceId.random(), ObjectId.random()]).toString(),
22
+ queue: makeRef({ id: ObjectId.random() }),
23
+ }),
24
+ },
25
+ }),
26
+ }),
27
+ );
@@ -0,0 +1,36 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { Capabilities, contributes, createSurface } from '@dxos/app-framework';
8
+ import { getSpace, isEchoObject, isSpace, type ReactiveEchoObject } from '@dxos/react-client/echo';
9
+
10
+ import { AutomationPanel, ChatContainer, ServiceRegistry } from '../components';
11
+ import { AUTOMATION_PLUGIN } from '../meta';
12
+ import { AIChatType } from '../types';
13
+
14
+ export default () =>
15
+ contributes(Capabilities.ReactSurface, [
16
+ createSurface({
17
+ id: `${AUTOMATION_PLUGIN}/ai-chat`,
18
+ role: 'article',
19
+ filter: (data): data is { subject: AIChatType } => data.subject instanceof AIChatType,
20
+ component: ({ data, role }) => <ChatContainer role={role} chat={data.subject} />,
21
+ }),
22
+ createSurface({
23
+ id: `${AUTOMATION_PLUGIN}/service-registry`,
24
+ role: 'complementary--service-registry',
25
+ component: ({ data }) => (
26
+ <ServiceRegistry space={isSpace(data.subject) ? data.subject : getSpace(data.subject)!} />
27
+ ),
28
+ }),
29
+ createSurface({
30
+ id: `${AUTOMATION_PLUGIN}/automation`,
31
+ role: 'complementary--automation',
32
+ filter: (data): data is { subject: ReactiveEchoObject<any> } =>
33
+ isEchoObject(data.subject) && !!getSpace(data.subject),
34
+ component: ({ data }) => <AutomationPanel space={getSpace(data.subject)!} object={data.subject} />,
35
+ }),
36
+ ]);
@@ -7,8 +7,7 @@ import '@dxos-theme';
7
7
  import { type Meta } from '@storybook/react';
8
8
  import React from 'react';
9
9
 
10
- import { FunctionTrigger } from '@dxos/functions';
11
- import { FunctionType } from '@dxos/plugin-script/types';
10
+ import { FunctionType, FunctionTrigger } from '@dxos/functions';
12
11
  import { create, useSpaces } from '@dxos/react-client/echo';
13
12
  import { withClientProvider } from '@dxos/react-client/testing';
14
13
  import { withLayout, withTheme } from '@dxos/storybook-utils';
@@ -5,8 +5,14 @@
5
5
  import React, { useState } from 'react';
6
6
 
7
7
  import { S } from '@dxos/echo-schema';
8
- import { FunctionTriggerSchema, FunctionTrigger, type FunctionTriggerType } from '@dxos/functions';
9
- import { FunctionType, ScriptType } from '@dxos/plugin-script';
8
+ import {
9
+ FunctionType,
10
+ FunctionTrigger,
11
+ FunctionTriggerSchema,
12
+ TriggerKind,
13
+ type FunctionTriggerType,
14
+ ScriptType,
15
+ } from '@dxos/functions';
10
16
  import { type Client, useClient } from '@dxos/react-client';
11
17
  import { create, Filter, useQuery, type Space, type ReactiveObject, getSpace } from '@dxos/react-client/echo';
12
18
  import { IconButton, Input, useTranslation, Button } from '@dxos/react-ui';
@@ -24,7 +30,7 @@ export type AutomationPanelProps = {
24
30
  };
25
31
 
26
32
  // TODO(burdon): Factor out common layout with ViewEditor.
27
- export const AutomationPanel = ({ space }: AutomationPanelProps) => {
33
+ export const AutomationPanel = ({ space, object }: AutomationPanelProps) => {
28
34
  const { t } = useTranslation(AUTOMATION_PLUGIN);
29
35
  const client = useClient();
30
36
  const triggers = useQuery(space, Filter.schema(FunctionTrigger));
@@ -41,7 +47,7 @@ export const AutomationPanel = ({ space }: AutomationPanelProps) => {
41
47
  };
42
48
 
43
49
  const handleAdd = () => {
44
- setTrigger(create(FunctionTriggerSchema, {}));
50
+ setTrigger(create(FunctionTriggerSchema, { meta: {} }));
45
51
  setSelected(undefined);
46
52
  };
47
53
 
@@ -71,43 +77,46 @@ export const AutomationPanel = ({ space }: AutomationPanelProps) => {
71
77
  <List.Root<FunctionTrigger> items={triggers} isItem={S.is(FunctionTrigger)} getId={(field) => field.id}>
72
78
  {({ items: triggers }) => (
73
79
  <div role='list' className='flex flex-col w-full'>
74
- {triggers?.map((trigger) => (
75
- <List.Item<FunctionTrigger>
76
- key={trigger.id}
77
- item={trigger}
78
- classNames={mx(grid, ghostHover, 'items-center')}
79
- >
80
- <Input.Root>
81
- <Input.Switch checked={trigger.enabled} onCheckedChange={(checked) => (trigger.enabled = checked)} />
82
- </Input.Root>
83
-
84
- <div className={'flex'}>
85
- <List.ItemTitle classNames='px-2 cursor-pointer w-0 shrink' onClick={() => handleSelect(trigger)}>
86
- {getFunctionName(scripts, functions, trigger)}
87
- </List.ItemTitle>
88
-
89
- {/* TODO: a better way to expose URL copy action */}
90
- <Button onClick={() => navigator.clipboard.writeText(getWebhookUrl(client, trigger))}>
91
- Copy URL
92
- </Button>
93
- </div>
94
-
95
- <List.ItemDeleteButton onClick={() => handleDelete(trigger)} />
96
- </List.Item>
97
- ))}
80
+ {triggers?.map((trigger) => {
81
+ const copyAction = getCopyAction(client, trigger);
82
+ return (
83
+ <List.Item<FunctionTrigger>
84
+ key={trigger.id}
85
+ item={trigger}
86
+ classNames={mx(grid, ghostHover, 'items-center', 'px-2')}
87
+ >
88
+ <Input.Root>
89
+ <Input.Switch
90
+ checked={trigger.enabled}
91
+ onCheckedChange={(checked) => (trigger.enabled = checked)}
92
+ />
93
+ </Input.Root>
94
+
95
+ <div className={'flex'}>
96
+ <List.ItemTitle
97
+ classNames='px-1 cursor-pointer w-0 shrink truncate'
98
+ onClick={() => handleSelect(trigger)}
99
+ >
100
+ {getFunctionName(scripts, functions, trigger) ?? '∅'}
101
+ </List.ItemTitle>
102
+
103
+ {/* TODO: a better way to expose copy action */}
104
+ {copyAction && (
105
+ <Button onClick={() => navigator.clipboard.writeText(copyAction.contentProvider())}>
106
+ {t(copyAction.translationKey)}
107
+ </Button>
108
+ )}
109
+ </div>
110
+
111
+ <List.ItemDeleteButton onClick={() => handleDelete(trigger)} />
112
+ </List.Item>
113
+ );
114
+ })}
98
115
  </div>
99
116
  )}
100
117
  </List.Root>
101
118
 
102
- {trigger && (
103
- <TriggerEditor
104
- space={space}
105
- storedTrigger={selected}
106
- trigger={trigger}
107
- onSave={handleSave}
108
- onCancel={handleCancel}
109
- />
110
- )}
119
+ {trigger && <TriggerEditor space={space} trigger={trigger} onSave={handleSave} onCancel={handleCancel} />}
111
120
 
112
121
  {!trigger && (
113
122
  <div className='flex p-2 justify-center'>
@@ -118,6 +127,18 @@ export const AutomationPanel = ({ space }: AutomationPanelProps) => {
118
127
  );
119
128
  };
120
129
 
130
+ const getCopyAction = (client: Client, trigger: FunctionTrigger | undefined) => {
131
+ if (trigger?.spec?.type === TriggerKind.Email) {
132
+ return { translationKey: 'trigger copy email', contentProvider: () => `${getSpace(trigger)!.id}@dxos.network` };
133
+ }
134
+
135
+ if (trigger?.spec?.type === TriggerKind.Webhook) {
136
+ return { translationKey: 'trigger copy url', contentProvider: () => getWebhookUrl(client, trigger) };
137
+ }
138
+
139
+ return undefined;
140
+ };
141
+
121
142
  const getWebhookUrl = (client: Client, trigger: FunctionTrigger) => {
122
143
  const spaceId = getSpace(trigger)!.id;
123
144
  const edgeUrl = new URL(client.config.values.runtime!.services!.edge!.url!);
@@ -127,9 +148,10 @@ const getWebhookUrl = (client: Client, trigger: FunctionTrigger) => {
127
148
  };
128
149
 
129
150
  const getFunctionName = (scripts: ScriptType[], functions: FunctionType[], trigger: FunctionTriggerType) => {
151
+ const shortId = trigger.function && `${trigger.function?.slice(0, 16)}…`;
130
152
  const functionObject = functions.find((fn) => fn.name === trigger.function);
131
153
  if (!functionObject) {
132
- return trigger.function;
154
+ return shortId;
133
155
  }
134
- return scripts.find((s) => functionObject.source?.id === s.id)?.name ?? functionObject.name;
156
+ return scripts.find((s) => functionObject.source?.target?.id === s.id)?.name ?? shortId;
135
157
  };
@@ -0,0 +1,52 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback } from 'react';
6
+
7
+ import { invariant } from '@dxos/invariant';
8
+ import { StackItem } from '@dxos/react-ui-stack';
9
+
10
+ import { useChatProcessor, useMessageQueue } from '../../hooks';
11
+ import { type AIChatType } from '../../types';
12
+ import { Thread } from '../Thread';
13
+
14
+ export const ChatContainer = ({ chat, role }: { chat: AIChatType; role: string }) => {
15
+ const processor = useChatProcessor(chat);
16
+ const messageQueue = useMessageQueue(chat);
17
+ const messages = [...(messageQueue?.items ?? []), ...processor.messages.value];
18
+
19
+ const handleSubmit = useCallback(
20
+ async (text: string) => {
21
+ if (processor.streaming.value) {
22
+ await processor.cancel();
23
+ }
24
+
25
+ invariant(messageQueue);
26
+ await processor.request(text, {
27
+ history: messageQueue.items,
28
+ onComplete: (messages) => messageQueue.append(messages),
29
+ });
30
+ },
31
+ [processor, messageQueue],
32
+ );
33
+
34
+ const handleStop = useCallback(() => {
35
+ if (processor.streaming.value) {
36
+ void processor.cancel();
37
+ }
38
+ }, [processor]);
39
+
40
+ return (
41
+ <StackItem.Content toolbar={false} role={role}>
42
+ <Thread
43
+ messages={messages}
44
+ streaming={processor.streaming.value}
45
+ collapse={true}
46
+ onSubmit={handleSubmit}
47
+ onSuggest={handleSubmit}
48
+ onStop={handleStop}
49
+ />
50
+ </StackItem.Content>
51
+ );
52
+ };
@@ -0,0 +1,8 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { ChatContainer } from './ChatContainer';
6
+
7
+ export * from './ChatContainer';
8
+ export default ChatContainer;
@@ -0,0 +1,56 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { type StoryObj, type Meta } from '@storybook/react';
8
+
9
+ import { faker } from '@dxos/random';
10
+ import { withLayout, withTheme } from '@dxos/storybook-utils';
11
+
12
+ import { MarkdownViewer } from './MarkdownViewer';
13
+
14
+ faker.seed(0);
15
+
16
+ const meta: Meta<typeof MarkdownViewer> = {
17
+ title: 'plugins/plugin-automation/MarkdownViewer',
18
+ component: MarkdownViewer,
19
+ decorators: [withTheme, withLayout({ fullscreen: true, classNames: 'justify-center' })],
20
+ };
21
+
22
+ export default meta;
23
+
24
+ type Story = StoryObj<typeof MarkdownViewer>;
25
+
26
+ const content = `
27
+ # Hello, world!
28
+
29
+ ${faker.lorem.paragraphs(1)}
30
+
31
+ Here's a JSON block:
32
+
33
+ ~~~json
34
+ {
35
+ "hello": "world"
36
+ }
37
+ ~~~
38
+
39
+ And some code:
40
+
41
+ ~~~ts
42
+ const App = () => {
43
+ const title = 'Hello, world!';
44
+ return <div>{title}</div>;
45
+ };
46
+ ~~~
47
+
48
+ ${faker.lorem.paragraphs(1)}
49
+ `;
50
+
51
+ export const Default: Story = {
52
+ args: {
53
+ classNames: 'w-[500px] border border-border rounded-md p-4',
54
+ content,
55
+ },
56
+ };
@@ -0,0 +1,79 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { type FC } from 'react';
6
+ import ReactMarkdown from 'react-markdown';
7
+
8
+ import { type ThemedClassName } from '@dxos/react-ui';
9
+ import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
10
+ import { mx } from '@dxos/react-ui-theme';
11
+ import { omit } from '@dxos/util';
12
+
13
+ type MarkdownViewerProps = ThemedClassName<{
14
+ content?: string;
15
+ }>;
16
+
17
+ /**
18
+ * Transform text into react elements.
19
+ *
20
+ * https://github.com/remarkjs/react-markdown
21
+ * markdown -> remark -> [mdast -> remark plugins] -> [hast -> rehype plugins] -> components -> react elements.
22
+ */
23
+ // TODO(burdon): Styles.
24
+ // TODO(burdon): Factor out (react-ui-syntax-highlighter).
25
+ export const MarkdownViewer: FC<MarkdownViewerProps> = ({ classNames, content = '' }) => {
26
+ return (
27
+ <div className={mx('space-y-2', classNames)}>
28
+ <ReactMarkdown
29
+ components={{
30
+ a: ({ node, children, href, ...props }) => (
31
+ <a
32
+ href={href}
33
+ className='text-primary-500 hover:text-primary-500'
34
+ target='_blank'
35
+ rel='noopener noreferrer'
36
+ {...props}
37
+ >
38
+ {children}
39
+ </a>
40
+ ),
41
+ ol: ({ node, children, ...props }) => (
42
+ <ol className='leading-tight list-decimal pl-6' {...omit(props, ['ordered'])}>
43
+ {children}
44
+ </ol>
45
+ ),
46
+ ul: ({ node, children, ...props }) => (
47
+ <ul className='leading-tight list-disc pl-6' {...omit(props, ['ordered'])}>
48
+ {children}
49
+ </ul>
50
+ ),
51
+ li: ({ node, children, ...props }) => (
52
+ <li className='' {...omit(props, ['ordered'])}>
53
+ {children}
54
+ </li>
55
+ ),
56
+ blockquote: ({ node, children, ...props }) => (
57
+ <blockquote className='border-l-4 border-primary-500 pl-4 my-4 text-primary-500' {...props}>
58
+ {children}
59
+ </blockquote>
60
+ ),
61
+ code: ({ children, className }) => {
62
+ const [_, language] = /language-(\w+)/.exec(className || '') || [];
63
+ return (
64
+ <SyntaxHighlighter PreTag='div' language={language} className='p-0'>
65
+ {children}
66
+ </SyntaxHighlighter>
67
+ );
68
+ },
69
+ }}
70
+ >
71
+ {content}
72
+ </ReactMarkdown>
73
+ </div>
74
+ );
75
+ };
76
+
77
+ // const Cursor = () => {
78
+ // return <span className='animate-[pulse_1s_steps(1)_infinite] text-primary-500'>▊</span>;
79
+ // };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './MarkdownViewer';
@@ -7,7 +7,7 @@ import '@dxos-theme';
7
7
  import { type Meta } from '@storybook/react';
8
8
  import React, { useState } from 'react';
9
9
 
10
- import { create } from '@dxos/live-object';
10
+ import { create, makeRef } from '@dxos/live-object';
11
11
  import { useClient } from '@dxos/react-client';
12
12
  import { withClientProvider } from '@dxos/react-client/testing';
13
13
  import { withLayout, withTheme } from '@dxos/storybook-utils';
@@ -34,14 +34,14 @@ const DefaultStory = () => {
34
34
  const space = client.spaces.default;
35
35
  return space.db.add(
36
36
  create(ChainType, {
37
- prompts: [create(ChainPromptType, { command: 'test', template, inputs: [] })],
37
+ prompts: [makeRef(create(ChainPromptType, { command: 'test', template, inputs: [] }))],
38
38
  }),
39
39
  );
40
40
  });
41
41
 
42
42
  return (
43
43
  <div role='none' className='flex w-[350px] border border-separator overflow-hidden'>
44
- <PromptEditor prompt={chain.prompts![0]!} />
44
+ <PromptEditor prompt={chain.prompts![0]!.target!} />
45
45
  </div>
46
46
  );
47
47
  };