@dxos/react-ui-canvas-compute 0.8.4-main.7ace549 → 0.8.4-main.8baae0fced

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 (114) hide show
  1. package/LICENSE +102 -5
  2. package/dist/lib/browser/index.mjs +903 -1144
  3. package/dist/lib/browser/index.mjs.map +4 -4
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/node-esm/index.mjs +903 -1144
  6. package/dist/lib/node-esm/index.mjs.map +4 -4
  7. package/dist/lib/node-esm/meta.json +1 -1
  8. package/dist/types/src/components/DiagnosticOverlay.d.ts.map +1 -1
  9. package/dist/types/src/compute-layout.d.ts.map +1 -1
  10. package/dist/types/src/compute.stories.d.ts +22 -1
  11. package/dist/types/src/compute.stories.d.ts.map +1 -1
  12. package/dist/types/src/graph/controller.d.ts +48 -29
  13. package/dist/types/src/graph/controller.d.ts.map +1 -1
  14. package/dist/types/src/graph/node-defs.d.ts.map +1 -1
  15. package/dist/types/src/hooks/useComputeGraphController.d.ts.map +1 -1
  16. package/dist/types/src/hooks/useComputeNodeState.d.ts +2 -3
  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/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 +7 -7
  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/{Queue.d.ts → Feed.d.ts} +9 -9
  37. package/dist/types/src/shapes/Feed.d.ts.map +1 -0
  38. package/dist/types/src/shapes/Function.d.ts +1 -1
  39. package/dist/types/src/shapes/Function.d.ts.map +1 -1
  40. package/dist/types/src/shapes/Gpt.d.ts +1 -1
  41. package/dist/types/src/shapes/Gpt.d.ts.map +1 -1
  42. package/dist/types/src/shapes/GptRealtime.d.ts +1 -1
  43. package/dist/types/src/shapes/GptRealtime.d.ts.map +1 -1
  44. package/dist/types/src/shapes/Json.d.ts +2 -2
  45. package/dist/types/src/shapes/Json.d.ts.map +1 -1
  46. package/dist/types/src/shapes/Logic.d.ts +2 -2
  47. package/dist/types/src/shapes/Logic.d.ts.map +1 -1
  48. package/dist/types/src/shapes/RNG.d.ts +2 -2
  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 +2 -2
  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 +6 -4
  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 +2 -2
  71. package/dist/types/src/shapes/common/FunctionBody.d.ts.map +1 -1
  72. package/dist/types/src/shapes/common/TypeSelect.d.ts +1 -1
  73. package/dist/types/src/shapes/common/TypeSelect.d.ts.map +1 -1
  74. package/dist/types/src/shapes/defs.d.ts +1 -1
  75. package/dist/types/src/shapes/defs.d.ts.map +1 -1
  76. package/dist/types/src/shapes/index.d.ts +2 -2
  77. package/dist/types/src/shapes/index.d.ts.map +1 -1
  78. package/dist/types/src/testing/circuits.d.ts +18 -24
  79. package/dist/types/src/testing/circuits.d.ts.map +1 -1
  80. package/dist/types/tsconfig.tsbuildinfo +1 -1
  81. package/package.json +62 -60
  82. package/src/README.md +0 -3
  83. package/src/compute.stories.tsx +91 -116
  84. package/src/graph/controller.ts +145 -75
  85. package/src/graph/node-defs.ts +28 -28
  86. package/src/hooks/useComputeNodeState.ts +3 -5
  87. package/src/hooks/useGraphMonitor.ts +9 -8
  88. package/src/json.test.ts +3 -3
  89. package/src/registry.ts +2 -2
  90. package/src/schema.test.ts +6 -6
  91. package/src/shapes/Audio.tsx +2 -3
  92. package/src/shapes/Beacon.tsx +1 -2
  93. package/src/shapes/Boolean.tsx +2 -2
  94. package/src/shapes/Chat.tsx +0 -1
  95. package/src/shapes/Constant.tsx +0 -1
  96. package/src/shapes/{Queue.tsx → Feed.tsx} +26 -21
  97. package/src/shapes/Function.tsx +12 -9
  98. package/src/shapes/Gpt.tsx +6 -2
  99. package/src/shapes/GptRealtime.tsx +1 -1
  100. package/src/shapes/Json.tsx +9 -3
  101. package/src/shapes/RNG.tsx +0 -1
  102. package/src/shapes/Scope.tsx +1 -2
  103. package/src/shapes/Surface.tsx +7 -3
  104. package/src/shapes/Switch.tsx +1 -2
  105. package/src/shapes/Template.tsx +0 -1
  106. package/src/shapes/Text.tsx +0 -1
  107. package/src/shapes/Thread.tsx +10 -8
  108. package/src/shapes/Trigger.tsx +20 -19
  109. package/src/shapes/common/Box.tsx +8 -11
  110. package/src/shapes/common/FunctionBody.tsx +4 -4
  111. package/src/shapes/common/TypeSelect.tsx +1 -1
  112. package/src/shapes/index.ts +2 -2
  113. package/src/testing/circuits.ts +6 -14
  114. package/dist/types/src/shapes/Queue.d.ts.map +0 -1
@@ -2,14 +2,22 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import type * as Context from 'effect/Context';
6
5
  import * as Effect from 'effect/Effect';
7
6
  import * as Either from 'effect/Either';
8
7
  import * as Exit from 'effect/Exit';
8
+ import * as Layer from 'effect/Layer';
9
9
  import * as Scope from 'effect/Scope';
10
10
 
11
+ import type { AiService } from '@dxos/ai';
11
12
  import { Event, synchronized } from '@dxos/async';
13
+ import { type Credential, type Operation, type OperationRegistry, Trace } from '@dxos/compute';
12
14
  import {
15
+ ComputeBeginEvent,
16
+ ComputeCustomEvent,
17
+ ComputeEndEvent,
18
+ ComputeInputEvent,
19
+ ComputeNodeContext,
20
+ ComputeOutputEvent,
13
21
  type ComputeEdge,
14
22
  type ComputeGraphModel,
15
23
  type ComputeNode,
@@ -22,15 +30,15 @@ import {
22
30
  isNotExecuted,
23
31
  } from '@dxos/conductor';
24
32
  import { Resource } from '@dxos/context';
25
- import { type ComputeEventLogger, type ComputeEventPayload } from '@dxos/functions';
26
- import { type ServiceContainer } from '@dxos/functions-runtime';
33
+ import type { Database, Feed } from '@dxos/echo';
34
+ import { unwrapExit } from '@dxos/effect';
35
+ import { type QueueService } from '@dxos/functions';
27
36
  import { log } from '@dxos/log';
28
37
  import { type CanvasGraphModel } from '@dxos/react-ui-canvas-editor';
29
38
  import { type ContentBlock } from '@dxos/types';
30
39
 
31
40
  import { createComputeGraph } from '../hooks';
32
41
  import { type ComputeShape } from '../shapes';
33
-
34
42
  import { resolveComputeNode } from './node-defs';
35
43
 
36
44
  // TODO(burdon): API package for conductor.
@@ -72,17 +80,47 @@ type ComputeOutputEvent = {
72
80
  value: RuntimeValue;
73
81
  };
74
82
 
83
+ /**
84
+ * Event emitted by the compute graph during execution.
85
+ */
86
+ export type ComputeEvent =
87
+ | { type: 'begin-compute'; nodeId: string; inputs: ReadonlyArray<string> }
88
+ | { type: 'end-compute'; nodeId: string; outputs: ReadonlyArray<string> }
89
+ | { type: 'compute-input'; nodeId: string; property: string; value: any }
90
+ | { type: 'compute-output'; nodeId: string; property: string; value: any }
91
+ | { type: 'custom'; nodeId: string; event: any };
92
+
93
+ // TODO(dmaretskyi): Re-use function servies definition.
94
+ export type ComputeServices =
95
+ | AiService.AiService
96
+ | Database.Service
97
+ | Feed.FeedService
98
+ | QueueService
99
+ | Credential.CredentialsService
100
+ | Operation.Service
101
+ | OperationRegistry.Service;
102
+
75
103
  /**
76
104
  * Nodes that will automatically trigger the execution of the graph on startup.
77
105
  */
78
106
  const AUTO_TRIGGER_NODES = ['chat', 'switch', 'constant'];
79
107
 
108
+ /**
109
+ * Minimal runtime interface required by the {@link ComputeGraphController}.
110
+ *
111
+ * Satisfied by both `effect/ManagedRuntime.ManagedRuntime` and ad-hoc adapters
112
+ * built on top of the app-framework `ProcessManagerRuntime`.
113
+ */
114
+ export interface ComputeGraphRuntime {
115
+ runPromiseExit<A, E>(effect: Effect.Effect<A, E, ComputeServices>): Promise<Exit.Exit<A, E>>;
116
+ }
117
+
80
118
  export const createComputeGraphController = (
81
119
  graph: CanvasGraphModel<ComputeShape>,
82
- serviceContainer: ServiceContainer,
120
+ computeRuntime: ComputeGraphRuntime,
83
121
  ) => {
84
122
  const computeGraph = createComputeGraph(graph);
85
- const controller = new ComputeGraphController(serviceContainer, computeGraph);
123
+ const controller = new ComputeGraphController(computeRuntime, computeGraph);
86
124
  return { controller, graph };
87
125
  };
88
126
 
@@ -114,10 +152,10 @@ export class ComputeGraphController extends Resource {
114
152
  /** Computed result. */
115
153
  public readonly output = new Event<ComputeOutputEvent>();
116
154
 
117
- public readonly events = new Event<ComputeEventPayload>();
155
+ public readonly events = new Event<ComputeEvent>();
118
156
 
119
157
  constructor(
120
- private readonly _serviceContainer: ServiceContainer,
158
+ private readonly _computeRuntime: ComputeGraphRuntime,
121
159
  /** Persistent compute graph. */
122
160
  private readonly _graph: ComputeGraphModel,
123
161
  ) {
@@ -232,37 +270,42 @@ export class ComputeGraphController extends Resource {
232
270
  executor.setOutputs(nodeId, Effect.succeed(ValueBag.make(outputs)));
233
271
  }
234
272
 
235
- const serviceLayer = this._serviceContainer.createLayer();
236
- await Effect.runPromise(
237
- Effect.gen(this, function* () {
238
- const scope = yield* Scope.make();
239
-
240
- // TODO(dmaretskyi): Code duplication.
241
- const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(nodeId)));
242
- const computingOutputs = executable.exec != null;
243
- // TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
244
- const effect = (computingOutputs ? executor.computeOutputs(nodeId) : executor.computeInputs(nodeId)).pipe(
245
- Effect.withSpan('runGraph'),
246
- Scope.extend(scope),
247
-
248
- Effect.flatMap(computeValueBag),
249
- Effect.provide(serviceLayer),
250
- Effect.withSpan('test'),
251
- Effect.tap((values) => {
252
- for (const [key, value] of Object.entries(values)) {
253
- if (computingOutputs) {
254
- this._onOutputComputed(nodeId, key, value);
255
- } else {
256
- this._onInputComputed(nodeId, key, value);
273
+ unwrapExit(
274
+ await this._computeRuntime.runPromiseExit(
275
+ Effect.gen(this, function* () {
276
+ const scope = yield* Scope.make();
277
+
278
+ // TODO(dmaretskyi): Code duplication.
279
+ const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(nodeId)));
280
+ const computingOutputs = executable.exec != null;
281
+ // TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
282
+ const effect = (computingOutputs ? executor.computeOutputs(nodeId) : executor.computeInputs(nodeId)).pipe(
283
+ Effect.withSpan('runGraph'),
284
+ Scope.extend(scope),
285
+ Effect.provide(
286
+ Layer.mergeAll(
287
+ Layer.succeed(Trace.TraceService, this._createTraceWriter()),
288
+ ComputeNodeContext.layerNoop,
289
+ ),
290
+ ),
291
+ Effect.flatMap(computeValueBag),
292
+ Effect.withSpan('test'),
293
+ Effect.tap((values) => {
294
+ for (const [key, value] of Object.entries(values)) {
295
+ if (computingOutputs) {
296
+ this._onOutputComputed(nodeId, key, value);
297
+ } else {
298
+ this._onInputComputed(nodeId, key, value);
299
+ }
257
300
  }
258
- }
259
- }),
260
- );
301
+ }),
302
+ );
261
303
 
262
- yield* effect;
304
+ yield* effect;
263
305
 
264
- yield* Scope.close(scope, Exit.void);
265
- }),
306
+ yield* Scope.close(scope, Exit.void);
307
+ }),
308
+ ),
266
309
  );
267
310
 
268
311
  this.update.emit();
@@ -290,59 +333,69 @@ export class ComputeGraphController extends Resource {
290
333
  : this._graph.nodes.filter((node) => node.type != null && AUTO_TRIGGER_NODES.includes(node.type));
291
334
  const allAffectedNodes = [...new Set(triggerNodes.flatMap((node) => executor.getAllDependantNodes(node.id)))];
292
335
 
293
- await Effect.runPromise(
294
- Effect.gen(this, function* () {
295
- const scope = yield* Scope.make();
296
-
297
- // TODO(burdon): Return map?
298
- const tasks: Effect.Effect<unknown, any, never>[] = [];
299
- for (const node of allAffectedNodes) {
300
- // TODO(dmaretskyi): Code duplication.
301
- const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(node)));
302
- const computingOutputs = executable.exec != null;
303
-
304
- // TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
305
- const effect = (computingOutputs ? executor.computeOutputs(node) : executor.computeInputs(node)).pipe(
306
- Effect.withSpan('runGraph'),
307
- Scope.extend(scope),
308
- Effect.flatMap(computeValueBag),
309
- Effect.provide(this._serviceContainer.createLayer()),
310
- Effect.withSpan('test'),
311
- Effect.tap((values) => {
312
- for (const [key, value] of Object.entries(values)) {
313
- if (computingOutputs) {
314
- this._onOutputComputed(node, key, value);
315
- } else {
316
- this._onInputComputed(node, key, value);
336
+ unwrapExit(
337
+ await this._computeRuntime.runPromiseExit(
338
+ Effect.gen(this, function* () {
339
+ const scope = yield* Scope.make();
340
+
341
+ // TODO(burdon): Return map?
342
+ const tasks: Effect.Effect<unknown, any, ComputeServices>[] = [];
343
+ for (const node of allAffectedNodes) {
344
+ // TODO(dmaretskyi): Code duplication.
345
+ const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(node)));
346
+ const computingOutputs = executable.exec != null;
347
+
348
+ // TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
349
+ const effect = (computingOutputs ? executor.computeOutputs(node) : executor.computeInputs(node)).pipe(
350
+ Effect.withSpan('runGraph'),
351
+ Scope.extend(scope),
352
+ Effect.flatMap(computeValueBag),
353
+ Effect.provide(
354
+ Layer.mergeAll(
355
+ Layer.succeed(Trace.TraceService, this._createTraceWriter()),
356
+ ComputeNodeContext.layerNoop,
357
+ ),
358
+ ),
359
+
360
+ Effect.withSpan('test'),
361
+ Effect.tap((values) => {
362
+ for (const [key, value] of Object.entries(values)) {
363
+ if (computingOutputs) {
364
+ this._onOutputComputed(node, key, value);
365
+ } else {
366
+ this._onInputComputed(node, key, value);
367
+ }
317
368
  }
318
- }
319
- }),
320
- );
369
+ }),
370
+ );
321
371
 
322
- tasks.push(effect);
323
- }
372
+ tasks.push(effect);
373
+ }
324
374
 
325
- //
326
- yield* Effect.all(tasks);
375
+ //
376
+ yield* Effect.all(tasks);
327
377
 
328
- //
329
- yield* Scope.close(scope, Exit.void);
330
- }),
378
+ //
379
+ yield* Scope.close(scope, Exit.void);
380
+ }),
381
+ ),
331
382
  );
332
383
 
333
384
  this.update.emit();
334
385
  }
335
386
 
336
- private _createLogger(): Context.Tag.Service<ComputeEventLogger> {
387
+ private _createTraceWriter(): Trace.TraceWriter {
337
388
  return {
338
- log: (event) => {
339
- this._handleEvent(event);
389
+ write: (eventType, payload) => {
390
+ const event = traceEventToComputeEvent(eventType.key, payload);
391
+ if (event) {
392
+ this._handleEvent(event);
393
+ }
340
394
  },
341
- nodeId: undefined, // Not in a context of a specific node.
342
395
  };
343
396
  }
344
397
 
345
- private _handleEvent(event: ComputeEventPayload): void {
398
+ private _handleEvent(event: ComputeEvent): void {
346
399
  log('handleEvent', { event });
347
400
  switch (event.type) {
348
401
  case 'compute-input': {
@@ -372,6 +425,23 @@ export class ComputeGraphController extends Resource {
372
425
  }
373
426
  }
374
427
 
428
+ const traceEventToComputeEvent = (key: string, payload: unknown): ComputeEvent | undefined => {
429
+ switch (key) {
430
+ case ComputeBeginEvent.key:
431
+ return { type: 'begin-compute', ...(payload as { nodeId: string; inputs: ReadonlyArray<string> }) };
432
+ case ComputeEndEvent.key:
433
+ return { type: 'end-compute', ...(payload as { nodeId: string; outputs: ReadonlyArray<string> }) };
434
+ case ComputeInputEvent.key:
435
+ return { type: 'compute-input', ...(payload as { nodeId: string; property: string; value: any }) };
436
+ case ComputeOutputEvent.key:
437
+ return { type: 'compute-output', ...(payload as { nodeId: string; property: string; value: any }) };
438
+ case ComputeCustomEvent.key:
439
+ return { type: 'custom', ...(payload as { nodeId: string; event: any }) };
440
+ default:
441
+ return undefined;
442
+ }
443
+ };
444
+
375
445
  /**
376
446
  * Waits for all effects in the bag to complete and returns the `RuntimeValue` for each property.
377
447
  */
@@ -39,41 +39,41 @@ 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
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 => ({
@@ -6,12 +6,10 @@ import * as Schema from 'effect/Schema';
6
6
  import { useCallback, useEffect, useState } from 'react';
7
7
 
8
8
  import type { ComputeNode, ComputeNodeMeta } from '@dxos/conductor';
9
- import type { ComputeEventPayload } from '@dxos/functions';
10
9
  import { invariant } from '@dxos/invariant';
11
10
 
12
- import { type RuntimeValue } from '../graph';
11
+ import { type ComputeEvent, type RuntimeValue } from '../graph';
13
12
  import { type ComputeShape } from '../shapes';
14
-
15
13
  import { useComputeContext } from './compute-context';
16
14
 
17
15
  export type ComputeNodeState = {
@@ -22,7 +20,7 @@ export type ComputeNodeState = {
22
20
  outputs: Record<string, RuntimeValue>;
23
21
  setOutput: (property: string, value: any) => void;
24
22
  evalNode: () => void;
25
- subscribeToEventLog: (cb: (event: ComputeEventPayload) => void) => void;
23
+ subscribeToEventLog: (cb: (event: ComputeEvent) => void) => () => void;
26
24
  };
27
25
  };
28
26
 
@@ -57,7 +55,7 @@ export const useComputeNodeState = (shape: ComputeShape): ComputeNodeState => {
57
55
  }, [shape.node]);
58
56
 
59
57
  const subscribeToEventLog = useCallback(
60
- (cb: (event: ComputeEventPayload) => void) => {
58
+ (cb: (event: ComputeEvent) => void): (() => void) => {
61
59
  return controller.events.on((ev) => {
62
60
  if (ev.nodeId === shape.node) {
63
61
  cb(ev);
@@ -7,8 +7,7 @@ import { useMemo } from 'react';
7
7
  import { type ComputeEdge, ComputeGraphModel, type ComputeNode, DEFAULT_INPUT, DEFAULT_OUTPUT } from '@dxos/conductor';
8
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 CanvasGraphModel, type Connection, type GraphMonitor } 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;
@@ -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
@@ -5,12 +5,12 @@
5
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,7 +22,7 @@ import {
22
22
  jsonTransformShape,
23
23
  notShape,
24
24
  orShape,
25
- queueShape,
25
+ feedShape,
26
26
  randomShape,
27
27
  reducerShape,
28
28
  scopeShape,
@@ -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,
@@ -5,11 +5,11 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
  import { describe, test } from 'vitest';
7
7
 
8
- import { BaseGraphNode, type Graph } from '@dxos/graph';
8
+ import { Graph } from '@dxos/graph';
9
9
  import {
10
+ CanvasBoard,
10
11
  CanvasGraphModel,
11
12
  Polygon,
12
- Shape,
13
13
  createEllipse,
14
14
  createPath,
15
15
  createRectangle,
@@ -26,10 +26,10 @@ describe('compute', () => {
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: Graph = { nodes: [], edges: [] };
32
+ const graph: Graph.Any = { nodes: [], edges: [] };
33
33
  graph.nodes.push(node);
34
34
 
35
35
  model.createNode(node);
@@ -39,7 +39,7 @@ describe('compute', () => {
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 } }));
@@ -9,7 +9,6 @@ import { Icon } from '@dxos/react-ui';
9
9
  import { type ShapeComponentProps, type ShapeDef, createAnchorMap } from '@dxos/react-ui-canvas-editor';
10
10
 
11
11
  import { useComputeNodeState } from '../hooks';
12
-
13
12
  import { ComputeShape, type CreateShapeProps, createAnchorId, createShape } from './defs';
14
13
 
15
14
  export const AudioShape = Schema.extend(
@@ -35,10 +34,10 @@ export const AudioComponent = ({ shape }: ShapeComponentProps<AudioShape>) => {
35
34
 
36
35
  // https://docs.pmnd.rs/react-three-fiber/api/canvas#render-props
37
36
  return (
38
- <div className='flex is-full justify-center items-center'>
37
+ <div className='flex w-full justify-center items-center'>
39
38
  <Icon
40
39
  icon={active ? 'ph--microphone--regular' : 'ph--microphone-slash--regular'}
41
- classNames={['transition opacity-20 duration-1000', active && 'opacity-100 text-red-500']}
40
+ classNames={['transition opacity-20 duration-1000', active && 'opacity-100 text-error-text']}
42
41
  size={8}
43
42
  onClick={() => setActive(!active)}
44
43
  />
@@ -10,7 +10,6 @@ import { Icon } from '@dxos/react-ui';
10
10
  import { type ShapeComponentProps, type ShapeDef, createAnchorMap } from '@dxos/react-ui-canvas-editor';
11
11
 
12
12
  import { useComputeNodeState } from '../hooks';
13
-
14
13
  import { ComputeShape, type CreateShapeProps, createAnchorId, createShape } from './defs';
15
14
 
16
15
  export const BeaconShape = Schema.extend(
@@ -33,7 +32,7 @@ export const BeaconComponent = ({ shape }: ShapeComponentProps<BeaconShape>) =>
33
32
  const value = input?.type === 'executed' ? input.value : false;
34
33
 
35
34
  return (
36
- <div className='flex is-full justify-center items-center'>
35
+ <div className='flex w-full justify-center items-center'>
37
36
  <Icon
38
37
  icon='ph--sun--regular'
39
38
  classNames={['transition opacity-20 duration-1000', isTruthy(value) && 'opacity-100 text-yellow-500']}
@@ -57,7 +57,7 @@ const defineShape = <S extends GateShape>({
57
57
  // Be careful not to name component factories with a capital letter.
58
58
  component: () => {
59
59
  return (
60
- <div className='flex is-full justify-center items-center'>
60
+ <div className='flex w-full justify-center items-center'>
61
61
  <Symbol />
62
62
  </div>
63
63
  );
@@ -95,7 +95,7 @@ const createSymbol =
95
95
  const paths = pathConstructor({ startX, endX, height });
96
96
 
97
97
  return (
98
- <svg viewBox={`0 0 ${width} ${height}`} className='is-full bs-full'>
98
+ <svg viewBox={`0 0 ${width} ${height}`} className='h-full w-full'>
99
99
  {/* Input line. */}
100
100
  {getAnchorPoints({ x: 0, y: centerY }, inputs).map(({ x, y }, i) => (
101
101
  <line key={i} x1={x} y1={y} x2={startX * 1.3} y2={y} strokeWidth={strokeWidth} className={className} />
@@ -16,7 +16,6 @@ import {
16
16
  import { createAnchorMap } from '@dxos/react-ui-canvas-editor';
17
17
 
18
18
  import { useComputeNodeState } from '../hooks';
19
-
20
19
  import { Box } from './common';
21
20
  import { ComputeShape, type CreateShapeProps, createAnchorId, createShape } from './defs';
22
21
 
@@ -18,7 +18,6 @@ import { createAnchorMap } from '@dxos/react-ui-canvas-editor';
18
18
  import { safeParseJson } from '@dxos/util';
19
19
 
20
20
  import { useComputeNodeState } from '../hooks';
21
-
22
21
  import { Box, TypeSelect } from './common';
23
22
  import { ComputeShape, type CreateShapeProps, createAnchorId, createShape } from './defs';
24
23