@alpic80/rivet-core 1.19.1-aidon.2 → 1.24.0-aidon.1
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/README.md +4 -0
- package/dist/cjs/bundle.cjs +4187 -1020
- package/dist/cjs/bundle.cjs.map +4 -4
- package/dist/esm/api/createProcessor.js +8 -17
- package/dist/esm/api/looseDataValue.js +16 -0
- package/dist/esm/exports.js +2 -0
- package/dist/esm/integrations/CodeRunner.js +36 -0
- package/dist/esm/integrations/GptTokenizerTokenizer.js +7 -4
- package/dist/esm/integrations/openai/OpenAIEmbeddingGenerator.js +1 -1
- package/dist/esm/model/DataValue.js +14 -2
- package/dist/esm/model/GraphProcessor.js +275 -104
- package/dist/esm/model/NodeBase.js +11 -1
- package/dist/esm/model/NodeImpl.js +8 -0
- package/dist/esm/model/Nodes.js +31 -4
- package/dist/esm/model/ProjectReferenceLoader.js +1 -0
- package/dist/esm/model/nodes/AssembleMessageNode.js +12 -2
- package/dist/esm/model/nodes/AssemblePromptNode.js +22 -0
- package/dist/esm/model/nodes/CallGraphNode.js +3 -4
- package/dist/esm/model/nodes/ChatLoopNode.js +150 -0
- package/dist/esm/model/nodes/ChatNode.js +7 -934
- package/dist/esm/model/nodes/ChatNodeBase.js +1275 -0
- package/dist/esm/model/nodes/ChunkNode.js +2 -2
- package/dist/esm/model/nodes/CodeNode.js +40 -4
- package/dist/esm/model/nodes/CronNode.js +248 -0
- package/dist/esm/model/nodes/DelegateFunctionCallNode.js +37 -12
- package/dist/esm/model/nodes/DestructureNode.js +1 -1
- package/dist/esm/model/nodes/DocumentNode.js +183 -0
- package/dist/esm/model/nodes/ExtractJsonNode.js +4 -4
- package/dist/esm/model/nodes/ExtractRegexNode.js +10 -11
- package/dist/esm/model/nodes/GetEmbeddingNode.js +1 -1
- package/dist/esm/model/nodes/HttpCallNode.js +3 -1
- package/dist/esm/model/nodes/IfNode.js +5 -0
- package/dist/esm/model/nodes/ImageToMDNode.js +116 -0
- package/dist/esm/model/nodes/LoopUntilNode.js +214 -0
- package/dist/esm/model/nodes/PromptNode.js +29 -6
- package/dist/esm/model/nodes/ReadAllFilesNode.js +210 -0
- package/dist/esm/model/nodes/ReadDirectoryNode.js +31 -25
- package/dist/esm/model/nodes/ReferencedGraphAliasNode.js +199 -0
- package/dist/esm/model/nodes/TextNode.js +9 -4
- package/dist/esm/model/nodes/ToMarkdownTableNode.js +119 -0
- package/dist/esm/model/nodes/ToTreeNode.js +133 -0
- package/dist/esm/model/nodes/{GptFunctionNode.js → ToolNode.js} +10 -10
- package/dist/esm/model/nodes/UserInputNode.js +10 -12
- package/dist/esm/plugins/aidon/nodes/ChatAidonNode.js +3 -3
- package/dist/esm/plugins/anthropic/anthropic.js +29 -10
- package/dist/esm/plugins/anthropic/fetchEventSource.js +3 -2
- package/dist/esm/plugins/anthropic/nodes/ChatAnthropicNode.js +267 -147
- package/dist/esm/plugins/anthropic/plugin.js +9 -1
- package/dist/esm/plugins/gentrace/plugin.js +6 -6
- package/dist/esm/plugins/google/google.js +113 -5
- package/dist/esm/plugins/google/nodes/ChatGoogleNode.js +211 -54
- package/dist/esm/plugins/google/plugin.js +13 -6
- package/dist/esm/plugins/openai/nodes/RunThreadNode.js +2 -2
- package/dist/esm/recording/ExecutionRecorder.js +5 -1
- package/dist/esm/utils/chatMessageToOpenAIChatCompletionMessage.js +15 -2
- package/dist/esm/utils/coerceType.js +1 -1
- package/dist/esm/utils/fetchEventSource.js +1 -1
- package/dist/esm/utils/interpolation.js +108 -3
- package/dist/esm/utils/openai.js +106 -50
- package/dist/esm/utils/paths.js +80 -0
- package/dist/esm/utils/serialization/serialization_v4.js +5 -0
- package/dist/types/api/createProcessor.d.ts +11 -5
- package/dist/types/api/looseDataValue.d.ts +4 -0
- package/dist/types/api/streaming.d.ts +1 -1
- package/dist/types/exports.d.ts +2 -0
- package/dist/types/integrations/CodeRunner.d.ts +18 -0
- package/dist/types/model/DataValue.d.ts +29 -6
- package/dist/types/model/EditorDefinition.d.ts +6 -1
- package/dist/types/model/GraphProcessor.d.ts +14 -7
- package/dist/types/model/NodeBase.d.ts +4 -0
- package/dist/types/model/NodeImpl.d.ts +5 -4
- package/dist/types/model/Nodes.d.ts +13 -4
- package/dist/types/model/ProcessContext.d.ts +16 -1
- package/dist/types/model/Project.d.ts +19 -7
- package/dist/types/model/ProjectReferenceLoader.d.ts +5 -0
- package/dist/types/model/RivetPlugin.d.ts +6 -0
- package/dist/types/model/RivetUIContext.d.ts +5 -1
- package/dist/types/model/Settings.d.ts +1 -0
- package/dist/types/model/nodes/AssemblePromptNode.d.ts +4 -1
- package/dist/types/model/nodes/ChatLoopNode.d.ts +21 -0
- package/dist/types/model/nodes/ChatNode.d.ts +2 -62
- package/dist/types/model/nodes/ChatNodeBase.d.ts +85 -0
- package/dist/types/model/nodes/CodeNode.d.ts +8 -2
- package/dist/types/model/nodes/CronNode.d.ts +34 -0
- package/dist/types/model/nodes/DelegateFunctionCallNode.d.ts +1 -0
- package/dist/types/model/nodes/DocumentNode.d.ts +28 -0
- package/dist/types/model/nodes/ImageToMDNode.d.ts +20 -0
- package/dist/types/model/nodes/LoopUntilNode.d.ts +32 -0
- package/dist/types/model/nodes/PromptNode.d.ts +2 -0
- package/dist/types/model/nodes/ReadAllFilesNode.d.ts +30 -0
- package/dist/types/model/nodes/ReadDirectoryNode.d.ts +1 -1
- package/dist/types/model/nodes/ReferencedGraphAliasNode.d.ts +31 -0
- package/dist/types/model/nodes/ToMarkdownTableNode.d.ts +19 -0
- package/dist/types/model/nodes/ToTreeNode.d.ts +21 -0
- package/dist/types/model/nodes/UserInputNode.d.ts +2 -3
- package/dist/types/plugins/anthropic/anthropic.d.ts +94 -13
- package/dist/types/plugins/anthropic/nodes/ChatAnthropicNode.d.ts +7 -2
- package/dist/types/plugins/google/google.d.ts +93 -18
- package/dist/types/plugins/google/nodes/ChatGoogleNode.d.ts +3 -2
- package/dist/types/recording/RecordedEvents.d.ts +2 -0
- package/dist/types/utils/base64.d.ts +1 -1
- package/dist/types/utils/chatMessageToOpenAIChatCompletionMessage.d.ts +3 -1
- package/dist/types/utils/interpolation.d.ts +3 -0
- package/dist/types/utils/openai.d.ts +127 -21
- package/dist/types/utils/paths.d.ts +8 -0
- package/package.json +15 -11
- /package/dist/types/model/nodes/{GptFunctionNode.d.ts → ToolNode.d.ts} +0 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import {} from '../NodeBase.js';
|
|
2
|
+
import {} from '../DataValue.js';
|
|
3
|
+
import { NodeImpl } from '../NodeImpl.js';
|
|
4
|
+
import { nodeDefinition } from '../NodeDefinition.js';
|
|
5
|
+
import { nanoid } from 'nanoid/non-secure';
|
|
6
|
+
import { getInputOrData } from '../../utils/index.js';
|
|
7
|
+
import {} from '../ProcessContext.js';
|
|
8
|
+
import { dedent } from 'ts-dedent';
|
|
9
|
+
import { uint8ArrayToBase64 } from '../../utils/base64.js';
|
|
10
|
+
export class ReadAllFilesNodeImpl extends NodeImpl {
|
|
11
|
+
static create() {
|
|
12
|
+
return {
|
|
13
|
+
id: nanoid(),
|
|
14
|
+
type: 'readAllFiles',
|
|
15
|
+
title: 'Read All Files',
|
|
16
|
+
visualData: { x: 0, y: 0, width: 250 },
|
|
17
|
+
data: {
|
|
18
|
+
path: '',
|
|
19
|
+
usePathInput: false,
|
|
20
|
+
recursive: false,
|
|
21
|
+
useRecursiveInput: false,
|
|
22
|
+
filterGlobs: [],
|
|
23
|
+
useFilterGlobsInput: false,
|
|
24
|
+
ignores: [],
|
|
25
|
+
useIgnoresInput: false,
|
|
26
|
+
asBinary: false,
|
|
27
|
+
errorOnMissingFile: false,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
getInputDefinitions() {
|
|
32
|
+
const inputDefinitions = [];
|
|
33
|
+
if (this.chartNode.data.usePathInput) {
|
|
34
|
+
inputDefinitions.push({
|
|
35
|
+
id: 'path',
|
|
36
|
+
title: 'Path',
|
|
37
|
+
dataType: 'string',
|
|
38
|
+
required: true,
|
|
39
|
+
coerced: false,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (this.chartNode.data.useRecursiveInput) {
|
|
43
|
+
inputDefinitions.push({
|
|
44
|
+
id: 'recursive',
|
|
45
|
+
title: 'Recursive',
|
|
46
|
+
dataType: 'boolean',
|
|
47
|
+
required: true,
|
|
48
|
+
coerced: false,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (this.chartNode.data.useFilterGlobsInput) {
|
|
52
|
+
inputDefinitions.push({
|
|
53
|
+
id: 'filterGlobs',
|
|
54
|
+
title: 'Filter Globs',
|
|
55
|
+
dataType: 'string[]',
|
|
56
|
+
required: true,
|
|
57
|
+
coerced: false,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (this.chartNode.data.useIgnoresInput) {
|
|
61
|
+
inputDefinitions.push({
|
|
62
|
+
id: 'ignores',
|
|
63
|
+
title: 'Ignores',
|
|
64
|
+
dataType: 'string[]',
|
|
65
|
+
required: true,
|
|
66
|
+
coerced: false,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return inputDefinitions;
|
|
70
|
+
}
|
|
71
|
+
getOutputDefinitions() {
|
|
72
|
+
return [
|
|
73
|
+
{
|
|
74
|
+
id: 'files',
|
|
75
|
+
title: 'Files',
|
|
76
|
+
dataType: 'object[]',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 'rootPath',
|
|
80
|
+
title: 'Root Path',
|
|
81
|
+
dataType: 'string',
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
getEditors() {
|
|
86
|
+
return [
|
|
87
|
+
{
|
|
88
|
+
type: 'directoryBrowser',
|
|
89
|
+
label: 'Path',
|
|
90
|
+
dataKey: 'path',
|
|
91
|
+
useInputToggleDataKey: 'usePathInput',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: 'toggle',
|
|
95
|
+
label: 'Recursive',
|
|
96
|
+
dataKey: 'recursive',
|
|
97
|
+
useInputToggleDataKey: 'useRecursiveInput',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: 'stringList',
|
|
101
|
+
label: 'Filter Globs',
|
|
102
|
+
dataKey: 'filterGlobs',
|
|
103
|
+
useInputToggleDataKey: 'useFilterGlobsInput',
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
type: 'stringList',
|
|
107
|
+
label: 'Ignores',
|
|
108
|
+
dataKey: 'ignores',
|
|
109
|
+
useInputToggleDataKey: 'useIgnoresInput',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
type: 'toggle',
|
|
113
|
+
label: 'Read as Binary',
|
|
114
|
+
dataKey: 'asBinary',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
type: 'toggle',
|
|
118
|
+
label: 'Error on Missing File',
|
|
119
|
+
dataKey: 'errorOnMissingFile',
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
getBody() {
|
|
124
|
+
return dedent `
|
|
125
|
+
${this.data.asBinary ? 'Read as Binary' : 'Read as Text'}
|
|
126
|
+
Path: ${this.data.usePathInput ? '(Input)' : this.data.path}
|
|
127
|
+
Recursive: ${this.data.useRecursiveInput ? '(Input)' : this.data.recursive}
|
|
128
|
+
Filters: ${this.data.useFilterGlobsInput
|
|
129
|
+
? '(Input)'
|
|
130
|
+
: this.data.filterGlobs.length > 0
|
|
131
|
+
? this.data.filterGlobs.join(', ')
|
|
132
|
+
: 'None'}
|
|
133
|
+
`;
|
|
134
|
+
}
|
|
135
|
+
static getUIData() {
|
|
136
|
+
return {
|
|
137
|
+
infoBoxBody: dedent `
|
|
138
|
+
Reads all files in the specified directory and outputs an array of objects containing each file's path and contents.
|
|
139
|
+
Each object has a 'path' (string) and 'content' (string or binary) property.
|
|
140
|
+
`,
|
|
141
|
+
infoBoxTitle: 'Read All Files Node',
|
|
142
|
+
contextMenuTitle: 'Read All Files',
|
|
143
|
+
group: ['Input/Output'],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async process(inputs, context) {
|
|
147
|
+
const { nativeApi } = context;
|
|
148
|
+
if (nativeApi == null) {
|
|
149
|
+
throw new Error('This node requires a native API to run.');
|
|
150
|
+
}
|
|
151
|
+
const path = getInputOrData(this.chartNode.data, inputs, 'path');
|
|
152
|
+
const recursive = getInputOrData(this.data, inputs, 'recursive', 'boolean');
|
|
153
|
+
const filterGlobs = getInputOrData(this.data, inputs, 'filterGlobs', 'string[]');
|
|
154
|
+
const ignores = getInputOrData(this.data, inputs, 'ignores', 'string[]');
|
|
155
|
+
try {
|
|
156
|
+
// First read the directory
|
|
157
|
+
const filePaths = await nativeApi.readdir(path, undefined, {
|
|
158
|
+
recursive,
|
|
159
|
+
includeDirectories: false, // We only want files since we're reading contents
|
|
160
|
+
filterGlobs,
|
|
161
|
+
relative: true, // Always use relative paths in output
|
|
162
|
+
ignores,
|
|
163
|
+
});
|
|
164
|
+
// Then read each file
|
|
165
|
+
const filePromises = filePaths.map(async (filePath) => {
|
|
166
|
+
try {
|
|
167
|
+
if (this.data.asBinary) {
|
|
168
|
+
const content = await nativeApi.readBinaryFile(`${path}/${filePath}`);
|
|
169
|
+
const buffer = await content.arrayBuffer();
|
|
170
|
+
return {
|
|
171
|
+
path: filePath,
|
|
172
|
+
content: (await uint8ArrayToBase64(new Uint8Array(buffer))) ?? '',
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
const content = await nativeApi.readTextFile(`${path}/${filePath}`, undefined);
|
|
177
|
+
return {
|
|
178
|
+
path: filePath,
|
|
179
|
+
content,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
if (this.chartNode.data.errorOnMissingFile) {
|
|
185
|
+
throw err;
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
path: filePath,
|
|
189
|
+
content: this.data.asBinary ? new Uint8Array() : '',
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
const files = await Promise.all(filePromises);
|
|
194
|
+
return {
|
|
195
|
+
['files']: { type: 'object[]', value: files },
|
|
196
|
+
['rootPath']: { type: 'string', value: path },
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
if (this.chartNode.data.errorOnMissingFile) {
|
|
201
|
+
throw err;
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
['files']: { type: 'object[]', value: [] },
|
|
205
|
+
['rootPath']: { type: 'string', value: path },
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
export const readAllFilesNode = nodeDefinition(ReadAllFilesNodeImpl, 'Read All Files');
|
|
@@ -6,7 +6,8 @@ import {} from '../GraphProcessor.js';
|
|
|
6
6
|
import {} from '../../index.js';
|
|
7
7
|
import {} from '../ProcessContext.js';
|
|
8
8
|
import { dedent } from 'ts-dedent';
|
|
9
|
-
import {
|
|
9
|
+
import { createTreeFromPaths } from '../../utils/paths.js';
|
|
10
|
+
import { getInputOrData } from '../../utils/inputs.js';
|
|
10
11
|
export class ReadDirectoryNodeImpl extends NodeImpl {
|
|
11
12
|
static create() {
|
|
12
13
|
return {
|
|
@@ -91,6 +92,11 @@ export class ReadDirectoryNodeImpl extends NodeImpl {
|
|
|
91
92
|
title: 'Paths',
|
|
92
93
|
dataType: 'string[]',
|
|
93
94
|
},
|
|
95
|
+
{
|
|
96
|
+
id: 'tree',
|
|
97
|
+
title: 'Tree',
|
|
98
|
+
dataType: 'object',
|
|
99
|
+
},
|
|
94
100
|
];
|
|
95
101
|
}
|
|
96
102
|
getBody() {
|
|
@@ -109,36 +115,27 @@ export class ReadDirectoryNodeImpl extends NodeImpl {
|
|
|
109
115
|
static getUIData() {
|
|
110
116
|
return {
|
|
111
117
|
infoBoxBody: dedent `
|
|
112
|
-
Reads the contents of the specified directory and outputs
|
|
118
|
+
Reads the contents of the specified directory and outputs:
|
|
119
|
+
1. An array of filenames
|
|
120
|
+
2. The root path of the search
|
|
121
|
+
3. A tree structure representing the directory hierarchy
|
|
113
122
|
`,
|
|
114
123
|
infoBoxTitle: 'Read Directory Node',
|
|
115
124
|
contextMenuTitle: 'Read Directory',
|
|
116
125
|
group: ['Input/Output'],
|
|
117
126
|
};
|
|
118
127
|
}
|
|
119
|
-
async process(
|
|
128
|
+
async process(inputs, context) {
|
|
120
129
|
const { nativeApi } = context;
|
|
121
130
|
if (nativeApi == null) {
|
|
122
131
|
throw new Error('This node requires a native API to run.');
|
|
123
132
|
}
|
|
124
|
-
const path = this.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const includeDirectories = this.chartNode.data.useIncludeDirectoriesInput
|
|
131
|
-
? expectType(inputData['includeDirectories'], 'boolean')
|
|
132
|
-
: this.chartNode.data.includeDirectories;
|
|
133
|
-
const filterGlobs = this.chartNode.data.useFilterGlobsInput
|
|
134
|
-
? expectType(inputData['filterGlobs'], 'string[]')
|
|
135
|
-
: this.chartNode.data.filterGlobs;
|
|
136
|
-
const relative = this.chartNode.data.useRelativeInput
|
|
137
|
-
? expectType(inputData['relative'], 'boolean')
|
|
138
|
-
: this.chartNode.data.relative;
|
|
139
|
-
const ignores = this.chartNode.data.useIgnoresInput
|
|
140
|
-
? expectType(inputData['ignores'], 'string[]')
|
|
141
|
-
: this.chartNode.data.ignores;
|
|
133
|
+
const path = getInputOrData(this.data, inputs, 'path');
|
|
134
|
+
const recursive = getInputOrData(this.data, inputs, 'recursive', 'boolean');
|
|
135
|
+
const includeDirectories = getInputOrData(this.data, inputs, 'includeDirectories', 'boolean');
|
|
136
|
+
const filterGlobs = getInputOrData(this.data, inputs, 'filterGlobs', 'string[]');
|
|
137
|
+
const relative = getInputOrData(this.data, inputs, 'relative', 'boolean');
|
|
138
|
+
const ignores = getInputOrData(this.data, inputs, 'ignores', 'string[]');
|
|
142
139
|
try {
|
|
143
140
|
const files = await nativeApi.readdir(path, undefined, {
|
|
144
141
|
recursive,
|
|
@@ -147,18 +144,27 @@ export class ReadDirectoryNodeImpl extends NodeImpl {
|
|
|
147
144
|
relative,
|
|
148
145
|
ignores,
|
|
149
146
|
});
|
|
150
|
-
const
|
|
147
|
+
const tree = createTreeFromPaths(files, path);
|
|
148
|
+
return {
|
|
151
149
|
['paths']: { type: 'string[]', value: files },
|
|
152
150
|
['rootPath']: { type: 'string', value: path },
|
|
151
|
+
['tree']: { type: 'object', value: tree },
|
|
153
152
|
};
|
|
154
|
-
return outputs;
|
|
155
153
|
}
|
|
156
154
|
catch (err) {
|
|
157
|
-
|
|
155
|
+
return {
|
|
158
156
|
['paths']: { type: 'string[]', value: ['(no such path)'] },
|
|
159
157
|
['rootPath']: { type: 'string', value: path },
|
|
158
|
+
['tree']: {
|
|
159
|
+
type: 'object',
|
|
160
|
+
value: {
|
|
161
|
+
path,
|
|
162
|
+
name: path.split('/').pop() || path,
|
|
163
|
+
isDirectory: true,
|
|
164
|
+
children: [],
|
|
165
|
+
},
|
|
166
|
+
},
|
|
160
167
|
};
|
|
161
|
-
return outputs;
|
|
162
168
|
}
|
|
163
169
|
}
|
|
164
170
|
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import {} from '../NodeBase.js';
|
|
2
|
+
import { NodeImpl } from '../NodeImpl.js';
|
|
3
|
+
import { nodeDefinition } from '../NodeDefinition.js';
|
|
4
|
+
import {} from '../GraphProcessor.js';
|
|
5
|
+
import {} from '../NodeGraph.js';
|
|
6
|
+
import { nanoid } from 'nanoid/non-secure';
|
|
7
|
+
import {} from '../Project.js';
|
|
8
|
+
import {} from './GraphInputNode.js';
|
|
9
|
+
import {} from './GraphOutputNode.js';
|
|
10
|
+
import {} from '../DataValue.js';
|
|
11
|
+
import {} from '../ProcessContext.js';
|
|
12
|
+
import { dedent } from 'ts-dedent';
|
|
13
|
+
import { getError } from '../../utils/errors.js';
|
|
14
|
+
export class ReferencedGraphAliasNodeImpl extends NodeImpl {
|
|
15
|
+
static create() {
|
|
16
|
+
const chartNode = {
|
|
17
|
+
type: 'referencedGraphAlias',
|
|
18
|
+
title: '', // Always set initially by the editor
|
|
19
|
+
id: nanoid(),
|
|
20
|
+
visualData: {
|
|
21
|
+
x: 0,
|
|
22
|
+
y: 0,
|
|
23
|
+
width: 300,
|
|
24
|
+
},
|
|
25
|
+
data: {
|
|
26
|
+
projectId: undefined, // Always set initially by the editor
|
|
27
|
+
graphId: undefined, // Always set initially by the editor
|
|
28
|
+
useErrorOutput: false,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
return chartNode;
|
|
32
|
+
}
|
|
33
|
+
getInputDefinitions(_connections, _nodes, _project, referencedProjects) {
|
|
34
|
+
const referencedProject = referencedProjects[this.data.projectId];
|
|
35
|
+
if (!referencedProject) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const graph = referencedProject.graphs[this.data.graphId];
|
|
39
|
+
if (!graph) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
const inputNodes = graph.nodes.filter((node) => node.type === 'graphInput');
|
|
43
|
+
const inputIds = [...new Set(inputNodes.map((node) => node.data.id))].sort();
|
|
44
|
+
return inputIds.map((id) => ({
|
|
45
|
+
id: id,
|
|
46
|
+
title: id,
|
|
47
|
+
dataType: inputNodes.find((node) => node.data.id === id).data.dataType,
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
getGraphOutputs(referencedProject) {
|
|
51
|
+
const graph = referencedProject.graphs[this.data.graphId];
|
|
52
|
+
if (!graph) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
const outputNodes = graph.nodes.filter((node) => node.type === 'graphOutput');
|
|
56
|
+
const outputIds = [...new Set(outputNodes.map((node) => node.data.id))].sort();
|
|
57
|
+
const outputs = outputIds.map((id) => ({
|
|
58
|
+
id: id,
|
|
59
|
+
title: id,
|
|
60
|
+
dataType: outputNodes.find((node) => node.data.id === id).data.dataType,
|
|
61
|
+
}));
|
|
62
|
+
return outputs;
|
|
63
|
+
}
|
|
64
|
+
getOutputDefinitions(_connections, _nodes, _project, referencedProjects) {
|
|
65
|
+
const outputs = [];
|
|
66
|
+
const referencedProject = referencedProjects[this.data.projectId];
|
|
67
|
+
if (!referencedProject) {
|
|
68
|
+
return outputs;
|
|
69
|
+
}
|
|
70
|
+
outputs.push(...this.getGraphOutputs(referencedProject));
|
|
71
|
+
if (this.data.useErrorOutput) {
|
|
72
|
+
outputs.push({
|
|
73
|
+
id: 'error',
|
|
74
|
+
title: 'Error',
|
|
75
|
+
dataType: 'string',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return outputs;
|
|
79
|
+
}
|
|
80
|
+
getEditors(context) {
|
|
81
|
+
const definitions = [
|
|
82
|
+
{
|
|
83
|
+
type: 'toggle',
|
|
84
|
+
label: 'Use Error Output',
|
|
85
|
+
dataKey: 'useErrorOutput',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
type: 'toggle',
|
|
89
|
+
label: 'Output Cost & Duration',
|
|
90
|
+
dataKey: 'outputCostDuration',
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
const referencedProject = context.referencedProjects[this.data.projectId];
|
|
94
|
+
if (referencedProject) {
|
|
95
|
+
const graph = referencedProject.graphs[this.data.graphId];
|
|
96
|
+
if (graph) {
|
|
97
|
+
const inputNodes = graph.nodes.filter((node) => node.type === 'graphInput');
|
|
98
|
+
const inputIds = [...new Set(inputNodes.map((node) => node.data.id))].sort();
|
|
99
|
+
for (const inputId of inputIds) {
|
|
100
|
+
const inputNode = inputNodes.find((node) => node.data.id === inputId);
|
|
101
|
+
definitions.push({
|
|
102
|
+
type: 'dynamic',
|
|
103
|
+
dataKey: 'inputData',
|
|
104
|
+
dynamicDataKey: inputNode.data.id,
|
|
105
|
+
dataType: inputNode.data.dataType,
|
|
106
|
+
label: inputNode.data.id,
|
|
107
|
+
editor: inputNode.data.editor ?? 'auto',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return definitions;
|
|
113
|
+
}
|
|
114
|
+
getBody(context) {
|
|
115
|
+
return context.referencedProjects[this.data.projectId]?.graphs[this.data.graphId]?.metadata?.description ?? '';
|
|
116
|
+
}
|
|
117
|
+
static getUIData() {
|
|
118
|
+
return {
|
|
119
|
+
infoBoxBody: dedent `
|
|
120
|
+
References a graph from another project. Inputs and outputs are defined by Graph Input and Graph Output nodes within the referenced graph.
|
|
121
|
+
`,
|
|
122
|
+
infoBoxTitle: 'Referenced Graph Alias Node',
|
|
123
|
+
contextMenuTitle: 'Referenced Graph Alias',
|
|
124
|
+
group: ['Advanced'],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async process(inputs, context) {
|
|
128
|
+
const referencedProject = context.referencedProjects[this.data.projectId];
|
|
129
|
+
if (!referencedProject) {
|
|
130
|
+
throw new Error(`ReferencedGraphAliasNode requires a project with id ${this.data.projectId} to be available in the context.referencedProjects.`);
|
|
131
|
+
}
|
|
132
|
+
const graph = referencedProject.graphs[this.data.graphId];
|
|
133
|
+
if (!graph) {
|
|
134
|
+
throw new Error(`ReferencedGraphAliasNode requires a graph with id ${this.data.graphId} to be present in the referenced project.`);
|
|
135
|
+
}
|
|
136
|
+
const inputNodes = graph.nodes.filter((node) => node.type === 'graphInput');
|
|
137
|
+
const inputIds = [...new Set(inputNodes.map((node) => node.data.id))].sort();
|
|
138
|
+
const inputData = inputIds.reduce((obj, id) => {
|
|
139
|
+
if (inputs[id] != null) {
|
|
140
|
+
return {
|
|
141
|
+
...obj,
|
|
142
|
+
[id]: inputs[id],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (this.data.inputData?.[id] != null) {
|
|
146
|
+
return {
|
|
147
|
+
...obj,
|
|
148
|
+
[id]: this.data.inputData[id],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return obj;
|
|
152
|
+
}, {});
|
|
153
|
+
// Create a subprocessor using the referenced project's graph
|
|
154
|
+
const subGraphProcessor = context.createSubProcessor(this.data.graphId, {
|
|
155
|
+
signal: context.signal,
|
|
156
|
+
project: referencedProject,
|
|
157
|
+
});
|
|
158
|
+
try {
|
|
159
|
+
const startTime = Date.now();
|
|
160
|
+
const outputs = await subGraphProcessor.processGraph(context, inputData, context.contextValues);
|
|
161
|
+
const duration = Date.now() - startTime;
|
|
162
|
+
if (this.data.useErrorOutput) {
|
|
163
|
+
outputs['error'] = {
|
|
164
|
+
type: 'control-flow-excluded',
|
|
165
|
+
value: undefined,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (outputs['duration'] == null) {
|
|
169
|
+
outputs['duration'] = {
|
|
170
|
+
type: 'number',
|
|
171
|
+
value: duration,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
if (!this.data.outputCostDuration) {
|
|
175
|
+
delete outputs['cost'];
|
|
176
|
+
delete outputs['duration'];
|
|
177
|
+
}
|
|
178
|
+
return outputs;
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
if (!this.data.useErrorOutput) {
|
|
182
|
+
throw err;
|
|
183
|
+
}
|
|
184
|
+
const outputs = this.getGraphOutputs(referencedProject).reduce((obj, output) => ({
|
|
185
|
+
...obj,
|
|
186
|
+
[output.id]: {
|
|
187
|
+
type: 'control-flow-excluded',
|
|
188
|
+
value: undefined,
|
|
189
|
+
},
|
|
190
|
+
}), {});
|
|
191
|
+
outputs['error'] = {
|
|
192
|
+
type: 'string',
|
|
193
|
+
value: getError(err).message,
|
|
194
|
+
};
|
|
195
|
+
return outputs;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
export const referencedGraphAliasNode = nodeDefinition(ReferencedGraphAliasNodeImpl, 'Referenced Graph Alias');
|
|
@@ -6,7 +6,7 @@ import {} from '../DataValue.js';
|
|
|
6
6
|
import {} from '../../index.js';
|
|
7
7
|
import { dedent } from 'ts-dedent';
|
|
8
8
|
import { coerceTypeOptional } from '../../utils/coerceType.js';
|
|
9
|
-
import { interpolate } from '../../utils/interpolation.js';
|
|
9
|
+
import { extractInterpolationVariables, interpolate } from '../../utils/interpolation.js';
|
|
10
10
|
export class TextNodeImpl extends NodeImpl {
|
|
11
11
|
static create() {
|
|
12
12
|
const chartNode = {
|
|
@@ -26,13 +26,13 @@ export class TextNodeImpl extends NodeImpl {
|
|
|
26
26
|
}
|
|
27
27
|
getInputDefinitions() {
|
|
28
28
|
// Extract inputs from text, everything like {{input}}
|
|
29
|
-
const inputNames =
|
|
29
|
+
const inputNames = extractInterpolationVariables(this.data.text);
|
|
30
30
|
return (inputNames?.map((inputName) => {
|
|
31
31
|
return {
|
|
32
32
|
type: 'string',
|
|
33
33
|
// id and title should not have the {{ and }}
|
|
34
|
-
id: inputName
|
|
35
|
-
title: inputName
|
|
34
|
+
id: inputName,
|
|
35
|
+
title: inputName,
|
|
36
36
|
dataType: 'string',
|
|
37
37
|
required: false,
|
|
38
38
|
};
|
|
@@ -49,6 +49,11 @@ export class TextNodeImpl extends NodeImpl {
|
|
|
49
49
|
}
|
|
50
50
|
getEditors() {
|
|
51
51
|
return [
|
|
52
|
+
{
|
|
53
|
+
type: 'custom',
|
|
54
|
+
label: 'AI Assist',
|
|
55
|
+
customEditorId: 'TextNodeAiAssist',
|
|
56
|
+
},
|
|
52
57
|
{
|
|
53
58
|
type: 'code',
|
|
54
59
|
label: 'Text',
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import {} from '../NodeBase.js';
|
|
2
|
+
import { nanoid } from 'nanoid/non-secure';
|
|
3
|
+
import { NodeImpl } from '../NodeImpl.js';
|
|
4
|
+
import { nodeDefinition } from '../NodeDefinition.js';
|
|
5
|
+
import {} from '../GraphProcessor.js';
|
|
6
|
+
import {} from '../../index.js';
|
|
7
|
+
import { dedent } from 'ts-dedent';
|
|
8
|
+
import { coerceType } from '../../utils/coerceType.js';
|
|
9
|
+
export class ToMarkdownTableNodeImpl extends NodeImpl {
|
|
10
|
+
static create() {
|
|
11
|
+
const chartNode = {
|
|
12
|
+
type: 'toMarkdownTable',
|
|
13
|
+
title: 'To Markdown Table',
|
|
14
|
+
id: nanoid(),
|
|
15
|
+
visualData: {
|
|
16
|
+
x: 0,
|
|
17
|
+
y: 0,
|
|
18
|
+
width: 200,
|
|
19
|
+
},
|
|
20
|
+
data: {
|
|
21
|
+
includeHeaders: true,
|
|
22
|
+
alignPipes: false,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
return chartNode;
|
|
26
|
+
}
|
|
27
|
+
getInputDefinitions() {
|
|
28
|
+
return [
|
|
29
|
+
{
|
|
30
|
+
id: 'data',
|
|
31
|
+
title: 'Data Array',
|
|
32
|
+
dataType: 'any',
|
|
33
|
+
required: true,
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
getOutputDefinitions() {
|
|
38
|
+
return [
|
|
39
|
+
{
|
|
40
|
+
id: 'markdown',
|
|
41
|
+
title: 'Markdown Table',
|
|
42
|
+
dataType: 'string',
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
getEditors() {
|
|
47
|
+
return [
|
|
48
|
+
{
|
|
49
|
+
type: 'toggle',
|
|
50
|
+
label: 'Include Headers',
|
|
51
|
+
dataKey: 'includeHeaders',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
type: 'toggle',
|
|
55
|
+
label: 'Align Pipes',
|
|
56
|
+
dataKey: 'alignPipes',
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
getBody() {
|
|
61
|
+
const parts = [];
|
|
62
|
+
if (this.data.includeHeaders)
|
|
63
|
+
parts.push('With Header Row');
|
|
64
|
+
if (this.data.alignPipes)
|
|
65
|
+
parts.push('Pipes Aligned');
|
|
66
|
+
return parts.length > 0 ? parts.join(', ') : undefined;
|
|
67
|
+
}
|
|
68
|
+
static getUIData() {
|
|
69
|
+
return {
|
|
70
|
+
infoBoxBody: dedent `
|
|
71
|
+
Converts an array of objects into a markdown table format.
|
|
72
|
+
Input should be an array of objects with consistent keys.
|
|
73
|
+
`,
|
|
74
|
+
infoBoxTitle: 'To Markdown Table Node',
|
|
75
|
+
contextMenuTitle: 'To Markdown Table',
|
|
76
|
+
group: ['Text'],
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async process(inputs) {
|
|
80
|
+
const data = coerceType(inputs['data'], 'object[]');
|
|
81
|
+
const keys = data.length === 0 ? [] : Object.keys(data[0]);
|
|
82
|
+
// Dynamic import because these are ESM-only, and top level imports are converted to CommonJS for rivet-node.
|
|
83
|
+
// Dynamic import is able to load ESM-only modules.
|
|
84
|
+
const { toMarkdown } = await import('mdast-util-to-markdown');
|
|
85
|
+
const { gfmTableToMarkdown } = await import('mdast-util-gfm-table');
|
|
86
|
+
const markdownTable = toMarkdown({
|
|
87
|
+
type: 'table',
|
|
88
|
+
children: [
|
|
89
|
+
...(this.data.includeHeaders
|
|
90
|
+
? [
|
|
91
|
+
{
|
|
92
|
+
type: 'tableRow',
|
|
93
|
+
children: keys.map((key) => ({
|
|
94
|
+
type: 'tableCell',
|
|
95
|
+
children: [{ type: 'text', value: key }],
|
|
96
|
+
})),
|
|
97
|
+
},
|
|
98
|
+
]
|
|
99
|
+
: []),
|
|
100
|
+
...data.map((row) => ({
|
|
101
|
+
type: 'tableRow',
|
|
102
|
+
children: keys.map((key) => ({
|
|
103
|
+
type: 'tableCell',
|
|
104
|
+
children: [{ type: 'text', value: `${row[key]}` }],
|
|
105
|
+
})),
|
|
106
|
+
})),
|
|
107
|
+
],
|
|
108
|
+
}, {
|
|
109
|
+
extensions: [gfmTableToMarkdown({ tablePipeAlign: this.data.alignPipes })],
|
|
110
|
+
});
|
|
111
|
+
return {
|
|
112
|
+
['markdown']: {
|
|
113
|
+
type: 'string',
|
|
114
|
+
value: markdownTable,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export const toMarkdownTableNode = nodeDefinition(ToMarkdownTableNodeImpl, 'To Markdown Table');
|