@dxos/react-ui-canvas-compute 0.7.5-labs.071a3e2

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 (155) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +1 -0
  3. package/dist/lib/browser/index.mjs +2535 -0
  4. package/dist/lib/browser/index.mjs.map +7 -0
  5. package/dist/lib/browser/meta.json +1 -0
  6. package/dist/lib/node/index.cjs +2627 -0
  7. package/dist/lib/node/index.cjs.map +7 -0
  8. package/dist/lib/node/meta.json +1 -0
  9. package/dist/lib/node-esm/index.mjs +2535 -0
  10. package/dist/lib/node-esm/index.mjs.map +7 -0
  11. package/dist/lib/node-esm/meta.json +1 -0
  12. package/dist/types/src/components/DiagnosticOverlay.d.ts +7 -0
  13. package/dist/types/src/components/DiagnosticOverlay.d.ts.map +1 -0
  14. package/dist/types/src/components/index.d.ts +2 -0
  15. package/dist/types/src/components/index.d.ts.map +1 -0
  16. package/dist/types/src/compute-layout.d.ts +9 -0
  17. package/dist/types/src/compute-layout.d.ts.map +1 -0
  18. package/dist/types/src/compute.stories.d.ts +28 -0
  19. package/dist/types/src/compute.stories.d.ts.map +1 -0
  20. package/dist/types/src/graph/controller.d.ts +142 -0
  21. package/dist/types/src/graph/controller.d.ts.map +1 -0
  22. package/dist/types/src/graph/index.d.ts +3 -0
  23. package/dist/types/src/graph/index.d.ts.map +1 -0
  24. package/dist/types/src/graph/node-defs.d.ts +6 -0
  25. package/dist/types/src/graph/node-defs.d.ts.map +1 -0
  26. package/dist/types/src/hooks/compute-context.d.ts +7 -0
  27. package/dist/types/src/hooks/compute-context.d.ts.map +1 -0
  28. package/dist/types/src/hooks/index.d.ts +4 -0
  29. package/dist/types/src/hooks/index.d.ts.map +1 -0
  30. package/dist/types/src/hooks/useComputeNodeState.d.ts +19 -0
  31. package/dist/types/src/hooks/useComputeNodeState.d.ts.map +1 -0
  32. package/dist/types/src/hooks/useGraphMonitor.d.ts +14 -0
  33. package/dist/types/src/hooks/useGraphMonitor.d.ts.map +1 -0
  34. package/dist/types/src/index.d.ts +6 -0
  35. package/dist/types/src/index.d.ts.map +1 -0
  36. package/dist/types/src/json.test.d.ts +21 -0
  37. package/dist/types/src/json.test.d.ts.map +1 -0
  38. package/dist/types/src/registry.d.ts +9 -0
  39. package/dist/types/src/registry.d.ts.map +1 -0
  40. package/dist/types/src/schema.test.d.ts +2 -0
  41. package/dist/types/src/schema.test.d.ts.map +1 -0
  42. package/dist/types/src/shapes/Append.d.ts +54 -0
  43. package/dist/types/src/shapes/Append.d.ts.map +1 -0
  44. package/dist/types/src/shapes/Array.d.ts +38 -0
  45. package/dist/types/src/shapes/Array.d.ts.map +1 -0
  46. package/dist/types/src/shapes/Audio.d.ts +54 -0
  47. package/dist/types/src/shapes/Audio.d.ts.map +1 -0
  48. package/dist/types/src/shapes/Beacon.d.ts +54 -0
  49. package/dist/types/src/shapes/Beacon.d.ts.map +1 -0
  50. package/dist/types/src/shapes/Boolean.d.ts +233 -0
  51. package/dist/types/src/shapes/Boolean.d.ts.map +1 -0
  52. package/dist/types/src/shapes/Chat.d.ts +57 -0
  53. package/dist/types/src/shapes/Chat.d.ts.map +1 -0
  54. package/dist/types/src/shapes/Constant.d.ts +60 -0
  55. package/dist/types/src/shapes/Constant.d.ts.map +1 -0
  56. package/dist/types/src/shapes/Database.d.ts +54 -0
  57. package/dist/types/src/shapes/Database.d.ts.map +1 -0
  58. package/dist/types/src/shapes/Function.d.ts +54 -0
  59. package/dist/types/src/shapes/Function.d.ts.map +1 -0
  60. package/dist/types/src/shapes/Gpt.d.ts +54 -0
  61. package/dist/types/src/shapes/Gpt.d.ts.map +1 -0
  62. package/dist/types/src/shapes/GptRealtime.d.ts +54 -0
  63. package/dist/types/src/shapes/GptRealtime.d.ts.map +1 -0
  64. package/dist/types/src/shapes/Json.d.ts +107 -0
  65. package/dist/types/src/shapes/Json.d.ts.map +1 -0
  66. package/dist/types/src/shapes/Logic.d.ts +109 -0
  67. package/dist/types/src/shapes/Logic.d.ts.map +1 -0
  68. package/dist/types/src/shapes/Queue.d.ts +58 -0
  69. package/dist/types/src/shapes/Queue.d.ts.map +1 -0
  70. package/dist/types/src/shapes/RNG.d.ts +58 -0
  71. package/dist/types/src/shapes/RNG.d.ts.map +1 -0
  72. package/dist/types/src/shapes/Scope.d.ts +54 -0
  73. package/dist/types/src/shapes/Scope.d.ts.map +1 -0
  74. package/dist/types/src/shapes/Surface.d.ts +54 -0
  75. package/dist/types/src/shapes/Surface.d.ts.map +1 -0
  76. package/dist/types/src/shapes/Switch.d.ts +54 -0
  77. package/dist/types/src/shapes/Switch.d.ts.map +1 -0
  78. package/dist/types/src/shapes/Table.d.ts +54 -0
  79. package/dist/types/src/shapes/Table.d.ts.map +1 -0
  80. package/dist/types/src/shapes/Template.d.ts +56 -0
  81. package/dist/types/src/shapes/Template.d.ts.map +1 -0
  82. package/dist/types/src/shapes/Text.d.ts +54 -0
  83. package/dist/types/src/shapes/Text.d.ts.map +1 -0
  84. package/dist/types/src/shapes/TextToImage.d.ts +54 -0
  85. package/dist/types/src/shapes/TextToImage.d.ts.map +1 -0
  86. package/dist/types/src/shapes/Thread.d.ts +58 -0
  87. package/dist/types/src/shapes/Thread.d.ts.map +1 -0
  88. package/dist/types/src/shapes/Trigger.d.ts +64 -0
  89. package/dist/types/src/shapes/Trigger.d.ts.map +1 -0
  90. package/dist/types/src/shapes/common/Box.d.ts +25 -0
  91. package/dist/types/src/shapes/common/Box.d.ts.map +1 -0
  92. package/dist/types/src/shapes/common/FunctionBody.d.ts +15 -0
  93. package/dist/types/src/shapes/common/FunctionBody.d.ts.map +1 -0
  94. package/dist/types/src/shapes/common/TypeSelect.d.ts +4 -0
  95. package/dist/types/src/shapes/common/TypeSelect.d.ts.map +1 -0
  96. package/dist/types/src/shapes/common/index.d.ts +4 -0
  97. package/dist/types/src/shapes/common/index.d.ts.map +1 -0
  98. package/dist/types/src/shapes/defs.d.ts +39 -0
  99. package/dist/types/src/shapes/defs.d.ts.map +1 -0
  100. package/dist/types/src/shapes/index.d.ts +27 -0
  101. package/dist/types/src/shapes/index.d.ts.map +1 -0
  102. package/dist/types/src/testing/circuits.d.ts +193 -0
  103. package/dist/types/src/testing/circuits.d.ts.map +1 -0
  104. package/dist/types/src/testing/index.d.ts +2 -0
  105. package/dist/types/src/testing/index.d.ts.map +1 -0
  106. package/dist/types/tsconfig.tsbuildinfo +1 -0
  107. package/package.json +85 -0
  108. package/src/README.md +47 -0
  109. package/src/components/DiagnosticOverlay.tsx +23 -0
  110. package/src/components/index.ts +5 -0
  111. package/src/compute-layout.ts +37 -0
  112. package/src/compute.stories.tsx +365 -0
  113. package/src/graph/controller.ts +419 -0
  114. package/src/graph/index.ts +6 -0
  115. package/src/graph/node-defs.ts +82 -0
  116. package/src/hooks/compute-context.ts +19 -0
  117. package/src/hooks/index.ts +7 -0
  118. package/src/hooks/useComputeNodeState.ts +83 -0
  119. package/src/hooks/useGraphMonitor.ts +133 -0
  120. package/src/index.ts +9 -0
  121. package/src/json.test.ts +35 -0
  122. package/src/registry.ts +100 -0
  123. package/src/schema.test.ts +62 -0
  124. package/src/shapes/Append.tsx +43 -0
  125. package/src/shapes/Array.tsx +61 -0
  126. package/src/shapes/Audio.tsx +55 -0
  127. package/src/shapes/Beacon.tsx +56 -0
  128. package/src/shapes/Boolean.tsx +215 -0
  129. package/src/shapes/Chat.tsx +77 -0
  130. package/src/shapes/Constant.tsx +125 -0
  131. package/src/shapes/Database.tsx +39 -0
  132. package/src/shapes/Function.tsx +40 -0
  133. package/src/shapes/Gpt.tsx +91 -0
  134. package/src/shapes/GptRealtime.tsx +175 -0
  135. package/src/shapes/Json.tsx +103 -0
  136. package/src/shapes/Logic.tsx +82 -0
  137. package/src/shapes/Queue.tsx +78 -0
  138. package/src/shapes/RNG.tsx +84 -0
  139. package/src/shapes/Scope.tsx +54 -0
  140. package/src/shapes/Surface.tsx +57 -0
  141. package/src/shapes/Switch.tsx +53 -0
  142. package/src/shapes/Table.tsx +45 -0
  143. package/src/shapes/Template.tsx +98 -0
  144. package/src/shapes/Text.tsx +56 -0
  145. package/src/shapes/TextToImage.tsx +39 -0
  146. package/src/shapes/Thread.tsx +87 -0
  147. package/src/shapes/Trigger.tsx +152 -0
  148. package/src/shapes/common/Box.tsx +74 -0
  149. package/src/shapes/common/FunctionBody.tsx +122 -0
  150. package/src/shapes/common/TypeSelect.tsx +31 -0
  151. package/src/shapes/common/index.ts +7 -0
  152. package/src/shapes/defs.ts +50 -0
  153. package/src/shapes/index.ts +31 -0
  154. package/src/testing/circuits.ts +320 -0
  155. package/src/testing/index.ts +5 -0
@@ -0,0 +1,215 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { type FC } from 'react';
6
+
7
+ import { S } from '@dxos/echo-schema';
8
+ import { type ShapeDef } from '@dxos/react-ui-canvas-editor';
9
+ import { createAnchors, getAnchorPoints } from '@dxos/react-ui-canvas-editor';
10
+
11
+ import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
12
+
13
+ //
14
+ // Gate utils.
15
+ // https://en.wikipedia.org/wiki/Logic_gate
16
+ //
17
+
18
+ type GateType = 'and' | 'or' | 'not';
19
+
20
+ const GateShape = S.extend(
21
+ ComputeShape,
22
+ S.Struct({
23
+ type: S.String,
24
+ }),
25
+ );
26
+
27
+ type GateShape = S.Schema.Type<typeof GateShape>;
28
+
29
+ type CreateGateProps = CreateShapeProps<GateShape> & { type: GateType };
30
+
31
+ const createGate = (props: CreateGateProps): GateShape =>
32
+ createShape<GateShape>({
33
+ size: { width: 64, height: 64 },
34
+ ...props,
35
+ });
36
+
37
+ const GateComponent = (Symbol: FC<GateSymbolProps>) => () => {
38
+ return (
39
+ <div className='flex w-full justify-center items-center'>
40
+ <Symbol />
41
+ </div>
42
+ );
43
+ };
44
+
45
+ // TODO(burdon): Create custom icons.
46
+ const defineShape = <S extends GateShape>({
47
+ type,
48
+ name,
49
+ icon,
50
+ Symbol,
51
+ createShape,
52
+ inputs,
53
+ outputs = [createAnchorId('output')],
54
+ }: {
55
+ type: GateType;
56
+ Symbol: FC<GateSymbolProps>;
57
+ createShape: ShapeDef<S>['createShape'];
58
+ inputs: string[];
59
+ outputs?: string[];
60
+ } & Pick<ShapeDef<GateShape>, 'name' | 'icon'>): ShapeDef<GateShape> => ({
61
+ type,
62
+ name,
63
+ icon,
64
+ component: GateComponent(Symbol),
65
+ createShape,
66
+ getAnchors: (shape) => createAnchors({ shape, inputs, outputs }),
67
+ });
68
+
69
+ //
70
+ // Symbols
71
+ //
72
+
73
+ type PathConstructor = (props: { startX: number; endX: number; height: number }) => string[];
74
+
75
+ type GateSymbolProps = {
76
+ width?: number;
77
+ height?: number;
78
+ className?: string;
79
+ strokeWidth?: number;
80
+ };
81
+
82
+ // TODO(burdon): Note inputs should line up with anchors.
83
+ const Symbol =
84
+ (pathConstructor: PathConstructor, inputs: number): FC<GateSymbolProps> =>
85
+ ({
86
+ width = 64,
87
+ height = 32,
88
+ // TODO(burdon): Same as line color.
89
+ className = 'fill-neutral-200 dark:fill-neutral-800 stroke-neutral-500',
90
+ strokeWidth = 1,
91
+ }) => {
92
+ const startX = width * 0.25;
93
+ const endX = width * 0.75;
94
+ const centerY = height / 2;
95
+ const paths = pathConstructor({ startX, endX, height });
96
+
97
+ return (
98
+ <svg viewBox={`0 0 ${width} ${height}`} className='w-full h-full'>
99
+ {/* Input line. */}
100
+ {getAnchorPoints({ x: 0, y: centerY }, inputs).map(({ x, y }, i) => (
101
+ <line key={i} x1={x} y1={y} x2={startX * 1.3} y2={y} strokeWidth={strokeWidth} className={className} />
102
+ ))}
103
+
104
+ {/* Output line. */}
105
+ <line x1={endX} y1={centerY} x2={width} y2={centerY} strokeWidth={strokeWidth} className={className} />
106
+
107
+ {/* And body. */}
108
+ {paths.map((path, i) => (
109
+ <path key={i} d={path} strokeWidth={strokeWidth} className={className} />
110
+ ))}
111
+ </svg>
112
+ );
113
+ };
114
+
115
+ //
116
+ // AND
117
+ //
118
+
119
+ const AndSymbol = Symbol(({ startX, endX, height }) => {
120
+ const arcRadius = (endX - startX) / 2;
121
+ return [
122
+ `
123
+ M ${startX},${height * 0.1}
124
+ L ${endX - arcRadius},${height * 0.1}
125
+ A ${arcRadius},${height * 0.4} 0 0 1 ${endX - arcRadius},${height * 0.9}
126
+ L ${startX},${height * 0.9}
127
+ Z
128
+ `,
129
+ ];
130
+ }, 2);
131
+
132
+ export const AndShape = GateShape;
133
+ export type AndShape = GateShape;
134
+
135
+ export const createAnd = (props: Omit<CreateGateProps, 'type' | 'node'>) => {
136
+ return createGate({ ...props, type: 'and' });
137
+ };
138
+ export const andShape = defineShape({
139
+ type: 'and',
140
+ name: 'AND',
141
+ icon: 'ph--intersection--regular',
142
+ Symbol: AndSymbol,
143
+ createShape: createAnd,
144
+ inputs: ['input.a', 'input.b'],
145
+ });
146
+
147
+ //
148
+ // OR
149
+ //
150
+
151
+ // TODO(burdon): Should have sharper point.
152
+ const OrSymbol = Symbol(({ startX, endX, height }) => {
153
+ const arcRadius = (endX - startX) / 2;
154
+ return [
155
+ `
156
+ M ${startX},${height * 0.1}
157
+ L ${endX - arcRadius},${height * 0.1}
158
+ A ${arcRadius},${height * 0.4} 0 0 1 ${endX - arcRadius},${height * 0.9}
159
+ L ${startX},${height * 0.9}
160
+ C ${startX * 1.4},${height * 0.5} ${startX * 1.4},${height * 0.5} ${startX},${height * 0.1}
161
+ Z
162
+ `,
163
+ ];
164
+ }, 2);
165
+
166
+ export const OrShape = GateShape;
167
+ export type OrShape = GateShape;
168
+
169
+ export const createOr = (props: Omit<CreateGateProps, 'type' | 'node'>) => {
170
+ return createGate({ ...props, type: 'or' });
171
+ };
172
+ export const orShape = defineShape({
173
+ type: 'or',
174
+ name: 'OR',
175
+ icon: 'ph--union--regular',
176
+ Symbol: OrSymbol,
177
+ createShape: createOr,
178
+ inputs: ['input.a', 'input.b'],
179
+ });
180
+
181
+ //
182
+ // NOT
183
+ //
184
+
185
+ const NotSymbol = Symbol(({ startX, endX, height }) => {
186
+ return [
187
+ `
188
+ M ${startX},${height * 0.1}
189
+ L ${endX * 0.9},${height * 0.5}
190
+ L ${startX},${height * 0.9}
191
+ Z
192
+ `,
193
+ `
194
+ M ${endX - height * 0.2},${height * 0.5}
195
+ A ${height * 0.1} ${height * 0.1} 0 0 1 ${endX},${height * 0.5}
196
+ A ${height * 0.1} ${height * 0.1} 0 0 1 ${endX - height * 0.2},${height * 0.5}
197
+ Z
198
+ `,
199
+ ];
200
+ }, 1);
201
+
202
+ export const NotShape = GateShape;
203
+ export type NotShape = GateShape;
204
+
205
+ export const createNot = (props: Omit<CreateGateProps, 'type' | 'node'>) => {
206
+ return createGate({ ...props, type: 'not' });
207
+ };
208
+ export const notShape = defineShape({
209
+ type: 'not',
210
+ name: 'NOT',
211
+ icon: 'ph--x--regular',
212
+ Symbol: NotSymbol,
213
+ createShape: createNot,
214
+ inputs: [createAnchorId('input')],
215
+ });
@@ -0,0 +1,77 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useRef } from 'react';
6
+
7
+ import { DEFAULT_OUTPUT } from '@dxos/conductor';
8
+ import { S } from '@dxos/echo-schema';
9
+ import {
10
+ type ShapeComponentProps,
11
+ type ShapeDef,
12
+ TextBox,
13
+ type TextBoxControl,
14
+ type TextBoxProps,
15
+ } from '@dxos/react-ui-canvas-editor';
16
+ import { createAnchorMap } from '@dxos/react-ui-canvas-editor';
17
+
18
+ import { Box } from './common';
19
+ import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
20
+ import { useComputeNodeState } from '../hooks';
21
+
22
+ //
23
+ // Data
24
+ //
25
+
26
+ export const ChatShape = S.extend(
27
+ ComputeShape,
28
+ S.Struct({
29
+ type: S.Literal('chat'),
30
+ }),
31
+ );
32
+
33
+ export type ChatShape = S.Schema.Type<typeof ChatShape>;
34
+
35
+ //
36
+ // Component
37
+ //
38
+
39
+ export type TextInputComponentProps = ShapeComponentProps<ChatShape> & TextBoxProps & { title?: string };
40
+
41
+ export const TextInputComponent = ({ shape, title, ...props }: TextInputComponentProps) => {
42
+ const { runtime } = useComputeNodeState(shape);
43
+ const inputRef = useRef<TextBoxControl>(null);
44
+
45
+ const handleEnter: TextBoxProps['onEnter'] = (text) => {
46
+ const value = text.trim();
47
+ if (value.length) {
48
+ runtime.setOutput(DEFAULT_OUTPUT, value);
49
+ inputRef.current?.setText('');
50
+ }
51
+ };
52
+
53
+ return (
54
+ <Box shape={shape} title={title}>
55
+ <TextBox ref={inputRef} onEnter={handleEnter} {...props} />
56
+ </Box>
57
+ );
58
+ };
59
+
60
+ //
61
+ // Defs
62
+ //
63
+
64
+ export type CreateChatProps = CreateShapeProps<ChatShape>;
65
+
66
+ export const createChat = (props: CreateChatProps) =>
67
+ createShape<ChatShape>({ type: 'chat', size: { width: 256, height: 128 }, ...props });
68
+
69
+ export const chatShape: ShapeDef<ChatShape> = {
70
+ type: 'chat',
71
+ name: 'Chat',
72
+ icon: 'ph--textbox--regular',
73
+ component: (props) => <TextInputComponent {...props} title={'Prompt'} placeholder={'Message'} />,
74
+ createShape: createChat,
75
+ getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('output')]: { x: 1, y: 0 } }),
76
+ resizable: true,
77
+ };
@@ -0,0 +1,125 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback, useRef, useState } from 'react';
6
+
7
+ import { ComputeValueType } from '@dxos/conductor';
8
+ import { S } from '@dxos/echo-schema';
9
+ import { Input } from '@dxos/react-ui';
10
+ import {
11
+ type ShapeComponentProps,
12
+ type ShapeDef,
13
+ TextBox,
14
+ type TextBoxControl,
15
+ type TextBoxProps,
16
+ } from '@dxos/react-ui-canvas-editor';
17
+ import { createAnchorMap } from '@dxos/react-ui-canvas-editor';
18
+ import { safeParseJson } from '@dxos/util';
19
+
20
+ import { Box, TypeSelect } from './common';
21
+ import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
22
+ import { useComputeNodeState } from '../hooks';
23
+
24
+ //
25
+ // Data
26
+ //
27
+
28
+ export const ConstantShape = S.extend(
29
+ ComputeShape,
30
+ S.Struct({
31
+ type: S.Literal('constant'),
32
+ value: S.optional(S.Any),
33
+ }),
34
+ );
35
+
36
+ export type ConstantShape = S.Schema.Type<typeof ConstantShape>;
37
+
38
+ //
39
+ // Component
40
+ //
41
+
42
+ export type ConstantComponentProps = ShapeComponentProps<ConstantShape> &
43
+ TextBoxProps & { title?: string; chat?: boolean };
44
+
45
+ const inferType = (value: any): string | undefined => {
46
+ if (typeof value === 'string') {
47
+ return 'string';
48
+ } else if (typeof value === 'number') {
49
+ return 'number';
50
+ } else if (typeof value === 'boolean') {
51
+ return 'boolean';
52
+ } else if (typeof value === 'object') {
53
+ return 'object';
54
+ }
55
+ };
56
+
57
+ export const ConstantComponent = ({ shape, title, chat, ...props }: ConstantComponentProps) => {
58
+ const { node } = useComputeNodeState(shape);
59
+ const [type, setType] = useState(inferType(node.value) ?? ComputeValueType.literals[0]);
60
+ const inputRef = useRef<TextBoxControl>(null);
61
+
62
+ const handleEnter = useCallback<NonNullable<TextBoxProps['onEnter']>>(
63
+ (text) => {
64
+ const value = text.trim();
65
+ if (value.length) {
66
+ // TODO(burdon): Set text filter.
67
+ if (type === 'number') {
68
+ const floatValue = parseFloat(value);
69
+ if (!isNaN(floatValue)) {
70
+ node.value = floatValue;
71
+ }
72
+ } else if (type === 'object') {
73
+ node.value = safeParseJson(value, {});
74
+ } else {
75
+ node.value = value;
76
+ }
77
+
78
+ inputRef.current?.focus();
79
+ }
80
+ },
81
+ [type],
82
+ );
83
+
84
+ return (
85
+ <Box shape={shape} title={title} status={<TypeSelect value={type} onValueChange={setType} />}>
86
+ {(type === 'string' || type === 'number') && (
87
+ <TextBox {...props} ref={inputRef} value={node.value} onEnter={handleEnter} />
88
+ )}
89
+ {type === 'object' && (
90
+ <TextBox {...props} ref={inputRef} value={JSON.stringify(node.value, null, 2)} language={'json'} />
91
+ )}
92
+ {type === 'boolean' && (
93
+ <div className='flex grow justify-center items-center'>
94
+ <Input.Root>
95
+ <Input.Switch
96
+ checked={node.value}
97
+ onCheckedChange={(value) => {
98
+ node.value = value;
99
+ }}
100
+ />
101
+ </Input.Root>
102
+ </div>
103
+ )}
104
+ </Box>
105
+ );
106
+ };
107
+
108
+ //
109
+ // Defs
110
+ //
111
+
112
+ export type CreateConstantProps = CreateShapeProps<ConstantShape>;
113
+
114
+ export const createConstant = (props: CreateConstantProps) =>
115
+ createShape<ConstantShape>({ type: 'constant', size: { width: 192, height: 128 }, ...props });
116
+
117
+ export const constantShape: ShapeDef<ConstantShape> = {
118
+ type: 'constant',
119
+ name: 'Value',
120
+ icon: 'ph--dots-three-circle--regular',
121
+ component: (props) => <ConstantComponent {...props} placeholder={'Constant'} />,
122
+ createShape: createConstant,
123
+ getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('output')]: { x: 1, y: 0 } }),
124
+ resizable: true,
125
+ };
@@ -0,0 +1,39 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { S } from '@dxos/echo-schema';
8
+ import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
9
+ import { createAnchorMap } from '@dxos/react-ui-canvas-editor';
10
+
11
+ import { Box } from './common';
12
+ import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
13
+
14
+ export const DatabaseShape = S.extend(
15
+ ComputeShape,
16
+ S.Struct({
17
+ type: S.Literal('database'),
18
+ }),
19
+ );
20
+
21
+ export type DatabaseShape = S.Schema.Type<typeof DatabaseShape>;
22
+
23
+ export type CreateDatabaseProps = CreateShapeProps<DatabaseShape>;
24
+
25
+ export const createDatabase = (props: CreateDatabaseProps) =>
26
+ createShape<DatabaseShape>({ type: 'database', size: { width: 128, height: 64 }, ...props });
27
+
28
+ export const DatabaseComponent = ({ shape }: ShapeComponentProps<DatabaseShape>) => {
29
+ return <Box shape={shape} />;
30
+ };
31
+
32
+ export const databaseShape: ShapeDef<DatabaseShape> = {
33
+ type: 'database',
34
+ name: 'ECHO',
35
+ icon: 'ph--database--regular',
36
+ component: DatabaseComponent,
37
+ createShape: createDatabase,
38
+ getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('output')]: { x: 1, y: 0 } }),
39
+ };
@@ -0,0 +1,40 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { AnyOutput, FunctionInput } 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
+ export const FunctionShape = S.extend(
15
+ ComputeShape,
16
+ S.Struct({
17
+ type: S.Literal('function'),
18
+ }),
19
+ );
20
+
21
+ export type FunctionShape = S.Schema.Type<typeof FunctionShape>;
22
+
23
+ export type CreateFunctionProps = CreateShapeProps<FunctionShape>;
24
+
25
+ export const createFunction = (props: CreateFunctionProps) =>
26
+ createShape<FunctionShape>({ type: 'function', size: { width: 192, height: getHeight(FunctionInput) }, ...props });
27
+
28
+ export const FunctionComponent = ({ shape }: ShapeComponentProps<FunctionShape>) => {
29
+ return <FunctionBody shape={shape} inputSchema={FunctionInput} outputSchema={AnyOutput} />;
30
+ };
31
+
32
+ export const functionShape: ShapeDef<FunctionShape> = {
33
+ type: 'function',
34
+ name: 'Function',
35
+ icon: 'ph--function--regular',
36
+ component: FunctionComponent,
37
+ createShape: createFunction,
38
+ // TODO(burdon): Get dynamic schema.
39
+ getAnchors: (shape) => createFunctionAnchors(shape, FunctionInput, AnyOutput),
40
+ };
@@ -0,0 +1,91 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useEffect, useState } from 'react';
6
+
7
+ import type { GenerationStreamEvent } from '@dxos/assistant';
8
+ import { GptInput, GptOutput } from '@dxos/conductor';
9
+ import { S } from '@dxos/echo-schema';
10
+ import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
11
+
12
+ import { createFunctionAnchors, FunctionBody, getHeight } from './common';
13
+ import { ComputeShape, createShape, type CreateShapeProps } from './defs';
14
+ import { useComputeNodeState } from '../hooks';
15
+
16
+ export const GptShape = S.extend(
17
+ ComputeShape,
18
+ S.Struct({
19
+ type: S.Literal('gpt'),
20
+ }),
21
+ );
22
+
23
+ export type GptShape = S.Schema.Type<typeof GptShape>;
24
+
25
+ export type CreateGptProps = CreateShapeProps<GptShape>;
26
+
27
+ export const createGpt = (props: CreateGptProps) =>
28
+ createShape<GptShape>({
29
+ type: 'gpt',
30
+ size: { width: 256, height: Math.max(getHeight(GptInput), getHeight(GptOutput)) },
31
+ ...props,
32
+ });
33
+
34
+ export const GptComponent = ({ shape }: ShapeComponentProps<GptShape>) => {
35
+ const { meta, runtime } = useComputeNodeState(shape);
36
+ const [text, setText] = useState('');
37
+ const [tokens, setTokens] = useState(0);
38
+
39
+ useEffect(() => {
40
+ return runtime.subscribeToEventLog((ev) => {
41
+ switch (ev.type) {
42
+ case 'begin-compute': {
43
+ setText('');
44
+ break;
45
+ }
46
+ case 'custom': {
47
+ const token: GenerationStreamEvent = ev.event;
48
+ switch (token.type) {
49
+ case 'content_block_delta':
50
+ switch (token.delta.type) {
51
+ case 'text_delta': {
52
+ const delta = token.delta.text;
53
+ setText((prev) => {
54
+ const text = prev + delta;
55
+ // TODO(burdon): Get token count.
56
+ setTokens(text.split(' ').length);
57
+ return text;
58
+ });
59
+ break;
60
+ }
61
+ }
62
+ break;
63
+
64
+ // TODO(dmaretskyi): Handle other types of events.
65
+ }
66
+ break;
67
+ }
68
+ }
69
+ });
70
+ }, [runtime?.subscribeToEventLog]);
71
+
72
+ return (
73
+ <FunctionBody
74
+ shape={shape}
75
+ content={<div className='px-2 py-1 overflow-y-scroll'>{text}</div>}
76
+ status={`${tokens} tokens`}
77
+ inputSchema={meta.input}
78
+ outputSchema={meta.output}
79
+ />
80
+ );
81
+ };
82
+
83
+ export const gptShape: ShapeDef<GptShape> = {
84
+ type: 'gpt',
85
+ name: 'GPT',
86
+ icon: 'ph--brain--regular',
87
+ component: GptComponent,
88
+ createShape: createGpt,
89
+ getAnchors: (shape) => createFunctionAnchors(shape, GptInput, GptOutput),
90
+ openable: true,
91
+ };