@dxos/react-ui-canvas-compute 0.8.3 → 0.8.4-main.1c7ec43d41

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 (128) hide show
  1. package/dist/lib/browser/index.mjs +1054 -1266
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +1054 -1266
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/components/DiagnosticOverlay.d.ts.map +1 -1
  8. package/dist/types/src/compute-layout.d.ts.map +1 -1
  9. package/dist/types/src/compute.stories.d.ts +33 -5
  10. package/dist/types/src/compute.stories.d.ts.map +1 -1
  11. package/dist/types/src/graph/controller.d.ts +45 -27
  12. package/dist/types/src/graph/controller.d.ts.map +1 -1
  13. package/dist/types/src/graph/node-defs.d.ts.map +1 -1
  14. package/dist/types/src/hooks/useComputeGraphController.d.ts +2 -2
  15. package/dist/types/src/hooks/useComputeGraphController.d.ts.map +1 -1
  16. package/dist/types/src/hooks/useComputeNodeState.d.ts +4 -4
  17. package/dist/types/src/hooks/useComputeNodeState.d.ts.map +1 -1
  18. package/dist/types/src/hooks/useGraphMonitor.d.ts +2 -2
  19. package/dist/types/src/hooks/useGraphMonitor.d.ts.map +1 -1
  20. package/dist/types/src/json.test.d.ts +1 -1
  21. package/dist/types/src/json.test.d.ts.map +1 -1
  22. package/dist/types/src/shapes/Append.d.ts +2 -2
  23. package/dist/types/src/shapes/Append.d.ts.map +1 -1
  24. package/dist/types/src/shapes/Array.d.ts +2 -2
  25. package/dist/types/src/shapes/Array.d.ts.map +1 -1
  26. package/dist/types/src/shapes/Audio.d.ts +2 -2
  27. package/dist/types/src/shapes/Audio.d.ts.map +1 -1
  28. package/dist/types/src/shapes/Beacon.d.ts +2 -2
  29. package/dist/types/src/shapes/Beacon.d.ts.map +1 -1
  30. package/dist/types/src/shapes/Boolean.d.ts +8 -8
  31. package/dist/types/src/shapes/Boolean.d.ts.map +1 -1
  32. package/dist/types/src/shapes/Chat.d.ts +2 -2
  33. package/dist/types/src/shapes/Chat.d.ts.map +1 -1
  34. package/dist/types/src/shapes/Constant.d.ts +2 -2
  35. package/dist/types/src/shapes/Constant.d.ts.map +1 -1
  36. package/dist/types/src/shapes/Database.d.ts +2 -2
  37. package/dist/types/src/shapes/Database.d.ts.map +1 -1
  38. package/dist/types/src/shapes/{Queue.d.ts → Feed.d.ts} +10 -10
  39. package/dist/types/src/shapes/Feed.d.ts.map +1 -0
  40. package/dist/types/src/shapes/Function.d.ts +2 -2
  41. package/dist/types/src/shapes/Function.d.ts.map +1 -1
  42. package/dist/types/src/shapes/Gpt.d.ts +2 -2
  43. package/dist/types/src/shapes/Gpt.d.ts.map +1 -1
  44. package/dist/types/src/shapes/GptRealtime.d.ts +2 -2
  45. package/dist/types/src/shapes/GptRealtime.d.ts.map +1 -1
  46. package/dist/types/src/shapes/Json.d.ts +3 -3
  47. package/dist/types/src/shapes/Json.d.ts.map +1 -1
  48. package/dist/types/src/shapes/Logic.d.ts +3 -3
  49. package/dist/types/src/shapes/Logic.d.ts.map +1 -1
  50. package/dist/types/src/shapes/RNG.d.ts +3 -3
  51. package/dist/types/src/shapes/RNG.d.ts.map +1 -1
  52. package/dist/types/src/shapes/Scope.d.ts +2 -2
  53. package/dist/types/src/shapes/Scope.d.ts.map +1 -1
  54. package/dist/types/src/shapes/Surface.d.ts +2 -2
  55. package/dist/types/src/shapes/Surface.d.ts.map +1 -1
  56. package/dist/types/src/shapes/Switch.d.ts +2 -2
  57. package/dist/types/src/shapes/Switch.d.ts.map +1 -1
  58. package/dist/types/src/shapes/Table.d.ts +2 -2
  59. package/dist/types/src/shapes/Table.d.ts.map +1 -1
  60. package/dist/types/src/shapes/Template.d.ts +3 -3
  61. package/dist/types/src/shapes/Template.d.ts.map +1 -1
  62. package/dist/types/src/shapes/Text.d.ts +2 -2
  63. package/dist/types/src/shapes/Text.d.ts.map +1 -1
  64. package/dist/types/src/shapes/TextToImage.d.ts +2 -2
  65. package/dist/types/src/shapes/TextToImage.d.ts.map +1 -1
  66. package/dist/types/src/shapes/Thread.d.ts +2 -2
  67. package/dist/types/src/shapes/Thread.d.ts.map +1 -1
  68. package/dist/types/src/shapes/Trigger.d.ts +8 -35
  69. package/dist/types/src/shapes/Trigger.d.ts.map +1 -1
  70. package/dist/types/src/shapes/common/Box.d.ts +4 -4
  71. package/dist/types/src/shapes/common/Box.d.ts.map +1 -1
  72. package/dist/types/src/shapes/common/FunctionBody.d.ts +3 -3
  73. package/dist/types/src/shapes/common/FunctionBody.d.ts.map +1 -1
  74. package/dist/types/src/shapes/common/TypeSelect.d.ts +1 -1
  75. package/dist/types/src/shapes/common/TypeSelect.d.ts.map +1 -1
  76. package/dist/types/src/shapes/defs.d.ts +3 -2
  77. package/dist/types/src/shapes/defs.d.ts.map +1 -1
  78. package/dist/types/src/shapes/index.d.ts +2 -2
  79. package/dist/types/src/shapes/index.d.ts.map +1 -1
  80. package/dist/types/src/testing/circuits.d.ts +18 -24
  81. package/dist/types/src/testing/circuits.d.ts.map +1 -1
  82. package/dist/types/tsconfig.tsbuildinfo +1 -1
  83. package/package.json +61 -54
  84. package/src/README.md +0 -3
  85. package/src/compute-layout.ts +1 -1
  86. package/src/compute.stories.tsx +104 -140
  87. package/src/graph/controller.ts +153 -81
  88. package/src/graph/node-defs.ts +34 -33
  89. package/src/hooks/useComputeGraphController.ts +2 -2
  90. package/src/hooks/useComputeNodeState.ts +9 -8
  91. package/src/hooks/useGraphMonitor.ts +11 -10
  92. package/src/json.test.ts +4 -4
  93. package/src/registry.ts +4 -4
  94. package/src/schema.test.ts +13 -13
  95. package/src/shapes/Append.tsx +3 -3
  96. package/src/shapes/Array.tsx +3 -3
  97. package/src/shapes/Audio.tsx +4 -4
  98. package/src/shapes/Beacon.tsx +4 -5
  99. package/src/shapes/Boolean.tsx +4 -4
  100. package/src/shapes/Chat.tsx +3 -3
  101. package/src/shapes/Constant.tsx +3 -3
  102. package/src/shapes/Database.tsx +2 -2
  103. package/src/shapes/{Queue.tsx → Feed.tsx} +29 -23
  104. package/src/shapes/Function.tsx +19 -16
  105. package/src/shapes/Gpt.tsx +12 -6
  106. package/src/shapes/GptRealtime.tsx +2 -2
  107. package/src/shapes/Json.tsx +12 -5
  108. package/src/shapes/Logic.tsx +3 -3
  109. package/src/shapes/RNG.tsx +9 -6
  110. package/src/shapes/Scope.tsx +4 -4
  111. package/src/shapes/Surface.tsx +15 -6
  112. package/src/shapes/Switch.tsx +3 -3
  113. package/src/shapes/Table.tsx +7 -6
  114. package/src/shapes/Template.tsx +5 -5
  115. package/src/shapes/Text.tsx +4 -4
  116. package/src/shapes/TextToImage.tsx +2 -2
  117. package/src/shapes/Thread.tsx +21 -14
  118. package/src/shapes/Trigger.tsx +47 -59
  119. package/src/shapes/common/Box.tsx +7 -10
  120. package/src/shapes/common/FunctionBody.tsx +5 -4
  121. package/src/shapes/common/TypeSelect.tsx +1 -1
  122. package/src/shapes/defs.ts +5 -4
  123. package/src/shapes/index.ts +2 -2
  124. package/src/testing/circuits.ts +10 -19
  125. package/dist/lib/node/index.cjs +0 -2896
  126. package/dist/lib/node/index.cjs.map +0 -7
  127. package/dist/lib/node/meta.json +0 -1
  128. package/dist/types/src/shapes/Queue.d.ts.map +0 -1
@@ -2,32 +2,45 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { type Context, Effect, Either, Exit, Scope } from 'effect';
6
-
7
- import { type ImageContentBlock } from '@dxos/ai';
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Either from 'effect/Either';
7
+ import * as Exit from 'effect/Exit';
8
+ import * as Layer from 'effect/Layer';
9
+ import type * as ManagedRuntime from 'effect/ManagedRuntime';
10
+ import * as Scope from 'effect/Scope';
11
+
12
+ import type { AiService } from '@dxos/ai';
8
13
  import { Event, synchronized } from '@dxos/async';
14
+ import { type Credential, type Operation, type OperationRegistry, Trace } from '@dxos/compute';
9
15
  import {
16
+ ComputeBeginEvent,
17
+ ComputeCustomEvent,
18
+ ComputeEndEvent,
19
+ ComputeInputEvent,
20
+ ComputeNodeContext,
21
+ ComputeOutputEvent,
10
22
  type ComputeEdge,
11
- type ComputeEvent,
12
23
  type ComputeGraphModel,
13
- type ComputeMeta,
14
24
  type ComputeNode,
15
- type EventLogger,
25
+ type ComputeNodeMeta,
16
26
  type GptInput,
17
27
  type GptOutput,
18
28
  type GraphDiagnostic,
19
29
  GraphExecutor,
20
- isNotExecuted,
21
30
  ValueBag,
31
+ isNotExecuted,
22
32
  } from '@dxos/conductor';
23
33
  import { Resource } from '@dxos/context';
24
- import type { ServiceContainer } from '@dxos/functions';
34
+ import type { Database, Feed } from '@dxos/echo';
35
+ import { unwrapExit } from '@dxos/effect';
36
+ import { type QueueService } from '@dxos/functions';
25
37
  import { log } from '@dxos/log';
26
38
  import { type CanvasGraphModel } from '@dxos/react-ui-canvas-editor';
39
+ import { type ContentBlock } from '@dxos/types';
27
40
 
28
- import { resolveComputeNode } from './node-defs';
29
41
  import { createComputeGraph } from '../hooks';
30
42
  import { type ComputeShape } from '../shapes';
43
+ import { resolveComputeNode } from './node-defs';
31
44
 
32
45
  // TODO(burdon): API package for conductor.
33
46
  export const InvalidStateError = Error;
@@ -43,7 +56,7 @@ export interface GptExecutor {
43
56
  invoke: FunctionCallback<GptInput, GptOutput>;
44
57
 
45
58
  // TODO(dmaretskyi): A hack to get image artifacts working. Rework into querying images from the ai-service store.
46
- imageCache: Map<string, ImageContentBlock>;
59
+ imageCache: Map<string, ContentBlock.Image>;
47
60
  }
48
61
 
49
62
  export type RuntimeValue =
@@ -68,6 +81,26 @@ type ComputeOutputEvent = {
68
81
  value: RuntimeValue;
69
82
  };
70
83
 
84
+ /**
85
+ * Event emitted by the compute graph during execution.
86
+ */
87
+ export type ComputeEvent =
88
+ | { type: 'begin-compute'; nodeId: string; inputs: ReadonlyArray<string> }
89
+ | { type: 'end-compute'; nodeId: string; outputs: ReadonlyArray<string> }
90
+ | { type: 'compute-input'; nodeId: string; property: string; value: any }
91
+ | { type: 'compute-output'; nodeId: string; property: string; value: any }
92
+ | { type: 'custom'; nodeId: string; event: any };
93
+
94
+ // TODO(dmaretskyi): Re-use function servies definition.
95
+ export type ComputeServices =
96
+ | AiService.AiService
97
+ | Database.Service
98
+ | Feed.FeedService
99
+ | QueueService
100
+ | Credential.CredentialsService
101
+ | Operation.Service
102
+ | OperationRegistry.Service;
103
+
71
104
  /**
72
105
  * Nodes that will automatically trigger the execution of the graph on startup.
73
106
  */
@@ -75,10 +108,10 @@ const AUTO_TRIGGER_NODES = ['chat', 'switch', 'constant'];
75
108
 
76
109
  export const createComputeGraphController = (
77
110
  graph: CanvasGraphModel<ComputeShape>,
78
- serviceContainer: ServiceContainer,
111
+ computeRuntime: ManagedRuntime.ManagedRuntime<ComputeServices, never>,
79
112
  ) => {
80
113
  const computeGraph = createComputeGraph(graph);
81
- const controller = new ComputeGraphController(serviceContainer, computeGraph);
114
+ const controller = new ComputeGraphController(computeRuntime, computeGraph);
82
115
  return { controller, graph };
83
116
  };
84
117
 
@@ -113,7 +146,7 @@ export class ComputeGraphController extends Resource {
113
146
  public readonly events = new Event<ComputeEvent>();
114
147
 
115
148
  constructor(
116
- private readonly _serviceContainer: ServiceContainer,
149
+ private readonly _computeRuntime: ManagedRuntime.ManagedRuntime<ComputeServices, never>,
117
150
  /** Persistent compute graph. */
118
151
  private readonly _graph: ComputeGraphModel,
119
152
  ) {
@@ -154,7 +187,14 @@ export class ComputeGraphController extends Resource {
154
187
  /**
155
188
  * Inputs and outputs for all nodes.
156
189
  */
157
- get state() {
190
+ get state(): Record<
191
+ string,
192
+ {
193
+ node: ComputeNode;
194
+ input: Record<string, RuntimeValue>;
195
+ output: Record<string, RuntimeValue>;
196
+ }
197
+ > {
158
198
  const ids = [...new Set([...Object.keys(this._runtimeStateInputs), ...Object.keys(this._runtimeStateOutputs)])];
159
199
  return Object.fromEntries(
160
200
  ids.map((id) => [
@@ -201,7 +241,7 @@ export class ComputeGraphController extends Resource {
201
241
  });
202
242
  }
203
243
 
204
- async getMeta(node: ComputeNode): Promise<ComputeMeta> {
244
+ async getMeta(node: ComputeNode): Promise<ComputeNodeMeta> {
205
245
  const { meta } = await resolveComputeNode(node);
206
246
  return meta;
207
247
  }
@@ -221,37 +261,42 @@ export class ComputeGraphController extends Resource {
221
261
  executor.setOutputs(nodeId, Effect.succeed(ValueBag.make(outputs)));
222
262
  }
223
263
 
224
- const serviceLayer = this._serviceContainer.createLayer();
225
- await Effect.runPromise(
226
- Effect.gen(this, function* () {
227
- const scope = yield* Scope.make();
228
-
229
- // TODO(dmaretskyi): Code duplication.
230
- const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(nodeId)));
231
- const computingOutputs = executable.exec != null;
232
- // TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
233
- const effect = (computingOutputs ? executor.computeOutputs(nodeId) : executor.computeInputs(nodeId)).pipe(
234
- Effect.withSpan('runGraph'),
235
- Scope.extend(scope),
236
-
237
- Effect.flatMap(computeValueBag),
238
- Effect.provide(serviceLayer),
239
- Effect.withSpan('test'),
240
- Effect.tap((values) => {
241
- for (const [key, value] of Object.entries(values)) {
242
- if (computingOutputs) {
243
- this._onOutputComputed(nodeId, key, value);
244
- } else {
245
- this._onInputComputed(nodeId, key, value);
264
+ unwrapExit(
265
+ await this._computeRuntime.runPromiseExit(
266
+ Effect.gen(this, function* () {
267
+ const scope = yield* Scope.make();
268
+
269
+ // TODO(dmaretskyi): Code duplication.
270
+ const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(nodeId)));
271
+ const computingOutputs = executable.exec != null;
272
+ // TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
273
+ const effect = (computingOutputs ? executor.computeOutputs(nodeId) : executor.computeInputs(nodeId)).pipe(
274
+ Effect.withSpan('runGraph'),
275
+ Scope.extend(scope),
276
+ Effect.provide(
277
+ Layer.mergeAll(
278
+ Layer.succeed(Trace.TraceService, this._createTraceWriter()),
279
+ ComputeNodeContext.layerNoop,
280
+ ),
281
+ ),
282
+ Effect.flatMap(computeValueBag),
283
+ Effect.withSpan('test'),
284
+ Effect.tap((values) => {
285
+ for (const [key, value] of Object.entries(values)) {
286
+ if (computingOutputs) {
287
+ this._onOutputComputed(nodeId, key, value);
288
+ } else {
289
+ this._onInputComputed(nodeId, key, value);
290
+ }
246
291
  }
247
- }
248
- }),
249
- );
292
+ }),
293
+ );
250
294
 
251
- yield* effect;
295
+ yield* effect;
252
296
 
253
- yield* Scope.close(scope, Exit.void);
254
- }),
297
+ yield* Scope.close(scope, Exit.void);
298
+ }),
299
+ ),
255
300
  );
256
301
 
257
302
  this.update.emit();
@@ -279,55 +324,65 @@ export class ComputeGraphController extends Resource {
279
324
  : this._graph.nodes.filter((node) => node.type != null && AUTO_TRIGGER_NODES.includes(node.type));
280
325
  const allAffectedNodes = [...new Set(triggerNodes.flatMap((node) => executor.getAllDependantNodes(node.id)))];
281
326
 
282
- await Effect.runPromise(
283
- Effect.gen(this, function* () {
284
- const scope = yield* Scope.make();
285
-
286
- // TODO(burdon): Return map?
287
- const tasks: Effect.Effect<unknown, any, never>[] = [];
288
- for (const node of allAffectedNodes) {
289
- // TODO(dmaretskyi): Code duplication.
290
- const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(node)));
291
- const computingOutputs = executable.exec != null;
292
-
293
- // TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
294
- const effect = (computingOutputs ? executor.computeOutputs(node) : executor.computeInputs(node)).pipe(
295
- Effect.withSpan('runGraph'),
296
- Scope.extend(scope),
297
- Effect.flatMap(computeValueBag),
298
- Effect.provide(this._serviceContainer.createLayer()),
299
- Effect.withSpan('test'),
300
- Effect.tap((values) => {
301
- for (const [key, value] of Object.entries(values)) {
302
- if (computingOutputs) {
303
- this._onOutputComputed(node, key, value);
304
- } else {
305
- this._onInputComputed(node, key, value);
327
+ unwrapExit(
328
+ await this._computeRuntime.runPromiseExit(
329
+ Effect.gen(this, function* () {
330
+ const scope = yield* Scope.make();
331
+
332
+ // TODO(burdon): Return map?
333
+ const tasks: Effect.Effect<unknown, any, ComputeServices>[] = [];
334
+ for (const node of allAffectedNodes) {
335
+ // TODO(dmaretskyi): Code duplication.
336
+ const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(node)));
337
+ const computingOutputs = executable.exec != null;
338
+
339
+ // TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
340
+ const effect = (computingOutputs ? executor.computeOutputs(node) : executor.computeInputs(node)).pipe(
341
+ Effect.withSpan('runGraph'),
342
+ Scope.extend(scope),
343
+ Effect.flatMap(computeValueBag),
344
+ Effect.provide(
345
+ Layer.mergeAll(
346
+ Layer.succeed(Trace.TraceService, this._createTraceWriter()),
347
+ ComputeNodeContext.layerNoop,
348
+ ),
349
+ ),
350
+
351
+ Effect.withSpan('test'),
352
+ Effect.tap((values) => {
353
+ for (const [key, value] of Object.entries(values)) {
354
+ if (computingOutputs) {
355
+ this._onOutputComputed(node, key, value);
356
+ } else {
357
+ this._onInputComputed(node, key, value);
358
+ }
306
359
  }
307
- }
308
- }),
309
- );
360
+ }),
361
+ );
310
362
 
311
- tasks.push(effect);
312
- }
363
+ tasks.push(effect);
364
+ }
313
365
 
314
- //
315
- yield* Effect.all(tasks);
366
+ //
367
+ yield* Effect.all(tasks);
316
368
 
317
- //
318
- yield* Scope.close(scope, Exit.void);
319
- }),
369
+ //
370
+ yield* Scope.close(scope, Exit.void);
371
+ }),
372
+ ),
320
373
  );
321
374
 
322
375
  this.update.emit();
323
376
  }
324
377
 
325
- private _createLogger(): Context.Tag.Service<EventLogger> {
378
+ private _createTraceWriter(): Trace.TraceWriter {
326
379
  return {
327
- log: (event) => {
328
- this._handleEvent(event);
380
+ write: (eventType, payload) => {
381
+ const event = traceEventToComputeEvent(eventType.key, payload);
382
+ if (event) {
383
+ this._handleEvent(event);
384
+ }
329
385
  },
330
- nodeId: undefined, // Not in a context of a specific node.
331
386
  };
332
387
  }
333
388
 
@@ -361,6 +416,23 @@ export class ComputeGraphController extends Resource {
361
416
  }
362
417
  }
363
418
 
419
+ const traceEventToComputeEvent = (key: string, payload: unknown): ComputeEvent | undefined => {
420
+ switch (key) {
421
+ case ComputeBeginEvent.key:
422
+ return { type: 'begin-compute', ...(payload as { nodeId: string; inputs: ReadonlyArray<string> }) };
423
+ case ComputeEndEvent.key:
424
+ return { type: 'end-compute', ...(payload as { nodeId: string; outputs: ReadonlyArray<string> }) };
425
+ case ComputeInputEvent.key:
426
+ return { type: 'compute-input', ...(payload as { nodeId: string; property: string; value: any }) };
427
+ case ComputeOutputEvent.key:
428
+ return { type: 'compute-output', ...(payload as { nodeId: string; property: string; value: any }) };
429
+ case ComputeCustomEvent.key:
430
+ return { type: 'custom', ...(payload as { nodeId: string; event: any }) };
431
+ default:
432
+ return undefined;
433
+ }
434
+ };
435
+
364
436
  /**
365
437
  * Waits for all effects in the bag to complete and returns the `RuntimeValue` for each property.
366
438
  */
@@ -3,16 +3,16 @@
3
3
  //
4
4
 
5
5
  import {
6
- NODE_INPUT,
7
- NODE_OUTPUT,
8
6
  type ComputeNode,
9
7
  type Executable,
8
+ NODE_INPUT,
9
+ NODE_OUTPUT,
10
10
  type NodeType,
11
- registry,
12
11
  getTemplateInputSchema,
12
+ registry,
13
13
  } from '@dxos/conductor';
14
14
  import { raise } from '@dxos/debug';
15
- import { ObjectId, toJsonSchema } from '@dxos/echo-schema';
15
+ import { JsonSchema, Obj } from '@dxos/echo';
16
16
  import { invariant } from '@dxos/invariant';
17
17
 
18
18
  import { type ComputeShape, type ConstantShape, type TemplateShape } from '../shapes';
@@ -39,44 +39,45 @@ const nodeFactory: Record<NodeType | 'trigger', (shape: ComputeShape) => Compute
39
39
  [NODE_OUTPUT]: () => createNode(NODE_OUTPUT),
40
40
 
41
41
  // Extensions.
42
- ['text-to-image' as const]: () => createNode('text-to-image'), // TODO(burdon): Rename ai-impage-tool
43
- ['and' as const]: () => createNode('and'),
44
- ['append' as const]: () => createNode('append'),
45
- ['audio' as const]: () => createNode('audio'),
46
- ['beacon' as const]: () => createNode('beacon'),
47
- ['chat' as const]: () => createNode('chat'),
48
- ['constant' as const]: (shape) =>
42
+ 'text-to-image': () => createNode('text-to-image'), // TODO(burdon): Rename ai-impage-tool
43
+ and: () => createNode('and'),
44
+ append: () => createNode('append'),
45
+ audio: () => createNode('audio'),
46
+ beacon: () => createNode('beacon'),
47
+ chat: () => createNode('chat'),
48
+ constant: (shape) =>
49
49
  createNode('constant', {
50
50
  value: (shape as ConstantShape).value,
51
51
  }),
52
- ['database' as const]: () => createNode('database'),
53
- ['gpt' as const]: () => createNode('gpt'),
54
- ['gpt-realtime' as const]: () => createNode('gpt-realtime'),
55
- ['if' as const]: () => createNode('if'),
56
- ['if-else' as const]: () => createNode('if-else'),
57
- ['function' as const]: () => createNode('function'),
58
- ['json' as const]: () => createNode('json'),
59
- ['json-transform' as const]: () => createNode('json-transform'),
60
- ['not' as const]: () => createNode('not'),
61
- ['or' as const]: () => createNode('or'),
62
- ['queue' as const]: () => createNode('queue'),
63
- ['rng' as const]: () => createNode('rng'),
64
- ['reducer' as const]: () => createNode('reducer'),
65
- ['scope' as const]: () => createNode('scope'),
66
- ['surface' as const]: () => createNode('surface'),
67
- ['switch' as const]: () => createNode('switch'),
68
- ['template' as const]: (shape) => {
52
+ 'make-queue': () => createNode('make-queue'),
53
+ database: () => createNode('database'),
54
+ gpt: () => createNode('gpt'),
55
+ 'gpt-realtime': () => createNode('gpt-realtime'),
56
+ if: () => createNode('if'),
57
+ 'if-else': () => createNode('if-else'),
58
+ function: () => createNode('function'),
59
+ json: () => createNode('json'),
60
+ 'json-transform': () => createNode('json-transform'),
61
+ not: () => createNode('not'),
62
+ or: () => createNode('or'),
63
+ queue: () => createNode('queue'),
64
+ rng: () => createNode('rng'),
65
+ reducer: () => createNode('reducer'),
66
+ scope: () => createNode('scope'),
67
+ surface: () => createNode('surface'),
68
+ switch: () => createNode('switch'),
69
+ template: (shape) => {
69
70
  const node = createNode('template', { valueType: (shape as TemplateShape).valueType, value: shape.text });
70
- node.inputSchema = toJsonSchema(getTemplateInputSchema(node));
71
+ node.inputSchema = JsonSchema.toJsonSchema(getTemplateInputSchema(node));
71
72
  return node;
72
73
  },
73
- ['text' as const]: () => createNode('text'),
74
- ['thread' as const]: () => createNode('thread'),
75
- ['trigger' as const]: () => createNode(NODE_INPUT),
74
+ text: () => createNode('text'),
75
+ thread: () => createNode('thread'),
76
+ trigger: () => createNode(NODE_INPUT),
76
77
  };
77
78
 
78
79
  const createNode = (type: string, props?: Partial<ComputeNode>): ComputeNode => ({
79
- id: ObjectId.random(),
80
+ id: Obj.ID.random(),
80
81
  type,
81
82
  ...props,
82
83
  });
@@ -5,7 +5,7 @@
5
5
  import { type RefObject, useEffect, useState } from 'react';
6
6
 
7
7
  import { type CleanupFn } from '@dxos/async';
8
- import { type EditorRootProps, type EditorController } from '@dxos/react-ui-canvas-editor';
8
+ import { type EditorController, type EditorRootProps } from '@dxos/react-ui-canvas-editor';
9
9
 
10
10
  import { type ComputeGraphController } from '../graph';
11
11
  import { type ComputeShape } from '../shapes';
@@ -21,7 +21,7 @@ const combine = (...cbs: CleanupFn[]) => {
21
21
 
22
22
  export type UseComputeGraphControllerOptions = Pick<EditorRootProps<ComputeShape>, 'graph'> & {
23
23
  controller: ComputeGraphController | null;
24
- editorRef: RefObject<EditorController>;
24
+ editorRef: RefObject<EditorController | null>;
25
25
  };
26
26
 
27
27
  export const useComputeGraphController = ({ controller, graph, editorRef }: UseComputeGraphControllerOptions) => {
@@ -2,25 +2,25 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
5
+ import * as Schema from 'effect/Schema';
6
6
  import { useCallback, useEffect, useState } from 'react';
7
7
 
8
- import type { ComputeNode, ComputeMeta, ComputeEvent } from '@dxos/conductor';
8
+ import type { ComputeNode, ComputeNodeMeta } from '@dxos/conductor';
9
9
  import { invariant } from '@dxos/invariant';
10
10
 
11
- import { useComputeContext } from './compute-context';
12
- import { type RuntimeValue } from '../graph';
11
+ import { type ComputeEvent, type RuntimeValue } from '../graph';
13
12
  import { type ComputeShape } from '../shapes';
13
+ import { useComputeContext } from './compute-context';
14
14
 
15
15
  export type ComputeNodeState = {
16
16
  node: ComputeNode;
17
- meta: ComputeMeta;
17
+ meta: ComputeNodeMeta;
18
18
  runtime: {
19
19
  inputs: Record<string, RuntimeValue>;
20
20
  outputs: Record<string, RuntimeValue>;
21
21
  setOutput: (property: string, value: any) => void;
22
22
  evalNode: () => void;
23
- subscribeToEventLog: (cb: (event: ComputeEvent) => void) => void;
23
+ subscribeToEventLog: (cb: (event: ComputeEvent) => void) => () => void;
24
24
  };
25
25
  };
26
26
 
@@ -31,7 +31,7 @@ export const useComputeNodeState = (shape: ComputeShape): ComputeNodeState => {
31
31
  const { controller } = useComputeContext();
32
32
  invariant(controller);
33
33
 
34
- const [meta, setMeta] = useState<ComputeMeta>();
34
+ const [meta, setMeta] = useState<ComputeNodeMeta>();
35
35
  useEffect(() => {
36
36
  let disposed = false;
37
37
  queueMicrotask(async () => {
@@ -41,6 +41,7 @@ export const useComputeNodeState = (shape: ComputeShape): ComputeNodeState => {
41
41
  if (disposed) {
42
42
  return;
43
43
  }
44
+
44
45
  setMeta(meta);
45
46
  });
46
47
 
@@ -54,7 +55,7 @@ export const useComputeNodeState = (shape: ComputeShape): ComputeNodeState => {
54
55
  }, [shape.node]);
55
56
 
56
57
  const subscribeToEventLog = useCallback(
57
- (cb: (event: ComputeEvent) => void) => {
58
+ (cb: (event: ComputeEvent) => void): (() => void) => {
58
59
  return controller.events.on((ev) => {
59
60
  if (ev.nodeId === shape.node) {
60
61
  cb(ev);
@@ -5,10 +5,9 @@
5
5
  import { useMemo } from 'react';
6
6
 
7
7
  import { type ComputeEdge, ComputeGraphModel, type ComputeNode, DEFAULT_INPUT, DEFAULT_OUTPUT } from '@dxos/conductor';
8
- import { ObjectId, Ref } from '@dxos/echo-schema';
8
+ import { Obj, Ref } from '@dxos/echo';
9
9
  import { invariant } from '@dxos/invariant';
10
- import { getSpace } from '@dxos/react-client/echo';
11
- import { type GraphMonitor, type CanvasGraphModel, type Connection } from '@dxos/react-ui-canvas-editor';
10
+ import { type CanvasBoard, type CanvasGraphModel, type GraphMonitor } from '@dxos/react-ui-canvas-editor';
12
11
  import { isNonNullable } from '@dxos/util';
13
12
 
14
13
  import { createComputeNode, isValidComputeNode } from '../graph';
@@ -19,7 +18,7 @@ import { type ComputeShape, type TriggerShape } from '../shapes';
19
18
  */
20
19
  export const mapEdge = (
21
20
  graph: CanvasGraphModel,
22
- { source, target, output = DEFAULT_OUTPUT, input = DEFAULT_INPUT }: Connection,
21
+ { source, target, output = DEFAULT_OUTPUT, input = DEFAULT_INPUT }: CanvasBoard.Connection,
23
22
  ): ComputeEdge => {
24
23
  const sourceNode = graph.findNode(source) as ComputeShape;
25
24
  const targetNode = graph.findNode(target) as ComputeShape;
@@ -27,7 +26,7 @@ export const mapEdge = (
27
26
  invariant(targetNode?.node);
28
27
 
29
28
  return {
30
- id: ObjectId.random(),
29
+ id: Obj.ID.random(),
31
30
  source: sourceNode.node,
32
31
  target: targetNode.node,
33
32
  output,
@@ -113,19 +112,21 @@ export const createComputeGraph = (graph?: CanvasGraphModel<ComputeShape>) => {
113
112
  const linkTriggerToCompute = (graph: ComputeGraphModel, computeNode: ComputeNode, triggerData: TriggerShape) => {
114
113
  const functionTrigger = triggerData.functionTrigger?.target;
115
114
  invariant(functionTrigger);
116
- functionTrigger.function = Ref.make(graph.root);
117
- functionTrigger.inputNodeId = computeNode.id;
115
+ Obj.update(functionTrigger, (functionTrigger) => {
116
+ functionTrigger.function = Ref.make(graph.root);
117
+ functionTrigger.inputNodeId = computeNode.id;
118
+ });
118
119
  };
119
120
 
120
121
  const deleteTriggerObjects = (computeGraph: ComputeGraphModel, deleted: CanvasGraphModel) => {
121
- const space = getSpace(computeGraph.root);
122
- if (!space) {
122
+ const db = Obj.getDatabase(computeGraph.root);
123
+ if (!db) {
123
124
  return;
124
125
  }
125
126
  for (const node of deleted.nodes) {
126
127
  if (node.type === 'trigger') {
127
128
  const trigger = node as TriggerShape;
128
- space.db.remove(trigger.functionTrigger!.target!);
129
+ db.remove(trigger.functionTrigger!.target!);
129
130
  }
130
131
  }
131
132
  };
package/src/json.test.ts CHANGED
@@ -2,15 +2,15 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
5
+ import * as Schema from 'effect/Schema';
6
6
  import { describe, test } from 'vitest';
7
7
 
8
- import { BaseGraphEdge, BaseGraphNode } from '@dxos/graph';
8
+ import { Graph } from '@dxos/graph';
9
9
 
10
10
  import { createGptCircuit } from './testing';
11
11
 
12
12
  export const Shape = Schema.extend(
13
- BaseGraphNode,
13
+ Graph.Node,
14
14
  Schema.Struct({
15
15
  text: Schema.optional(Schema.String),
16
16
  guide: Schema.optional(Schema.Boolean),
@@ -19,7 +19,7 @@ export const Shape = Schema.extend(
19
19
  );
20
20
 
21
21
  export const Connection = Schema.extend(
22
- BaseGraphEdge,
22
+ Graph.Edge,
23
23
  Schema.Struct({
24
24
  input: Schema.optional(Schema.String),
25
25
  output: Schema.optional(Schema.String),
package/src/registry.ts CHANGED
@@ -22,17 +22,17 @@ import {
22
22
  jsonTransformShape,
23
23
  notShape,
24
24
  orShape,
25
- queueShape,
25
+ feedShape,
26
26
  randomShape,
27
27
  reducerShape,
28
28
  scopeShape,
29
29
  surfaceShape,
30
30
  switchShape,
31
31
  templateShape,
32
- threadShape,
32
+ textShape,
33
33
  textToImageShape,
34
+ threadShape,
34
35
  triggerShape,
35
- textShape,
36
36
  } from './shapes';
37
37
 
38
38
  /**
@@ -82,7 +82,7 @@ export const computeShapes: { title: string; shapes: ShapeDef[] }[] = [
82
82
  shapes: [
83
83
  //
84
84
  jsonShape,
85
- queueShape,
85
+ feedShape,
86
86
  threadShape,
87
87
  textShape,
88
88
  surfaceShape,