@librechat/agents 1.8.8 → 1.8.9
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/dist/cjs/common/enum.cjs +1 -0
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/events.cjs +8 -1
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/llm.cjs +117 -0
- package/dist/cjs/llm/anthropic/llm.cjs.map +1 -0
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +277 -0
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -0
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +135 -0
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -0
- package/dist/cjs/llm/providers.cjs +5 -4
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/llm/text.cjs +58 -0
- package/dist/cjs/llm/text.cjs.map +1 -0
- package/dist/cjs/main.cjs +3 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages.cjs +4 -4
- package/dist/cjs/messages.cjs.map +1 -1
- package/dist/cjs/stream.cjs +63 -48
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +20 -5
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/utils/misc.cjs +49 -0
- package/dist/cjs/utils/misc.cjs.map +1 -0
- package/dist/esm/common/enum.mjs +1 -0
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/events.mjs +8 -1
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/llm/anthropic/llm.mjs +115 -0
- package/dist/esm/llm/anthropic/llm.mjs.map +1 -0
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +274 -0
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -0
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +133 -0
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -0
- package/dist/esm/llm/providers.mjs +5 -4
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/llm/text.mjs +56 -0
- package/dist/esm/llm/text.mjs.map +1 -0
- package/dist/esm/main.mjs +2 -1
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/messages.mjs +4 -4
- package/dist/esm/messages.mjs.map +1 -1
- package/dist/esm/stream.mjs +63 -49
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +22 -7
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/utils/misc.mjs +47 -0
- package/dist/esm/utils/misc.mjs.map +1 -0
- package/dist/types/common/enum.d.ts +2 -1
- package/dist/types/llm/anthropic/types.d.ts +4 -0
- package/dist/types/llm/anthropic/utils/message_inputs.d.ts +1 -1
- package/dist/types/llm/text.d.ts +6 -6
- package/dist/types/stream.d.ts +2 -0
- package/dist/types/types/llm.d.ts +6 -1
- package/dist/types/utils/index.d.ts +1 -0
- package/dist/types/utils/misc.d.ts +6 -0
- package/package.json +7 -6
- package/src/common/enum.ts +1 -0
- package/src/events.ts +9 -1
- package/src/llm/anthropic/llm.ts +1 -1
- package/src/llm/anthropic/types.ts +7 -1
- package/src/llm/anthropic/utils/message_inputs.ts +86 -8
- package/src/llm/providers.ts +6 -4
- package/src/llm/text.ts +30 -45
- package/src/messages.ts +4 -4
- package/src/scripts/args.ts +1 -1
- package/src/scripts/code_exec.ts +4 -0
- package/src/scripts/simple.ts +4 -0
- package/src/stream.ts +68 -50
- package/src/tools/ToolNode.ts +25 -9
- package/src/types/llm.ts +6 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/llmConfig.ts +6 -0
- package/src/utils/misc.ts +45 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { isAIMessage, HumanMessage } from '@langchain/core/messages';
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
/**
|
|
5
|
+
* This util file contains functions for converting LangChain messages to Anthropic messages.
|
|
6
|
+
*/
|
|
7
|
+
function _formatImage(imageUrl) {
|
|
8
|
+
const regex = /^data:(image\/.+);base64,(.+)$/;
|
|
9
|
+
const match = imageUrl.match(regex);
|
|
10
|
+
if (match === null) {
|
|
11
|
+
throw new Error([
|
|
12
|
+
'Anthropic only supports base64-encoded images currently.',
|
|
13
|
+
'Example: data:image/png;base64,/9j/4AAQSk...',
|
|
14
|
+
].join('\n\n'));
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
type: 'base64',
|
|
18
|
+
media_type: match[1] ?? '',
|
|
19
|
+
data: match[2] ?? '',
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function _ensureMessageContents(messages) {
|
|
24
|
+
// Merge runs of human/tool messages into single human messages with content blocks.
|
|
25
|
+
const updatedMsgs = [];
|
|
26
|
+
for (const message of messages) {
|
|
27
|
+
if (message._getType() === 'tool') {
|
|
28
|
+
if (typeof message.content === 'string') {
|
|
29
|
+
const previousMessage = updatedMsgs[updatedMsgs.length - 1];
|
|
30
|
+
if (previousMessage &&
|
|
31
|
+
previousMessage._getType() === 'human' &&
|
|
32
|
+
Array.isArray(previousMessage.content) &&
|
|
33
|
+
'type' in previousMessage.content[0] &&
|
|
34
|
+
previousMessage.content[0].type === 'tool_result') {
|
|
35
|
+
// If the previous message was a tool result, we merge this tool message into it.
|
|
36
|
+
previousMessage.content.push({
|
|
37
|
+
type: 'tool_result',
|
|
38
|
+
content: message.content,
|
|
39
|
+
tool_use_id: message.tool_call_id,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// If not, we create a new human message with the tool result.
|
|
44
|
+
updatedMsgs.push(new HumanMessage({
|
|
45
|
+
content: [
|
|
46
|
+
{
|
|
47
|
+
type: 'tool_result',
|
|
48
|
+
content: message.content,
|
|
49
|
+
tool_use_id: message.tool_call_id,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
updatedMsgs.push(new HumanMessage({
|
|
57
|
+
content: [
|
|
58
|
+
{
|
|
59
|
+
type: 'tool_result',
|
|
60
|
+
content: _formatContent(message.content),
|
|
61
|
+
tool_use_id: message.tool_call_id,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
updatedMsgs.push(message);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return updatedMsgs;
|
|
72
|
+
}
|
|
73
|
+
function _convertLangChainToolCallToAnthropic(toolCall) {
|
|
74
|
+
if (toolCall.id === undefined) {
|
|
75
|
+
throw new Error('Anthropic requires all tool calls to have an "id".');
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
type: 'tool_use',
|
|
79
|
+
id: toolCall.id,
|
|
80
|
+
name: toolCall.name,
|
|
81
|
+
input: toolCall.args,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
+
function _formatContent(content) {
|
|
86
|
+
const toolTypes = ['tool_use', 'tool_result', 'input_json_delta'];
|
|
87
|
+
const textTypes = ['text', 'text_delta'];
|
|
88
|
+
if (typeof content === 'string') {
|
|
89
|
+
return content;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
const contentBlocks = content.map((contentPart) => {
|
|
93
|
+
const cacheControl = 'cache_control' in contentPart ? contentPart.cache_control : undefined;
|
|
94
|
+
if (contentPart.type === 'image_url') {
|
|
95
|
+
let source;
|
|
96
|
+
if (typeof contentPart.image_url === 'string') {
|
|
97
|
+
source = _formatImage(contentPart.image_url);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
source = _formatImage(contentPart.image_url.url);
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
type: 'image', // Explicitly setting the type as "image"
|
|
104
|
+
source,
|
|
105
|
+
...(cacheControl ? { cache_control: cacheControl } : {}),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
else if (textTypes.find((t) => t === contentPart.type) != null &&
|
|
109
|
+
'text' in contentPart) {
|
|
110
|
+
// Assuming contentPart is of type MessageContentText here
|
|
111
|
+
return {
|
|
112
|
+
type: 'text', // Explicitly setting the type as "text"
|
|
113
|
+
text: contentPart.text,
|
|
114
|
+
...(cacheControl ? { cache_control: cacheControl } : {}),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
else if (toolTypes.find((t) => t === contentPart.type) != null) {
|
|
118
|
+
const contentPartCopy = { ...contentPart };
|
|
119
|
+
if ('index' in contentPartCopy) {
|
|
120
|
+
// Anthropic does not support passing the index field here, so we remove it.
|
|
121
|
+
delete contentPartCopy.index;
|
|
122
|
+
}
|
|
123
|
+
if (contentPartCopy.type === 'input_json_delta') {
|
|
124
|
+
// `input_json_delta` type only represents yielding partial tool inputs
|
|
125
|
+
// and is not a valid type for Anthropic messages.
|
|
126
|
+
contentPartCopy.type = 'tool_use';
|
|
127
|
+
}
|
|
128
|
+
if ('input' in contentPartCopy) {
|
|
129
|
+
// Anthropic tool use inputs should be valid objects, when applicable.
|
|
130
|
+
try {
|
|
131
|
+
contentPartCopy.input = JSON.parse(contentPartCopy.input);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// no-op
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// TODO: Fix when SDK types are fixed
|
|
138
|
+
return {
|
|
139
|
+
...contentPartCopy,
|
|
140
|
+
...(cacheControl ? { cache_control: cacheControl } : {}),
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
throw new Error('Unsupported message content format');
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
return contentBlocks;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Formats messages as a prompt for the model.
|
|
153
|
+
* Used in LangSmith, export is important here.
|
|
154
|
+
* @param messages The base messages to format as a prompt.
|
|
155
|
+
* @returns The formatted prompt.
|
|
156
|
+
*/
|
|
157
|
+
function _convertMessagesToAnthropicPayload(messages) {
|
|
158
|
+
const mergedMessages = _ensureMessageContents(messages);
|
|
159
|
+
let system;
|
|
160
|
+
if (mergedMessages.length > 0 && mergedMessages[0]._getType() === 'system') {
|
|
161
|
+
system = messages[0].content;
|
|
162
|
+
}
|
|
163
|
+
const conversationMessages = system !== undefined ? mergedMessages.slice(1) : mergedMessages;
|
|
164
|
+
const formattedMessages = conversationMessages.map((message) => {
|
|
165
|
+
let role;
|
|
166
|
+
if (message._getType() === 'human') {
|
|
167
|
+
role = 'user';
|
|
168
|
+
}
|
|
169
|
+
else if (message._getType() === 'ai') {
|
|
170
|
+
role = 'assistant';
|
|
171
|
+
}
|
|
172
|
+
else if (message._getType() === 'tool') {
|
|
173
|
+
role = 'user';
|
|
174
|
+
}
|
|
175
|
+
else if (message._getType() === 'system') {
|
|
176
|
+
throw new Error('System messages are only permitted as the first passed message.');
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
throw new Error(`Message type "${message._getType()}" is not supported.`);
|
|
180
|
+
}
|
|
181
|
+
if (isAIMessage(message) && !!message.tool_calls?.length) {
|
|
182
|
+
if (typeof message.content === 'string') {
|
|
183
|
+
if (message.content === '') {
|
|
184
|
+
return {
|
|
185
|
+
role,
|
|
186
|
+
content: message.tool_calls.map(_convertLangChainToolCallToAnthropic),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
return {
|
|
191
|
+
role,
|
|
192
|
+
content: [
|
|
193
|
+
{ type: 'text', text: message.content },
|
|
194
|
+
...message.tool_calls.map(_convertLangChainToolCallToAnthropic),
|
|
195
|
+
],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
const { content } = message;
|
|
201
|
+
const hasMismatchedToolCalls = !message.tool_calls.every((toolCall) => content.find((contentPart) => (contentPart.type === 'tool_use' ||
|
|
202
|
+
contentPart.type === 'input_json_delta') &&
|
|
203
|
+
contentPart.id === toolCall.id));
|
|
204
|
+
if (hasMismatchedToolCalls) {
|
|
205
|
+
console.warn('The "tool_calls" field on a message is only respected if content is a string.');
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
role,
|
|
209
|
+
content: _formatContent(message.content),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
return {
|
|
215
|
+
role,
|
|
216
|
+
content: _formatContent(message.content),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
return {
|
|
221
|
+
messages: mergeMessages(formattedMessages),
|
|
222
|
+
system,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function mergeMessages(messages) {
|
|
226
|
+
if (!messages || messages.length <= 1) {
|
|
227
|
+
return messages ?? [];
|
|
228
|
+
}
|
|
229
|
+
const result = [];
|
|
230
|
+
let currentMessage = messages[0];
|
|
231
|
+
const normalizeContent = (content) => {
|
|
232
|
+
if (typeof content === 'string') {
|
|
233
|
+
return [
|
|
234
|
+
{
|
|
235
|
+
type: 'text',
|
|
236
|
+
text: content,
|
|
237
|
+
},
|
|
238
|
+
];
|
|
239
|
+
}
|
|
240
|
+
return content;
|
|
241
|
+
};
|
|
242
|
+
const isToolResultMessage = (msg) => {
|
|
243
|
+
if (msg.role !== 'user')
|
|
244
|
+
return false;
|
|
245
|
+
if (typeof msg.content === 'string') {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
return (Array.isArray(msg.content) &&
|
|
249
|
+
msg.content.every((item) => item.type === 'tool_result'));
|
|
250
|
+
};
|
|
251
|
+
for (let i = 1; i < messages.length; i += 1) {
|
|
252
|
+
const nextMessage = messages[i];
|
|
253
|
+
if (isToolResultMessage(currentMessage) &&
|
|
254
|
+
isToolResultMessage(nextMessage)) {
|
|
255
|
+
// Merge the messages by combining their content arrays
|
|
256
|
+
currentMessage = {
|
|
257
|
+
...currentMessage,
|
|
258
|
+
content: [
|
|
259
|
+
...normalizeContent(currentMessage.content),
|
|
260
|
+
...normalizeContent(nextMessage.content),
|
|
261
|
+
],
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
result.push(currentMessage);
|
|
266
|
+
currentMessage = nextMessage;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
result.push(currentMessage);
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export { _convertLangChainToolCallToAnthropic, _convertMessagesToAnthropicPayload };
|
|
274
|
+
//# sourceMappingURL=message_inputs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message_inputs.mjs","sources":["../../../../../src/llm/anthropic/utils/message_inputs.ts"],"sourcesContent":["/* eslint-disable no-console */\n/**\n * This util file contains functions for converting LangChain messages to Anthropic messages.\n */\nimport {\n AIMessage,\n BaseMessage,\n ToolMessage,\n isAIMessage,\n HumanMessage,\n SystemMessage,\n MessageContent,\n} from '@langchain/core/messages';\nimport { ToolCall } from '@langchain/core/messages/tool';\nimport type {\n AnthropicToolResponse,\n AnthropicMessageParam,\n AnthropicTextBlockParam,\n AnthropicImageBlockParam,\n AnthropicToolUseBlockParam,\n AnthropicMessageCreateParams,\n AnthropicToolResultBlockParam,\n} from '@/llm/anthropic/types';\n\nfunction _formatImage(imageUrl: string): { type: string; media_type: string; data: string } {\n const regex = /^data:(image\\/.+);base64,(.+)$/;\n const match = imageUrl.match(regex);\n if (match === null) {\n throw new Error(\n [\n 'Anthropic only supports base64-encoded images currently.',\n 'Example: data:image/png;base64,/9j/4AAQSk...',\n ].join('\\n\\n')\n );\n }\n return {\n type: 'base64',\n media_type: match[1] ?? '',\n data: match[2] ?? '',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n}\n\nfunction _ensureMessageContents(\n messages: BaseMessage[]\n): (SystemMessage | HumanMessage | AIMessage)[] {\n // Merge runs of human/tool messages into single human messages with content blocks.\n const updatedMsgs = [];\n for (const message of messages) {\n if (message._getType() === 'tool') {\n if (typeof message.content === 'string') {\n const previousMessage = updatedMsgs[updatedMsgs.length - 1] as BaseMessage | undefined;\n if (\n previousMessage &&\n previousMessage._getType() === 'human' &&\n Array.isArray(previousMessage.content) &&\n 'type' in previousMessage.content[0] &&\n previousMessage.content[0].type === 'tool_result'\n ) {\n // If the previous message was a tool result, we merge this tool message into it.\n previousMessage.content.push({\n type: 'tool_result',\n content: message.content,\n tool_use_id: (message as ToolMessage).tool_call_id,\n });\n } else {\n // If not, we create a new human message with the tool result.\n updatedMsgs.push(\n new HumanMessage({\n content: [\n {\n type: 'tool_result',\n content: message.content,\n tool_use_id: (message as ToolMessage).tool_call_id,\n },\n ],\n })\n );\n }\n } else {\n updatedMsgs.push(\n new HumanMessage({\n content: [\n {\n type: 'tool_result',\n content: _formatContent(message.content),\n tool_use_id: (message as ToolMessage).tool_call_id,\n },\n ],\n })\n );\n }\n } else {\n updatedMsgs.push(message);\n }\n }\n return updatedMsgs;\n}\n\nexport function _convertLangChainToolCallToAnthropic(\n toolCall: ToolCall\n): AnthropicToolResponse {\n if (toolCall.id === undefined) {\n throw new Error('Anthropic requires all tool calls to have an \"id\".');\n }\n return {\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.name,\n input: toolCall.args,\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction _formatContent(content: MessageContent): string | Record<string, any>[] {\n const toolTypes = ['tool_use', 'tool_result', 'input_json_delta'];\n const textTypes = ['text', 'text_delta'];\n\n if (typeof content === 'string') {\n return content;\n } else {\n const contentBlocks = content.map((contentPart) => {\n const cacheControl =\n 'cache_control' in contentPart ? contentPart.cache_control : undefined;\n\n if (contentPart.type === 'image_url') {\n let source;\n if (typeof contentPart.image_url === 'string') {\n source = _formatImage(contentPart.image_url);\n } else {\n source = _formatImage(contentPart.image_url.url);\n }\n return {\n type: 'image' as const, // Explicitly setting the type as \"image\"\n source,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n } else if (\n textTypes.find((t) => t === contentPart.type) != null &&\n 'text' in contentPart\n ) {\n // Assuming contentPart is of type MessageContentText here\n return {\n type: 'text' as const, // Explicitly setting the type as \"text\"\n text: contentPart.text,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n } else if (toolTypes.find((t) => t === contentPart.type) != null) {\n const contentPartCopy = { ...contentPart };\n if ('index' in contentPartCopy) {\n // Anthropic does not support passing the index field here, so we remove it.\n delete contentPartCopy.index;\n }\n\n if (contentPartCopy.type === 'input_json_delta') {\n // `input_json_delta` type only represents yielding partial tool inputs\n // and is not a valid type for Anthropic messages.\n contentPartCopy.type = 'tool_use';\n }\n\n if ('input' in contentPartCopy) {\n // Anthropic tool use inputs should be valid objects, when applicable.\n try {\n contentPartCopy.input = JSON.parse(contentPartCopy.input);\n } catch {\n // no-op\n }\n }\n\n // TODO: Fix when SDK types are fixed\n return {\n ...contentPartCopy,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n } else {\n throw new Error('Unsupported message content format');\n }\n });\n return contentBlocks;\n }\n}\n\n/**\n * Formats messages as a prompt for the model.\n * Used in LangSmith, export is important here.\n * @param messages The base messages to format as a prompt.\n * @returns The formatted prompt.\n */\nexport function _convertMessagesToAnthropicPayload(\n messages: BaseMessage[]\n): AnthropicMessageCreateParams {\n const mergedMessages = _ensureMessageContents(messages);\n let system;\n if (mergedMessages.length > 0 && mergedMessages[0]._getType() === 'system') {\n system = messages[0].content;\n }\n const conversationMessages =\n system !== undefined ? mergedMessages.slice(1) : mergedMessages;\n const formattedMessages = conversationMessages.map((message) => {\n let role;\n if (message._getType() === 'human') {\n role = 'user' as const;\n } else if (message._getType() === 'ai') {\n role = 'assistant' as const;\n } else if (message._getType() === 'tool') {\n role = 'user' as const;\n } else if (message._getType() === 'system') {\n throw new Error(\n 'System messages are only permitted as the first passed message.'\n );\n } else {\n throw new Error(`Message type \"${message._getType()}\" is not supported.`);\n }\n if (isAIMessage(message) && !!message.tool_calls?.length) {\n if (typeof message.content === 'string') {\n if (message.content === '') {\n return {\n role,\n content: message.tool_calls.map(\n _convertLangChainToolCallToAnthropic\n ),\n };\n } else {\n return {\n role,\n content: [\n { type: 'text', text: message.content },\n ...message.tool_calls.map(_convertLangChainToolCallToAnthropic),\n ],\n };\n }\n } else {\n const { content } = message;\n const hasMismatchedToolCalls = !message.tool_calls.every((toolCall) =>\n content.find(\n (contentPart) =>\n (contentPart.type === 'tool_use' ||\n contentPart.type === 'input_json_delta') &&\n contentPart.id === toolCall.id\n )\n );\n if (hasMismatchedToolCalls) {\n console.warn(\n 'The \"tool_calls\" field on a message is only respected if content is a string.'\n );\n }\n return {\n role,\n content: _formatContent(message.content),\n };\n }\n } else {\n return {\n role,\n content: _formatContent(message.content),\n };\n }\n });\n return {\n messages: mergeMessages(formattedMessages as AnthropicMessageCreateParams['messages']),\n system,\n } as AnthropicMessageCreateParams;\n}\n\nfunction mergeMessages(messages?: AnthropicMessageCreateParams['messages']): AnthropicMessageParam[] {\n if (!messages || messages.length <= 1) {\n return messages ?? [];\n }\n\n const result: AnthropicMessageCreateParams['messages'] = [];\n let currentMessage = messages[0];\n\n const normalizeContent = (\n content:\n | string\n | Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n >\n ): Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n > => {\n if (typeof content === 'string') {\n return [\n {\n type: 'text',\n text: content,\n },\n ];\n }\n return content;\n };\n\n const isToolResultMessage = (msg: (typeof messages)[0]): boolean => {\n if (msg.role !== 'user') return false;\n\n if (typeof msg.content === 'string') {\n return false;\n }\n\n return (\n Array.isArray(msg.content) &&\n msg.content.every((item) => item.type === 'tool_result')\n );\n };\n\n for (let i = 1; i < messages.length; i += 1) {\n const nextMessage = messages[i];\n\n if (\n isToolResultMessage(currentMessage) &&\n isToolResultMessage(nextMessage)\n ) {\n // Merge the messages by combining their content arrays\n currentMessage = {\n ...currentMessage,\n content: [\n ...normalizeContent(currentMessage.content),\n ...normalizeContent(nextMessage.content),\n ],\n };\n } else {\n result.push(currentMessage);\n currentMessage = nextMessage;\n }\n }\n\n result.push(currentMessage);\n return result;\n}"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { AIMessageChunk } from '@langchain/core/messages';
|
|
2
|
+
|
|
3
|
+
function _makeMessageChunkFromAnthropicEvent(data, fields) {
|
|
4
|
+
if (data.type === 'message_start') {
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
6
|
+
const { content, usage, ...additionalKwargs } = data.message;
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
+
const filteredAdditionalKwargs = {};
|
|
9
|
+
for (const [key, value] of Object.entries(additionalKwargs)) {
|
|
10
|
+
if (value !== undefined && value !== null) {
|
|
11
|
+
filteredAdditionalKwargs[key] = value;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const usageMetadata = {
|
|
15
|
+
input_tokens: usage.input_tokens,
|
|
16
|
+
output_tokens: usage.output_tokens,
|
|
17
|
+
total_tokens: usage.input_tokens + usage.output_tokens,
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
chunk: new AIMessageChunk({
|
|
21
|
+
content: fields.coerceContentToString ? '' : [],
|
|
22
|
+
additional_kwargs: filteredAdditionalKwargs,
|
|
23
|
+
usage_metadata: fields.streamUsage ? usageMetadata : undefined,
|
|
24
|
+
id: data.message.id,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
else if (data.type === 'message_delta') {
|
|
29
|
+
const usageMetadata = {
|
|
30
|
+
input_tokens: 0,
|
|
31
|
+
output_tokens: data.usage.output_tokens,
|
|
32
|
+
total_tokens: data.usage.output_tokens,
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
chunk: new AIMessageChunk({
|
|
36
|
+
content: fields.coerceContentToString ? '' : [],
|
|
37
|
+
additional_kwargs: { ...data.delta },
|
|
38
|
+
usage_metadata: fields.streamUsage ? usageMetadata : undefined,
|
|
39
|
+
}),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
else if (data.type === 'content_block_start' &&
|
|
43
|
+
data.content_block.type === 'tool_use') {
|
|
44
|
+
const toolCallContentBlock = data.content_block;
|
|
45
|
+
return {
|
|
46
|
+
chunk: new AIMessageChunk({
|
|
47
|
+
content: fields.coerceContentToString
|
|
48
|
+
? ''
|
|
49
|
+
: [
|
|
50
|
+
{
|
|
51
|
+
index: data.index,
|
|
52
|
+
...data.content_block,
|
|
53
|
+
input: '',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
additional_kwargs: {},
|
|
57
|
+
tool_call_chunks: [
|
|
58
|
+
{
|
|
59
|
+
id: toolCallContentBlock.id,
|
|
60
|
+
index: data.index,
|
|
61
|
+
name: toolCallContentBlock.name,
|
|
62
|
+
args: '',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
}),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
else if (data.type === 'content_block_delta' &&
|
|
69
|
+
data.delta.type === 'text_delta') {
|
|
70
|
+
const content = data.delta.text;
|
|
71
|
+
if (content !== undefined) {
|
|
72
|
+
return {
|
|
73
|
+
chunk: new AIMessageChunk({
|
|
74
|
+
content: fields.coerceContentToString
|
|
75
|
+
? content
|
|
76
|
+
: [
|
|
77
|
+
{
|
|
78
|
+
index: data.index,
|
|
79
|
+
...data.delta,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
additional_kwargs: {},
|
|
83
|
+
}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (data.type === 'content_block_delta' &&
|
|
88
|
+
data.delta.type === 'input_json_delta') {
|
|
89
|
+
return {
|
|
90
|
+
chunk: new AIMessageChunk({
|
|
91
|
+
content: fields.coerceContentToString
|
|
92
|
+
? ''
|
|
93
|
+
: [
|
|
94
|
+
{
|
|
95
|
+
index: data.index,
|
|
96
|
+
input: data.delta.partial_json,
|
|
97
|
+
type: data.delta.type,
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
additional_kwargs: {},
|
|
101
|
+
tool_call_chunks: [
|
|
102
|
+
{
|
|
103
|
+
index: data.index,
|
|
104
|
+
args: data.delta.partial_json,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
}),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
else if (data.type === 'content_block_start' &&
|
|
111
|
+
data.content_block.type === 'text') {
|
|
112
|
+
const content = data.content_block.text;
|
|
113
|
+
if (content !== undefined) {
|
|
114
|
+
return {
|
|
115
|
+
chunk: new AIMessageChunk({
|
|
116
|
+
content: fields.coerceContentToString
|
|
117
|
+
? content
|
|
118
|
+
: [
|
|
119
|
+
{
|
|
120
|
+
index: data.index,
|
|
121
|
+
...data.content_block,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
additional_kwargs: {},
|
|
125
|
+
}),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export { _makeMessageChunkFromAnthropicEvent };
|
|
133
|
+
//# sourceMappingURL=message_outputs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message_outputs.mjs","sources":["../../../../../src/llm/anthropic/utils/message_outputs.ts"],"sourcesContent":["/**\n * This util file contains functions for converting Anthropic messages to LangChain messages.\n */\nimport Anthropic from '@anthropic-ai/sdk';\nimport {\n AIMessage,\n UsageMetadata,\n AIMessageChunk,\n} from '@langchain/core/messages';\nimport { ToolCall } from '@langchain/core/messages/tool';\nimport { ChatGeneration } from '@langchain/core/outputs';\nimport { AnthropicMessageResponse } from '../types.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function extractToolCalls(content: Record<string, any>[]): ToolCall[] {\n const toolCalls: ToolCall[] = [];\n for (const block of content) {\n if (block.type === 'tool_use') {\n toolCalls.push({\n name: block.name,\n args: block.input,\n id: block.id,\n type: 'tool_call',\n });\n }\n }\n return toolCalls;\n}\n\nexport function _makeMessageChunkFromAnthropicEvent(\n data: Anthropic.Messages.RawMessageStreamEvent,\n fields: {\n streamUsage: boolean;\n coerceContentToString: boolean;\n }\n): {\n chunk: AIMessageChunk;\n} | null {\n if (data.type === 'message_start') {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { content, usage, ...additionalKwargs } = data.message;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const filteredAdditionalKwargs: Record<string, any> = {};\n for (const [key, value] of Object.entries(additionalKwargs)) {\n if (value !== undefined && value !== null) {\n filteredAdditionalKwargs[key] = value;\n }\n }\n const usageMetadata: UsageMetadata = {\n input_tokens: usage.input_tokens,\n output_tokens: usage.output_tokens,\n total_tokens: usage.input_tokens + usage.output_tokens,\n };\n return {\n chunk: new AIMessageChunk({\n content: fields.coerceContentToString ? '' : [],\n additional_kwargs: filteredAdditionalKwargs,\n usage_metadata: fields.streamUsage ? usageMetadata : undefined,\n id: data.message.id,\n }),\n };\n } else if (data.type === 'message_delta') {\n const usageMetadata: UsageMetadata = {\n input_tokens: 0,\n output_tokens: data.usage.output_tokens,\n total_tokens: data.usage.output_tokens,\n };\n return {\n chunk: new AIMessageChunk({\n content: fields.coerceContentToString ? '' : [],\n additional_kwargs: { ...data.delta },\n usage_metadata: fields.streamUsage ? usageMetadata : undefined,\n }),\n };\n } else if (\n data.type === 'content_block_start' &&\n data.content_block.type === 'tool_use'\n ) {\n const toolCallContentBlock =\n data.content_block as Anthropic.Messages.ToolUseBlock;\n return {\n chunk: new AIMessageChunk({\n content: fields.coerceContentToString\n ? ''\n : [\n {\n index: data.index,\n ...data.content_block,\n input: '',\n },\n ],\n additional_kwargs: {},\n tool_call_chunks: [\n {\n id: toolCallContentBlock.id,\n index: data.index,\n name: toolCallContentBlock.name,\n args: '',\n },\n ],\n }),\n };\n } else if (\n data.type === 'content_block_delta' &&\n data.delta.type === 'text_delta'\n ) {\n const content = data.delta.text;\n if (content !== undefined) {\n return {\n chunk: new AIMessageChunk({\n content: fields.coerceContentToString\n ? content\n : [\n {\n index: data.index,\n ...data.delta,\n },\n ],\n additional_kwargs: {},\n }),\n };\n }\n } else if (\n data.type === 'content_block_delta' &&\n data.delta.type === 'input_json_delta'\n ) {\n return {\n chunk: new AIMessageChunk({\n content: fields.coerceContentToString\n ? ''\n : [\n {\n index: data.index,\n input: data.delta.partial_json,\n type: data.delta.type,\n },\n ],\n additional_kwargs: {},\n tool_call_chunks: [\n {\n index: data.index,\n args: data.delta.partial_json,\n },\n ],\n }),\n };\n } else if (\n data.type === 'content_block_start' &&\n data.content_block.type === 'text'\n ) {\n const content = data.content_block.text;\n if (content !== undefined) {\n return {\n chunk: new AIMessageChunk({\n content: fields.coerceContentToString\n ? content\n : [\n {\n index: data.index,\n ...data.content_block,\n },\n ],\n additional_kwargs: {},\n }),\n };\n }\n }\n\n return null;\n}\n\nexport function anthropicResponseToChatMessages(\n messages: AnthropicMessageResponse[],\n additionalKwargs: Record<string, unknown>\n): ChatGeneration[] {\n const usage: Record<string, number> | null | undefined =\n additionalKwargs.usage as Record<string, number> | null | undefined;\n const usageMetadata =\n usage != null\n ? {\n input_tokens: usage.input_tokens ?? 0,\n output_tokens: usage.output_tokens ?? 0,\n total_tokens: (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),\n }\n : undefined;\n if (messages.length === 1 && messages[0].type === 'text') {\n return [\n {\n text: messages[0].text,\n message: new AIMessage({\n content: messages[0].text,\n additional_kwargs: additionalKwargs,\n usage_metadata: usageMetadata,\n response_metadata: additionalKwargs,\n id: additionalKwargs.id as string,\n }),\n },\n ];\n } else {\n const toolCalls = extractToolCalls(messages);\n const generations: ChatGeneration[] = [\n {\n text: '',\n message: new AIMessage({\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n content: messages as any,\n additional_kwargs: additionalKwargs,\n tool_calls: toolCalls,\n usage_metadata: usageMetadata,\n response_metadata: additionalKwargs,\n id: additionalKwargs.id as string,\n }),\n },\n ];\n return generations;\n }\n}"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { ChatOpenAI } from '@langchain/openai';
|
|
2
2
|
import { ChatOllama } from '@langchain/ollama';
|
|
3
3
|
import { ChatBedrockConverse } from '@langchain/aws';
|
|
4
|
-
import { ChatAnthropic } from '@langchain/anthropic';
|
|
5
4
|
import { ChatMistralAI } from '@langchain/mistralai';
|
|
6
5
|
import { ChatVertexAI } from '@langchain/google-vertexai';
|
|
6
|
+
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
|
|
7
7
|
import { BedrockChat } from '@langchain/community/chat_models/bedrock/web';
|
|
8
8
|
import { Providers } from '../common/enum.mjs';
|
|
9
|
+
import { CustomAnthropic } from './anthropic/llm.mjs';
|
|
9
10
|
|
|
10
11
|
// src/llm/providers.ts
|
|
11
|
-
// import { CustomAnthropic } from '@/llm/anthropic/llm';
|
|
12
12
|
const llmProviders = {
|
|
13
13
|
[Providers.OPENAI]: ChatOpenAI,
|
|
14
14
|
[Providers.OLLAMA]: ChatOllama,
|
|
@@ -16,8 +16,9 @@ const llmProviders = {
|
|
|
16
16
|
[Providers.BEDROCK_LEGACY]: BedrockChat,
|
|
17
17
|
[Providers.MISTRALAI]: ChatMistralAI,
|
|
18
18
|
[Providers.BEDROCK]: ChatBedrockConverse,
|
|
19
|
-
|
|
20
|
-
[Providers.ANTHROPIC]: ChatAnthropic,
|
|
19
|
+
[Providers.ANTHROPIC]: CustomAnthropic,
|
|
20
|
+
// [Providers.ANTHROPIC]: ChatAnthropic,
|
|
21
|
+
[Providers.GOOGLE]: ChatGoogleGenerativeAI,
|
|
21
22
|
};
|
|
22
23
|
const manualToolStreamProviders = new Set([Providers.ANTHROPIC, Providers.BEDROCK, Providers.OLLAMA]);
|
|
23
24
|
const getChatModelClass = (provider) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers.mjs","sources":["../../../src/llm/providers.ts"],"sourcesContent":["// src/llm/providers.ts\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatOllama } from '@langchain/ollama';\nimport { ChatBedrockConverse } from '@langchain/aws';\
|
|
1
|
+
{"version":3,"file":"providers.mjs","sources":["../../../src/llm/providers.ts"],"sourcesContent":["// src/llm/providers.ts\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatOllama } from '@langchain/ollama';\nimport { ChatBedrockConverse } from '@langchain/aws';\n// import { ChatAnthropic } from '@langchain/anthropic';\nimport { ChatMistralAI } from '@langchain/mistralai';\nimport { ChatVertexAI } from '@langchain/google-vertexai';\nimport { ChatGoogleGenerativeAI } from '@langchain/google-genai';\nimport { BedrockChat } from '@langchain/community/chat_models/bedrock/web';\nimport type { ChatModelConstructorMap, ProviderOptionsMap, ChatModelMap } from '@/types';\nimport { Providers } from '@/common';\nimport { CustomAnthropic } from '@/llm/anthropic/llm';\n\nexport const llmProviders: Partial<ChatModelConstructorMap> = {\n [Providers.OPENAI]: ChatOpenAI,\n [Providers.OLLAMA]: ChatOllama,\n [Providers.VERTEXAI]: ChatVertexAI,\n [Providers.BEDROCK_LEGACY]: BedrockChat,\n [Providers.MISTRALAI]: ChatMistralAI,\n [Providers.BEDROCK]: ChatBedrockConverse,\n [Providers.ANTHROPIC]: CustomAnthropic,\n // [Providers.ANTHROPIC]: ChatAnthropic,\n [Providers.GOOGLE]: ChatGoogleGenerativeAI,\n};\n\nexport const manualToolStreamProviders = new Set<Providers | string>([Providers.ANTHROPIC, Providers.BEDROCK, Providers.OLLAMA]);\n\nexport const getChatModelClass = <P extends Providers>(\n provider: P\n): new (config: ProviderOptionsMap[P]) => ChatModelMap[P] => {\n const ChatModelClass = llmProviders[provider];\n if (!ChatModelClass) {\n throw new Error(`Unsupported LLM provider: ${provider}`);\n }\n\n return ChatModelClass;\n};"],"names":[],"mappings":";;;;;;;;;;AAAA;AAaa,MAAA,YAAY,GAAqC;AAC5D,IAAA,CAAC,SAAS,CAAC,MAAM,GAAG,UAAU;AAC9B,IAAA,CAAC,SAAS,CAAC,MAAM,GAAG,UAAU;AAC9B,IAAA,CAAC,SAAS,CAAC,QAAQ,GAAG,YAAY;AAClC,IAAA,CAAC,SAAS,CAAC,cAAc,GAAG,WAAW;AACvC,IAAA,CAAC,SAAS,CAAC,SAAS,GAAG,aAAa;AACpC,IAAA,CAAC,SAAS,CAAC,OAAO,GAAG,mBAAmB;AACxC,IAAA,CAAC,SAAS,CAAC,SAAS,GAAG,eAAe;;AAEtC,IAAA,CAAC,SAAS,CAAC,MAAM,GAAG,sBAAsB;EAC1C;MAEW,yBAAyB,GAAG,IAAI,GAAG,CAAqB,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE;AAEpH,MAAA,iBAAiB,GAAG,CAC/B,QAAW,KAC+C;AAC1D,IAAA,MAAM,cAAc,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,cAAc,EAAE;AACnB,QAAA,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAA,CAAE,CAAC,CAAC;KAC1D;AAED,IAAA,OAAO,cAAc,CAAC;AACxB;;;;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
class TextStream {
|
|
2
|
+
text;
|
|
3
|
+
currentIndex;
|
|
4
|
+
minChunkSize;
|
|
5
|
+
maxChunkSize;
|
|
6
|
+
delay;
|
|
7
|
+
firstWordChunk;
|
|
8
|
+
constructor(text, options = {}) {
|
|
9
|
+
this.text = text;
|
|
10
|
+
this.currentIndex = 0;
|
|
11
|
+
this.minChunkSize = options.minChunkSize ?? 4;
|
|
12
|
+
this.maxChunkSize = options.maxChunkSize ?? 8;
|
|
13
|
+
this.delay = options.delay ?? 20;
|
|
14
|
+
this.firstWordChunk = options.firstWordChunk ?? true;
|
|
15
|
+
}
|
|
16
|
+
randomInt(min, max) {
|
|
17
|
+
return Math.floor(Math.random() * (max - min)) + min;
|
|
18
|
+
}
|
|
19
|
+
static BOUNDARIES = new Set([' ', '.', ',', '!', '?', ';', ':']);
|
|
20
|
+
findFirstWordBoundary(text, minSize) {
|
|
21
|
+
if (minSize >= text.length)
|
|
22
|
+
return text.length;
|
|
23
|
+
// Ensure we meet the minimum size first
|
|
24
|
+
let pos = minSize;
|
|
25
|
+
// Look forward until we find a boundary
|
|
26
|
+
while (pos < text.length) {
|
|
27
|
+
if (TextStream.BOUNDARIES.has(text[pos])) {
|
|
28
|
+
return pos + 1; // Include the boundary character
|
|
29
|
+
}
|
|
30
|
+
pos++;
|
|
31
|
+
}
|
|
32
|
+
return text.length; // If no boundary found, return entire remaining text
|
|
33
|
+
}
|
|
34
|
+
async *generateText(progressCallback) {
|
|
35
|
+
const { delay, minChunkSize, maxChunkSize } = this;
|
|
36
|
+
while (this.currentIndex < this.text.length) {
|
|
37
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
38
|
+
const remainingText = this.text.slice(this.currentIndex);
|
|
39
|
+
let chunkSize;
|
|
40
|
+
if (this.firstWordChunk) {
|
|
41
|
+
chunkSize = this.findFirstWordBoundary(remainingText, minChunkSize);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const remainingChars = remainingText.length;
|
|
45
|
+
chunkSize = Math.min(this.randomInt(minChunkSize, maxChunkSize + 1), remainingChars);
|
|
46
|
+
}
|
|
47
|
+
const chunk = this.text.slice(this.currentIndex, this.currentIndex + chunkSize);
|
|
48
|
+
progressCallback?.(chunk);
|
|
49
|
+
yield chunk;
|
|
50
|
+
this.currentIndex += chunkSize;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { TextStream };
|
|
56
|
+
//# sourceMappingURL=text.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.mjs","sources":["../../../src/llm/text.ts"],"sourcesContent":["/* eslint-disable no-console */\nexport interface TextStreamOptions {\n minChunkSize?: number;\n maxChunkSize?: number;\n delay?: number;\n firstWordChunk?: boolean;\n}\n\nexport type ProgressCallback = (chunk: string) => void;\nexport type PostChunkCallback = (chunk: string) => void;\n\nexport class TextStream {\n private text: string;\n private currentIndex: number;\n private minChunkSize: number;\n private maxChunkSize: number;\n private delay: number;\n private firstWordChunk: boolean;\n\n constructor(text: string, options: TextStreamOptions = {}) {\n this.text = text;\n this.currentIndex = 0;\n this.minChunkSize = options.minChunkSize ?? 4;\n this.maxChunkSize = options.maxChunkSize ?? 8;\n this.delay = options.delay ?? 20;\n this.firstWordChunk = options.firstWordChunk ?? true;\n }\n\n private randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min)) + min;\n }\n\n private static readonly BOUNDARIES = new Set([' ', '.', ',', '!', '?', ';', ':']);\n\n private findFirstWordBoundary(text: string, minSize: number): number {\n if (minSize >= text.length) return text.length;\n\n // Ensure we meet the minimum size first\n let pos = minSize;\n\n // Look forward until we find a boundary\n while (pos < text.length) {\n if (TextStream.BOUNDARIES.has(text[pos])) {\n return pos + 1; // Include the boundary character\n }\n pos++;\n }\n\n return text.length; // If no boundary found, return entire remaining text\n }\n\n async *generateText(progressCallback?: ProgressCallback): AsyncGenerator<string, void, unknown> {\n const { delay, minChunkSize, maxChunkSize } = this;\n\n while (this.currentIndex < this.text.length) {\n await new Promise(resolve => setTimeout(resolve, delay));\n\n const remainingText = this.text.slice(this.currentIndex);\n let chunkSize: number;\n\n if (this.firstWordChunk) {\n chunkSize = this.findFirstWordBoundary(remainingText, minChunkSize);\n } else {\n const remainingChars = remainingText.length;\n chunkSize = Math.min(this.randomInt(minChunkSize, maxChunkSize + 1), remainingChars);\n }\n\n const chunk = this.text.slice(this.currentIndex, this.currentIndex + chunkSize);\n progressCallback?.(chunk);\n\n yield chunk;\n this.currentIndex += chunkSize;\n }\n }\n}"],"names":[],"mappings":"MAWa,UAAU,CAAA;AACb,IAAA,IAAI,CAAS;AACb,IAAA,YAAY,CAAS;AACrB,IAAA,YAAY,CAAS;AACrB,IAAA,YAAY,CAAS;AACrB,IAAA,KAAK,CAAS;AACd,IAAA,cAAc,CAAU;IAEhC,WAAY,CAAA,IAAY,EAAE,OAAA,GAA6B,EAAE,EAAA;AACvD,QAAA,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;AACjB,QAAA,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;QACjC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC;KACtD;IAEO,SAAS,CAAC,GAAW,EAAE,GAAW,EAAA;AACxC,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;KACtD;IAEO,OAAgB,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAE1E,qBAAqB,CAAC,IAAY,EAAE,OAAe,EAAA;AACzD,QAAA,IAAI,OAAO,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC;;QAG/C,IAAI,GAAG,GAAG,OAAO,CAAC;;AAGlB,QAAA,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE;AACxB,YAAA,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE;AACxC,gBAAA,OAAO,GAAG,GAAG,CAAC,CAAC;aAChB;AACD,YAAA,GAAG,EAAE,CAAC;SACP;AAED,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC;KACpB;AAED,IAAA,OAAO,YAAY,CAAC,gBAAmC,EAAA;QACrD,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;QAEnD,OAAO,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;AAC3C,YAAA,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;AAEzD,YAAA,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;AACzD,YAAA,IAAI,SAAiB,CAAC;AAEtB,YAAA,IAAI,IAAI,CAAC,cAAc,EAAE;gBACvB,SAAS,GAAG,IAAI,CAAC,qBAAqB,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;aACrE;iBAAM;AACL,gBAAA,MAAM,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC;AAC5C,gBAAA,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,GAAG,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;aACtF;AAED,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;AAChF,YAAA,gBAAgB,GAAG,KAAK,CAAC,CAAC;AAE1B,YAAA,MAAM,KAAK,CAAC;AACZ,YAAA,IAAI,CAAC,YAAY,IAAI,SAAS,CAAC;SAChC;KACF;;;;;"}
|
package/dist/esm/main.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export { Run } from './run.mjs';
|
|
2
|
-
export { ChatModelStreamHandler, createContentAggregator } from './stream.mjs';
|
|
2
|
+
export { ChatModelStreamHandler, createContentAggregator, handleToolCalls } from './stream.mjs';
|
|
3
3
|
export { HandlerRegistry, LLMStreamHandler, ModelEndHandler, TestChatStreamHandler, TestLLMStreamHandler, ToolEndHandler, createMetadataAggregator } from './events.mjs';
|
|
4
4
|
export { convertMessagesToContent, findLastIndex, formatAnthropicArtifactContent, formatAnthropicMessage, formatOpenAIArtifactContent, getConverseOverrideMessage, modifyDeltaProperties } from './messages.mjs';
|
|
5
5
|
export { Graph, StandardGraph } from './graphs/Graph.mjs';
|
|
6
6
|
export { createCodeExecutionTool, getCodeBaseURL, imageExtRegex } from './tools/CodeExecutor.mjs';
|
|
7
7
|
export { Callback, CommonEvents, Constants, ContentTypes, EnvVar, GraphEvents, GraphNodeActions, GraphNodeKeys, Providers, StepTypes, ToolCallTypes } from './common/enum.mjs';
|
|
8
8
|
export { joinKeys, resetIfNotEmpty } from './utils/graph.mjs';
|
|
9
|
+
export { unescapeObject } from './utils/misc.mjs';
|
|
9
10
|
export { RunnableCallable, sleep } from './utils/run.mjs';
|
|
10
11
|
//# sourceMappingURL=main.mjs.map
|
package/dist/esm/main.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"main.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
|
package/dist/esm/messages.mjs
CHANGED
|
@@ -21,7 +21,7 @@ User: ${userMessage[1]}
|
|
|
21
21
|
}
|
|
22
22
|
const modifyContent = (messageType, content) => {
|
|
23
23
|
return content.map(item => {
|
|
24
|
-
if (item && typeof item === 'object' && 'type' in item && item.type) {
|
|
24
|
+
if (item && typeof item === 'object' && 'type' in item && item.type != null && item.type) {
|
|
25
25
|
let newType = item.type;
|
|
26
26
|
if (newType.endsWith('_delta')) {
|
|
27
27
|
newType = newType.replace('_delta', '');
|
|
@@ -61,10 +61,10 @@ function formatAnthropicMessage(message) {
|
|
|
61
61
|
formattedContent = message.content.reduce((acc, item) => {
|
|
62
62
|
if (typeof item === 'object' && item !== null) {
|
|
63
63
|
const extendedItem = item;
|
|
64
|
-
if (extendedItem.type === 'text' && extendedItem.text) {
|
|
64
|
+
if (extendedItem.type === 'text' && extendedItem.text != null && extendedItem.text) {
|
|
65
65
|
acc.push({ type: 'text', text: extendedItem.text });
|
|
66
66
|
}
|
|
67
|
-
else if (extendedItem.type === 'tool_use' && extendedItem.id) {
|
|
67
|
+
else if (extendedItem.type === 'tool_use' && extendedItem.id != null && extendedItem.id) {
|
|
68
68
|
const toolCall = toolCallMap.get(extendedItem.id);
|
|
69
69
|
if (toolCall) {
|
|
70
70
|
acc.push({
|
|
@@ -75,7 +75,7 @@ function formatAnthropicMessage(message) {
|
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
else if ('input' in extendedItem && extendedItem.input) {
|
|
78
|
+
else if ('input' in extendedItem && extendedItem.input != null && extendedItem.input) {
|
|
79
79
|
try {
|
|
80
80
|
const parsedInput = JSON.parse(extendedItem.input);
|
|
81
81
|
const toolCall = message.tool_calls?.find(tc => tc.args.input === parsedInput.input);
|