@dxos/react-ui-canvas-compute 0.8.4-main.72ec0f3 → 0.8.4-main.74a063c4e0
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.
- package/dist/lib/browser/index.mjs +894 -1059
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +894 -1059
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/compute.stories.d.ts +22 -1
- package/dist/types/src/compute.stories.d.ts.map +1 -1
- package/dist/types/src/graph/controller.d.ts +8 -4
- package/dist/types/src/graph/controller.d.ts.map +1 -1
- package/dist/types/src/hooks/useComputeNodeState.d.ts.map +1 -1
- package/dist/types/src/hooks/useGraphMonitor.d.ts +2 -2
- package/dist/types/src/hooks/useGraphMonitor.d.ts.map +1 -1
- package/dist/types/src/shapes/Audio.d.ts.map +1 -1
- package/dist/types/src/shapes/Beacon.d.ts.map +1 -1
- package/dist/types/src/shapes/Chat.d.ts.map +1 -1
- package/dist/types/src/shapes/Constant.d.ts.map +1 -1
- package/dist/types/src/shapes/{Queue.d.ts → Feed.d.ts} +8 -8
- package/dist/types/src/shapes/Feed.d.ts.map +1 -0
- package/dist/types/src/shapes/Function.d.ts.map +1 -1
- package/dist/types/src/shapes/Gpt.d.ts.map +1 -1
- package/dist/types/src/shapes/Json.d.ts.map +1 -1
- package/dist/types/src/shapes/RNG.d.ts.map +1 -1
- package/dist/types/src/shapes/Scope.d.ts.map +1 -1
- package/dist/types/src/shapes/Surface.d.ts.map +1 -1
- package/dist/types/src/shapes/Switch.d.ts.map +1 -1
- package/dist/types/src/shapes/Template.d.ts.map +1 -1
- package/dist/types/src/shapes/Text.d.ts.map +1 -1
- package/dist/types/src/shapes/Thread.d.ts.map +1 -1
- package/dist/types/src/shapes/Trigger.d.ts +4 -2
- package/dist/types/src/shapes/Trigger.d.ts.map +1 -1
- package/dist/types/src/shapes/common/Box.d.ts +4 -4
- package/dist/types/src/shapes/common/Box.d.ts.map +1 -1
- package/dist/types/src/shapes/common/FunctionBody.d.ts +2 -2
- package/dist/types/src/shapes/common/FunctionBody.d.ts.map +1 -1
- package/dist/types/src/shapes/index.d.ts +2 -2
- package/dist/types/src/shapes/index.d.ts.map +1 -1
- package/dist/types/src/testing/circuits.d.ts +18 -24
- package/dist/types/src/testing/circuits.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +60 -56
- package/src/README.md +0 -3
- package/src/compute.stories.tsx +80 -116
- package/src/graph/controller.ts +101 -68
- package/src/graph/node-defs.ts +31 -31
- package/src/hooks/useComputeNodeState.ts +0 -1
- package/src/hooks/useGraphMonitor.ts +11 -10
- package/src/json.test.ts +3 -3
- package/src/registry.ts +2 -2
- package/src/schema.test.ts +11 -11
- package/src/shapes/Audio.tsx +2 -3
- package/src/shapes/Beacon.tsx +1 -2
- package/src/shapes/Boolean.tsx +2 -2
- package/src/shapes/Chat.tsx +0 -1
- package/src/shapes/Constant.tsx +0 -1
- package/src/shapes/{Queue.tsx → Feed.tsx} +26 -21
- package/src/shapes/Function.tsx +10 -8
- package/src/shapes/Gpt.tsx +6 -2
- package/src/shapes/GptRealtime.tsx +1 -1
- package/src/shapes/Json.tsx +7 -3
- package/src/shapes/RNG.tsx +0 -1
- package/src/shapes/Scope.tsx +1 -2
- package/src/shapes/Surface.tsx +4 -3
- package/src/shapes/Switch.tsx +1 -2
- package/src/shapes/Template.tsx +0 -1
- package/src/shapes/Text.tsx +0 -1
- package/src/shapes/Thread.tsx +15 -9
- package/src/shapes/Trigger.tsx +13 -8
- package/src/shapes/common/Box.tsx +8 -11
- package/src/shapes/common/FunctionBody.tsx +4 -4
- package/src/shapes/common/TypeSelect.tsx +1 -1
- package/src/shapes/defs.ts +3 -3
- package/src/shapes/index.ts +2 -2
- package/src/testing/circuits.ts +7 -16
- package/dist/types/src/shapes/Queue.d.ts.map +0 -1
package/src/graph/controller.ts
CHANGED
|
@@ -6,8 +6,11 @@ import type * as Context from 'effect/Context';
|
|
|
6
6
|
import * as Effect from 'effect/Effect';
|
|
7
7
|
import * as Either from 'effect/Either';
|
|
8
8
|
import * as Exit from 'effect/Exit';
|
|
9
|
+
import * as Layer from 'effect/Layer';
|
|
10
|
+
import type * as ManagedRuntime from 'effect/ManagedRuntime';
|
|
9
11
|
import * as Scope from 'effect/Scope';
|
|
10
12
|
|
|
13
|
+
import type { AiService } from '@dxos/ai';
|
|
11
14
|
import { Event, synchronized } from '@dxos/async';
|
|
12
15
|
import {
|
|
13
16
|
type ComputeEdge,
|
|
@@ -22,15 +25,23 @@ import {
|
|
|
22
25
|
isNotExecuted,
|
|
23
26
|
} from '@dxos/conductor';
|
|
24
27
|
import { Resource } from '@dxos/context';
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
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
|
+
Trace,
|
|
37
|
+
TracingService,
|
|
38
|
+
} from '@dxos/functions';
|
|
27
39
|
import { log } from '@dxos/log';
|
|
28
40
|
import { type CanvasGraphModel } from '@dxos/react-ui-canvas-editor';
|
|
29
41
|
import { type ContentBlock } from '@dxos/types';
|
|
30
42
|
|
|
31
43
|
import { createComputeGraph } from '../hooks';
|
|
32
44
|
import { type ComputeShape } from '../shapes';
|
|
33
|
-
|
|
34
45
|
import { resolveComputeNode } from './node-defs';
|
|
35
46
|
|
|
36
47
|
// TODO(burdon): API package for conductor.
|
|
@@ -72,6 +83,15 @@ type ComputeOutputEvent = {
|
|
|
72
83
|
value: RuntimeValue;
|
|
73
84
|
};
|
|
74
85
|
|
|
86
|
+
// TODO(dmaretskyi): Re-use function servies definition.
|
|
87
|
+
export type ComputeServices =
|
|
88
|
+
| AiService.AiService
|
|
89
|
+
| Database.Service
|
|
90
|
+
| Feed.FeedService
|
|
91
|
+
| QueueService
|
|
92
|
+
| CredentialsService
|
|
93
|
+
| FunctionInvocationService;
|
|
94
|
+
|
|
75
95
|
/**
|
|
76
96
|
* Nodes that will automatically trigger the execution of the graph on startup.
|
|
77
97
|
*/
|
|
@@ -79,10 +99,10 @@ const AUTO_TRIGGER_NODES = ['chat', 'switch', 'constant'];
|
|
|
79
99
|
|
|
80
100
|
export const createComputeGraphController = (
|
|
81
101
|
graph: CanvasGraphModel<ComputeShape>,
|
|
82
|
-
|
|
102
|
+
computeRuntime: ManagedRuntime.ManagedRuntime<ComputeServices, never>,
|
|
83
103
|
) => {
|
|
84
104
|
const computeGraph = createComputeGraph(graph);
|
|
85
|
-
const controller = new ComputeGraphController(
|
|
105
|
+
const controller = new ComputeGraphController(computeRuntime, computeGraph);
|
|
86
106
|
return { controller, graph };
|
|
87
107
|
};
|
|
88
108
|
|
|
@@ -117,7 +137,7 @@ export class ComputeGraphController extends Resource {
|
|
|
117
137
|
public readonly events = new Event<ComputeEventPayload>();
|
|
118
138
|
|
|
119
139
|
constructor(
|
|
120
|
-
private readonly
|
|
140
|
+
private readonly _computeRuntime: ManagedRuntime.ManagedRuntime<ComputeServices, never>,
|
|
121
141
|
/** Persistent compute graph. */
|
|
122
142
|
private readonly _graph: ComputeGraphModel,
|
|
123
143
|
) {
|
|
@@ -232,37 +252,42 @@ export class ComputeGraphController extends Resource {
|
|
|
232
252
|
executor.setOutputs(nodeId, Effect.succeed(ValueBag.make(outputs)));
|
|
233
253
|
}
|
|
234
254
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
+
Layer.provideMerge(Trace.writerLayerNoop),
|
|
271
|
+
),
|
|
272
|
+
),
|
|
273
|
+
Effect.flatMap(computeValueBag),
|
|
274
|
+
Effect.withSpan('test'),
|
|
275
|
+
Effect.tap((values) => {
|
|
276
|
+
for (const [key, value] of Object.entries(values)) {
|
|
277
|
+
if (computingOutputs) {
|
|
278
|
+
this._onOutputComputed(nodeId, key, value);
|
|
279
|
+
} else {
|
|
280
|
+
this._onInputComputed(nodeId, key, value);
|
|
281
|
+
}
|
|
257
282
|
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
);
|
|
283
|
+
}),
|
|
284
|
+
);
|
|
261
285
|
|
|
262
|
-
|
|
286
|
+
yield* effect;
|
|
263
287
|
|
|
264
|
-
|
|
265
|
-
|
|
288
|
+
yield* Scope.close(scope, Exit.void);
|
|
289
|
+
}),
|
|
290
|
+
),
|
|
266
291
|
);
|
|
267
292
|
|
|
268
293
|
this.update.emit();
|
|
@@ -290,44 +315,52 @@ export class ComputeGraphController extends Resource {
|
|
|
290
315
|
: this._graph.nodes.filter((node) => node.type != null && AUTO_TRIGGER_NODES.includes(node.type));
|
|
291
316
|
const allAffectedNodes = [...new Set(triggerNodes.flatMap((node) => executor.getAllDependantNodes(node.id)))];
|
|
292
317
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
318
|
+
unwrapExit(
|
|
319
|
+
await this._computeRuntime.runPromiseExit(
|
|
320
|
+
Effect.gen(this, function* () {
|
|
321
|
+
const scope = yield* Scope.make();
|
|
322
|
+
|
|
323
|
+
// TODO(burdon): Return map?
|
|
324
|
+
const tasks: Effect.Effect<unknown, any, ComputeServices>[] = [];
|
|
325
|
+
for (const node of allAffectedNodes) {
|
|
326
|
+
// TODO(dmaretskyi): Code duplication.
|
|
327
|
+
const executable = yield* Effect.promise(() => resolveComputeNode(this._graph.getNode(node)));
|
|
328
|
+
const computingOutputs = executable.exec != null;
|
|
329
|
+
|
|
330
|
+
// TODO(dmaretskyi): Check if the node has a compute function and run computeOutputs if it does.
|
|
331
|
+
const effect = (computingOutputs ? executor.computeOutputs(node) : executor.computeInputs(node)).pipe(
|
|
332
|
+
Effect.withSpan('runGraph'),
|
|
333
|
+
Scope.extend(scope),
|
|
334
|
+
Effect.flatMap(computeValueBag),
|
|
335
|
+
Effect.provide(
|
|
336
|
+
ComputeEventLogger.layerFromTracing.pipe(
|
|
337
|
+
Layer.provideMerge(TracingService.layerNoop), // TODO(dmaretskyi): Plug-in tracing events to visual feedback in the compute graph editor.
|
|
338
|
+
Layer.provideMerge(Trace.writerLayerNoop),
|
|
339
|
+
),
|
|
340
|
+
),
|
|
341
|
+
|
|
342
|
+
Effect.withSpan('test'),
|
|
343
|
+
Effect.tap((values) => {
|
|
344
|
+
for (const [key, value] of Object.entries(values)) {
|
|
345
|
+
if (computingOutputs) {
|
|
346
|
+
this._onOutputComputed(node, key, value);
|
|
347
|
+
} else {
|
|
348
|
+
this._onInputComputed(node, key, value);
|
|
349
|
+
}
|
|
317
350
|
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
);
|
|
351
|
+
}),
|
|
352
|
+
);
|
|
321
353
|
|
|
322
|
-
|
|
323
|
-
|
|
354
|
+
tasks.push(effect);
|
|
355
|
+
}
|
|
324
356
|
|
|
325
|
-
|
|
326
|
-
|
|
357
|
+
//
|
|
358
|
+
yield* Effect.all(tasks);
|
|
327
359
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
360
|
+
//
|
|
361
|
+
yield* Scope.close(scope, Exit.void);
|
|
362
|
+
}),
|
|
363
|
+
),
|
|
331
364
|
);
|
|
332
365
|
|
|
333
366
|
this.update.emit();
|
package/src/graph/node-defs.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
registry,
|
|
13
13
|
} from '@dxos/conductor';
|
|
14
14
|
import { raise } from '@dxos/debug';
|
|
15
|
-
import {
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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:
|
|
80
|
+
id: Obj.ID.random(),
|
|
81
81
|
type,
|
|
82
82
|
...props,
|
|
83
83
|
});
|
|
@@ -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 {
|
|
8
|
+
import { Obj, Ref } from '@dxos/echo';
|
|
9
9
|
import { invariant } from '@dxos/invariant';
|
|
10
|
-
import {
|
|
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;
|
|
@@ -27,7 +26,7 @@ export const mapEdge = (
|
|
|
27
26
|
invariant(targetNode?.node);
|
|
28
27
|
|
|
29
28
|
return {
|
|
30
|
-
id:
|
|
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
|
|
117
|
-
|
|
115
|
+
Obj.change(functionTrigger, (obj) => {
|
|
116
|
+
obj.function = Ref.make(graph.root);
|
|
117
|
+
obj.inputNodeId = computeNode.id;
|
|
118
|
+
});
|
|
118
119
|
};
|
|
119
120
|
|
|
120
121
|
const deleteTriggerObjects = (computeGraph: ComputeGraphModel, deleted: CanvasGraphModel) => {
|
|
121
|
-
const
|
|
122
|
-
if (!
|
|
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
|
-
|
|
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 {
|
|
8
|
+
import { Graph } from '@dxos/graph';
|
|
9
9
|
|
|
10
10
|
import { createGptCircuit } from './testing';
|
|
11
11
|
|
|
12
12
|
export const Shape = Schema.extend(
|
|
13
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
85
|
+
feedShape,
|
|
86
86
|
threadShape,
|
|
87
87
|
textShape,
|
|
88
88
|
surfaceShape,
|
package/src/schema.test.ts
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
import { describe, test } from 'vitest';
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import { BaseGraphNode, Graph } from '@dxos/graph';
|
|
8
|
+
import { Graph } from '@dxos/graph';
|
|
10
9
|
import {
|
|
10
|
+
CanvasBoard,
|
|
11
|
+
CanvasGraphModel,
|
|
11
12
|
Polygon,
|
|
12
|
-
Shape,
|
|
13
13
|
createEllipse,
|
|
14
14
|
createPath,
|
|
15
15
|
createRectangle,
|
|
@@ -21,25 +21,25 @@ import { ComputeShape, createFunction, createSwitch } from './shapes';
|
|
|
21
21
|
|
|
22
22
|
describe('compute', () => {
|
|
23
23
|
test('model', ({ expect }) => {
|
|
24
|
-
|
|
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(
|
|
29
|
+
expect(Schema.is(CanvasBoard.Shape)(node)).toBe(true);
|
|
30
|
+
expect(Schema.is(Graph.Node)(node)).toBe(true);
|
|
31
31
|
|
|
32
|
-
const graph =
|
|
33
|
-
graph.nodes.push(node);
|
|
32
|
+
const graph: Graph.Any = { nodes: [], edges: [] };
|
|
33
|
+
graph.nodes.push(node);
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
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 } }));
|
package/src/shapes/Audio.tsx
CHANGED
|
@@ -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
|
|
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-
|
|
40
|
+
classNames={['transition opacity-20 duration-1000', active && 'opacity-100 text-error-text']}
|
|
42
41
|
size={8}
|
|
43
42
|
onClick={() => setActive(!active)}
|
|
44
43
|
/>
|
package/src/shapes/Beacon.tsx
CHANGED
|
@@ -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
|
|
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']}
|
package/src/shapes/Boolean.tsx
CHANGED
|
@@ -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
|
|
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='
|
|
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} />
|
package/src/shapes/Chat.tsx
CHANGED
|
@@ -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
|
|
package/src/shapes/Constant.tsx
CHANGED
|
@@ -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
|
|
|
@@ -6,31 +6,34 @@ import * as Schema from 'effect/Schema';
|
|
|
6
6
|
import React, { Fragment } from 'react';
|
|
7
7
|
|
|
8
8
|
import { DEFAULT_OUTPUT, QueueInput, QueueOutput } from '@dxos/conductor';
|
|
9
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
9
|
+
import { ScrollArea, type ThemedClassName } from '@dxos/react-ui';
|
|
10
10
|
import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
11
|
-
import { mx } from '@dxos/
|
|
11
|
+
import { mx } from '@dxos/ui-theme';
|
|
12
12
|
|
|
13
13
|
import { useComputeNodeState } from '../hooks';
|
|
14
|
-
|
|
15
14
|
import { createFunctionAnchors } from './common';
|
|
16
15
|
import { Box, type BoxActionHandler } from './common';
|
|
17
16
|
import { ComputeShape, type CreateShapeProps, createShape } from './defs';
|
|
18
17
|
|
|
19
|
-
export const
|
|
18
|
+
export const FeedShape = Schema.extend(
|
|
20
19
|
ComputeShape,
|
|
21
20
|
Schema.Struct({
|
|
22
21
|
type: Schema.Literal('queue'),
|
|
23
22
|
}),
|
|
24
23
|
);
|
|
25
24
|
|
|
26
|
-
export type
|
|
25
|
+
export type FeedShape = Schema.Schema.Type<typeof FeedShape>;
|
|
27
26
|
|
|
28
|
-
export type
|
|
27
|
+
export type CreateFeedProps = CreateShapeProps<FeedShape>;
|
|
29
28
|
|
|
30
|
-
export const
|
|
31
|
-
createShape<
|
|
29
|
+
export const createFeed = (props: CreateFeedProps) =>
|
|
30
|
+
createShape<FeedShape>({
|
|
31
|
+
type: 'queue',
|
|
32
|
+
size: { width: 256, height: 512 },
|
|
33
|
+
...props,
|
|
34
|
+
});
|
|
32
35
|
|
|
33
|
-
export const
|
|
36
|
+
export const FeedComponent = ({ shape }: ShapeComponentProps<FeedShape>) => {
|
|
34
37
|
const { runtime } = useComputeNodeState(shape);
|
|
35
38
|
const items = runtime.outputs[DEFAULT_OUTPUT]?.type === 'executed' ? runtime.outputs[DEFAULT_OUTPUT].value : [];
|
|
36
39
|
|
|
@@ -42,22 +45,24 @@ export const QueueComponent = ({ shape }: ShapeComponentProps<QueueShape>) => {
|
|
|
42
45
|
|
|
43
46
|
return (
|
|
44
47
|
<Box shape={shape} status={`${items.length} items`} onAction={handleAction}>
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
<ScrollArea.Root orientation='vertical'>
|
|
49
|
+
<ScrollArea.Viewport classNames='divide-y divide-separator'>
|
|
50
|
+
{[...items].map((item, i) => (
|
|
51
|
+
<FeedItem key={i} classNames='p-1 px-2' item={item} />
|
|
52
|
+
))}
|
|
53
|
+
</ScrollArea.Viewport>
|
|
54
|
+
</ScrollArea.Root>
|
|
50
55
|
</Box>
|
|
51
56
|
);
|
|
52
57
|
};
|
|
53
58
|
|
|
54
|
-
export const
|
|
59
|
+
export const FeedItem = ({ classNames, item }: ThemedClassName<{ item: any }>) => {
|
|
55
60
|
if (typeof item !== 'object') {
|
|
56
61
|
return <div className={mx(classNames, 'whitespace-pre-wrap')}>{item}</div>;
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
return (
|
|
60
|
-
<div className={mx('grid grid-cols-[
|
|
65
|
+
<div className={mx('grid grid-cols-[80px_1fr]', classNames)}>
|
|
61
66
|
{Object.entries(item).map(([key, value]) => (
|
|
62
67
|
<Fragment key={key}>
|
|
63
68
|
<div className='p-1 text-xs text-subdued'>{key}</div>
|
|
@@ -68,12 +73,12 @@ export const QueueItem = ({ classNames, item }: ThemedClassName<{ item: any }>)
|
|
|
68
73
|
);
|
|
69
74
|
};
|
|
70
75
|
|
|
71
|
-
export const
|
|
72
|
-
type: '
|
|
73
|
-
name: '
|
|
76
|
+
export const feedShape: ShapeDef<FeedShape> = {
|
|
77
|
+
type: 'feed',
|
|
78
|
+
name: 'Feed',
|
|
74
79
|
icon: 'ph--queue--regular',
|
|
75
|
-
component:
|
|
76
|
-
createShape:
|
|
80
|
+
component: FeedComponent,
|
|
81
|
+
createShape: createFeed,
|
|
77
82
|
getAnchors: (shape) => createFunctionAnchors(shape, QueueInput, QueueOutput),
|
|
78
83
|
resizable: true,
|
|
79
84
|
};
|