@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
|
@@ -1 +1,11 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export const IF_PORT = {
|
|
2
|
+
id: `$if`,
|
|
3
|
+
title: 'if',
|
|
4
|
+
dataType: 'boolean',
|
|
5
|
+
coerced: true,
|
|
6
|
+
description: 'Only run the node if this condition is true',
|
|
7
|
+
defaultValue: 'false',
|
|
8
|
+
};
|
|
9
|
+
export function isBuiltInInputDefinition(input) {
|
|
10
|
+
return input.id === IF_PORT.id;
|
|
11
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IF_PORT, } from './NodeBase.js';
|
|
1
2
|
export class NodeImpl {
|
|
2
3
|
chartNode;
|
|
3
4
|
constructor(chartNode) {
|
|
@@ -18,6 +19,13 @@ export class NodeImpl {
|
|
|
18
19
|
get data() {
|
|
19
20
|
return this.chartNode.data;
|
|
20
21
|
}
|
|
22
|
+
getInputDefinitionsIncludingBuiltIn(connections, nodes, project, referencedProjects) {
|
|
23
|
+
const ports = [...this.getInputDefinitions(connections, nodes, project, referencedProjects)];
|
|
24
|
+
if (this.chartNode.isConditional) {
|
|
25
|
+
ports.push(IF_PORT);
|
|
26
|
+
}
|
|
27
|
+
return ports;
|
|
28
|
+
}
|
|
21
29
|
getEditors(_context) {
|
|
22
30
|
return [];
|
|
23
31
|
}
|
package/dist/esm/model/Nodes.js
CHANGED
|
@@ -5,6 +5,7 @@ import { textNode } from './nodes/TextNode.js';
|
|
|
5
5
|
export * from './nodes/TextNode.js';
|
|
6
6
|
import { chatNode } from './nodes/ChatNode.js';
|
|
7
7
|
export * from './nodes/ChatNode.js';
|
|
8
|
+
export * from './nodes/ChatNodeBase.js';
|
|
8
9
|
import { promptNode } from './nodes/PromptNode.js';
|
|
9
10
|
export * from './nodes/PromptNode.js';
|
|
10
11
|
import { extractRegexNode } from './nodes/ExtractRegexNode.js';
|
|
@@ -61,8 +62,8 @@ import { getGlobalNode } from './nodes/GetGlobalNode.js';
|
|
|
61
62
|
export * from './nodes/GetGlobalNode.js';
|
|
62
63
|
import { waitForEventNode } from './nodes/WaitForEventNode.js';
|
|
63
64
|
export * from './nodes/WaitForEventNode.js';
|
|
64
|
-
import { gptFunctionNode } from './nodes/
|
|
65
|
-
export * from './nodes/
|
|
65
|
+
import { gptFunctionNode } from './nodes/ToolNode.js';
|
|
66
|
+
export * from './nodes/ToolNode.js';
|
|
66
67
|
import { toYamlNode } from './nodes/ToYamlNode.js';
|
|
67
68
|
export * from './nodes/ToYamlNode.js';
|
|
68
69
|
import { getEmbeddingNode } from './nodes/GetEmbeddingNode.js';
|
|
@@ -145,7 +146,22 @@ import { delegateFunctionCallNode } from './nodes/DelegateFunctionCallNode.js';
|
|
|
145
146
|
export * from './nodes/DelegateFunctionCallNode.js';
|
|
146
147
|
import { playAudioNode } from './nodes/PlayAudioNode.js';
|
|
147
148
|
export * from './nodes/PlayAudioNode.js';
|
|
148
|
-
|
|
149
|
+
import { documentNode } from './nodes/DocumentNode.js';
|
|
150
|
+
export * from './nodes/DocumentNode.js';
|
|
151
|
+
import { chatLoopNode } from './nodes/ChatLoopNode.js';
|
|
152
|
+
export * from './nodes/ChatLoopNode.js';
|
|
153
|
+
import { readAllFilesNode } from './nodes/ReadAllFilesNode.js';
|
|
154
|
+
export * from './nodes/ReadAllFilesNode.js';
|
|
155
|
+
import { toMarkdownTableNode } from './nodes/ToMarkdownTableNode.js';
|
|
156
|
+
export * from './nodes/ToMarkdownTableNode.js';
|
|
157
|
+
import { cronNode } from './nodes/CronNode.js';
|
|
158
|
+
export * from './nodes/CronNode.js';
|
|
159
|
+
import { toTreeNode } from './nodes/ToTreeNode.js';
|
|
160
|
+
export * from './nodes/ToTreeNode.js';
|
|
161
|
+
import { loopUntilNode } from './nodes/LoopUntilNode.js';
|
|
162
|
+
export * from './nodes/LoopUntilNode.js';
|
|
163
|
+
import { referencedGraphAliasNode } from './nodes/ReferencedGraphAliasNode.js';
|
|
164
|
+
export * from './nodes/ReferencedGraphAliasNode.js';
|
|
149
165
|
export const registerBuiltInNodes = (registry) => {
|
|
150
166
|
return registry
|
|
151
167
|
.register(toYamlNode)
|
|
@@ -220,7 +236,15 @@ export const registerBuiltInNodes = (registry) => {
|
|
|
220
236
|
.register(graphReferenceNode)
|
|
221
237
|
.register(callGraphNode)
|
|
222
238
|
.register(delegateFunctionCallNode)
|
|
223
|
-
.register(playAudioNode)
|
|
239
|
+
.register(playAudioNode)
|
|
240
|
+
.register(documentNode)
|
|
241
|
+
.register(chatLoopNode)
|
|
242
|
+
.register(readAllFilesNode)
|
|
243
|
+
.register(toMarkdownTableNode)
|
|
244
|
+
.register(cronNode)
|
|
245
|
+
.register(toTreeNode)
|
|
246
|
+
.register(loopUntilNode)
|
|
247
|
+
.register(referencedGraphAliasNode);
|
|
224
248
|
};
|
|
225
249
|
let globalRivetNodeRegistry = registerBuiltInNodes(new NodeRegistration());
|
|
226
250
|
export { globalRivetNodeRegistry };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -54,7 +54,7 @@ export class AssembleMessageNodeImpl extends NodeImpl {
|
|
|
54
54
|
}
|
|
55
55
|
for (let i = 1; i <= messageCount; i++) {
|
|
56
56
|
inputs.push({
|
|
57
|
-
dataType: ['string', 'image', 'string[]', 'image[]', 'object', 'object[]'],
|
|
57
|
+
dataType: ['string', 'image', 'string[]', 'image[]', 'object', 'object[]', 'document', 'document[]'],
|
|
58
58
|
id: `part${i}`,
|
|
59
59
|
title: `Part ${i}`,
|
|
60
60
|
description: 'A part of the message to assemble.',
|
|
@@ -112,7 +112,7 @@ export class AssembleMessageNodeImpl extends NodeImpl {
|
|
|
112
112
|
return {
|
|
113
113
|
infoBoxBody: dedent `
|
|
114
114
|
Assembles a single chat message from multiple parts. This is similar to a Prompt node, but works with multimodal
|
|
115
|
-
models, as you can include
|
|
115
|
+
models, as you can include text, images, and documents in the message.
|
|
116
116
|
`,
|
|
117
117
|
infoBoxTitle: 'Assemble Message Node',
|
|
118
118
|
contextMenuTitle: 'Assemble Message',
|
|
@@ -181,6 +181,16 @@ export class AssembleMessageNodeImpl extends NodeImpl {
|
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
|
+
else if (message.type === 'document') {
|
|
185
|
+
outMessage.message.push({
|
|
186
|
+
type: 'document',
|
|
187
|
+
data: message.value.data,
|
|
188
|
+
mediaType: message.value.mediaType,
|
|
189
|
+
context: message.value.context,
|
|
190
|
+
title: message.value.title,
|
|
191
|
+
enableCitations: message.value.enableCitations,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
184
194
|
else {
|
|
185
195
|
const coerced = coerceTypeOptional(message, 'string');
|
|
186
196
|
if (coerced) {
|
|
@@ -7,6 +7,7 @@ import { coerceType } from '../../utils/coerceType.js';
|
|
|
7
7
|
import { orderBy } from 'lodash-es';
|
|
8
8
|
import { dedent } from 'ts-dedent';
|
|
9
9
|
import { nodeDefinition } from '../NodeDefinition.js';
|
|
10
|
+
import { getInputOrData } from '../../utils/inputs.js';
|
|
10
11
|
export class AssemblePromptNodeImpl extends NodeImpl {
|
|
11
12
|
static create() {
|
|
12
13
|
const chartNode = {
|
|
@@ -25,6 +26,14 @@ export class AssemblePromptNodeImpl extends NodeImpl {
|
|
|
25
26
|
getInputDefinitions(connections) {
|
|
26
27
|
const inputs = [];
|
|
27
28
|
const messageCount = this.#getMessagePortCount(connections);
|
|
29
|
+
if (this.data.useIsLastMessageCacheBreakpointInput) {
|
|
30
|
+
inputs.push({
|
|
31
|
+
dataType: 'boolean',
|
|
32
|
+
id: 'isLastMessageCacheBreakpoint',
|
|
33
|
+
title: 'Is Last Message Cache Breakpoint',
|
|
34
|
+
description: 'Whether the last message in the prompt should be a cache breakpoint.',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
28
37
|
for (let i = 1; i <= messageCount; i++) {
|
|
29
38
|
inputs.push({
|
|
30
39
|
dataType: ['chat-message', 'chat-message[]'],
|
|
@@ -87,10 +96,20 @@ export class AssemblePromptNodeImpl extends NodeImpl {
|
|
|
87
96
|
label: 'Compute Token Count',
|
|
88
97
|
dataKey: 'computeTokenCount',
|
|
89
98
|
},
|
|
99
|
+
{
|
|
100
|
+
type: 'toggle',
|
|
101
|
+
label: 'Is Last Message Cache Breakpoint',
|
|
102
|
+
dataKey: 'isLastMessageCacheBreakpoint',
|
|
103
|
+
helperMessage: 'For Anthropic, marks the last message as a cache breakpoint - this message and every message before it will be cached using Prompt Caching.',
|
|
104
|
+
},
|
|
90
105
|
];
|
|
91
106
|
}
|
|
107
|
+
getBody(_context) {
|
|
108
|
+
return this.data.isLastMessageCacheBreakpoint ? 'Last message is cache breakpoint' : '';
|
|
109
|
+
}
|
|
92
110
|
async process(inputs, context) {
|
|
93
111
|
const output = {};
|
|
112
|
+
const isLastMessageCacheBreakpoint = getInputOrData(this.data, inputs, 'isLastMessageCacheBreakpoint', 'boolean');
|
|
94
113
|
const outMessages = [];
|
|
95
114
|
const inputMessages = orderBy(Object.entries(inputs).filter(([key]) => key.startsWith('message')), ([key]) => key, 'asc');
|
|
96
115
|
for (const [, inputMessage] of inputMessages) {
|
|
@@ -110,6 +129,9 @@ export class AssemblePromptNodeImpl extends NodeImpl {
|
|
|
110
129
|
}
|
|
111
130
|
}
|
|
112
131
|
}
|
|
132
|
+
if (isLastMessageCacheBreakpoint && outMessages.length > 1) {
|
|
133
|
+
outMessages.at(-1).isCacheBreakpoint = true;
|
|
134
|
+
}
|
|
113
135
|
output['prompt'] = {
|
|
114
136
|
type: 'chat-message[]',
|
|
115
137
|
value: outMessages,
|
|
@@ -2,12 +2,11 @@ import {} from '../NodeBase.js';
|
|
|
2
2
|
import { NodeImpl } from '../NodeImpl.js';
|
|
3
3
|
import { nodeDefinition } from '../NodeDefinition.js';
|
|
4
4
|
import {} from '../GraphProcessor.js';
|
|
5
|
-
import {} from '../NodeGraph.js';
|
|
6
5
|
import { nanoid } from 'nanoid/non-secure';
|
|
7
6
|
import {} from '../ProcessContext.js';
|
|
8
7
|
import { dedent } from 'ts-dedent';
|
|
9
|
-
import {
|
|
10
|
-
import { looseDataValuesToDataValues } from '../../
|
|
8
|
+
import { coerceTypeOptional } from '../../utils/coerceType.js';
|
|
9
|
+
import { looseDataValuesToDataValues } from '../../api/looseDataValue.js';
|
|
11
10
|
import { getError } from '../../utils/errors.js';
|
|
12
11
|
export class CallGraphNodeImpl extends NodeImpl {
|
|
13
12
|
static create() {
|
|
@@ -93,7 +92,7 @@ export class CallGraphNodeImpl extends NodeImpl {
|
|
|
93
92
|
};
|
|
94
93
|
}
|
|
95
94
|
const subGraphProcessor = context.createSubProcessor(graphRef.graphId, { signal: context.signal });
|
|
96
|
-
|
|
95
|
+
const outputs = {};
|
|
97
96
|
try {
|
|
98
97
|
const startTime = Date.now();
|
|
99
98
|
const inputData = looseDataValuesToDataValues(graphInputs);
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {} from '../NodeBase.js';
|
|
2
|
+
import { nanoid } from 'nanoid/non-secure';
|
|
3
|
+
import { NodeImpl } from '../NodeImpl.js';
|
|
4
|
+
import {} from '../ProcessContext.js';
|
|
5
|
+
import {} from '../../index.js';
|
|
6
|
+
import { dedent } from 'ts-dedent';
|
|
7
|
+
import { nodeDefinition } from '../NodeDefinition.js';
|
|
8
|
+
import { ChatNodeBase } from './ChatNodeBase.js';
|
|
9
|
+
import { coerceType } from '../../utils/coerceType.js';
|
|
10
|
+
export class ChatLoopNodeImpl extends NodeImpl {
|
|
11
|
+
static create() {
|
|
12
|
+
const chartNode = {
|
|
13
|
+
type: 'chatLoop',
|
|
14
|
+
title: 'Chat Loop',
|
|
15
|
+
id: nanoid(),
|
|
16
|
+
visualData: {
|
|
17
|
+
x: 0,
|
|
18
|
+
y: 0,
|
|
19
|
+
width: 250,
|
|
20
|
+
},
|
|
21
|
+
data: {
|
|
22
|
+
...ChatNodeBase.defaultData(),
|
|
23
|
+
userPrompt: 'Your response:',
|
|
24
|
+
renderingFormat: 'markdown',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
return chartNode;
|
|
28
|
+
}
|
|
29
|
+
getInputDefinitions() {
|
|
30
|
+
return ChatNodeBase.getInputDefinitions(this.data);
|
|
31
|
+
}
|
|
32
|
+
getOutputDefinitions() {
|
|
33
|
+
return [
|
|
34
|
+
{
|
|
35
|
+
dataType: 'string[]',
|
|
36
|
+
id: 'conversation',
|
|
37
|
+
title: 'Full Conversation',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
dataType: 'string',
|
|
41
|
+
id: 'lastMessage',
|
|
42
|
+
title: 'Last Message',
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
static getUIData() {
|
|
47
|
+
return {
|
|
48
|
+
infoBoxBody: dedent `
|
|
49
|
+
Creates an interactive chat loop with an AI model. The node will:
|
|
50
|
+
1. Send the initial prompt to the AI
|
|
51
|
+
2. Show the AI's response and prompt for user input
|
|
52
|
+
3. Send the user's input back to the AI
|
|
53
|
+
4. Repeat steps 2-3 until the user ends the conversation
|
|
54
|
+
|
|
55
|
+
The conversation history is maintained and sent with each new message.
|
|
56
|
+
`,
|
|
57
|
+
contextMenuTitle: 'Chat Loop',
|
|
58
|
+
infoBoxTitle: 'Chat Loop Node',
|
|
59
|
+
group: ['Convenience'],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
getEditors() {
|
|
63
|
+
return [
|
|
64
|
+
...ChatNodeBase.getEditors(),
|
|
65
|
+
{
|
|
66
|
+
type: 'code',
|
|
67
|
+
label: 'User Prompt',
|
|
68
|
+
dataKey: 'userPrompt',
|
|
69
|
+
language: 'plain-text',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: 'group',
|
|
73
|
+
label: 'Rendering',
|
|
74
|
+
editors: [
|
|
75
|
+
{
|
|
76
|
+
type: 'dropdown',
|
|
77
|
+
dataKey: 'renderingFormat',
|
|
78
|
+
label: 'Format',
|
|
79
|
+
options: [
|
|
80
|
+
{ label: 'Text', value: 'text' },
|
|
81
|
+
{ label: 'Markdown', value: 'markdown' },
|
|
82
|
+
],
|
|
83
|
+
defaultValue: 'markdown',
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
getBody() {
|
|
90
|
+
return ChatNodeBase.getBody(this.data);
|
|
91
|
+
}
|
|
92
|
+
async process(inputs, context) {
|
|
93
|
+
const conversation = [];
|
|
94
|
+
let continueChat = true;
|
|
95
|
+
conversation.push(...coerceType(inputs['prompt'], 'chat-message[]'));
|
|
96
|
+
// Initial chat call
|
|
97
|
+
const initialResponse = await ChatNodeBase.process(this.data, this.chartNode, inputs, context);
|
|
98
|
+
const firstMessage = coerceType(initialResponse['response'], 'string');
|
|
99
|
+
conversation.push({
|
|
100
|
+
type: 'assistant',
|
|
101
|
+
message: firstMessage,
|
|
102
|
+
function_calls: undefined,
|
|
103
|
+
function_call: undefined,
|
|
104
|
+
});
|
|
105
|
+
let messageToUser = firstMessage;
|
|
106
|
+
while (continueChat) {
|
|
107
|
+
// Get user input
|
|
108
|
+
const userResponse = await context.requestUserInput([messageToUser], this.data.renderingFormat ?? 'text');
|
|
109
|
+
// Check if user wants to end conversation
|
|
110
|
+
if (!userResponse || userResponse.value.length === 0 || userResponse.value[0]?.length === 0) {
|
|
111
|
+
continueChat = false;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
// Add user message to conversation
|
|
115
|
+
conversation.push({
|
|
116
|
+
type: 'user',
|
|
117
|
+
message: userResponse.value[0],
|
|
118
|
+
});
|
|
119
|
+
// Prepare next AI message
|
|
120
|
+
const chatInputs = {
|
|
121
|
+
...inputs,
|
|
122
|
+
prompt: {
|
|
123
|
+
type: 'chat-message[]',
|
|
124
|
+
value: conversation,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
// Get AI response
|
|
128
|
+
const aiResponse = await ChatNodeBase.process(this.data, this.chartNode, chatInputs, context);
|
|
129
|
+
const aiMessage = coerceType(aiResponse['response'], 'string');
|
|
130
|
+
conversation.push({
|
|
131
|
+
type: 'assistant',
|
|
132
|
+
message: aiMessage,
|
|
133
|
+
function_calls: undefined,
|
|
134
|
+
function_call: undefined,
|
|
135
|
+
});
|
|
136
|
+
messageToUser = aiMessage;
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
['conversation']: {
|
|
140
|
+
type: 'chat-message[]',
|
|
141
|
+
value: conversation,
|
|
142
|
+
},
|
|
143
|
+
['lastMessage']: {
|
|
144
|
+
type: 'chat-message',
|
|
145
|
+
value: conversation.at(-1),
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
export const chatLoopNode = nodeDefinition(ChatLoopNodeImpl, 'Chat Loop');
|