@dxos/plugin-assistant 0.8.3-main.672df60 → 0.8.3-staging.0fa589b

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 (220) hide show
  1. package/dist/lib/browser/{AssistantDialog-UAZSN6GT.mjs → AssistantDialog-MQOOR364.mjs} +5 -4
  2. package/dist/lib/browser/BlueprintContainer-AT5Y7EXG.mjs +321 -0
  3. package/dist/lib/browser/BlueprintContainer-AT5Y7EXG.mjs.map +7 -0
  4. package/dist/lib/browser/{ChatContainer-UTN3AO5U.mjs → ChatContainer-C2NEAS3A.mjs} +5 -4
  5. package/dist/lib/browser/{TemplateContainer-AKUYL4AV.mjs → TemplateContainer-QQHVOTSI.mjs} +2 -2
  6. package/dist/lib/browser/TemplateContainer-QQHVOTSI.mjs.map +7 -0
  7. package/dist/lib/browser/{ai-client-COXVUC6V.mjs → ai-client-MK2ZZII2.mjs} +12 -8
  8. package/dist/lib/browser/ai-client-MK2ZZII2.mjs.map +7 -0
  9. package/dist/lib/browser/{app-graph-builder-56OZ5RW4.mjs → app-graph-builder-E4H5DCOJ.mjs} +52 -33
  10. package/dist/lib/browser/app-graph-builder-E4H5DCOJ.mjs.map +7 -0
  11. package/dist/lib/browser/{chunk-NBSPGIHL.mjs → chunk-AAOKC2JN.mjs} +17 -15
  12. package/dist/lib/browser/chunk-AAOKC2JN.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-6SD7S7W5.mjs → chunk-BI6AHRNJ.mjs} +8 -8
  14. package/dist/lib/browser/{chunk-6SD7S7W5.mjs.map → chunk-BI6AHRNJ.mjs.map} +3 -3
  15. package/dist/lib/browser/{chunk-Q6XE3O3E.mjs → chunk-JO4W3MF7.mjs} +44 -73
  16. package/dist/lib/browser/chunk-JO4W3MF7.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-MEGMOFJB.mjs +16 -0
  18. package/dist/lib/browser/chunk-MEGMOFJB.mjs.map +7 -0
  19. package/dist/lib/browser/{chunk-3F44MBHU.mjs → chunk-UE3IZ4PN.mjs} +1 -1
  20. package/dist/lib/browser/{chunk-3F44MBHU.mjs.map → chunk-UE3IZ4PN.mjs.map} +2 -2
  21. package/dist/lib/browser/index.mjs +84 -30
  22. package/dist/lib/browser/index.mjs.map +4 -4
  23. package/dist/lib/browser/{intent-resolver-GWELYIX2.mjs → intent-resolver-3UICTGPM.mjs} +12 -8
  24. package/dist/lib/browser/intent-resolver-3UICTGPM.mjs.map +7 -0
  25. package/dist/lib/browser/meta.json +1 -1
  26. package/dist/lib/browser/{react-surface-DGS34EON.mjs → react-surface-LXCNUSZN.mjs} +29 -14
  27. package/dist/lib/browser/react-surface-LXCNUSZN.mjs.map +7 -0
  28. package/dist/lib/browser/{settings-BTFB7IQ6.mjs → settings-XRHXVWGB.mjs} +4 -4
  29. package/dist/lib/browser/settings-XRHXVWGB.mjs.map +7 -0
  30. package/dist/lib/browser/types/index.mjs +1 -1
  31. package/dist/lib/node/{AssistantDialog-RTB5Q7FP.cjs → AssistantDialog-AN4Z6YUV.cjs} +9 -8
  32. package/dist/lib/node/{AssistantDialog-RTB5Q7FP.cjs.map → AssistantDialog-AN4Z6YUV.cjs.map} +1 -1
  33. package/dist/lib/node/BlueprintContainer-NOWLDYCZ.cjs +344 -0
  34. package/dist/lib/node/BlueprintContainer-NOWLDYCZ.cjs.map +7 -0
  35. package/dist/lib/node/{ChatContainer-P3JL4VZ7.cjs → ChatContainer-VKYBQHUB.cjs} +9 -8
  36. package/dist/lib/node/{ChatContainer-P3JL4VZ7.cjs.map → ChatContainer-VKYBQHUB.cjs.map} +1 -1
  37. package/dist/lib/node/{TemplateContainer-CTG2MB4W.cjs → TemplateContainer-JZF2DCCG.cjs} +5 -5
  38. package/dist/lib/node/TemplateContainer-JZF2DCCG.cjs.map +7 -0
  39. package/dist/lib/node/{ai-client-R2CGEYZW.cjs → ai-client-7HNSMUMT.cjs} +14 -10
  40. package/dist/lib/node/ai-client-7HNSMUMT.cjs.map +7 -0
  41. package/dist/lib/node/{app-graph-builder-QLF353LH.cjs → app-graph-builder-PPR5B5KU.cjs} +63 -44
  42. package/dist/lib/node/app-graph-builder-PPR5B5KU.cjs.map +7 -0
  43. package/dist/lib/node/chunk-FUAGEO7Q.cjs +52 -0
  44. package/dist/lib/node/chunk-FUAGEO7Q.cjs.map +7 -0
  45. package/dist/lib/node/{chunk-BWL5A3O5.cjs → chunk-IKZBMHSW.cjs} +14 -14
  46. package/dist/lib/node/{chunk-BWL5A3O5.cjs.map → chunk-IKZBMHSW.cjs.map} +3 -3
  47. package/dist/lib/node/{chunk-UNVDZOLA.cjs → chunk-LMDJEGZ2.cjs} +28 -26
  48. package/dist/lib/node/chunk-LMDJEGZ2.cjs.map +7 -0
  49. package/dist/lib/node/{chunk-PG7YNQ4R.cjs → chunk-NIDICM57.cjs} +66 -96
  50. package/dist/lib/node/chunk-NIDICM57.cjs.map +7 -0
  51. package/dist/lib/node/{chunk-TS3H5OSX.cjs → chunk-QGPWY6GW.cjs} +4 -4
  52. package/dist/lib/node/{chunk-TS3H5OSX.cjs.map → chunk-QGPWY6GW.cjs.map} +2 -2
  53. package/dist/lib/node/index.cjs +129 -73
  54. package/dist/lib/node/index.cjs.map +4 -4
  55. package/dist/lib/node/{intent-resolver-U7663JU7.cjs → intent-resolver-QSWGTKON.cjs} +17 -13
  56. package/dist/lib/node/intent-resolver-QSWGTKON.cjs.map +7 -0
  57. package/dist/lib/node/meta.json +1 -1
  58. package/dist/lib/node/{react-surface-QXZTILW6.cjs → react-surface-D3NBYRZ6.cjs} +41 -26
  59. package/dist/lib/node/react-surface-D3NBYRZ6.cjs.map +7 -0
  60. package/dist/lib/node/{settings-LBJMT6YB.cjs → settings-2JXLKYGE.cjs} +7 -7
  61. package/dist/lib/node/settings-2JXLKYGE.cjs.map +7 -0
  62. package/dist/lib/node/types/index.cjs +14 -14
  63. package/dist/lib/node/types/index.cjs.map +1 -1
  64. package/dist/lib/node-esm/{AssistantDialog-DONAO6SA.mjs → AssistantDialog-6WEMLUPU.mjs} +5 -4
  65. package/dist/lib/{browser/AssistantDialog-UAZSN6GT.mjs.map → node-esm/AssistantDialog-6WEMLUPU.mjs.map} +1 -1
  66. package/dist/lib/node-esm/BlueprintContainer-STOJAVML.mjs +322 -0
  67. package/dist/lib/node-esm/BlueprintContainer-STOJAVML.mjs.map +7 -0
  68. package/dist/lib/node-esm/{ChatContainer-FVIGCDIG.mjs → ChatContainer-3MVBTUJN.mjs} +5 -4
  69. package/dist/lib/{browser/ChatContainer-UTN3AO5U.mjs.map → node-esm/ChatContainer-3MVBTUJN.mjs.map} +1 -1
  70. package/dist/lib/node-esm/{TemplateContainer-IVDQ4XQG.mjs → TemplateContainer-SOEWY2ZN.mjs} +2 -2
  71. package/dist/lib/node-esm/TemplateContainer-SOEWY2ZN.mjs.map +7 -0
  72. package/dist/lib/node-esm/{ai-client-I5LXHMOZ.mjs → ai-client-XGZBJ6BE.mjs} +12 -8
  73. package/dist/lib/node-esm/ai-client-XGZBJ6BE.mjs.map +7 -0
  74. package/dist/lib/node-esm/{app-graph-builder-5YX5TKKT.mjs → app-graph-builder-3SY5MBIK.mjs} +52 -33
  75. package/dist/lib/node-esm/app-graph-builder-3SY5MBIK.mjs.map +7 -0
  76. package/dist/lib/node-esm/chunk-34EX6E5Q.mjs +18 -0
  77. package/dist/lib/node-esm/chunk-34EX6E5Q.mjs.map +7 -0
  78. package/dist/lib/node-esm/{chunk-HLPGKJ7N.mjs → chunk-3UEZLJ2V.mjs} +1 -1
  79. package/dist/lib/node-esm/{chunk-HLPGKJ7N.mjs.map → chunk-3UEZLJ2V.mjs.map} +2 -2
  80. package/dist/lib/node-esm/{chunk-TQYSF2GS.mjs → chunk-J6UXXZGJ.mjs} +17 -15
  81. package/dist/lib/node-esm/chunk-J6UXXZGJ.mjs.map +7 -0
  82. package/dist/lib/node-esm/{chunk-MNH6E6EB.mjs → chunk-OD574YIU.mjs} +44 -73
  83. package/dist/lib/node-esm/chunk-OD574YIU.mjs.map +7 -0
  84. package/dist/lib/node-esm/{chunk-GJE4WCUJ.mjs → chunk-UCOFKNKN.mjs} +8 -8
  85. package/dist/lib/node-esm/{chunk-GJE4WCUJ.mjs.map → chunk-UCOFKNKN.mjs.map} +3 -3
  86. package/dist/lib/node-esm/index.mjs +84 -30
  87. package/dist/lib/node-esm/index.mjs.map +4 -4
  88. package/dist/lib/node-esm/{intent-resolver-N5TM3RTL.mjs → intent-resolver-E6MXTYAU.mjs} +12 -8
  89. package/dist/lib/node-esm/intent-resolver-E6MXTYAU.mjs.map +7 -0
  90. package/dist/lib/node-esm/meta.json +1 -1
  91. package/dist/lib/node-esm/{react-surface-FTKGQQD2.mjs → react-surface-7HA5EDWY.mjs} +29 -14
  92. package/dist/lib/node-esm/react-surface-7HA5EDWY.mjs.map +7 -0
  93. package/dist/lib/node-esm/{settings-TGCCAH5D.mjs → settings-5IAY6BT4.mjs} +4 -4
  94. package/dist/lib/node-esm/settings-5IAY6BT4.mjs.map +7 -0
  95. package/dist/lib/node-esm/types/index.mjs +1 -1
  96. package/dist/types/src/AssistantPlugin.d.ts.map +1 -1
  97. package/dist/types/src/capabilities/ai-client.d.ts +2 -2
  98. package/dist/types/src/capabilities/ai-client.d.ts.map +1 -1
  99. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  100. package/dist/types/src/capabilities/capabilities.d.ts +2 -2
  101. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  102. package/dist/types/src/capabilities/index.d.ts +1 -1
  103. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  104. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  105. package/dist/types/src/components/AmbientDialog/AmbientDialog.stories.d.ts.map +1 -1
  106. package/dist/types/src/components/BlueprintContainer.d.ts +9 -0
  107. package/dist/types/src/components/BlueprintContainer.d.ts.map +1 -0
  108. package/dist/types/src/components/BlueprintEditor/BlueprintEditor.d.ts +8 -3
  109. package/dist/types/src/components/BlueprintEditor/BlueprintEditor.d.ts.map +1 -1
  110. package/dist/types/src/components/BlueprintEditor/index.d.ts +1 -2
  111. package/dist/types/src/components/BlueprintEditor/index.d.ts.map +1 -1
  112. package/dist/types/src/components/TemplateContainer.d.ts +2 -2
  113. package/dist/types/src/components/TemplateContainer.d.ts.map +1 -1
  114. package/dist/types/src/components/Thread/Thread.stories.d.ts.map +1 -1
  115. package/dist/types/src/components/Thread/ThreadContainer.d.ts.map +1 -1
  116. package/dist/types/src/components/Thread/ThreadContainer.stories.d.ts +1 -1
  117. package/dist/types/src/components/Thread/ThreadContainer.stories.d.ts.map +1 -1
  118. package/dist/types/src/components/index.d.ts +4 -3
  119. package/dist/types/src/components/index.d.ts.map +1 -1
  120. package/dist/types/src/events.d.ts +4 -0
  121. package/dist/types/src/events.d.ts.map +1 -0
  122. package/dist/types/src/hooks/processor.d.ts +3 -3
  123. package/dist/types/src/hooks/useContextProvider.d.ts.map +1 -1
  124. package/dist/types/src/hooks/useMessageQueue.d.ts +8 -8
  125. package/dist/types/src/hooks/useMessageQueue.d.ts.map +1 -1
  126. package/dist/types/src/index.d.ts +2 -0
  127. package/dist/types/src/index.d.ts.map +1 -1
  128. package/dist/types/src/parser/filter-generator.d.ts +1 -1
  129. package/dist/types/src/parser/filter-generator.d.ts.map +1 -1
  130. package/dist/types/src/queue-logger.d.ts +11 -0
  131. package/dist/types/src/queue-logger.d.ts.map +1 -0
  132. package/dist/types/src/stories/Query.stories.d.ts.map +1 -1
  133. package/dist/types/src/stories/Research.stories.d.ts +1 -1
  134. package/dist/types/src/stories/Research.stories.d.ts.map +1 -1
  135. package/dist/types/src/testing/test-blueprint.d.ts +4 -10
  136. package/dist/types/src/testing/test-blueprint.d.ts.map +1 -1
  137. package/dist/types/src/tools/openapi.d.ts.map +1 -1
  138. package/dist/types/src/translations.d.ts +15 -0
  139. package/dist/types/src/translations.d.ts.map +1 -1
  140. package/dist/types/src/types/chat.d.ts +13 -10
  141. package/dist/types/src/types/chat.d.ts.map +1 -1
  142. package/dist/types/src/types/service.d.ts +88 -9
  143. package/dist/types/src/types/service.d.ts.map +1 -1
  144. package/dist/types/src/types/template.d.ts +3 -23
  145. package/dist/types/src/types/template.d.ts.map +1 -1
  146. package/dist/types/src/types/types.d.ts +6 -6
  147. package/package.json +71 -68
  148. package/src/AssistantPlugin.tsx +30 -7
  149. package/src/capabilities/ai-client.ts +11 -6
  150. package/src/capabilities/app-graph-builder.ts +69 -54
  151. package/src/capabilities/capabilities.ts +3 -2
  152. package/src/capabilities/intent-resolver.ts +12 -5
  153. package/src/capabilities/react-surface.tsx +23 -19
  154. package/src/capabilities/settings.ts +2 -2
  155. package/src/components/AmbientDialog/AmbientDialog.stories.tsx +1 -0
  156. package/src/components/BlueprintContainer.tsx +148 -0
  157. package/src/components/BlueprintEditor/BlueprintEditor.stories.tsx +2 -2
  158. package/src/components/BlueprintEditor/BlueprintEditor.tsx +31 -21
  159. package/src/components/BlueprintEditor/index.ts +1 -3
  160. package/src/components/PromptSettings.tsx +1 -1
  161. package/src/components/TemplateContainer.tsx +5 -2
  162. package/src/components/TemplateEditor/TemplateEditor.stories.tsx +2 -2
  163. package/src/components/TemplateEditor/TemplateForm.stories.tsx +2 -2
  164. package/src/components/Thread/Thread.stories.tsx +19 -27
  165. package/src/components/Thread/ThreadContainer.stories.tsx +11 -12
  166. package/src/components/Thread/ThreadContainer.tsx +3 -4
  167. package/src/components/Thread/reducer.ts +3 -3
  168. package/src/components/index.ts +1 -1
  169. package/src/events.ts +11 -0
  170. package/src/hooks/processor.ts +4 -4
  171. package/src/hooks/useContextProvider.ts +13 -16
  172. package/src/hooks/useMessageQueue.ts +3 -2
  173. package/src/index.ts +2 -0
  174. package/src/parser/filter-generator.test.ts +1 -1
  175. package/src/parser/filter-generator.ts +1 -1
  176. package/src/queue-logger.ts +125 -0
  177. package/src/stories/Query.stories.tsx +28 -29
  178. package/src/stories/Research.stories.tsx +32 -46
  179. package/src/stories/test-data.ts +12 -12
  180. package/src/testing/test-blueprint.ts +14 -6
  181. package/src/testing/test-services.ts +6 -6
  182. package/src/tools/function.ts +2 -2
  183. package/src/tools/openapi.test.ts +7 -13
  184. package/src/tools/openapi.ts +5 -5
  185. package/src/translations.ts +19 -5
  186. package/src/types/chat.ts +3 -4
  187. package/src/types/service.ts +8 -4
  188. package/src/types/template.ts +11 -3
  189. package/dist/lib/browser/BlueprintEditor-DGV4KJDM.mjs +0 -45
  190. package/dist/lib/browser/BlueprintEditor-DGV4KJDM.mjs.map +0 -7
  191. package/dist/lib/browser/TemplateContainer-AKUYL4AV.mjs.map +0 -7
  192. package/dist/lib/browser/ai-client-COXVUC6V.mjs.map +0 -7
  193. package/dist/lib/browser/app-graph-builder-56OZ5RW4.mjs.map +0 -7
  194. package/dist/lib/browser/chunk-NBSPGIHL.mjs.map +0 -7
  195. package/dist/lib/browser/chunk-Q6XE3O3E.mjs.map +0 -7
  196. package/dist/lib/browser/intent-resolver-GWELYIX2.mjs.map +0 -7
  197. package/dist/lib/browser/react-surface-DGS34EON.mjs.map +0 -7
  198. package/dist/lib/browser/settings-BTFB7IQ6.mjs.map +0 -7
  199. package/dist/lib/node/BlueprintEditor-43VM3XPO.cjs +0 -72
  200. package/dist/lib/node/BlueprintEditor-43VM3XPO.cjs.map +0 -7
  201. package/dist/lib/node/TemplateContainer-CTG2MB4W.cjs.map +0 -7
  202. package/dist/lib/node/ai-client-R2CGEYZW.cjs.map +0 -7
  203. package/dist/lib/node/app-graph-builder-QLF353LH.cjs.map +0 -7
  204. package/dist/lib/node/chunk-PG7YNQ4R.cjs.map +0 -7
  205. package/dist/lib/node/chunk-UNVDZOLA.cjs.map +0 -7
  206. package/dist/lib/node/intent-resolver-U7663JU7.cjs.map +0 -7
  207. package/dist/lib/node/react-surface-QXZTILW6.cjs.map +0 -7
  208. package/dist/lib/node/settings-LBJMT6YB.cjs.map +0 -7
  209. package/dist/lib/node-esm/BlueprintEditor-CTARB2FO.mjs +0 -47
  210. package/dist/lib/node-esm/BlueprintEditor-CTARB2FO.mjs.map +0 -7
  211. package/dist/lib/node-esm/TemplateContainer-IVDQ4XQG.mjs.map +0 -7
  212. package/dist/lib/node-esm/ai-client-I5LXHMOZ.mjs.map +0 -7
  213. package/dist/lib/node-esm/app-graph-builder-5YX5TKKT.mjs.map +0 -7
  214. package/dist/lib/node-esm/chunk-MNH6E6EB.mjs.map +0 -7
  215. package/dist/lib/node-esm/chunk-TQYSF2GS.mjs.map +0 -7
  216. package/dist/lib/node-esm/intent-resolver-N5TM3RTL.mjs.map +0 -7
  217. package/dist/lib/node-esm/react-surface-FTKGQQD2.mjs.map +0 -7
  218. package/dist/lib/node-esm/settings-TGCCAH5D.mjs.map +0 -7
  219. /package/dist/lib/{node-esm/AssistantDialog-DONAO6SA.mjs.map → browser/AssistantDialog-MQOOR364.mjs.map} +0 -0
  220. /package/dist/lib/{node-esm/ChatContainer-FVIGCDIG.mjs.map → browser/ChatContainer-C2NEAS3A.mjs.map} +0 -0
@@ -13,22 +13,22 @@ import {
13
13
  type PromiseIntentDispatcher,
14
14
  type PluginContext,
15
15
  } from '@dxos/app-framework';
16
- import { isInstanceOf } from '@dxos/echo-schema';
16
+ import { Blueprint } from '@dxos/assistant';
17
+ import { Obj } from '@dxos/echo';
17
18
  import { invariant } from '@dxos/invariant';
18
19
  import { ClientCapabilities } from '@dxos/plugin-client';
19
20
  import { PLANK_COMPANION_TYPE, ATTENDABLE_PATH_SEPARATOR } from '@dxos/plugin-deck/types';
20
21
  import { createExtension, ROOT_ID } from '@dxos/plugin-graph';
21
- import { rxFromQuery } from '@dxos/plugin-space';
22
+ import { getActiveSpace, rxFromQuery } from '@dxos/plugin-space';
22
23
  import { SPACE_TYPE, SpaceAction } from '@dxos/plugin-space/types';
23
24
  import {
24
25
  type Space,
25
26
  Filter,
27
+ Query,
28
+ type QueryResult,
26
29
  fullyQualifiedId,
27
30
  getSpace,
28
31
  isSpace,
29
- Query,
30
- type QueryResult,
31
- isEchoObject,
32
32
  } from '@dxos/react-client/echo';
33
33
 
34
34
  import { ASSISTANT_DIALOG, ASSISTANT_PLUGIN } from '../meta';
@@ -49,25 +49,9 @@ export default (context: PluginContext) =>
49
49
  data: async () => {
50
50
  const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
51
51
  const client = context.getCapability(ClientCapabilities.Client);
52
- const layout = context.getCapability(Capabilities.Layout);
53
- const { graph } = context.getCapability(Capabilities.AppGraph);
54
-
55
- // TODO(burdon): Get space from workspace.
56
- // TODO(burdon): If need to create chat, then add to dispatch stack below.
57
- let chat: AIChatType | undefined;
58
- if (layout.active.length > 0) {
59
- const node = graph.getNode(layout.active[0]).pipe(Option.getOrNull);
60
- if (node) {
61
- const space = getSpace(node.data);
62
- if (space) {
63
- chat = await getOrCreateChat(dispatch, space);
64
- }
65
- }
66
- } else {
67
- const space = client.spaces.default;
68
- chat = await getOrCreateChat(dispatch, space);
69
- }
70
52
 
53
+ const space = getActiveSpace(context) ?? client.spaces.default;
54
+ const chat = await getOrCreateChat(dispatch, space);
71
55
  if (!chat) {
72
56
  return;
73
57
  }
@@ -107,38 +91,66 @@ export default (context: PluginContext) =>
107
91
  id: `${ASSISTANT_PLUGIN}/object-chat-companion`,
108
92
  connector: (node) => {
109
93
  let query: QueryResult<AIChatType> | undefined;
110
- return Rx.make((get) =>
94
+ return Rx.make((get) => {
95
+ const nodeOption = get(node);
96
+ if (Option.isNone(nodeOption)) {
97
+ return [];
98
+ }
99
+
100
+ const object = nodeOption.value.data;
101
+ if (!Obj.isObject(object)) {
102
+ return [];
103
+ }
104
+
105
+ const space = getSpace(object);
106
+ if (!space) {
107
+ return [];
108
+ }
109
+
110
+ if (!query) {
111
+ query = space.db.query(Query.select(Filter.ids(object.id)).targetOf(CompanionTo).source());
112
+ }
113
+
114
+ const chat = get(rxFromQuery(query))[0];
115
+ return [
116
+ {
117
+ id: [fullyQualifiedId(object), 'assistant-chat'].join(ATTENDABLE_PATH_SEPARATOR),
118
+ type: PLANK_COMPANION_TYPE,
119
+ data: chat ?? 'assistant-chat',
120
+ properties: {
121
+ label: ['assistant chat label', { ns: ASSISTANT_PLUGIN }],
122
+ icon: 'ph--sparkle--regular',
123
+ position: 'hoist',
124
+ disposition: 'hidden',
125
+ },
126
+ },
127
+ ];
128
+ });
129
+ },
130
+ }),
131
+
132
+ createExtension({
133
+ id: `${ASSISTANT_PLUGIN}/blueprint-logs`,
134
+ connector: (node) =>
135
+ Rx.make((get) =>
111
136
  pipe(
112
137
  get(node),
113
- Option.flatMap((node) => (isEchoObject(node.data) ? Option.some(node.data) : Option.none())),
114
- Option.flatMap((object) => {
115
- const space = getSpace(object);
116
- return space ? Option.some({ space, object }) : Option.none();
117
- }),
118
- Option.map(({ space, object }) => {
119
- if (!query) {
120
- query = space.db.query(Query.select(Filter.ids(object.id)).targetOf(CompanionTo).source());
121
- }
122
-
123
- const chat = get(rxFromQuery(query))[0];
124
- return [
125
- {
126
- id: [fullyQualifiedId(object), 'assistant-chat'].join(ATTENDABLE_PATH_SEPARATOR),
127
- type: PLANK_COMPANION_TYPE,
128
- data: chat ?? 'assistant-chat',
129
- properties: {
130
- label: ['assistant chat label', { ns: ASSISTANT_PLUGIN }],
131
- icon: 'ph--sparkle--regular',
132
- position: 'hoist',
133
- disposition: 'hidden',
134
- },
138
+ Option.flatMap((node) => (Obj.instanceOf(Blueprint, node.data) ? Option.some(node) : Option.none())),
139
+ Option.map((node) => [
140
+ {
141
+ id: [node.id, 'logs'].join(ATTENDABLE_PATH_SEPARATOR),
142
+ type: PLANK_COMPANION_TYPE,
143
+ data: 'logs',
144
+ properties: {
145
+ label: ['blueprint logs label', { ns: ASSISTANT_PLUGIN }],
146
+ icon: 'ph--clock-countdown--regular',
147
+ disposition: 'hidden',
135
148
  },
136
- ];
137
- }),
149
+ },
150
+ ]),
138
151
  Option.getOrElse(() => []),
139
152
  ),
140
- );
141
- },
153
+ ),
142
154
  }),
143
155
 
144
156
  createExtension({
@@ -219,15 +231,18 @@ export default (context: PluginContext) =>
219
231
 
220
232
  // TODO(burdon): Factor out.
221
233
  const getOrCreateChat = async (dispatch: PromiseIntentDispatcher, space: Space): Promise<AIChatType | undefined> => {
222
- const { objects } = await space.db.query(Filter.type(AIChatType)).run();
234
+ // TODO(wittjosiah): This should be possible with a single query.
235
+ const { objects: allChats } = await space.db.query(Query.type(AIChatType)).run();
236
+ const { objects: relatedChats } = await space.db.query(Query.type(AIChatType).sourceOf(CompanionTo).source()).run();
237
+ const chats = allChats.filter((chat) => !relatedChats.includes(chat));
223
238
  // console.log('objects', JSON.stringify(objects, null, 2));
224
- if (objects.length > 0) {
239
+ if (chats.length > 0) {
225
240
  // TODO(burdon): Is this the most recent?
226
- return objects[objects.length - 1];
241
+ return chats[chats.length - 1];
227
242
  }
228
243
 
229
244
  const { data } = await dispatch(createIntent(AssistantAction.CreateChat, { space }));
230
- invariant(isInstanceOf(AIChatType, data?.object));
245
+ invariant(Obj.instanceOf(AIChatType, data?.object));
231
246
  await dispatch(createIntent(SpaceAction.AddObject, { target: space, object: data.object }));
232
247
  return data.object;
233
248
  };
@@ -4,11 +4,12 @@
4
4
 
5
5
  import { type ReadonlySignal } from '@preact/signals-core';
6
6
 
7
- import { type AIServiceClient } from '@dxos/ai';
7
+ import { type AiServiceClient } from '@dxos/ai';
8
8
  import { defineCapability } from '@dxos/app-framework';
9
9
 
10
10
  import { ASSISTANT_PLUGIN } from '../meta';
11
11
 
12
+ // TODO(burdon): Move to types to import from other plugins?
12
13
  export namespace AssistantCapabilities {
13
- export const AiClient = defineCapability<ReadonlySignal<AIServiceClient>>(`${ASSISTANT_PLUGIN}/capability/ai-client`);
14
+ export const AiClient = defineCapability<ReadonlySignal<AiServiceClient>>(`${ASSISTANT_PLUGIN}/capability/ai-client`);
14
15
  }
@@ -4,8 +4,7 @@
4
4
 
5
5
  import { Capabilities, contributes, createResolver } from '@dxos/app-framework';
6
6
  import { Blueprint } from '@dxos/assistant';
7
- import { createQueueDxn } from '@dxos/echo-schema';
8
- import { live, refFromDXN } from '@dxos/live-object';
7
+ import { Key, Obj, Ref } from '@dxos/echo';
9
8
 
10
9
  import { AssistantAction, AIChatType } from '../types';
11
10
 
@@ -16,9 +15,9 @@ export default () => [
16
15
  intent: AssistantAction.CreateChat,
17
16
  resolve: ({ space, name }) => ({
18
17
  data: {
19
- object: live(AIChatType, {
18
+ object: Obj.make(AIChatType, {
20
19
  name,
21
- queue: refFromDXN(createQueueDxn(space.id)),
20
+ queue: Ref.fromDXN(space.queues.create().dxn),
22
21
  }),
23
22
  },
24
23
  }),
@@ -30,7 +29,15 @@ export default () => [
30
29
  intent: AssistantAction.CreateBlueprint,
31
30
  resolve: ({ name }) => ({
32
31
  data: {
33
- object: live(Blueprint, { name, steps: [] }),
32
+ object: Obj.make(Blueprint, {
33
+ name,
34
+ steps: [
35
+ {
36
+ id: Key.ObjectId.random(),
37
+ instructions: 'You are a helpful assistant.',
38
+ },
39
+ ],
40
+ }),
34
41
  },
35
42
  }),
36
43
  }),
@@ -7,24 +7,17 @@ import React, { useEffect, useMemo } from 'react';
7
7
 
8
8
  import { Capabilities, contributes, createIntent, createSurface, useIntentDispatcher } from '@dxos/app-framework';
9
9
  import { Blueprint } from '@dxos/assistant';
10
- import { Obj } from '@dxos/echo';
11
- import { Filter, isInstanceOf, Query } from '@dxos/echo-schema';
10
+ import { InvocationTraceContainer } from '@dxos/devtools';
11
+ import { Filter, type Key, Obj, Query } from '@dxos/echo';
12
12
  import { SettingsStore } from '@dxos/local-storage';
13
13
  import { SpaceAction } from '@dxos/plugin-space/types';
14
- import {
15
- type AnyLiveObject,
16
- fullyQualifiedId,
17
- getSpace,
18
- getTypename,
19
- isEchoObject,
20
- type SpaceId,
21
- } from '@dxos/react-client/echo';
14
+ import { fullyQualifiedId, getSpace, getTypename } from '@dxos/react-client/echo';
22
15
  import { StackItem } from '@dxos/react-ui-stack';
23
16
 
24
17
  import {
25
18
  AssistantDialog,
26
19
  AssistantSettings,
27
- BlueprintEditor,
20
+ BlueprintContainer,
28
21
  ChatContainer,
29
22
  PromptSettings,
30
23
  TemplateContainer,
@@ -51,15 +44,16 @@ export default () =>
51
44
  createSurface({
52
45
  id: `${ASSISTANT_PLUGIN}/object-chat`,
53
46
  role: 'article',
54
- filter: (data): data is { companionTo: AnyLiveObject<any>; subject: AIChatType | 'assistant-chat' } =>
55
- isEchoObject(data.companionTo) && (isInstanceOf(AIChatType, data.subject) || data.subject === 'assistant-chat'),
47
+ filter: (data): data is { companionTo: Obj.Any; subject: AIChatType | 'assistant-chat' } =>
48
+ Obj.isObject(data.companionTo) &&
49
+ (Obj.instanceOf(AIChatType, data.subject) || data.subject === 'assistant-chat'),
56
50
  component: ({ data, role }) => {
57
51
  const { dispatch } = useIntentDispatcher();
58
52
  const associatedArtifact = useMemo(
59
53
  () => ({
60
54
  id: fullyQualifiedId(data.companionTo),
61
55
  typename: getTypename(data.companionTo) ?? 'unknown',
62
- spaceId: (getSpace(data.companionTo)?.id ?? 'unknown') as SpaceId,
56
+ spaceId: (getSpace(data.companionTo)?.id ?? 'unknown') as Key.SpaceId,
63
57
  }),
64
58
  [data.companionTo],
65
59
  );
@@ -106,11 +100,21 @@ export default () =>
106
100
  id: `${ASSISTANT_PLUGIN}/blueprint`,
107
101
  role: 'article',
108
102
  filter: (data): data is { subject: Blueprint } => Obj.instanceOf(Blueprint, data.subject),
109
- component: ({ data, role }) => (
110
- <StackItem.Content role={role}>
111
- <BlueprintEditor blueprint={data.subject} />
112
- </StackItem.Content>
113
- ),
103
+ component: ({ data, role }) => <BlueprintContainer role={role} blueprint={data.subject} />,
104
+ }),
105
+ createSurface({
106
+ id: `${ASSISTANT_PLUGIN}/companion/logs`,
107
+ role: 'article',
108
+ filter: (data): data is { companionTo: Blueprint } =>
109
+ Obj.instanceOf(Blueprint, data.companionTo) && data.subject === 'logs',
110
+ component: ({ data, role }) => {
111
+ const space = getSpace(data.companionTo);
112
+ return (
113
+ <StackItem.Content role={role}>
114
+ <InvocationTraceContainer space={space} target={data.companionTo} detailAxis='block' />
115
+ </StackItem.Content>
116
+ );
117
+ },
114
118
  }),
115
119
  createSurface({
116
120
  id: `${ASSISTANT_PLUGIN}/template`,
@@ -5,15 +5,15 @@
5
5
  import { Capabilities, contributes } from '@dxos/app-framework';
6
6
  import { live } from '@dxos/live-object';
7
7
 
8
- import { ASSISTANT_PLUGIN } from '../meta';
8
+ import { meta } from '../meta';
9
9
  import { type AssistantSettingsProps, AssistantSettingsSchema } from '../types';
10
10
 
11
11
  export default () => {
12
12
  const settings = live<AssistantSettingsProps>({});
13
13
 
14
14
  return contributes(Capabilities.Settings, {
15
+ prefix: meta.id,
15
16
  schema: AssistantSettingsSchema,
16
- prefix: ASSISTANT_PLUGIN,
17
17
  value: settings,
18
18
  });
19
19
  };
@@ -52,6 +52,7 @@ const meta: Meta<typeof AmbientDialog> = {
52
52
  );
53
53
  },
54
54
  decorators: [
55
+ // TODO(burdon): Replace with ClientPlugin.
55
56
  withClientProvider({
56
57
  config: new Config({
57
58
  runtime: {
@@ -0,0 +1,148 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type EditorView } from '@codemirror/view';
6
+ import JSON5 from 'json5';
7
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
8
+
9
+ import { ToolRegistry } from '@dxos/ai';
10
+ import { useCapability } from '@dxos/app-framework';
11
+ import {
12
+ type Blueprint,
13
+ type BlueprintDefinition,
14
+ BlueprintMachine,
15
+ createLocalSearchTool,
16
+ createExaTool,
17
+ createGraphWriterTool,
18
+ } from '@dxos/assistant';
19
+ import { getSpace } from '@dxos/client/echo';
20
+ import { DXN, Key } from '@dxos/echo';
21
+ import { Toolbar, useTranslation } from '@dxos/react-ui';
22
+ import { getSelectionSet, useSelectionManager } from '@dxos/react-ui-attention';
23
+ import { StackItem, type StackItemContentProps } from '@dxos/react-ui-stack';
24
+
25
+ import { BlueprintEditor } from './BlueprintEditor';
26
+ import { AssistantCapabilities } from '../capabilities';
27
+ import { meta } from '../meta';
28
+ import { QueueLogger } from '../queue-logger';
29
+
30
+ // TODO(burdon): Move to config.
31
+ export const EXA_API_KEY = '9c7e17ff-0c85-4cd5-827a-8b489f139e03';
32
+
33
+ // TODO(burdon): Validate.
34
+ const parseBlueprint = (text: string): BlueprintDefinition | undefined => {
35
+ try {
36
+ const json = JSON5.parse(text);
37
+ const { steps } = json;
38
+ return { steps };
39
+ } catch (error) {
40
+ // Ignore.
41
+ }
42
+ };
43
+
44
+ export const BlueprintContainer = ({
45
+ role,
46
+ blueprint,
47
+ }: Pick<StackItemContentProps, 'role'> & { blueprint: Blueprint }) => {
48
+ const { t } = useTranslation(meta.id);
49
+ const aiClient = useCapability(AssistantCapabilities.AiClient);
50
+ const selectionManager = useSelectionManager();
51
+ const [definition, setDefinition] = useState<BlueprintDefinition>();
52
+ useEffect(() => {
53
+ setDefinition({
54
+ steps: blueprint.steps.map(({ instructions, tools }) => ({ instructions, tools })),
55
+ });
56
+ }, [blueprint]);
57
+
58
+ const editorRef = useRef<EditorView | undefined>(undefined);
59
+
60
+ // TODO(burdon): Factor out.
61
+ const toolRegistry = useMemo(() => {
62
+ const space = getSpace(blueprint);
63
+ if (!space) {
64
+ return;
65
+ }
66
+
67
+ // TODO(burdon): How should the queue be created?
68
+ const queue = space.queues.create();
69
+
70
+ return new ToolRegistry([
71
+ createExaTool({ apiKey: EXA_API_KEY }),
72
+ createLocalSearchTool(space.db, queue),
73
+ createGraphWriterTool({
74
+ db: space.db,
75
+ queue,
76
+ schema: [], // TODO(burdon): Get schema from client/blueprint?
77
+ onDone: async (objects) => {
78
+ await queue.append(objects);
79
+ },
80
+ }),
81
+ ]);
82
+ }, [blueprint]);
83
+
84
+ const formatAndSave = useCallback((): BlueprintDefinition | undefined => {
85
+ if (!blueprint) {
86
+ return;
87
+ }
88
+
89
+ const text = editorRef.current?.state.doc.toString();
90
+ if (!text) {
91
+ return;
92
+ }
93
+
94
+ const definition = parseBlueprint(text);
95
+ if (!definition) {
96
+ return;
97
+ }
98
+
99
+ setDefinition(definition);
100
+ const formatted = JSON.stringify(definition, null, 2);
101
+ editorRef.current?.dispatch({
102
+ changes: { from: 0, to: text.length, insert: formatted },
103
+ });
104
+
105
+ blueprint.steps.length = 0;
106
+ for (const step of definition.steps) {
107
+ blueprint.steps.push({
108
+ id: Key.ObjectId.random(),
109
+ instructions: step.instructions,
110
+ tools: step.tools,
111
+ });
112
+ }
113
+
114
+ return blueprint;
115
+ }, [blueprint]);
116
+
117
+ // TODO(burdon): Save raw blueprint separately from parsed blueprint? (like Script).
118
+ const handleSave = useCallback(() => formatAndSave(), [formatAndSave]);
119
+
120
+ const handleRun = useCallback(async () => {
121
+ if (!aiClient?.value || !toolRegistry) {
122
+ return;
123
+ }
124
+
125
+ formatAndSave();
126
+
127
+ // Get input from selection.
128
+ const input = Array.from(getSelectionSet(selectionManager)).map((id) => DXN.fromLocalObjectId(id));
129
+ if (!input.length) {
130
+ return;
131
+ }
132
+
133
+ const machine = new BlueprintMachine(toolRegistry, blueprint).setLogger(new QueueLogger(blueprint));
134
+ await machine.runToCompletion({ aiClient: aiClient.value, input });
135
+ }, [aiClient.value, blueprint, formatAndSave, selectionManager, toolRegistry]);
136
+
137
+ return (
138
+ <StackItem.Content role={role} toolbar>
139
+ <Toolbar.Root>
140
+ <Toolbar.Button onClick={handleSave}>{t('button save')}</Toolbar.Button>
141
+ <Toolbar.Button onClick={handleRun}>{t('button run')}</Toolbar.Button>
142
+ </Toolbar.Root>
143
+ {definition && <BlueprintEditor ref={editorRef} blueprint={definition} />}
144
+ </StackItem.Content>
145
+ );
146
+ };
147
+
148
+ export default BlueprintContainer;
@@ -9,7 +9,7 @@ import { type StoryObj, type Meta } from '@storybook/react';
9
9
  import { withLayout, withTheme } from '@dxos/storybook-utils';
10
10
 
11
11
  import { BlueprintEditor } from './BlueprintEditor';
12
- import { RESEARCH_BLUEPRINT } from '../../testing';
12
+ import { RESEARCH_BLUEPRINT_DEFINITION } from '../../testing';
13
13
  import translations from '../../translations';
14
14
 
15
15
  const meta: Meta<typeof BlueprintEditor> = {
@@ -27,6 +27,6 @@ type Story = StoryObj<typeof BlueprintEditor>;
27
27
 
28
28
  export const Default: Story = {
29
29
  args: {
30
- blueprint: RESEARCH_BLUEPRINT,
30
+ blueprint: RESEARCH_BLUEPRINT_DEFINITION,
31
31
  },
32
32
  };
@@ -2,39 +2,49 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React from 'react';
5
+ import React, { forwardRef, useImperativeHandle } from 'react';
6
6
 
7
- import { Blueprint } from '@dxos/assistant';
8
- import { toJsonSchema } from '@dxos/echo-schema';
7
+ import { BlueprintDefinition } from '@dxos/assistant';
8
+ import { Type } from '@dxos/echo';
9
9
  import { useThemeContext, type ThemedClassName } from '@dxos/react-ui';
10
10
  import {
11
+ type EditorView,
11
12
  createBasicExtensions,
12
13
  createJsonExtensions,
13
14
  createThemeExtensions,
14
- editorMonospace,
15
15
  useTextEditor,
16
16
  } from '@dxos/react-ui-editor';
17
17
  import { mx } from '@dxos/react-ui-theme';
18
18
 
19
19
  export type BlueprintEditorProps = ThemedClassName<{
20
- blueprint: Blueprint;
20
+ blueprint: BlueprintDefinition;
21
21
  }>;
22
22
 
23
23
  // TODO(burdon): Factor out JsonEditor.
24
- // TODO(burdon): Make editable.
25
- export const BlueprintEditor = ({ classNames, blueprint }: BlueprintEditorProps) => {
26
- const { themeMode } = useThemeContext();
27
- const { parentRef } = useTextEditor({
28
- initialValue: JSON.stringify(blueprint, null, 2),
29
- extensions: [
30
- createBasicExtensions({ lineWrapping: false }),
31
- createThemeExtensions({ themeMode, syntaxHighlighting: true }),
32
- createJsonExtensions({ schema: toJsonSchema(Blueprint, { strict: true }) }),
33
- editorMonospace,
34
- ],
35
- });
24
+ export const BlueprintEditor = forwardRef<EditorView | undefined, BlueprintEditorProps>(
25
+ ({ classNames, blueprint }, forwardedRef) => {
26
+ const { themeMode } = useThemeContext();
27
+ const { parentRef, view } = useTextEditor({
28
+ initialValue: JSON.stringify(blueprint, null, 2),
29
+ extensions: [
30
+ createBasicExtensions({
31
+ lineNumbers: true,
32
+ lineWrapping: false,
33
+ monospace: true,
34
+ scrollPastEnd: true,
35
+ }),
36
+ createThemeExtensions({
37
+ themeMode,
38
+ syntaxHighlighting: true,
39
+ }),
40
+ createJsonExtensions({
41
+ schema: Type.toJsonSchema(BlueprintDefinition, { strict: true }),
42
+ }),
43
+ ],
44
+ });
36
45
 
37
- return (
38
- <div ref={parentRef} className={mx('flex w-full pli-2 overflow-x-scroll border-x border-separator', classNames)} />
39
- );
40
- };
46
+ useImperativeHandle(forwardedRef, () => view, [view]);
47
+
48
+ return <div ref={parentRef} className={mx('overflow-hidden', classNames)} />;
49
+ },
50
+ );
@@ -2,6 +2,4 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { BlueprintEditor } from './BlueprintEditor';
6
-
7
- export default BlueprintEditor;
5
+ export * from './BlueprintEditor';
@@ -48,7 +48,7 @@ export const PromptSettings = ({ template }: { template: TemplateType }) => {
48
48
  );
49
49
 
50
50
  return (
51
- <div className='p-2 flex flex-col gap-4'>
51
+ <div className='flex flex-col gap-4'>
52
52
  <h2>{t('prompt rules label')}</h2>
53
53
  <Toolbar.Root>
54
54
  <Select.Root value={template.kind.include} onValueChange={handleKindChange}>
@@ -4,12 +4,15 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { StackItem } from '@dxos/react-ui-stack';
7
+ import { StackItem, type StackItemContentProps } from '@dxos/react-ui-stack';
8
8
 
9
9
  import { TemplateEditor } from './TemplateEditor';
10
10
  import { type TemplateType } from '../types';
11
11
 
12
- export const TemplateContainer = ({ template, role }: { template: TemplateType; role: string }) => {
12
+ export const TemplateContainer = ({
13
+ role,
14
+ template,
15
+ }: Pick<StackItemContentProps, 'role'> & { template: TemplateType }) => {
13
16
  return (
14
17
  <StackItem.Content role={role} classNames='container-max-width'>
15
18
  <TemplateEditor template={template} />
@@ -8,7 +8,7 @@ import { type Meta } from '@storybook/react';
8
8
  import React, { useState } from 'react';
9
9
 
10
10
  import { createSystemPrompt } from '@dxos/artifact';
11
- import { live } from '@dxos/live-object';
11
+ import { Obj } from '@dxos/echo';
12
12
  import { useClient } from '@dxos/react-client';
13
13
  import { withClientProvider } from '@dxos/react-client/testing';
14
14
  import { withLayout, withTheme } from '@dxos/storybook-utils';
@@ -38,7 +38,7 @@ const DefaultStory = ({ text }: TemplateEditorProps & { text: string }) => {
38
38
  const client = useClient();
39
39
  const [template] = useState(() => {
40
40
  const space = client.spaces.default;
41
- return space.db.add(live(TemplateType, { source: text, kind: { include: 'manual' } }));
41
+ return space.db.add(Obj.make(TemplateType, { source: text, kind: { include: 'manual' } }));
42
42
  });
43
43
 
44
44
  return (
@@ -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 { live } from '@dxos/live-object';
10
+ import { Obj } from '@dxos/echo';
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';
@@ -30,7 +30,7 @@ const DefaultStory = () => {
30
30
  const client = useClient();
31
31
  const [template] = useState(() => {
32
32
  const space = client.spaces.default;
33
- return space.db.add(live(TemplateType, { source: TEMPLATE, kind: { include: 'manual' } }));
33
+ return space.db.add(Obj.make(TemplateType, { source: TEMPLATE, kind: { include: 'manual' } }));
34
34
  });
35
35
 
36
36
  return (