@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,49 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { type Meta, type StoryObj } from '@storybook/react';
8
+ import React from 'react';
9
+
10
+ import { useSpace } from '@dxos/react-client/echo';
11
+ import { withClientProvider } from '@dxos/react-client/testing';
12
+ import { withLayout, withTheme } from '@dxos/storybook-utils';
13
+
14
+ import { ServiceRegistry } from './ServiceRegistry';
15
+ import { ServiceType } from '../../types';
16
+
17
+ const meta: Meta<typeof ServiceRegistry> = {
18
+ title: 'plugins/plugin-automation/ServiceRegistry',
19
+ component: ServiceRegistry,
20
+ render: ({ space: _ignore, ...args }) => {
21
+ const space = useSpace();
22
+ if (!space) {
23
+ return <div />;
24
+ }
25
+
26
+ return (
27
+ <div className='h-full w-[300px] overflow-hidden'>
28
+ <ServiceRegistry space={space} {...args} />
29
+ </div>
30
+ );
31
+ },
32
+ decorators: [
33
+ withClientProvider({
34
+ createIdentity: true,
35
+ createSpace: true,
36
+ types: [ServiceType],
37
+ }),
38
+ withLayout({ fullscreen: true, tooltips: true, classNames: 'flex justify-center' }),
39
+ withTheme,
40
+ ],
41
+ };
42
+
43
+ export default meta;
44
+
45
+ type Story = StoryObj<typeof ServiceRegistry>;
46
+
47
+ export const Default: Story = {
48
+ args: {},
49
+ };
@@ -0,0 +1,75 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { useMemo } from 'react';
6
+
7
+ import { Filter, type Space } from '@dxos/client/echo';
8
+ import { useQuery } from '@dxos/react-client/echo';
9
+ import { Icon, Input, List, ListItem } from '@dxos/react-ui';
10
+
11
+ import { useServices } from '../../hooks';
12
+ import { categoryIcons, ServiceType } from '../../types';
13
+
14
+ // TODO(burdon): Option to show all/enabled/filter.
15
+ export const ServiceRegistry = ({ space }: { space: Space }) => {
16
+ const matchingServices = useServices(space);
17
+ const enabledServices = useQuery(space, Filter.schema(ServiceType));
18
+
19
+ // Join matching services with enabled services.
20
+ const services = useMemo(() => {
21
+ return matchingServices.map((service) => enabledServices.find((s) => s.serviceId === service.serviceId) ?? service);
22
+ }, [matchingServices, enabledServices]);
23
+
24
+ const handleSetEnabled = (service: ServiceType, enabled: boolean) => {
25
+ if (enabled) {
26
+ space.db.add(service);
27
+ } else {
28
+ // TODO(burdon): Remove or disable?
29
+ space.db.remove(service);
30
+ }
31
+ };
32
+
33
+ return (
34
+ <List classNames='h-full grid auto-rows-[5rem] gap-2 p-2 pis-2 pie-2 overflow-y-auto scrollbar-thin'>
35
+ {services.map((service) => (
36
+ <ServiceItem
37
+ key={service.serviceId}
38
+ service={service}
39
+ enabled={service.enabled}
40
+ setEnabled={(enabled) => handleSetEnabled(service, enabled)}
41
+ />
42
+ ))}
43
+ </List>
44
+ );
45
+ };
46
+
47
+ const ServiceItem = ({
48
+ service,
49
+ enabled,
50
+ setEnabled,
51
+ }: {
52
+ service: ServiceType;
53
+ enabled?: boolean;
54
+ setEnabled?: (enabled: boolean) => void;
55
+ }) => {
56
+ return (
57
+ <ListItem.Root classNames='flex flex-col gap-1 p-1 overflow-hidden rounded-md border border-separator'>
58
+ <div className='grid grid-cols-[40px_1fr_40px]'>
59
+ <div className='flex gow justify-center items-center'>
60
+ <Icon icon={categoryIcons[service.category ?? 'default'] ?? 'ph--placeholder--regular'} size={6} />
61
+ </div>
62
+ <div className='grow items-center truncate mie-2'>{service.name}</div>
63
+ <div className='flex gow justify-center items-center'>
64
+ <Input.Root>
65
+ <Input.Switch checked={enabled} onClick={() => setEnabled?.(!enabled)} />
66
+ </Input.Root>
67
+ </div>
68
+ </div>
69
+ <div className='grid grid-cols-[40px_1fr]'>
70
+ <div />
71
+ <div className='text-sm text-subdued line-clamp-2 mie-1'>{service.description}</div>
72
+ </div>
73
+ </ListItem.Root>
74
+ );
75
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './ServiceRegistry';
@@ -0,0 +1,92 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, {
6
+ forwardRef,
7
+ type PropsWithChildren,
8
+ type UIEventHandler,
9
+ useCallback,
10
+ useEffect,
11
+ useImperativeHandle,
12
+ useRef,
13
+ useState,
14
+ } from 'react';
15
+
16
+ import { invariant } from '@dxos/invariant';
17
+ import { type ThemedClassName } from '@dxos/react-ui';
18
+ import { mx } from '@dxos/react-ui-theme';
19
+
20
+ export interface ScrollController {
21
+ scrollToBottom: () => void;
22
+ }
23
+
24
+ export type ScrollContainerProps = ThemedClassName<PropsWithChildren>;
25
+
26
+ /**
27
+ * Scroll container that automatically scrolls to the bottom when new content is added.
28
+ */
29
+ // TODO(burdon): Move to react-ui.
30
+ // TODO(burdon): Custom scrollbar.
31
+ export const ScrollContainer = forwardRef<ScrollController, ScrollContainerProps>(
32
+ ({ children, classNames }, forwardedRef) => {
33
+ const containerRef = useRef<HTMLDivElement>(null);
34
+ const autoScrollRef = useRef(false);
35
+
36
+ // Controller.
37
+ useImperativeHandle(
38
+ forwardedRef,
39
+ () => ({
40
+ scrollToBottom: () => {
41
+ invariant(containerRef.current);
42
+ containerRef.current.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'smooth' });
43
+ autoScrollRef.current = false;
44
+ },
45
+ }),
46
+ [],
47
+ );
48
+
49
+ // Auto scroll.
50
+ const [sticky, setSticky] = useState(true);
51
+ useEffect(() => {
52
+ if (!sticky || !containerRef.current) {
53
+ return;
54
+ }
55
+
56
+ autoScrollRef.current = true;
57
+ containerRef.current.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'smooth' });
58
+ }, [children]);
59
+
60
+ // Detect scroll end.
61
+ useEffect(() => {
62
+ invariant(containerRef.current);
63
+ const handleScrollEnd = () => {
64
+ autoScrollRef.current = false;
65
+ };
66
+
67
+ containerRef.current.addEventListener('scrollend', handleScrollEnd);
68
+ return () => containerRef.current?.removeEventListener('scrollend', handleScrollEnd);
69
+ }, []);
70
+
71
+ // Scrolling.
72
+ const handleScroll = useCallback<UIEventHandler<HTMLDivElement>>((ev) => {
73
+ if (autoScrollRef.current) {
74
+ return;
75
+ }
76
+
77
+ const { scrollTop, clientHeight, scrollHeight } = ev.currentTarget;
78
+ const sticky = scrollTop + clientHeight >= scrollHeight;
79
+ setSticky(sticky);
80
+ }, []);
81
+
82
+ return (
83
+ <div
84
+ ref={containerRef}
85
+ onScroll={handleScroll}
86
+ className={mx('flex flex-col grow overflow-y-scroll scrollbar-none', classNames)}
87
+ >
88
+ {children}
89
+ </div>
90
+ );
91
+ },
92
+ );
@@ -0,0 +1,52 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { type StoryObj, type Meta } from '@storybook/react';
8
+ import React, { useState } from 'react';
9
+
10
+ import { faker } from '@dxos/random';
11
+ import { Button } from '@dxos/react-ui';
12
+ import { withLayout, withTheme, withSignals } from '@dxos/storybook-utils';
13
+
14
+ import { StatusLine } from './StatusLine';
15
+
16
+ const meta: Meta<typeof StatusLine> = {
17
+ title: 'plugins/plugin-automation/StatusLine',
18
+ component: StatusLine,
19
+ decorators: [withSignals, withTheme, withLayout()],
20
+ parameters: {
21
+ layout: 'centered',
22
+ },
23
+ };
24
+
25
+ export default meta;
26
+
27
+ type Story = StoryObj<typeof StatusLine>;
28
+
29
+ export const Default: Story = {
30
+ args: {
31
+ classNames: 'w-96 px-2',
32
+ lines: Array.from({ length: 5 }, (_, i) => `${i}. ${faker.lorem.paragraph()}`),
33
+ autoAdvance: true,
34
+ },
35
+ };
36
+
37
+ export const Demo: Story = {
38
+ render: () => {
39
+ const [lines, setLines] = useState<string[]>([]);
40
+
41
+ return (
42
+ <div className='flex flex-col w-96 gap-4'>
43
+ <StatusLine lines={lines} autoAdvance advance={500} />
44
+ <div>
45
+ <Button onClick={() => setLines((lines) => [...lines, `${lines.length + 1}. ${faker.lorem.paragraph()}`])}>
46
+ Add
47
+ </Button>
48
+ </div>
49
+ </div>
50
+ );
51
+ },
52
+ };
@@ -0,0 +1,76 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { useEffect, useRef, useState } from 'react';
6
+
7
+ import { type ThemedClassName } from '@dxos/react-ui';
8
+ import { mx } from '@dxos/react-ui-theme';
9
+
10
+ const emptyLines: string[] = [];
11
+
12
+ export type StatusLineProps = ThemedClassName<{
13
+ line?: number;
14
+ lines?: string[];
15
+ transition?: number;
16
+ advance?: number;
17
+ autoAdvance?: boolean;
18
+ }>;
19
+
20
+ export const StatusLine = ({
21
+ classNames,
22
+ line = -1,
23
+ lines = emptyLines,
24
+ transition = 300,
25
+ advance = 1_000,
26
+ autoAdvance,
27
+ }: StatusLineProps) => {
28
+ const containerRef = useRef<HTMLDivElement>(null);
29
+ const [currentLine, setCurrentLine] = useState(line);
30
+ useEffect(() => {
31
+ setCurrentLine(line);
32
+ }, [line]);
33
+
34
+ useEffect(() => {
35
+ if (!autoAdvance) {
36
+ return;
37
+ }
38
+
39
+ const next = () => {
40
+ setCurrentLine((prev) => {
41
+ if (prev >= lines.length - 1) {
42
+ clearInterval(interval);
43
+ return prev;
44
+ }
45
+
46
+ return prev + 1;
47
+ });
48
+ };
49
+
50
+ next();
51
+ const interval = setInterval(next, advance);
52
+
53
+ return () => clearInterval(interval);
54
+ }, [lines.length, autoAdvance, advance]);
55
+
56
+ useEffect(() => {
57
+ if (containerRef.current) {
58
+ containerRef.current.style.transition = `transform ${transition}ms ease-in-out`;
59
+ containerRef.current.style.transform = `translateY(-${currentLine * 24}px)`;
60
+ }
61
+ }, [currentLine]);
62
+
63
+ return (
64
+ <div className={mx('relative h-[24px] overflow-hidden', classNames)}>
65
+ <div ref={containerRef} className='h-[24px]'>
66
+ <div className='flex flex-col'>
67
+ {lines.map((line, i) => (
68
+ <div key={i} className={mx('flex h-[24px] items-center')}>
69
+ <span className='truncate'>{line}</span>
70
+ </div>
71
+ ))}
72
+ </div>
73
+ </div>
74
+ </div>
75
+ );
76
+ };
@@ -0,0 +1,52 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { type StoryObj, type Meta } from '@storybook/react';
8
+ import React, { useState } from 'react';
9
+
10
+ import { faker } from '@dxos/random';
11
+ import { withLayout, withTheme, withSignals } from '@dxos/storybook-utils';
12
+
13
+ import { Tabs } from './Tabbed';
14
+ import { ToggleContainer } from './ToggleContainer';
15
+
16
+ const content = Array.from({ length: 4 }, (_, i) => ({
17
+ title: faker.lorem.paragraph(),
18
+ content: faker.lorem.paragraphs(3),
19
+ }));
20
+
21
+ const meta: Meta<typeof Tabs> = {
22
+ title: 'plugins/plugin-automation/Tabbed',
23
+ component: Tabs,
24
+ decorators: [withSignals, withTheme, withLayout({ fullscreen: true, classNames: 'justify-center' })],
25
+ };
26
+
27
+ export default meta;
28
+
29
+ type Story = StoryObj<typeof Tabs>;
30
+
31
+ export const Default: Story = {
32
+ render: () => {
33
+ const [selected, setSelected] = useState(0);
34
+ return (
35
+ <div className='flex flex-col w-[500px] p-4 bg-attention'>
36
+ <ToggleContainer
37
+ title={content[selected].title}
38
+ classNames='p-1 rounded-lg bg-baseSurface border border-neutral-500'
39
+ toggle
40
+ defaultOpen
41
+ >
42
+ <div className='flex w-full overflow-hidden'>
43
+ <Tabs length={content.length} selected={selected} onSelect={setSelected} />
44
+ <div className='flex-1 pis-2 pie-2 overflow-y-auto'>
45
+ <div>{content[selected].content}</div>
46
+ </div>
47
+ </div>
48
+ </ToggleContainer>
49
+ </div>
50
+ );
51
+ },
52
+ };
@@ -0,0 +1,72 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { type FC } from 'react';
6
+
7
+ import { Icon, type ThemedClassName } from '@dxos/react-ui';
8
+ import { mx } from '@dxos/react-ui-theme';
9
+
10
+ const numbers = [
11
+ { regular: 'ph--number-circle-zero--thin', active: 'ph--number-circle-zero--duotone' },
12
+ { regular: 'ph--number-circle-one--thin', active: 'ph--number-circle-one--duotone' },
13
+ { regular: 'ph--number-circle-two--thin', active: 'ph--number-circle-two--duotone' },
14
+ { regular: 'ph--number-circle-three--thin', active: 'ph--number-circle-three--duotone' },
15
+ { regular: 'ph--number-circle-four--thin', active: 'ph--number-circle-four--duotone' },
16
+ { regular: 'ph--number-circle-five--thin', active: 'ph--number-circle-five--duotone' },
17
+ { regular: 'ph--number-circle-six--thin', active: 'ph--number-circle-six--duotone' },
18
+ { regular: 'ph--number-circle-seven--thin', active: 'ph--number-circle-seven--duotone' },
19
+ { regular: 'ph--number-circle-eight--thin', active: 'ph--number-circle-eight--duotone' },
20
+ { regular: 'ph--number-circle-nine--thin', active: 'ph--number-circle-nine--duotone' },
21
+ ];
22
+
23
+ export type TabsProps = ThemedClassName<{ length: number; selected?: number; onSelect?: (index: number) => void }>;
24
+
25
+ // TODO(burdon): Key up/down.
26
+ export const Tabs: FC<TabsProps> = ({ classNames, length, selected = 0, onSelect }) => {
27
+ return (
28
+ <div
29
+ className={mx('flex flex-col overflow-hidden outline-none', classNames)}
30
+ tabIndex={-1}
31
+ onKeyDown={(ev) => {
32
+ // TODO(burdon): Focus when open Toggle.
33
+ switch (ev.key) {
34
+ case 'ArrowDown':
35
+ case 'ArrowRight': {
36
+ if (selected < length - 1) {
37
+ onSelect?.(selected + 1);
38
+ }
39
+ break;
40
+ }
41
+ case 'ArrowUp':
42
+ case 'ArrowLeft': {
43
+ if (selected > 0) {
44
+ onSelect?.(selected - 1);
45
+ }
46
+ break;
47
+ }
48
+ }
49
+ }}
50
+ >
51
+ {Array.from({ length }).map((_, i) => {
52
+ const icon = numbers[i + 1];
53
+ return (
54
+ <div
55
+ key={i}
56
+ className={mx(
57
+ 'relative flex w-[24px] h-[28px] justify-center cursor-pointer text-subdued',
58
+ selected === i && '!text-green-500', // TODO(burdon): accent.
59
+ )}
60
+ >
61
+ {i < length - 1 && <div className='absolute left-[11.5px] top-[21px] w-[1px] h-[10px] bg-neutral-400' />}
62
+ <Icon
63
+ icon={selected === i ? icon.regular : icon.regular}
64
+ classNames='z-10 !p-0 !w-[24px] !h-[24px] outline-none'
65
+ onClick={() => onSelect?.(i)}
66
+ />
67
+ </div>
68
+ );
69
+ })}
70
+ </div>
71
+ );
72
+ };
@@ -0,0 +1,190 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { type StoryObj, type Meta } from '@storybook/react';
8
+ import React, { useCallback, useEffect, useState } from 'react';
9
+
10
+ import { type Message } from '@dxos/artifact';
11
+ import { ObjectId } from '@dxos/echo-schema';
12
+ import { faker } from '@dxos/random';
13
+ import { withLayout, withSignals, withTheme } from '@dxos/storybook-utils';
14
+
15
+ import { Thread, type ThreadProps } from './Thread';
16
+ import translations from '../../translations';
17
+
18
+ faker.seed(1);
19
+
20
+ const Render = ({ messages: _messages, ...props }: ThreadProps) => {
21
+ const [streaming, setStreaming] = useState(false);
22
+ const [messages, setMessages] = useState<Message[]>(_messages ?? []);
23
+ useEffect(() => {
24
+ setMessages(_messages ?? []);
25
+ }, [_messages]);
26
+
27
+ const handleSubmit = useCallback(
28
+ (text: string) => {
29
+ const request: Message = { id: ObjectId.random(), role: 'user', content: [{ type: 'text', text }] };
30
+ const response: Message = {
31
+ id: ObjectId.random(),
32
+ role: 'assistant',
33
+ content: [{ type: 'text', disposition: 'cot', pending: true, text: faker.lorem.paragraphs(1) }],
34
+ };
35
+ setMessages([...messages, request, response]);
36
+ setStreaming(true);
37
+ setTimeout(() => {
38
+ response.content[0].pending = false;
39
+ setMessages([
40
+ ...messages,
41
+ request,
42
+ response,
43
+ {
44
+ id: ObjectId.random(),
45
+ role: 'assistant',
46
+ content: [{ type: 'text', text: faker.lorem.paragraphs(1) }],
47
+ },
48
+ ]);
49
+ setStreaming(false);
50
+ }, 3_000);
51
+ },
52
+ [messages],
53
+ );
54
+
55
+ return (
56
+ <div className='flex grow justify-center overflow-center bg-base'>
57
+ <div className='flex w-[500px] bg-white dark:bg-black'>
58
+ <Thread {...props} messages={messages} streaming={streaming} onSubmit={handleSubmit} onStop={() => {}} />
59
+ </div>
60
+ </div>
61
+ );
62
+ };
63
+
64
+ const meta: Meta<ThreadProps> = {
65
+ title: 'plugins/plugin-automation/Thread',
66
+ render: Render,
67
+ component: Thread,
68
+ decorators: [withSignals, withTheme, withLayout({ fullscreen: true, tooltips: true })],
69
+ parameters: {
70
+ translations,
71
+ },
72
+ };
73
+
74
+ export default meta;
75
+
76
+ type Story = StoryObj<ThreadProps>;
77
+
78
+ const TEST_MESSAGES: Message[] = [
79
+ {
80
+ id: ObjectId.random(),
81
+ role: 'user',
82
+ content: [
83
+ {
84
+ type: 'text',
85
+ text: faker.lorem.sentence(5),
86
+ },
87
+ ],
88
+ },
89
+ {
90
+ id: ObjectId.random(),
91
+ role: 'assistant',
92
+ content: [
93
+ {
94
+ type: 'text',
95
+ disposition: 'cot',
96
+ text: Array.from({ length: faker.number.int({ min: 3, max: 5 }) })
97
+ .map((_, idx) => `${idx + 1}. ${faker.lorem.paragraph()}`)
98
+ .join('\n'),
99
+ },
100
+ {
101
+ type: 'text',
102
+ text: Array.from({ length: faker.number.int({ min: 2, max: 5 }) })
103
+ .map(() => faker.lorem.paragraphs())
104
+ .join('\n\n'),
105
+ },
106
+ {
107
+ type: 'tool_use',
108
+ id: '1234',
109
+ name: 'search',
110
+ input: {},
111
+ },
112
+ ],
113
+ },
114
+ {
115
+ id: ObjectId.random(),
116
+ role: 'user',
117
+ content: [
118
+ {
119
+ type: 'tool_result',
120
+ toolUseId: '1234',
121
+ content: 'This is a tool result.',
122
+ },
123
+ ],
124
+ },
125
+ {
126
+ id: ObjectId.random(),
127
+ role: 'assistant',
128
+ content: [
129
+ {
130
+ type: 'tool_use',
131
+ id: '4567',
132
+ name: 'create',
133
+ input: {},
134
+ },
135
+ ],
136
+ },
137
+ {
138
+ id: ObjectId.random(),
139
+ role: 'user',
140
+ content: [
141
+ {
142
+ type: 'tool_result',
143
+ toolUseId: '4567',
144
+ content: 'This is a tool result.',
145
+ },
146
+ ],
147
+ },
148
+ {
149
+ id: ObjectId.random(),
150
+ role: 'assistant',
151
+ content: [
152
+ {
153
+ type: 'text',
154
+ text: faker.lorem.paragraphs(1),
155
+ },
156
+ ],
157
+ },
158
+ ];
159
+
160
+ export const Default: Story = {
161
+ args: {
162
+ debug: true,
163
+ messages: TEST_MESSAGES,
164
+ },
165
+ };
166
+
167
+ export const Input: Story = {
168
+ args: {
169
+ streaming: true,
170
+ },
171
+ };
172
+
173
+ export const Incremental: Story = {
174
+ render: () => {
175
+ const [messages, setMessages] = useState<Message[]>([]);
176
+ useEffect(() => {
177
+ let i = 0;
178
+ const interval = setInterval(() => {
179
+ setMessages((messages) => [...messages, TEST_MESSAGES[i++]]);
180
+ if (i >= TEST_MESSAGES.length) {
181
+ clearInterval(interval);
182
+ }
183
+ }, 2_000);
184
+
185
+ return () => clearInterval(interval);
186
+ }, []);
187
+
188
+ return <Render messages={messages} collapse />;
189
+ },
190
+ };