@alpic80/rivet-core 1.19.1-aidon.3 → 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 +3993 -943
- 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 +28 -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/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 +2 -2
- 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 +12 -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/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
|
@@ -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');
|
|
@@ -0,0 +1,133 @@
|
|
|
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 '../DataValue.js';
|
|
6
|
+
import {} from '../EditorDefinition.js';
|
|
7
|
+
import { dedent } from 'ts-dedent';
|
|
8
|
+
import { coerceTypeOptional } from '../../utils/coerceType.js';
|
|
9
|
+
import { extractInterpolationVariables, interpolate } from '../../utils/interpolation.js';
|
|
10
|
+
import { get, sortBy } from 'lodash-es';
|
|
11
|
+
export class ToTreeNodeImpl extends NodeImpl {
|
|
12
|
+
static create() {
|
|
13
|
+
const chartNode = {
|
|
14
|
+
type: 'toTree',
|
|
15
|
+
title: 'To Tree',
|
|
16
|
+
id: nanoid(),
|
|
17
|
+
visualData: {
|
|
18
|
+
x: 0,
|
|
19
|
+
y: 0,
|
|
20
|
+
width: 300,
|
|
21
|
+
},
|
|
22
|
+
data: {
|
|
23
|
+
format: '{{path}}',
|
|
24
|
+
childrenProperty: 'children',
|
|
25
|
+
useSortAlphabetically: true,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
return chartNode;
|
|
29
|
+
}
|
|
30
|
+
getInputDefinitions() {
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
id: 'objects',
|
|
34
|
+
title: 'Objects',
|
|
35
|
+
dataType: ['object[]', 'object'],
|
|
36
|
+
required: true,
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
getOutputDefinitions() {
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
id: 'tree',
|
|
44
|
+
title: 'Tree',
|
|
45
|
+
dataType: 'string',
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
getEditors() {
|
|
50
|
+
return [
|
|
51
|
+
{
|
|
52
|
+
type: 'string',
|
|
53
|
+
label: 'Children Property',
|
|
54
|
+
dataKey: 'childrenProperty',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: 'code',
|
|
58
|
+
label: 'Format',
|
|
59
|
+
dataKey: 'format',
|
|
60
|
+
language: 'prompt-interpolation-markdown',
|
|
61
|
+
theme: 'prompt-interpolation',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
type: 'toggle',
|
|
65
|
+
label: 'Sort Alphabetically',
|
|
66
|
+
dataKey: 'useSortAlphabetically',
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
getBody() {
|
|
71
|
+
return dedent `
|
|
72
|
+
Format: ${this.data.format}
|
|
73
|
+
Children: ${this.data.childrenProperty}
|
|
74
|
+
Sort: ${this.data.useSortAlphabetically ? 'Yes' : 'No'}
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
77
|
+
static getUIData() {
|
|
78
|
+
return {
|
|
79
|
+
infoBoxBody: dedent `
|
|
80
|
+
Converts an array of objects into a tree structure and renders it as text.
|
|
81
|
+
|
|
82
|
+
The format field supports interpolation using {{property}} syntax to determine
|
|
83
|
+
how each node is displayed.
|
|
84
|
+
|
|
85
|
+
Use the children property to specify which field contains child nodes.
|
|
86
|
+
`,
|
|
87
|
+
infoBoxTitle: 'To Tree Node',
|
|
88
|
+
contextMenuTitle: 'To Tree',
|
|
89
|
+
group: ['Text'],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
buildTree(objects, parentPath = '', level = 0, isLast = true) {
|
|
93
|
+
if (!Array.isArray(objects) || objects.length === 0)
|
|
94
|
+
return '';
|
|
95
|
+
let result = '';
|
|
96
|
+
const sortedObjects = this.data.useSortAlphabetically
|
|
97
|
+
? sortBy(objects, (obj) => String(get(obj, 'path', '')))
|
|
98
|
+
: objects;
|
|
99
|
+
sortedObjects.forEach((obj, index) => {
|
|
100
|
+
const isLastItem = index === sortedObjects.length - 1;
|
|
101
|
+
const prefix = level === 0 ? '' : isLast ? '└── ' : '├── ';
|
|
102
|
+
const indent = level === 0 ? '' : ' '.repeat(level - 1) + (isLast ? ' ' : '│ ');
|
|
103
|
+
// Get all potential interpolation variables from the format string
|
|
104
|
+
const matches = extractInterpolationVariables(this.data.format);
|
|
105
|
+
const interpolationVars = matches.reduce((acc, match) => {
|
|
106
|
+
const key = match;
|
|
107
|
+
acc[key] = String(get(obj, key, ''));
|
|
108
|
+
return acc;
|
|
109
|
+
}, {});
|
|
110
|
+
const formattedNode = interpolate(this.data.format, interpolationVars);
|
|
111
|
+
// Add this node to the result
|
|
112
|
+
result += indent + prefix + formattedNode + '\n';
|
|
113
|
+
// Process children if they exist
|
|
114
|
+
const children = get(obj, this.data.childrenProperty);
|
|
115
|
+
if (Array.isArray(children) && children.length > 0) {
|
|
116
|
+
const newPath = parentPath ? `${parentPath}/${formattedNode}` : formattedNode;
|
|
117
|
+
result += this.buildTree(children, newPath, level + 1, isLastItem);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
async process(inputs) {
|
|
123
|
+
const objects = coerceTypeOptional(inputs['objects'], 'object[]') ?? [];
|
|
124
|
+
const treeOutput = this.buildTree(objects);
|
|
125
|
+
return {
|
|
126
|
+
['tree']: {
|
|
127
|
+
type: 'string',
|
|
128
|
+
value: treeOutput,
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export const toTreeNode = nodeDefinition(ToTreeNodeImpl, 'To Tree');
|
|
@@ -13,7 +13,7 @@ export class GptFunctionNodeImpl extends NodeImpl {
|
|
|
13
13
|
static create() {
|
|
14
14
|
const chartNode = {
|
|
15
15
|
type: 'gptFunction',
|
|
16
|
-
title: '
|
|
16
|
+
title: 'Tool',
|
|
17
17
|
id: nanoid(),
|
|
18
18
|
visualData: {
|
|
19
19
|
x: 0,
|
|
@@ -21,7 +21,7 @@ export class GptFunctionNodeImpl extends NodeImpl {
|
|
|
21
21
|
width: 250,
|
|
22
22
|
},
|
|
23
23
|
data: {
|
|
24
|
-
name: '
|
|
24
|
+
name: 'newTool',
|
|
25
25
|
description: 'No description provided',
|
|
26
26
|
schema: dedent `
|
|
27
27
|
{
|
|
@@ -39,7 +39,7 @@ export class GptFunctionNodeImpl extends NodeImpl {
|
|
|
39
39
|
id: 'name',
|
|
40
40
|
title: 'Name',
|
|
41
41
|
dataType: 'string',
|
|
42
|
-
description: 'The name of the
|
|
42
|
+
description: 'The name of the tool that the LLM will see as available to call',
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
if (this.data.useDescriptionInput) {
|
|
@@ -47,7 +47,7 @@ export class GptFunctionNodeImpl extends NodeImpl {
|
|
|
47
47
|
id: 'description',
|
|
48
48
|
title: 'Description',
|
|
49
49
|
dataType: 'string',
|
|
50
|
-
description: 'The description of the
|
|
50
|
+
description: 'The description of the tool that the LLM will see as available to call',
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
53
|
if (this.data.useSchemaInput) {
|
|
@@ -55,7 +55,7 @@ export class GptFunctionNodeImpl extends NodeImpl {
|
|
|
55
55
|
id: 'schema',
|
|
56
56
|
title: 'Schema',
|
|
57
57
|
dataType: 'object',
|
|
58
|
-
description: 'The schema of the
|
|
58
|
+
description: 'The schema of the tool that the LLM will see as available to call',
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
// Extract inputs from promptText, everything like {{input}}
|
|
@@ -81,7 +81,7 @@ export class GptFunctionNodeImpl extends NodeImpl {
|
|
|
81
81
|
id: 'function',
|
|
82
82
|
title: 'Function',
|
|
83
83
|
dataType: 'gpt-function',
|
|
84
|
-
description: 'The
|
|
84
|
+
description: 'The tool that can be called by the LLM.',
|
|
85
85
|
},
|
|
86
86
|
];
|
|
87
87
|
}
|
|
@@ -127,10 +127,10 @@ export class GptFunctionNodeImpl extends NodeImpl {
|
|
|
127
127
|
static getUIData() {
|
|
128
128
|
return {
|
|
129
129
|
infoBoxBody: dedent `
|
|
130
|
-
Defines a
|
|
130
|
+
Defines a tool, which is a method that the LLM can call in its responses.
|
|
131
131
|
`,
|
|
132
|
-
infoBoxTitle: '
|
|
133
|
-
contextMenuTitle: '
|
|
132
|
+
infoBoxTitle: 'Tool Node',
|
|
133
|
+
contextMenuTitle: 'Tool',
|
|
134
134
|
group: ['AI'],
|
|
135
135
|
};
|
|
136
136
|
}
|
|
@@ -166,4 +166,4 @@ export class GptFunctionNodeImpl extends NodeImpl {
|
|
|
166
166
|
};
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
|
-
export const gptFunctionNode = nodeDefinition(GptFunctionNodeImpl, '
|
|
169
|
+
export const gptFunctionNode = nodeDefinition(GptFunctionNodeImpl, 'Tool');
|