@dxos/react-ui-canvas-compute 0.7.5-labs.5f04cf6
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/LICENSE +8 -0
- package/README.md +1 -0
- package/dist/lib/browser/index.mjs +2499 -0
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -0
- package/dist/lib/node/index.cjs +2591 -0
- package/dist/lib/node/index.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -0
- package/dist/lib/node-esm/index.mjs +2499 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/types/src/compute-layout.d.ts +9 -0
- package/dist/types/src/compute-layout.d.ts.map +1 -0
- package/dist/types/src/compute.stories.d.ts +28 -0
- package/dist/types/src/compute.stories.d.ts.map +1 -0
- package/dist/types/src/graph/controller.d.ts +139 -0
- package/dist/types/src/graph/controller.d.ts.map +1 -0
- package/dist/types/src/graph/index.d.ts +3 -0
- package/dist/types/src/graph/index.d.ts.map +1 -0
- package/dist/types/src/graph/node-defs.d.ts +6 -0
- package/dist/types/src/graph/node-defs.d.ts.map +1 -0
- package/dist/types/src/hooks/compute-context.d.ts +7 -0
- package/dist/types/src/hooks/compute-context.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +4 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useComputeNodeState.d.ts +19 -0
- package/dist/types/src/hooks/useComputeNodeState.d.ts.map +1 -0
- package/dist/types/src/hooks/useGraphMonitor.d.ts +14 -0
- package/dist/types/src/hooks/useGraphMonitor.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +6 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/json.test.d.ts +21 -0
- package/dist/types/src/json.test.d.ts.map +1 -0
- package/dist/types/src/registry.d.ts +9 -0
- package/dist/types/src/registry.d.ts.map +1 -0
- package/dist/types/src/schema.test.d.ts +2 -0
- package/dist/types/src/schema.test.d.ts.map +1 -0
- package/dist/types/src/shapes/Append.d.ts +54 -0
- package/dist/types/src/shapes/Append.d.ts.map +1 -0
- package/dist/types/src/shapes/Array.d.ts +38 -0
- package/dist/types/src/shapes/Array.d.ts.map +1 -0
- package/dist/types/src/shapes/Audio.d.ts +54 -0
- package/dist/types/src/shapes/Audio.d.ts.map +1 -0
- package/dist/types/src/shapes/Beacon.d.ts +54 -0
- package/dist/types/src/shapes/Beacon.d.ts.map +1 -0
- package/dist/types/src/shapes/Boolean.d.ts +233 -0
- package/dist/types/src/shapes/Boolean.d.ts.map +1 -0
- package/dist/types/src/shapes/Chat.d.ts +57 -0
- package/dist/types/src/shapes/Chat.d.ts.map +1 -0
- package/dist/types/src/shapes/Constant.d.ts +60 -0
- package/dist/types/src/shapes/Constant.d.ts.map +1 -0
- package/dist/types/src/shapes/Database.d.ts +54 -0
- package/dist/types/src/shapes/Database.d.ts.map +1 -0
- package/dist/types/src/shapes/Function.d.ts +54 -0
- package/dist/types/src/shapes/Function.d.ts.map +1 -0
- package/dist/types/src/shapes/Gpt.d.ts +54 -0
- package/dist/types/src/shapes/Gpt.d.ts.map +1 -0
- package/dist/types/src/shapes/GptRealtime.d.ts +54 -0
- package/dist/types/src/shapes/GptRealtime.d.ts.map +1 -0
- package/dist/types/src/shapes/Json.d.ts +107 -0
- package/dist/types/src/shapes/Json.d.ts.map +1 -0
- package/dist/types/src/shapes/Logic.d.ts +109 -0
- package/dist/types/src/shapes/Logic.d.ts.map +1 -0
- package/dist/types/src/shapes/Queue.d.ts +58 -0
- package/dist/types/src/shapes/Queue.d.ts.map +1 -0
- package/dist/types/src/shapes/RNG.d.ts +58 -0
- package/dist/types/src/shapes/RNG.d.ts.map +1 -0
- package/dist/types/src/shapes/Scope.d.ts +54 -0
- package/dist/types/src/shapes/Scope.d.ts.map +1 -0
- package/dist/types/src/shapes/Surface.d.ts +54 -0
- package/dist/types/src/shapes/Surface.d.ts.map +1 -0
- package/dist/types/src/shapes/Switch.d.ts +54 -0
- package/dist/types/src/shapes/Switch.d.ts.map +1 -0
- package/dist/types/src/shapes/Table.d.ts +54 -0
- package/dist/types/src/shapes/Table.d.ts.map +1 -0
- package/dist/types/src/shapes/Template.d.ts +56 -0
- package/dist/types/src/shapes/Template.d.ts.map +1 -0
- package/dist/types/src/shapes/Text.d.ts +54 -0
- package/dist/types/src/shapes/Text.d.ts.map +1 -0
- package/dist/types/src/shapes/TextToImage.d.ts +54 -0
- package/dist/types/src/shapes/TextToImage.d.ts.map +1 -0
- package/dist/types/src/shapes/Thread.d.ts +58 -0
- package/dist/types/src/shapes/Thread.d.ts.map +1 -0
- package/dist/types/src/shapes/Trigger.d.ts +64 -0
- package/dist/types/src/shapes/Trigger.d.ts.map +1 -0
- package/dist/types/src/shapes/common/Box.d.ts +25 -0
- package/dist/types/src/shapes/common/Box.d.ts.map +1 -0
- package/dist/types/src/shapes/common/FunctionBody.d.ts +15 -0
- package/dist/types/src/shapes/common/FunctionBody.d.ts.map +1 -0
- package/dist/types/src/shapes/common/TypeSelect.d.ts +4 -0
- package/dist/types/src/shapes/common/TypeSelect.d.ts.map +1 -0
- package/dist/types/src/shapes/common/index.d.ts +4 -0
- package/dist/types/src/shapes/common/index.d.ts.map +1 -0
- package/dist/types/src/shapes/defs.d.ts +39 -0
- package/dist/types/src/shapes/defs.d.ts.map +1 -0
- package/dist/types/src/shapes/index.d.ts +27 -0
- package/dist/types/src/shapes/index.d.ts.map +1 -0
- package/dist/types/src/testing/circuits.d.ts +193 -0
- package/dist/types/src/testing/circuits.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +85 -0
- package/src/README.md +47 -0
- package/src/compute-layout.ts +37 -0
- package/src/compute.stories.tsx +362 -0
- package/src/graph/controller.ts +405 -0
- package/src/graph/index.ts +6 -0
- package/src/graph/node-defs.ts +82 -0
- package/src/hooks/compute-context.ts +19 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useComputeNodeState.ts +83 -0
- package/src/hooks/useGraphMonitor.ts +133 -0
- package/src/index.ts +9 -0
- package/src/json.test.ts +35 -0
- package/src/registry.ts +100 -0
- package/src/schema.test.ts +62 -0
- package/src/shapes/Append.tsx +43 -0
- package/src/shapes/Array.tsx +61 -0
- package/src/shapes/Audio.tsx +55 -0
- package/src/shapes/Beacon.tsx +56 -0
- package/src/shapes/Boolean.tsx +215 -0
- package/src/shapes/Chat.tsx +77 -0
- package/src/shapes/Constant.tsx +125 -0
- package/src/shapes/Database.tsx +39 -0
- package/src/shapes/Function.tsx +40 -0
- package/src/shapes/Gpt.tsx +91 -0
- package/src/shapes/GptRealtime.tsx +168 -0
- package/src/shapes/Json.tsx +103 -0
- package/src/shapes/Logic.tsx +82 -0
- package/src/shapes/Queue.tsx +78 -0
- package/src/shapes/RNG.tsx +84 -0
- package/src/shapes/Scope.tsx +54 -0
- package/src/shapes/Surface.tsx +57 -0
- package/src/shapes/Switch.tsx +53 -0
- package/src/shapes/Table.tsx +45 -0
- package/src/shapes/Template.tsx +98 -0
- package/src/shapes/Text.tsx +56 -0
- package/src/shapes/TextToImage.tsx +39 -0
- package/src/shapes/Thread.tsx +87 -0
- package/src/shapes/Trigger.tsx +152 -0
- package/src/shapes/common/Box.tsx +74 -0
- package/src/shapes/common/FunctionBody.tsx +122 -0
- package/src/shapes/common/TypeSelect.tsx +27 -0
- package/src/shapes/common/index.ts +7 -0
- package/src/shapes/defs.ts +50 -0
- package/src/shapes/index.ts +31 -0
- package/src/testing/circuits.ts +320 -0
- package/src/testing/index.ts +5 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { S } from '@dxos/echo-schema';
|
|
8
|
+
import { Icon } from '@dxos/react-ui';
|
|
9
|
+
import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
10
|
+
|
|
11
|
+
import { createFunctionAnchors } from './common';
|
|
12
|
+
import { ComputeShape, createShape, type CreateShapeProps } from './defs';
|
|
13
|
+
|
|
14
|
+
export const GptRealtimeShape = S.extend(
|
|
15
|
+
ComputeShape,
|
|
16
|
+
S.Struct({
|
|
17
|
+
type: S.Literal('gpt-realtime'),
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export type GptRealtimeShape = S.Schema.Type<typeof GptRealtimeShape>;
|
|
22
|
+
|
|
23
|
+
export type CreateGptRealtimeProps = CreateShapeProps<GptRealtimeShape>;
|
|
24
|
+
|
|
25
|
+
export const createGptRealtime = (props: CreateGptRealtimeProps) =>
|
|
26
|
+
createShape<GptRealtimeShape>({ type: 'gpt-realtime', size: { width: 256, height: 256 }, ...props });
|
|
27
|
+
|
|
28
|
+
export const GptRealtimeComponent = ({ shape }: ShapeComponentProps<GptRealtimeShape>) => {
|
|
29
|
+
const [isLive, setIsLive] = useState(false);
|
|
30
|
+
const [isReady, setIsReady] = useState(false);
|
|
31
|
+
|
|
32
|
+
const start = async () => {
|
|
33
|
+
setIsLive(true);
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
// Create WebRTC connection
|
|
37
|
+
const peerConnection = new RTCPeerConnection();
|
|
38
|
+
|
|
39
|
+
// Handle incoming audio
|
|
40
|
+
peerConnection.ontrack = (event) => {
|
|
41
|
+
const audioElement = document.createElement('audio');
|
|
42
|
+
audioElement.srcObject = event.streams[0];
|
|
43
|
+
audioElement.autoplay = true;
|
|
44
|
+
audioElement.controls = false;
|
|
45
|
+
audioElement.style.display = 'none';
|
|
46
|
+
document.body.appendChild(audioElement);
|
|
47
|
+
setIsReady(true);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Get microphone stream
|
|
51
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
52
|
+
|
|
53
|
+
// Add microphone track to connection
|
|
54
|
+
stream.getTracks().forEach((track) => peerConnection.addTransceiver(track, { direction: 'sendrecv' }));
|
|
55
|
+
|
|
56
|
+
// Create offer
|
|
57
|
+
const offer = await peerConnection.createOffer();
|
|
58
|
+
await peerConnection.setLocalDescription(offer);
|
|
59
|
+
|
|
60
|
+
// Send offer to backend and get answer
|
|
61
|
+
const response = await fetch(`${AI_SERVICE_URL}/rtc-connect`, {
|
|
62
|
+
method: 'POST',
|
|
63
|
+
body: offer.sdp,
|
|
64
|
+
headers: {
|
|
65
|
+
'Content-Type': 'application/sdp',
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const answer = await response.text();
|
|
70
|
+
|
|
71
|
+
// Set remote description with answer
|
|
72
|
+
await peerConnection.setRemoteDescription({
|
|
73
|
+
sdp: answer,
|
|
74
|
+
type: 'answer',
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const dataChannel = peerConnection.createDataChannel('response');
|
|
78
|
+
|
|
79
|
+
const configureData = () => {
|
|
80
|
+
console.log('Configuring data channel');
|
|
81
|
+
const event = {
|
|
82
|
+
type: 'session.update',
|
|
83
|
+
session: {
|
|
84
|
+
modalities: ['text', 'audio'],
|
|
85
|
+
// Provide the tools. Note they match the keys in the `fns` object above
|
|
86
|
+
tools: [],
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
dataChannel.send(JSON.stringify(event));
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
dataChannel.addEventListener('open', (ev) => {
|
|
93
|
+
console.log('Opening data channel', ev);
|
|
94
|
+
configureData();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// {
|
|
98
|
+
// "type": "response.function_call_arguments.done",
|
|
99
|
+
// "event_id": "event_Ad2gt864G595umbCs2aF9",
|
|
100
|
+
// "response_id": "resp_Ad2griUWUjsyeLyAVtTtt",
|
|
101
|
+
// "item_id": "item_Ad2gsxA84w9GgEvFwW1Ex",
|
|
102
|
+
// "output_index": 1,
|
|
103
|
+
// "call_id": "call_PG12S5ER7l7HrvZz",
|
|
104
|
+
// "name": "get_weather",
|
|
105
|
+
// "arguments": "{\"location\":\"Portland, Oregon\"}"
|
|
106
|
+
// }
|
|
107
|
+
|
|
108
|
+
dataChannel.addEventListener('message', async (ev) => {
|
|
109
|
+
const msg = JSON.parse(ev.data);
|
|
110
|
+
// console.log('realtime gpt event', msg);
|
|
111
|
+
// Handle function calls
|
|
112
|
+
if (msg.type === 'response.function_call_arguments.done') {
|
|
113
|
+
// const fn = fns[msg.name];
|
|
114
|
+
// if (fn !== undefined) {
|
|
115
|
+
// console.log(`Calling local function ${msg.name} with ${msg.arguments}`);
|
|
116
|
+
// const args = JSON.parse(msg.arguments);
|
|
117
|
+
// const result = await fn(args);
|
|
118
|
+
// console.log('result', result);
|
|
119
|
+
// // Let OpenAI know that the function has been called and share it's output
|
|
120
|
+
// const event = {
|
|
121
|
+
// type: 'conversation.item.create',
|
|
122
|
+
// item: {
|
|
123
|
+
// type: 'function_call_output',
|
|
124
|
+
// call_id: msg.call_id, // call_id from the function_call message
|
|
125
|
+
// output: JSON.stringify(result), // result of the function
|
|
126
|
+
// },
|
|
127
|
+
// };
|
|
128
|
+
// dataChannel.send(JSON.stringify(event));
|
|
129
|
+
// }
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error('Error in realtime session:', error);
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<div className='flex w-full justify-center items-center'>
|
|
140
|
+
<Icon
|
|
141
|
+
icon={isReady ? 'ph--waveform--regular' : isLive ? 'ph--pulse--regular' : 'ph--play--regular'}
|
|
142
|
+
size={16}
|
|
143
|
+
classNames={!isLive && 'cursor-pointer'}
|
|
144
|
+
onClick={start}
|
|
145
|
+
/>
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export const gptRealtimeShape: ShapeDef<GptRealtimeShape> = {
|
|
151
|
+
type: 'gpt-realtime',
|
|
152
|
+
name: 'GPT Realtime',
|
|
153
|
+
icon: 'ph--pulse--regular',
|
|
154
|
+
component: GptRealtimeComponent,
|
|
155
|
+
createShape: createGptRealtime,
|
|
156
|
+
// TODO(dmaretskyi): Can we fetch the schema dynamically?
|
|
157
|
+
getAnchors: (shape) =>
|
|
158
|
+
createFunctionAnchors(
|
|
159
|
+
shape,
|
|
160
|
+
S.Struct({
|
|
161
|
+
audio: S.Any,
|
|
162
|
+
}),
|
|
163
|
+
S.Struct({}),
|
|
164
|
+
),
|
|
165
|
+
resizable: true,
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const AI_SERVICE_URL = 'http://localhost:8788';
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { DEFAULT_INPUT, DefaultOutput, JsonTransformInput } from '@dxos/conductor';
|
|
8
|
+
import { S } from '@dxos/echo-schema';
|
|
9
|
+
import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
10
|
+
import { createAnchorMap } from '@dxos/react-ui-canvas-editor';
|
|
11
|
+
import { JsonFilter } from '@dxos/react-ui-syntax-highlighter';
|
|
12
|
+
|
|
13
|
+
import { createFunctionAnchors, getHeight, Box } from './common';
|
|
14
|
+
import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
|
|
15
|
+
import { useComputeNodeState } from '../hooks';
|
|
16
|
+
|
|
17
|
+
//
|
|
18
|
+
// Data
|
|
19
|
+
//
|
|
20
|
+
|
|
21
|
+
export const JsonShape = S.extend(
|
|
22
|
+
ComputeShape,
|
|
23
|
+
S.Struct({
|
|
24
|
+
type: S.Literal('json'),
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export type JsonShape = S.Schema.Type<typeof JsonShape>;
|
|
29
|
+
|
|
30
|
+
export const JsonTransformShape = S.extend(
|
|
31
|
+
ComputeShape,
|
|
32
|
+
S.Struct({
|
|
33
|
+
type: S.Literal('json-transform'),
|
|
34
|
+
}),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
export type JsonTransformShape = S.Schema.Type<typeof JsonTransformShape>;
|
|
38
|
+
|
|
39
|
+
//
|
|
40
|
+
// Component
|
|
41
|
+
//
|
|
42
|
+
|
|
43
|
+
export type JsonComponentProps = ShapeComponentProps<JsonShape>;
|
|
44
|
+
|
|
45
|
+
export const JsonComponent = ({ shape, ...props }: JsonComponentProps) => {
|
|
46
|
+
const { runtime } = useComputeNodeState(shape);
|
|
47
|
+
const input = runtime.inputs[DEFAULT_INPUT];
|
|
48
|
+
const value = input?.type === 'executed' ? input.value : undefined;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<Box shape={shape}>
|
|
52
|
+
<JsonFilter data={value} classNames='text-xs' />
|
|
53
|
+
</Box>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type JsonTransformComponentProps = ShapeComponentProps<JsonTransformShape>;
|
|
58
|
+
|
|
59
|
+
export const JsonTransformComponent = ({ shape, ...props }: JsonTransformComponentProps) => {
|
|
60
|
+
return <Box shape={shape} />;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
//
|
|
64
|
+
// Defs
|
|
65
|
+
//
|
|
66
|
+
|
|
67
|
+
export type CreateJsonProps = CreateShapeProps<JsonShape>;
|
|
68
|
+
|
|
69
|
+
export const createJson = (props: CreateJsonProps) =>
|
|
70
|
+
createShape<JsonShape>({ type: 'json', size: { width: 256, height: 256 }, ...props });
|
|
71
|
+
|
|
72
|
+
export const jsonShape: ShapeDef<JsonShape> = {
|
|
73
|
+
type: 'json',
|
|
74
|
+
name: 'JSON',
|
|
75
|
+
icon: 'ph--code--regular',
|
|
76
|
+
component: (props) => <JsonComponent {...props} />,
|
|
77
|
+
createShape: createJson,
|
|
78
|
+
getAnchors: (shape) =>
|
|
79
|
+
createAnchorMap(shape, {
|
|
80
|
+
[createAnchorId('input')]: { x: -1, y: 0 },
|
|
81
|
+
[createAnchorId('output')]: { x: 1, y: 0 },
|
|
82
|
+
}),
|
|
83
|
+
resizable: true,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export type CreateJsonTransformProps = CreateShapeProps<JsonTransformShape> & { expression?: string };
|
|
87
|
+
|
|
88
|
+
export const createJsonTransform = (props: CreateJsonTransformProps) =>
|
|
89
|
+
createShape<JsonTransformShape>({
|
|
90
|
+
type: 'json-transform',
|
|
91
|
+
size: { width: 128, height: getHeight(JsonTransformInput) },
|
|
92
|
+
...props,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export const jsonTransformShape: ShapeDef<JsonTransformShape> = {
|
|
96
|
+
type: 'json-transform',
|
|
97
|
+
name: 'Transform',
|
|
98
|
+
icon: 'ph--shuffle-simple--regular',
|
|
99
|
+
component: (props) => <JsonTransformComponent {...props} />,
|
|
100
|
+
createShape: createJsonTransform,
|
|
101
|
+
getAnchors: (shape) => createFunctionAnchors(shape, JsonTransformInput, DefaultOutput),
|
|
102
|
+
resizable: true,
|
|
103
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { IfElseInput, IfElseOutput, IfInput, IfOutput } from '@dxos/conductor';
|
|
8
|
+
import { S } from '@dxos/echo-schema';
|
|
9
|
+
import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
10
|
+
|
|
11
|
+
import { createFunctionAnchors, FunctionBody, getHeight } from './common';
|
|
12
|
+
import { ComputeShape, createShape, type CreateShapeProps } from './defs';
|
|
13
|
+
|
|
14
|
+
//
|
|
15
|
+
// Data
|
|
16
|
+
//
|
|
17
|
+
|
|
18
|
+
export const IfShape = S.extend(
|
|
19
|
+
ComputeShape,
|
|
20
|
+
S.Struct({
|
|
21
|
+
type: S.Literal('if'),
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export type IfShape = S.Schema.Type<typeof IfShape>;
|
|
26
|
+
|
|
27
|
+
export const IfElseShape = S.extend(
|
|
28
|
+
ComputeShape,
|
|
29
|
+
S.Struct({
|
|
30
|
+
type: S.Literal('if-else'),
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export type IfElseShape = S.Schema.Type<typeof IfElseShape>;
|
|
35
|
+
|
|
36
|
+
//
|
|
37
|
+
// Components
|
|
38
|
+
//
|
|
39
|
+
|
|
40
|
+
export type IfComponentProps = ShapeComponentProps<IfShape>;
|
|
41
|
+
|
|
42
|
+
export const IfComponent = ({ shape, ...props }: IfComponentProps) => {
|
|
43
|
+
return <FunctionBody shape={shape} inputSchema={IfInput} outputSchema={IfOutput} />;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type IfElseComponentProps = ShapeComponentProps<IfElseShape>;
|
|
47
|
+
|
|
48
|
+
export const IfElseComponent = ({ shape, ...props }: IfElseComponentProps) => {
|
|
49
|
+
return <FunctionBody shape={shape} inputSchema={IfElseInput} outputSchema={IfElseOutput} />;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
//
|
|
53
|
+
// Defs
|
|
54
|
+
//
|
|
55
|
+
|
|
56
|
+
export type CreateIfProps = CreateShapeProps<IfShape> & { if?: string };
|
|
57
|
+
|
|
58
|
+
export const createIf = (props: CreateIfProps) =>
|
|
59
|
+
createShape<IfShape>({ type: 'if', size: { width: 192, height: getHeight(IfInput) }, ...props });
|
|
60
|
+
|
|
61
|
+
export const ifShape: ShapeDef<IfShape> = {
|
|
62
|
+
type: 'if',
|
|
63
|
+
name: 'IF',
|
|
64
|
+
icon: 'ph--arrows-split--regular',
|
|
65
|
+
component: (props) => <IfComponent {...props} />,
|
|
66
|
+
createShape: createIf,
|
|
67
|
+
getAnchors: (shape) => createFunctionAnchors(shape, IfInput, IfOutput),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export type CreateIfElseProps = CreateShapeProps<IfShape> & { if?: string };
|
|
71
|
+
|
|
72
|
+
export const createIfElse = (props: CreateIfElseProps) =>
|
|
73
|
+
createShape<IfElseShape>({ type: 'if-else', size: { width: 192, height: getHeight(IfElseInput) }, ...props });
|
|
74
|
+
|
|
75
|
+
export const ifElseShape: ShapeDef<IfElseShape> = {
|
|
76
|
+
type: 'if-else',
|
|
77
|
+
name: 'IF/ELSE',
|
|
78
|
+
icon: 'ph--arrows-merge--regular',
|
|
79
|
+
component: (props) => <IfElseComponent {...props} />,
|
|
80
|
+
createShape: createIfElse,
|
|
81
|
+
getAnchors: (shape) => createFunctionAnchors(shape, IfElseInput, IfElseOutput),
|
|
82
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { Fragment } from 'react';
|
|
6
|
+
|
|
7
|
+
import { DEFAULT_OUTPUT, QueueInput, QueueOutput } from '@dxos/conductor';
|
|
8
|
+
import { S } from '@dxos/echo-schema';
|
|
9
|
+
import { type ThemedClassName } from '@dxos/react-ui';
|
|
10
|
+
import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
11
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
12
|
+
|
|
13
|
+
import { createFunctionAnchors } from './common';
|
|
14
|
+
import { Box, type BoxActionHandler } from './common';
|
|
15
|
+
import { ComputeShape, createShape, type CreateShapeProps } from './defs';
|
|
16
|
+
import { useComputeNodeState } from '../hooks';
|
|
17
|
+
|
|
18
|
+
export const QueueShape = S.extend(
|
|
19
|
+
ComputeShape,
|
|
20
|
+
S.Struct({
|
|
21
|
+
type: S.Literal('queue'),
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export type QueueShape = S.Schema.Type<typeof QueueShape>;
|
|
26
|
+
|
|
27
|
+
export type CreateQueueProps = CreateShapeProps<QueueShape>;
|
|
28
|
+
|
|
29
|
+
export const createQueue = (props: CreateQueueProps) =>
|
|
30
|
+
createShape<QueueShape>({ type: 'queue', size: { width: 256, height: 512 }, ...props });
|
|
31
|
+
|
|
32
|
+
export const QueueComponent = ({ shape }: ShapeComponentProps<QueueShape>) => {
|
|
33
|
+
const { runtime } = useComputeNodeState(shape);
|
|
34
|
+
const items = runtime.outputs[DEFAULT_OUTPUT]?.type === 'executed' ? runtime.outputs[DEFAULT_OUTPUT].value : [];
|
|
35
|
+
|
|
36
|
+
const handleAction: BoxActionHandler = (action) => {
|
|
37
|
+
if (action === 'run') {
|
|
38
|
+
runtime.evalNode();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Box shape={shape} status={`${items.length} items`} onAction={handleAction}>
|
|
44
|
+
<div className='flex flex-col w-full overflow-y-scroll divide-y divide-separator'>
|
|
45
|
+
{[...items].map((item, i) => (
|
|
46
|
+
<QueueItem key={i} classNames='p-1 px-2' item={item} />
|
|
47
|
+
))}
|
|
48
|
+
</div>
|
|
49
|
+
</Box>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const QueueItem = ({ classNames, item }: ThemedClassName<{ item: any }>) => {
|
|
54
|
+
if (typeof item !== 'object') {
|
|
55
|
+
return <div className={mx(classNames, 'whitespace-pre-wrap')}>{item}</div>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div className={mx('grid grid-cols-[80px,1fr]', classNames)}>
|
|
60
|
+
{Object.entries(item).map(([key, value]) => (
|
|
61
|
+
<Fragment key={key}>
|
|
62
|
+
<div className='p-1 text-xs text-subdued'>{key}</div>
|
|
63
|
+
<div>{typeof value === 'string' ? value : JSON.stringify(value)}</div>
|
|
64
|
+
</Fragment>
|
|
65
|
+
))}
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const queueShape: ShapeDef<QueueShape> = {
|
|
71
|
+
type: 'queue',
|
|
72
|
+
name: 'Queue',
|
|
73
|
+
icon: 'ph--queue--regular',
|
|
74
|
+
component: QueueComponent,
|
|
75
|
+
createShape: createQueue,
|
|
76
|
+
getAnchors: (shape) => createFunctionAnchors(shape, QueueInput, QueueOutput),
|
|
77
|
+
resizable: true,
|
|
78
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useEffect, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { DEFAULT_OUTPUT } from '@dxos/conductor';
|
|
8
|
+
import { S } from '@dxos/echo-schema';
|
|
9
|
+
import { Icon, type IconProps } from '@dxos/react-ui';
|
|
10
|
+
import { createAnchorMap, type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
11
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
12
|
+
|
|
13
|
+
import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
|
|
14
|
+
import { useComputeNodeState } from '../hooks';
|
|
15
|
+
|
|
16
|
+
export const RandomShape = S.extend(
|
|
17
|
+
ComputeShape,
|
|
18
|
+
S.Struct({
|
|
19
|
+
type: S.Literal('rng'),
|
|
20
|
+
min: S.optional(S.Number),
|
|
21
|
+
max: S.optional(S.Number),
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export type RandomShape = S.Schema.Type<typeof RandomShape>;
|
|
26
|
+
|
|
27
|
+
export type CreateRandomProps = CreateShapeProps<RandomShape>;
|
|
28
|
+
|
|
29
|
+
export const createRandom = (props: CreateRandomProps) =>
|
|
30
|
+
createShape<RandomShape>({ type: 'rng', size: { width: 64, height: 64 }, ...props });
|
|
31
|
+
|
|
32
|
+
const icons = [
|
|
33
|
+
'ph--dice-one--regular',
|
|
34
|
+
'ph--dice-two--regular',
|
|
35
|
+
'ph--dice-three--regular',
|
|
36
|
+
'ph--dice-four--regular',
|
|
37
|
+
'ph--dice-five--regular',
|
|
38
|
+
'ph--dice-six--regular',
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const pickIcon = () => icons[Math.floor(Math.random() * icons.length)];
|
|
42
|
+
|
|
43
|
+
// TODO(burdon): Optional range.
|
|
44
|
+
export const RandomComponent = ({ shape }: ShapeComponentProps<RandomShape>) => {
|
|
45
|
+
const { runtime } = useComputeNodeState(shape);
|
|
46
|
+
|
|
47
|
+
const [spin, setSpin] = useState(false);
|
|
48
|
+
const [icon, setIcon] = useState(pickIcon());
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (!spin) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const i = setInterval(() => setIcon(pickIcon()), 250);
|
|
55
|
+
const t1 = setTimeout(() => clearInterval(i), 900);
|
|
56
|
+
const t2 = setTimeout(() => setSpin(false), 1_100);
|
|
57
|
+
return () => {
|
|
58
|
+
clearInterval(i);
|
|
59
|
+
clearTimeout(t1);
|
|
60
|
+
clearTimeout(t2);
|
|
61
|
+
};
|
|
62
|
+
}, [spin]);
|
|
63
|
+
|
|
64
|
+
const handleClick: IconProps['onClick'] = (ev) => {
|
|
65
|
+
ev.stopPropagation();
|
|
66
|
+
runtime.setOutput(DEFAULT_OUTPUT, Math.random());
|
|
67
|
+
setSpin(true);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div className='flex grow items-center justify-center'>
|
|
72
|
+
<Icon icon={icon} classNames={mx(spin && 'animate-[spin_1s]')} size={10} onClick={handleClick} />
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const randomShape: ShapeDef<RandomShape> = {
|
|
78
|
+
type: 'rng',
|
|
79
|
+
name: 'Random',
|
|
80
|
+
icon: 'ph--dice-six--regular',
|
|
81
|
+
component: RandomComponent,
|
|
82
|
+
createShape: createRandom,
|
|
83
|
+
getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('output')]: { x: 1, y: 0 } }),
|
|
84
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { DEFAULT_INPUT } from '@dxos/conductor';
|
|
8
|
+
import { S } from '@dxos/echo-schema';
|
|
9
|
+
import { createAnchorMap, type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
10
|
+
import { useAudioStream, Chaos, shaderPresets } from '@dxos/react-ui-sfx';
|
|
11
|
+
|
|
12
|
+
import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
|
|
13
|
+
import { useComputeNodeState } from '../hooks';
|
|
14
|
+
|
|
15
|
+
export const ScopeShape = S.extend(
|
|
16
|
+
ComputeShape,
|
|
17
|
+
S.Struct({
|
|
18
|
+
type: S.Literal('scope'),
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export type ScopeShape = S.Schema.Type<typeof ScopeShape>;
|
|
23
|
+
|
|
24
|
+
export type CreateScopeProps = CreateShapeProps<ScopeShape>;
|
|
25
|
+
|
|
26
|
+
export const createScope = (props: CreateScopeProps) =>
|
|
27
|
+
createShape<ScopeShape>({
|
|
28
|
+
type: 'scope',
|
|
29
|
+
size: { width: 128, height: 128 },
|
|
30
|
+
classNames: 'rounded-full border-primary-800',
|
|
31
|
+
...props,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const ScopeComponent = ({ shape }: ShapeComponentProps<ScopeShape>) => {
|
|
35
|
+
const { runtime } = useComputeNodeState(shape);
|
|
36
|
+
const input = runtime.inputs[DEFAULT_INPUT];
|
|
37
|
+
const active = input?.type === 'executed' ? input.value : false;
|
|
38
|
+
const { getAverage } = useAudioStream(active);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div className='flex w-full justify-center items-center bg-black'>
|
|
42
|
+
<Chaos active={active} getValue={getAverage} options={{ ...shaderPresets.heptapod, zoom: 1.2 }} />
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const scopeShape: ShapeDef<ScopeShape> = {
|
|
48
|
+
type: 'scope',
|
|
49
|
+
name: 'Scope',
|
|
50
|
+
icon: 'ph--waveform--regular',
|
|
51
|
+
component: ScopeComponent,
|
|
52
|
+
createShape: createScope,
|
|
53
|
+
getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('input')]: { x: -1, y: 0 } }),
|
|
54
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { Surface } from '@dxos/app-framework';
|
|
8
|
+
import { DEFAULT_INPUT } from '@dxos/conductor';
|
|
9
|
+
import { S } from '@dxos/echo-schema';
|
|
10
|
+
import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
11
|
+
import { createAnchorMap } from '@dxos/react-ui-canvas-editor';
|
|
12
|
+
|
|
13
|
+
import { Box, type BoxActionHandler } from './common';
|
|
14
|
+
import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
|
|
15
|
+
import { useComputeNodeState } from '../hooks';
|
|
16
|
+
|
|
17
|
+
export const SurfaceShape = S.extend(
|
|
18
|
+
ComputeShape,
|
|
19
|
+
S.Struct({
|
|
20
|
+
type: S.Literal('surface'),
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export type SurfaceShape = S.Schema.Type<typeof SurfaceShape>;
|
|
25
|
+
|
|
26
|
+
export type CreateSurfaceProps = CreateShapeProps<SurfaceShape>;
|
|
27
|
+
|
|
28
|
+
export const createSurface = (props: CreateSurfaceProps) =>
|
|
29
|
+
createShape<SurfaceShape>({ type: 'surface', size: { width: 384, height: 384 }, ...props });
|
|
30
|
+
|
|
31
|
+
export const SurfaceComponent = ({ shape }: ShapeComponentProps<SurfaceShape>) => {
|
|
32
|
+
const { runtime } = useComputeNodeState(shape);
|
|
33
|
+
const input = runtime.inputs[DEFAULT_INPUT];
|
|
34
|
+
const value = input?.type === 'executed' ? input.value : null;
|
|
35
|
+
|
|
36
|
+
const handleAction: BoxActionHandler = (action) => {
|
|
37
|
+
if (action === 'run') {
|
|
38
|
+
runtime.evalNode();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Box shape={shape} onAction={handleAction}>
|
|
44
|
+
{value !== null && <Surface role='canvas-node' data={{ value }} limit={1} />}
|
|
45
|
+
</Box>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const surfaceShape: ShapeDef<SurfaceShape> = {
|
|
50
|
+
type: 'surface',
|
|
51
|
+
name: 'Surface',
|
|
52
|
+
icon: 'ph--frame-corners--regular',
|
|
53
|
+
component: SurfaceComponent,
|
|
54
|
+
createShape: createSurface,
|
|
55
|
+
getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('input')]: { x: -1, y: 0 } }),
|
|
56
|
+
resizable: true,
|
|
57
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useEffect, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { DEFAULT_OUTPUT } from '@dxos/conductor';
|
|
8
|
+
import { S } from '@dxos/echo-schema';
|
|
9
|
+
import { Input } from '@dxos/react-ui';
|
|
10
|
+
import { createAnchorMap, type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
11
|
+
|
|
12
|
+
import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
|
|
13
|
+
import { useComputeNodeState } from '../hooks';
|
|
14
|
+
|
|
15
|
+
export const SwitchShape = S.extend(
|
|
16
|
+
ComputeShape,
|
|
17
|
+
S.Struct({
|
|
18
|
+
type: S.Literal('switch'),
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export type SwitchShape = S.Schema.Type<typeof SwitchShape>;
|
|
23
|
+
|
|
24
|
+
export type CreateSwitchProps = CreateShapeProps<SwitchShape>;
|
|
25
|
+
|
|
26
|
+
export const createSwitch = (props: CreateSwitchProps) =>
|
|
27
|
+
createShape<SwitchShape>({ type: 'switch', size: { width: 64, height: 64 }, ...props });
|
|
28
|
+
|
|
29
|
+
// TODO(burdon): Should model as a constant.
|
|
30
|
+
export const SwitchComponent = ({ shape }: ShapeComponentProps<SwitchShape>) => {
|
|
31
|
+
const { runtime } = useComputeNodeState(shape);
|
|
32
|
+
const [value, setValue] = useState(false);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
runtime.setOutput(DEFAULT_OUTPUT, value);
|
|
35
|
+
}, [value]);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div className='flex w-full justify-center items-center' onClick={(ev) => ev.stopPropagation()}>
|
|
39
|
+
<Input.Root>
|
|
40
|
+
<Input.Switch checked={value} onCheckedChange={(value) => setValue(value)} />
|
|
41
|
+
</Input.Root>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const switchShape: ShapeDef<SwitchShape> = {
|
|
47
|
+
type: 'switch',
|
|
48
|
+
name: 'Switch',
|
|
49
|
+
icon: 'ph--toggle-left--regular',
|
|
50
|
+
component: SwitchComponent,
|
|
51
|
+
createShape: createSwitch,
|
|
52
|
+
getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('output')]: { x: 1, y: 0 } }),
|
|
53
|
+
};
|