@dxos/react-ui-canvas-compute 0.8.4-main.c1de068 → 0.8.4-main.c85a9c8dae

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 (117) hide show
  1. package/dist/lib/browser/index.mjs +890 -1029
  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 +890 -1029
  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/compute.stories.d.ts +33 -5
  8. package/dist/types/src/compute.stories.d.ts.map +1 -1
  9. package/dist/types/src/graph/controller.d.ts +40 -27
  10. package/dist/types/src/graph/controller.d.ts.map +1 -1
  11. package/dist/types/src/graph/node-defs.d.ts.map +1 -1
  12. package/dist/types/src/hooks/useComputeGraphController.d.ts +2 -2
  13. package/dist/types/src/hooks/useComputeGraphController.d.ts.map +1 -1
  14. package/dist/types/src/hooks/useComputeNodeState.d.ts +4 -3
  15. package/dist/types/src/hooks/useComputeNodeState.d.ts.map +1 -1
  16. package/dist/types/src/hooks/useGraphMonitor.d.ts +2 -2
  17. package/dist/types/src/hooks/useGraphMonitor.d.ts.map +1 -1
  18. package/dist/types/src/json.test.d.ts +1 -1
  19. package/dist/types/src/json.test.d.ts.map +1 -1
  20. package/dist/types/src/shapes/Append.d.ts +1 -1
  21. package/dist/types/src/shapes/Append.d.ts.map +1 -1
  22. package/dist/types/src/shapes/Array.d.ts +1 -1
  23. package/dist/types/src/shapes/Array.d.ts.map +1 -1
  24. package/dist/types/src/shapes/Audio.d.ts +1 -1
  25. package/dist/types/src/shapes/Audio.d.ts.map +1 -1
  26. package/dist/types/src/shapes/Beacon.d.ts +1 -1
  27. package/dist/types/src/shapes/Beacon.d.ts.map +1 -1
  28. package/dist/types/src/shapes/Boolean.d.ts +1 -1
  29. package/dist/types/src/shapes/Boolean.d.ts.map +1 -1
  30. package/dist/types/src/shapes/Chat.d.ts +1 -1
  31. package/dist/types/src/shapes/Chat.d.ts.map +1 -1
  32. package/dist/types/src/shapes/Constant.d.ts +1 -1
  33. package/dist/types/src/shapes/Constant.d.ts.map +1 -1
  34. package/dist/types/src/shapes/Database.d.ts +1 -1
  35. package/dist/types/src/shapes/Database.d.ts.map +1 -1
  36. package/dist/types/src/shapes/Function.d.ts +1 -1
  37. package/dist/types/src/shapes/Function.d.ts.map +1 -1
  38. package/dist/types/src/shapes/Gpt.d.ts +1 -1
  39. package/dist/types/src/shapes/Gpt.d.ts.map +1 -1
  40. package/dist/types/src/shapes/GptRealtime.d.ts +1 -1
  41. package/dist/types/src/shapes/GptRealtime.d.ts.map +1 -1
  42. package/dist/types/src/shapes/Json.d.ts +1 -1
  43. package/dist/types/src/shapes/Json.d.ts.map +1 -1
  44. package/dist/types/src/shapes/Logic.d.ts +1 -1
  45. package/dist/types/src/shapes/Logic.d.ts.map +1 -1
  46. package/dist/types/src/shapes/Queue.d.ts +1 -1
  47. package/dist/types/src/shapes/Queue.d.ts.map +1 -1
  48. package/dist/types/src/shapes/RNG.d.ts +1 -1
  49. package/dist/types/src/shapes/RNG.d.ts.map +1 -1
  50. package/dist/types/src/shapes/Scope.d.ts +1 -1
  51. package/dist/types/src/shapes/Scope.d.ts.map +1 -1
  52. package/dist/types/src/shapes/Surface.d.ts +1 -1
  53. package/dist/types/src/shapes/Surface.d.ts.map +1 -1
  54. package/dist/types/src/shapes/Switch.d.ts +1 -1
  55. package/dist/types/src/shapes/Switch.d.ts.map +1 -1
  56. package/dist/types/src/shapes/Table.d.ts +1 -1
  57. package/dist/types/src/shapes/Table.d.ts.map +1 -1
  58. package/dist/types/src/shapes/Template.d.ts +1 -1
  59. package/dist/types/src/shapes/Template.d.ts.map +1 -1
  60. package/dist/types/src/shapes/Text.d.ts +1 -1
  61. package/dist/types/src/shapes/Text.d.ts.map +1 -1
  62. package/dist/types/src/shapes/TextToImage.d.ts +1 -1
  63. package/dist/types/src/shapes/TextToImage.d.ts.map +1 -1
  64. package/dist/types/src/shapes/Thread.d.ts +1 -1
  65. package/dist/types/src/shapes/Thread.d.ts.map +1 -1
  66. package/dist/types/src/shapes/Trigger.d.ts +7 -34
  67. package/dist/types/src/shapes/Trigger.d.ts.map +1 -1
  68. package/dist/types/src/shapes/common/Box.d.ts +4 -4
  69. package/dist/types/src/shapes/common/Box.d.ts.map +1 -1
  70. package/dist/types/src/shapes/common/FunctionBody.d.ts +3 -3
  71. package/dist/types/src/shapes/common/FunctionBody.d.ts.map +1 -1
  72. package/dist/types/src/shapes/defs.d.ts +2 -1
  73. package/dist/types/src/shapes/defs.d.ts.map +1 -1
  74. package/dist/types/src/testing/circuits.d.ts +18 -24
  75. package/dist/types/src/testing/circuits.d.ts.map +1 -1
  76. package/dist/types/tsconfig.tsbuildinfo +1 -1
  77. package/package.json +60 -53
  78. package/src/README.md +0 -3
  79. package/src/compute-layout.ts +1 -1
  80. package/src/compute.stories.tsx +82 -122
  81. package/src/graph/controller.ts +121 -79
  82. package/src/graph/node-defs.ts +34 -34
  83. package/src/hooks/useComputeGraphController.ts +2 -2
  84. package/src/hooks/useComputeNodeState.ts +10 -7
  85. package/src/hooks/useGraphMonitor.ts +11 -10
  86. package/src/json.test.ts +4 -4
  87. package/src/registry.ts +2 -2
  88. package/src/schema.test.ts +13 -13
  89. package/src/shapes/Append.tsx +3 -3
  90. package/src/shapes/Array.tsx +3 -3
  91. package/src/shapes/Audio.tsx +4 -3
  92. package/src/shapes/Beacon.tsx +4 -3
  93. package/src/shapes/Boolean.tsx +3 -3
  94. package/src/shapes/Chat.tsx +4 -3
  95. package/src/shapes/Constant.tsx +4 -3
  96. package/src/shapes/Database.tsx +2 -2
  97. package/src/shapes/Function.tsx +17 -14
  98. package/src/shapes/Gpt.tsx +13 -6
  99. package/src/shapes/GptRealtime.tsx +2 -2
  100. package/src/shapes/Json.tsx +4 -3
  101. package/src/shapes/Logic.tsx +3 -3
  102. package/src/shapes/Queue.tsx +19 -12
  103. package/src/shapes/RNG.tsx +9 -4
  104. package/src/shapes/Scope.tsx +5 -4
  105. package/src/shapes/Surface.tsx +13 -6
  106. package/src/shapes/Switch.tsx +4 -3
  107. package/src/shapes/Table.tsx +6 -6
  108. package/src/shapes/Template.tsx +6 -5
  109. package/src/shapes/Text.tsx +5 -4
  110. package/src/shapes/TextToImage.tsx +2 -2
  111. package/src/shapes/Thread.tsx +20 -14
  112. package/src/shapes/Trigger.tsx +50 -57
  113. package/src/shapes/common/Box.tsx +6 -7
  114. package/src/shapes/common/FunctionBody.tsx +5 -4
  115. package/src/shapes/common/TypeSelect.tsx +1 -1
  116. package/src/shapes/defs.ts +5 -4
  117. package/src/testing/circuits.ts +5 -14
@@ -2,17 +2,21 @@
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 type * as Context from 'effect/Context';
6
+ import * as Effect from 'effect/Effect';
7
+ import * as Either from 'effect/Either';
8
+ import * as Exit from 'effect/Exit';
9
+ import * as Layer from 'effect/Layer';
10
+ import type * as ManagedRuntime from 'effect/ManagedRuntime';
11
+ import * as Scope from 'effect/Scope';
12
+
13
+ import type { AiService } from '@dxos/ai';
8
14
  import { Event, synchronized } from '@dxos/async';
9
15
  import {
10
16
  type ComputeEdge,
11
- type ComputeEvent,
12
17
  type ComputeGraphModel,
13
- type ComputeMeta,
14
18
  type ComputeNode,
15
- type EventLogger,
19
+ type ComputeNodeMeta,
16
20
  type GptInput,
17
21
  type GptOutput,
18
22
  type GraphDiagnostic,
@@ -21,14 +25,25 @@ import {
21
25
  isNotExecuted,
22
26
  } from '@dxos/conductor';
23
27
  import { Resource } from '@dxos/context';
24
- import { type ServiceContainer } from '@dxos/functions';
28
+ import type { Database, Feed } from '@dxos/echo';
29
+ import { unwrapExit } from '@dxos/effect';
30
+ import {
31
+ ComputeEventLogger,
32
+ type ComputeEventPayload,
33
+ type CredentialsService,
34
+ type FunctionInvocationService,
35
+ type QueueService,
36
+ TracingService,
37
+ } from '@dxos/functions';
25
38
  import { log } from '@dxos/log';
26
39
  import { type CanvasGraphModel } from '@dxos/react-ui-canvas-editor';
40
+ import { type ContentBlock } from '@dxos/types';
27
41
 
28
- import { resolveComputeNode } from './node-defs';
29
42
  import { createComputeGraph } from '../hooks';
30
43
  import { type ComputeShape } from '../shapes';
31
44
 
45
+ import { resolveComputeNode } from './node-defs';
46
+
32
47
  // TODO(burdon): API package for conductor.
33
48
  export const InvalidStateError = Error;
34
49
 
@@ -43,7 +58,7 @@ export interface GptExecutor {
43
58
  invoke: FunctionCallback<GptInput, GptOutput>;
44
59
 
45
60
  // TODO(dmaretskyi): A hack to get image artifacts working. Rework into querying images from the ai-service store.
46
- imageCache: Map<string, ImageContentBlock>;
61
+ imageCache: Map<string, ContentBlock.Image>;
47
62
  }
48
63
 
49
64
  export type RuntimeValue =
@@ -68,6 +83,15 @@ type ComputeOutputEvent = {
68
83
  value: RuntimeValue;
69
84
  };
70
85
 
86
+ // TODO(dmaretskyi): Re-use function servies definition.
87
+ export type ComputeServices =
88
+ | AiService.AiService
89
+ | Database.Service
90
+ | Feed.Service
91
+ | QueueService
92
+ | CredentialsService
93
+ | FunctionInvocationService;
94
+
71
95
  /**
72
96
  * Nodes that will automatically trigger the execution of the graph on startup.
73
97
  */
@@ -75,10 +99,10 @@ const AUTO_TRIGGER_NODES = ['chat', 'switch', 'constant'];
75
99
 
76
100
  export const createComputeGraphController = (
77
101
  graph: CanvasGraphModel<ComputeShape>,
78
- serviceContainer: ServiceContainer,
102
+ computeRuntime: ManagedRuntime.ManagedRuntime<ComputeServices, never>,
79
103
  ) => {
80
104
  const computeGraph = createComputeGraph(graph);
81
- const controller = new ComputeGraphController(serviceContainer, computeGraph);
105
+ const controller = new ComputeGraphController(computeRuntime, computeGraph);
82
106
  return { controller, graph };
83
107
  };
84
108
 
@@ -110,10 +134,10 @@ export class ComputeGraphController extends Resource {
110
134
  /** Computed result. */
111
135
  public readonly output = new Event<ComputeOutputEvent>();
112
136
 
113
- public readonly events = new Event<ComputeEvent>();
137
+ public readonly events = new Event<ComputeEventPayload>();
114
138
 
115
139
  constructor(
116
- private readonly _serviceContainer: ServiceContainer,
140
+ private readonly _computeRuntime: ManagedRuntime.ManagedRuntime<ComputeServices, never>,
117
141
  /** Persistent compute graph. */
118
142
  private readonly _graph: ComputeGraphModel,
119
143
  ) {
@@ -154,7 +178,14 @@ export class ComputeGraphController extends Resource {
154
178
  /**
155
179
  * Inputs and outputs for all nodes.
156
180
  */
157
- get state() {
181
+ get state(): Record<
182
+ string,
183
+ {
184
+ node: ComputeNode;
185
+ input: Record<string, RuntimeValue>;
186
+ output: Record<string, RuntimeValue>;
187
+ }
188
+ > {
158
189
  const ids = [...new Set([...Object.keys(this._runtimeStateInputs), ...Object.keys(this._runtimeStateOutputs)])];
159
190
  return Object.fromEntries(
160
191
  ids.map((id) => [
@@ -201,7 +232,7 @@ export class ComputeGraphController extends Resource {
201
232
  });
202
233
  }
203
234
 
204
- async getMeta(node: ComputeNode): Promise<ComputeMeta> {
235
+ async getMeta(node: ComputeNode): Promise<ComputeNodeMeta> {
205
236
  const { meta } = await resolveComputeNode(node);
206
237
  return meta;
207
238
  }
@@ -221,37 +252,41 @@ export class ComputeGraphController extends Resource {
221
252
  executor.setOutputs(nodeId, Effect.succeed(ValueBag.make(outputs)));
222
253
  }
223
254
 
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);
255
+ unwrapExit(
256
+ await this._computeRuntime.runPromiseExit(
257
+ Effect.gen(this, function* () {
258
+ const scope = yield* Scope.make();
259
+
260
+ // TODO(dmaretskyi): Code duplication.
261
+ const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(nodeId)));
262
+ const computingOutputs = executable.exec != null;
263
+ // TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
264
+ const effect = (computingOutputs ? executor.computeOutputs(nodeId) : executor.computeInputs(nodeId)).pipe(
265
+ Effect.withSpan('runGraph'),
266
+ Scope.extend(scope),
267
+ Effect.provide(
268
+ ComputeEventLogger.layerFromTracing.pipe(
269
+ Layer.provideMerge(TracingService.layerNoop), // TODO(dmaretskyi): Plug-in tracing events to visual feedback in the compute graph editor.
270
+ ),
271
+ ),
272
+ Effect.flatMap(computeValueBag),
273
+ Effect.withSpan('test'),
274
+ Effect.tap((values) => {
275
+ for (const [key, value] of Object.entries(values)) {
276
+ if (computingOutputs) {
277
+ this._onOutputComputed(nodeId, key, value);
278
+ } else {
279
+ this._onInputComputed(nodeId, key, value);
280
+ }
246
281
  }
247
- }
248
- }),
249
- );
282
+ }),
283
+ );
250
284
 
251
- yield* effect;
285
+ yield* effect;
252
286
 
253
- yield* Scope.close(scope, Exit.void);
254
- }),
287
+ yield* Scope.close(scope, Exit.void);
288
+ }),
289
+ ),
255
290
  );
256
291
 
257
292
  this.update.emit();
@@ -279,50 +314,57 @@ export class ComputeGraphController extends Resource {
279
314
  : this._graph.nodes.filter((node) => node.type != null && AUTO_TRIGGER_NODES.includes(node.type));
280
315
  const allAffectedNodes = [...new Set(triggerNodes.flatMap((node) => executor.getAllDependantNodes(node.id)))];
281
316
 
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);
317
+ unwrapExit(
318
+ await this._computeRuntime.runPromiseExit(
319
+ Effect.gen(this, function* () {
320
+ const scope = yield* Scope.make();
321
+
322
+ // TODO(burdon): Return map?
323
+ const tasks: Effect.Effect<unknown, any, ComputeServices>[] = [];
324
+ for (const node of allAffectedNodes) {
325
+ // TODO(dmaretskyi): Code duplication.
326
+ const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(node)));
327
+ const computingOutputs = executable.exec != null;
328
+
329
+ // TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
330
+ const effect = (computingOutputs ? executor.computeOutputs(node) : executor.computeInputs(node)).pipe(
331
+ Effect.withSpan('runGraph'),
332
+ Scope.extend(scope),
333
+ Effect.flatMap(computeValueBag),
334
+ Effect.provide(
335
+ ComputeEventLogger.layerFromTracing.pipe(
336
+ Layer.provideMerge(TracingService.layerNoop), // TODO(dmaretskyi): Plug-in tracing events to visual feedback in the compute graph editor.
337
+ ),
338
+ ),
339
+
340
+ Effect.withSpan('test'),
341
+ Effect.tap((values) => {
342
+ for (const [key, value] of Object.entries(values)) {
343
+ if (computingOutputs) {
344
+ this._onOutputComputed(node, key, value);
345
+ } else {
346
+ this._onInputComputed(node, key, value);
347
+ }
306
348
  }
307
- }
308
- }),
309
- );
349
+ }),
350
+ );
310
351
 
311
- tasks.push(effect);
312
- }
352
+ tasks.push(effect);
353
+ }
313
354
 
314
- //
315
- yield* Effect.all(tasks);
355
+ //
356
+ yield* Effect.all(tasks);
316
357
 
317
- //
318
- yield* Scope.close(scope, Exit.void);
319
- }),
358
+ //
359
+ yield* Scope.close(scope, Exit.void);
360
+ }),
361
+ ),
320
362
  );
321
363
 
322
364
  this.update.emit();
323
365
  }
324
366
 
325
- private _createLogger(): Context.Tag.Service<EventLogger> {
367
+ private _createLogger(): Context.Tag.Service<ComputeEventLogger> {
326
368
  return {
327
369
  log: (event) => {
328
370
  this._handleEvent(event);
@@ -331,7 +373,7 @@ export class ComputeGraphController extends Resource {
331
373
  };
332
374
  }
333
375
 
334
- private _handleEvent(event: ComputeEvent): void {
376
+ private _handleEvent(event: ComputeEventPayload): void {
335
377
  log('handleEvent', { event });
336
378
  switch (event.type) {
337
379
  case 'compute-input': {
@@ -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,45 +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
- ['make-queue' as const]: () => createNode('make-queue'),
53
- ['database' as const]: () => createNode('database'),
54
- ['gpt' as const]: () => createNode('gpt'),
55
- ['gpt-realtime' as const]: () => createNode('gpt-realtime'),
56
- ['if' as const]: () => createNode('if'),
57
- ['if-else' as const]: () => createNode('if-else'),
58
- ['function' as const]: () => createNode('function'),
59
- ['json' as const]: () => createNode('json'),
60
- ['json-transform' as const]: () => createNode('json-transform'),
61
- ['not' as const]: () => createNode('not'),
62
- ['or' as const]: () => createNode('or'),
63
- ['queue' as const]: () => createNode('queue'),
64
- ['rng' as const]: () => createNode('rng'),
65
- ['reducer' as const]: () => createNode('reducer'),
66
- ['scope' as const]: () => createNode('scope'),
67
- ['surface' as const]: () => createNode('surface'),
68
- ['switch' as const]: () => createNode('switch'),
69
- ['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) => {
70
70
  const node = createNode('template', { valueType: (shape as TemplateShape).valueType, value: shape.text });
71
- node.inputSchema = toJsonSchema(getTemplateInputSchema(node));
71
+ node.inputSchema = JsonSchema.toJsonSchema(getTemplateInputSchema(node));
72
72
  return node;
73
73
  },
74
- ['text' as const]: () => createNode('text'),
75
- ['thread' as const]: () => createNode('thread'),
76
- ['trigger' as const]: () => createNode(NODE_INPUT),
74
+ text: () => createNode('text'),
75
+ thread: () => createNode('thread'),
76
+ trigger: () => createNode(NODE_INPUT),
77
77
  };
78
78
 
79
79
  const createNode = (type: string, props?: Partial<ComputeNode>): ComputeNode => ({
80
- id: ObjectId.random(),
80
+ id: Obj.ID.random(),
81
81
  type,
82
82
  ...props,
83
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,27 @@
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
+ import type { ComputeEventPayload } from '@dxos/functions';
9
10
  import { invariant } from '@dxos/invariant';
10
11
 
11
- import { useComputeContext } from './compute-context';
12
12
  import { type RuntimeValue } from '../graph';
13
13
  import { type ComputeShape } from '../shapes';
14
14
 
15
+ import { useComputeContext } from './compute-context';
16
+
15
17
  export type ComputeNodeState = {
16
18
  node: ComputeNode;
17
- meta: ComputeMeta;
19
+ meta: ComputeNodeMeta;
18
20
  runtime: {
19
21
  inputs: Record<string, RuntimeValue>;
20
22
  outputs: Record<string, RuntimeValue>;
21
23
  setOutput: (property: string, value: any) => void;
22
24
  evalNode: () => void;
23
- subscribeToEventLog: (cb: (event: ComputeEvent) => void) => void;
25
+ subscribeToEventLog: (cb: (event: ComputeEventPayload) => void) => void;
24
26
  };
25
27
  };
26
28
 
@@ -31,7 +33,7 @@ export const useComputeNodeState = (shape: ComputeShape): ComputeNodeState => {
31
33
  const { controller } = useComputeContext();
32
34
  invariant(controller);
33
35
 
34
- const [meta, setMeta] = useState<ComputeMeta>();
36
+ const [meta, setMeta] = useState<ComputeNodeMeta>();
35
37
  useEffect(() => {
36
38
  let disposed = false;
37
39
  queueMicrotask(async () => {
@@ -41,6 +43,7 @@ export const useComputeNodeState = (shape: ComputeShape): ComputeNodeState => {
41
43
  if (disposed) {
42
44
  return;
43
45
  }
46
+
44
47
  setMeta(meta);
45
48
  });
46
49
 
@@ -54,7 +57,7 @@ export const useComputeNodeState = (shape: ComputeShape): ComputeNodeState => {
54
57
  }, [shape.node]);
55
58
 
56
59
  const subscribeToEventLog = useCallback(
57
- (cb: (event: ComputeEvent) => void) => {
60
+ (cb: (event: ComputeEventPayload) => void) => {
58
61
  return controller.events.on((ev) => {
59
62
  if (ev.nodeId === shape.node) {
60
63
  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.change(functionTrigger, (t) => {
116
+ t.function = Ref.make(graph.root);
117
+ t.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
@@ -29,10 +29,10 @@ import {
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
  /**
@@ -2,44 +2,44 @@
2
2
  // Copyright 2024 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 { live } from '@dxos/client/echo';
9
- import { BaseGraphNode, Graph } from '@dxos/graph';
8
+ import { Graph } from '@dxos/graph';
10
9
  import {
10
+ CanvasBoard,
11
+ CanvasGraphModel,
11
12
  Polygon,
12
13
  createEllipse,
13
14
  createPath,
14
15
  createRectangle,
15
16
  isPath,
16
17
  isPolygon,
17
- Shape,
18
18
  } from '@dxos/react-ui-canvas-editor';
19
19
 
20
- import { createSwitch, ComputeShape, createFunction } from './shapes';
20
+ import { ComputeShape, createFunction, createSwitch } from './shapes';
21
21
 
22
22
  describe('compute', () => {
23
23
  test('model', ({ expect }) => {
24
- // const model = CanvasGraphModel.create<ComputeShape>();
24
+ const model = CanvasGraphModel.create<ComputeShape>();
25
25
  const node = createSwitch({ id: 'x', center: { x: 0, y: 0 }, size: { width: 80, height: 80 } });
26
26
  console.log(JSON.stringify(node, null, 2));
27
27
  expect(Schema.is(ComputeShape)(node)).toBe(true);
28
28
  expect(Schema.is(Polygon)(node)).toBe(true);
29
- expect(Schema.is(Shape)(node)).toBe(true);
30
- expect(Schema.is(BaseGraphNode)(node)).toBe(true);
29
+ expect(Schema.is(CanvasBoard.Shape)(node)).toBe(true);
30
+ expect(Schema.is(Graph.Node)(node)).toBe(true);
31
31
 
32
- const graph = live(Graph, { nodes: [], edges: [] });
33
- graph.nodes.push(node); // Throws.
32
+ const graph: Graph.Any = { nodes: [], edges: [] };
33
+ graph.nodes.push(node);
34
34
 
35
- // model.createNode(node);
36
- // console.log(JSON.stringify(model, null, 2));
35
+ model.createNode(node);
36
+ console.log(JSON.stringify(model, null, 2));
37
37
  });
38
38
  });
39
39
 
40
40
  describe('schema', () => {
41
41
  test('basic types', ({ expect }) => {
42
- const shapes: Shape[] = [];
42
+ const shapes: CanvasBoard.Shape[] = [];
43
43
  shapes.push(createRectangle({ id: 'shape-1', center: { x: 0, y: 0 }, size: { width: 80, height: 80 } }));
44
44
  shapes.push(createEllipse({ id: 'shape-2', center: { x: 0, y: 0 }, size: { width: 80, height: 80 } }));
45
45
  shapes.push(createFunction({ id: 'shape-3', center: { x: 0, y: 0 } }));
@@ -2,14 +2,14 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
5
+ import * as Schema from 'effect/Schema';
6
6
  import React from 'react';
7
7
 
8
8
  import { AppendInput } from '@dxos/conductor';
9
9
  import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
10
10
 
11
- import { createFunctionAnchors, FunctionBody, getHeight } from './common';
12
- import { ComputeShape, createShape, type CreateShapeProps } from './defs';
11
+ import { FunctionBody, createFunctionAnchors, getHeight } from './common';
12
+ import { ComputeShape, type CreateShapeProps, createShape } from './defs';
13
13
 
14
14
  export const AppendShape = Schema.extend(
15
15
  ComputeShape,