illuma-agents 1.0.5 → 1.0.7
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/events.cjs +34 -10
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +6 -4
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/main.cjs +3 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +87 -14
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +188 -7
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/esm/events.mjs +34 -10
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +6 -4
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/main.mjs +2 -2
- package/dist/esm/messages/cache.mjs +86 -15
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +188 -8
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/types/events.d.ts +3 -1
- package/dist/types/messages/cache.d.ts +16 -0
- package/dist/types/messages/format.d.ts +21 -1
- package/dist/types/types/stream.d.ts +1 -1
- package/package.json +6 -3
- package/src/events.ts +37 -15
- package/src/graphs/Graph.ts +8 -4
- package/src/llm/anthropic/utils/message_outputs.ts +289 -289
- package/src/messages/cache.test.ts +499 -3
- package/src/messages/cache.ts +115 -25
- package/src/messages/ensureThinkingBlock.test.ts +75 -0
- package/src/messages/format.ts +240 -7
- package/src/messages/labelContentByAgent.test.ts +887 -0
- package/src/scripts/test-multi-agent-list-handoff.ts +116 -10
- package/src/scripts/test-parallel-agent-labeling.ts +325 -0
- package/src/types/stream.ts +1 -1
|
@@ -4,6 +4,9 @@ var _enum = require('../common/enum.cjs');
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Anthropic API: Adds cache control to the appropriate user messages in the payload.
|
|
7
|
+
* Strips ALL existing cache control (both Anthropic and Bedrock formats) from all messages,
|
|
8
|
+
* then adds fresh cache control to the last 2 user messages in a single backward pass.
|
|
9
|
+
* This ensures we don't accumulate stale cache points across multiple turns.
|
|
7
10
|
* @param messages - The array of message objects.
|
|
8
11
|
* @returns - The updated array of message objects with cache control added.
|
|
9
12
|
*/
|
|
@@ -13,12 +16,20 @@ function addCacheControl(messages) {
|
|
|
13
16
|
}
|
|
14
17
|
const updatedMessages = [...messages];
|
|
15
18
|
let userMessagesModified = 0;
|
|
16
|
-
for (let i = updatedMessages.length - 1; i >= 0
|
|
19
|
+
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
17
20
|
const message = updatedMessages[i];
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
const isUserMessage = ('getType' in message && message.getType() === 'human') ||
|
|
22
|
+
('role' in message && message.role === 'user');
|
|
23
|
+
if (Array.isArray(message.content)) {
|
|
24
|
+
message.content = message.content.filter((block) => !isCachePoint(block));
|
|
25
|
+
for (let j = 0; j < message.content.length; j++) {
|
|
26
|
+
const block = message.content[j];
|
|
27
|
+
if ('cache_control' in block) {
|
|
28
|
+
delete block.cache_control;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
20
31
|
}
|
|
21
|
-
|
|
32
|
+
if (userMessagesModified >= 2 || !isUserMessage) {
|
|
22
33
|
continue;
|
|
23
34
|
}
|
|
24
35
|
if (typeof message.content === 'string') {
|
|
@@ -46,10 +57,60 @@ function addCacheControl(messages) {
|
|
|
46
57
|
}
|
|
47
58
|
return updatedMessages;
|
|
48
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Checks if a content block is a cache point
|
|
62
|
+
*/
|
|
63
|
+
function isCachePoint(block) {
|
|
64
|
+
return 'cachePoint' in block && !('type' in block);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Removes all Anthropic cache_control fields from messages
|
|
68
|
+
* Used when switching from Anthropic to Bedrock provider
|
|
69
|
+
*/
|
|
70
|
+
function stripAnthropicCacheControl(messages) {
|
|
71
|
+
if (!Array.isArray(messages)) {
|
|
72
|
+
return messages;
|
|
73
|
+
}
|
|
74
|
+
const updatedMessages = [...messages];
|
|
75
|
+
for (let i = 0; i < updatedMessages.length; i++) {
|
|
76
|
+
const message = updatedMessages[i];
|
|
77
|
+
const content = message.content;
|
|
78
|
+
if (Array.isArray(content)) {
|
|
79
|
+
for (let j = 0; j < content.length; j++) {
|
|
80
|
+
const block = content[j];
|
|
81
|
+
if ('cache_control' in block) {
|
|
82
|
+
delete block.cache_control;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return updatedMessages;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Removes all Bedrock cachePoint blocks from messages
|
|
91
|
+
* Used when switching from Bedrock to Anthropic provider
|
|
92
|
+
*/
|
|
93
|
+
function stripBedrockCacheControl(messages) {
|
|
94
|
+
if (!Array.isArray(messages)) {
|
|
95
|
+
return messages;
|
|
96
|
+
}
|
|
97
|
+
const updatedMessages = [...messages];
|
|
98
|
+
for (let i = 0; i < updatedMessages.length; i++) {
|
|
99
|
+
const message = updatedMessages[i];
|
|
100
|
+
const content = message.content;
|
|
101
|
+
if (Array.isArray(content)) {
|
|
102
|
+
message.content = content.filter((block) => !isCachePoint(block));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return updatedMessages;
|
|
106
|
+
}
|
|
49
107
|
/**
|
|
50
108
|
* Adds Bedrock Converse API cache points to the last two messages.
|
|
51
109
|
* Inserts `{ cachePoint: { type: 'default' } }` as a separate content block
|
|
52
110
|
* immediately after the last text block in each targeted message.
|
|
111
|
+
* Strips ALL existing cache control (both Bedrock and Anthropic formats) from all messages,
|
|
112
|
+
* then adds fresh cache points to the last 2 messages in a single backward pass.
|
|
113
|
+
* This ensures we don't accumulate stale cache points across multiple turns.
|
|
53
114
|
* @param messages - The array of message objects.
|
|
54
115
|
* @returns - The updated array of message objects with cache points added.
|
|
55
116
|
*/
|
|
@@ -59,14 +120,24 @@ function addBedrockCacheControl(messages) {
|
|
|
59
120
|
}
|
|
60
121
|
const updatedMessages = messages.slice();
|
|
61
122
|
let messagesModified = 0;
|
|
62
|
-
for (let i = updatedMessages.length - 1; i >= 0
|
|
123
|
+
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
63
124
|
const message = updatedMessages[i];
|
|
64
|
-
|
|
125
|
+
const isToolMessage = 'getType' in message &&
|
|
65
126
|
typeof message.getType === 'function' &&
|
|
66
|
-
message.getType() === 'tool'
|
|
127
|
+
message.getType() === 'tool';
|
|
128
|
+
const content = message.content;
|
|
129
|
+
if (Array.isArray(content)) {
|
|
130
|
+
message.content = content.filter((block) => !isCachePoint(block));
|
|
131
|
+
for (let j = 0; j < message.content.length; j++) {
|
|
132
|
+
const block = message.content[j];
|
|
133
|
+
if ('cache_control' in block) {
|
|
134
|
+
delete block.cache_control;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (messagesModified >= 2 || isToolMessage) {
|
|
67
139
|
continue;
|
|
68
140
|
}
|
|
69
|
-
const content = message.content;
|
|
70
141
|
if (typeof content === 'string' && content === '') {
|
|
71
142
|
continue;
|
|
72
143
|
}
|
|
@@ -78,9 +149,9 @@ function addBedrockCacheControl(messages) {
|
|
|
78
149
|
messagesModified++;
|
|
79
150
|
continue;
|
|
80
151
|
}
|
|
81
|
-
if (Array.isArray(content)) {
|
|
152
|
+
if (Array.isArray(message.content)) {
|
|
82
153
|
let hasCacheableContent = false;
|
|
83
|
-
for (const block of content) {
|
|
154
|
+
for (const block of message.content) {
|
|
84
155
|
if (block.type === _enum.ContentTypes.TEXT) {
|
|
85
156
|
if (typeof block.text === 'string' && block.text !== '') {
|
|
86
157
|
hasCacheableContent = true;
|
|
@@ -92,15 +163,15 @@ function addBedrockCacheControl(messages) {
|
|
|
92
163
|
continue;
|
|
93
164
|
}
|
|
94
165
|
let inserted = false;
|
|
95
|
-
for (let j = content.length - 1; j >= 0; j--) {
|
|
96
|
-
const block = content[j];
|
|
166
|
+
for (let j = message.content.length - 1; j >= 0; j--) {
|
|
167
|
+
const block = message.content[j];
|
|
97
168
|
const type = block.type;
|
|
98
169
|
if (type === _enum.ContentTypes.TEXT || type === 'text') {
|
|
99
170
|
const text = block.text;
|
|
100
171
|
if (text === '' || text === undefined) {
|
|
101
172
|
continue;
|
|
102
173
|
}
|
|
103
|
-
content.splice(j + 1, 0, {
|
|
174
|
+
message.content.splice(j + 1, 0, {
|
|
104
175
|
cachePoint: { type: 'default' },
|
|
105
176
|
});
|
|
106
177
|
inserted = true;
|
|
@@ -108,7 +179,7 @@ function addBedrockCacheControl(messages) {
|
|
|
108
179
|
}
|
|
109
180
|
}
|
|
110
181
|
if (!inserted) {
|
|
111
|
-
content.push({
|
|
182
|
+
message.content.push({
|
|
112
183
|
cachePoint: { type: 'default' },
|
|
113
184
|
});
|
|
114
185
|
}
|
|
@@ -120,4 +191,6 @@ function addBedrockCacheControl(messages) {
|
|
|
120
191
|
|
|
121
192
|
exports.addBedrockCacheControl = addBedrockCacheControl;
|
|
122
193
|
exports.addCacheControl = addCacheControl;
|
|
194
|
+
exports.stripAnthropicCacheControl = stripAnthropicCacheControl;
|
|
195
|
+
exports.stripBedrockCacheControl = stripBedrockCacheControl;
|
|
123
196
|
//# sourceMappingURL=cache.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.cjs","sources":["../../../src/messages/cache.ts"],"sourcesContent":["import { BaseMessage, MessageContentComplex } from '@langchain/core/messages';\nimport type { AnthropicMessage } from '@/types/messages';\nimport type Anthropic from '@anthropic-ai/sdk';\nimport { ContentTypes } from '@/common/enum';\n\ntype MessageWithContent = {\n content?: string | MessageContentComplex[];\n};\n\n/**\n * Anthropic API: Adds cache control to the appropriate user messages in the payload.\n * @param messages - The array of message objects.\n * @returns - The updated array of message objects with cache control added.\n */\nexport function addCacheControl<T extends AnthropicMessage | BaseMessage>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages = [...messages];\n let userMessagesModified = 0;\n\n for (\n let i = updatedMessages.length - 1;\n i >= 0 && userMessagesModified < 2;\n i--\n ) {\n const message = updatedMessages[i];\n if ('getType' in message && message.getType() !== 'human') {\n continue;\n } else if ('role' in message && message.role !== 'user') {\n continue;\n }\n\n if (typeof message.content === 'string') {\n message.content = [\n {\n type: 'text',\n text: message.content,\n cache_control: { type: 'ephemeral' },\n },\n ];\n userMessagesModified++;\n } else if (Array.isArray(message.content)) {\n for (let j = message.content.length - 1; j >= 0; j--) {\n const contentPart = message.content[j];\n if ('type' in contentPart && contentPart.type === 'text') {\n (contentPart as Anthropic.TextBlockParam).cache_control = {\n type: 'ephemeral',\n };\n userMessagesModified++;\n break;\n }\n }\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Adds Bedrock Converse API cache points to the last two messages.\n * Inserts `{ cachePoint: { type: 'default' } }` as a separate content block\n * immediately after the last text block in each targeted message.\n * @param messages - The array of message objects.\n * @returns - The updated array of message objects with cache points added.\n */\nexport function addBedrockCacheControl<\n T extends Partial<BaseMessage> & MessageWithContent,\n>(messages: T[]): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages: T[] = messages.slice();\n let messagesModified = 0;\n\n for (\n let i = updatedMessages.length - 1;\n i >= 0 && messagesModified < 2;\n i--\n ) {\n const message = updatedMessages[i];\n\n if (\n 'getType' in message &&\n typeof message.getType === 'function' &&\n message.getType() === 'tool'\n ) {\n continue;\n }\n\n const content = message.content;\n\n if (typeof content === 'string' && content === '') {\n continue;\n }\n\n if (typeof content === 'string') {\n message.content = [\n { type: ContentTypes.TEXT, text: content },\n { cachePoint: { type: 'default' } },\n ] as MessageContentComplex[];\n messagesModified++;\n continue;\n }\n\n if (Array.isArray(content)) {\n let hasCacheableContent = false;\n for (const block of content) {\n if (block.type === ContentTypes.TEXT) {\n if (typeof block.text === 'string' && block.text !== '') {\n hasCacheableContent = true;\n break;\n }\n }\n }\n\n if (!hasCacheableContent) {\n continue;\n }\n\n let inserted = false;\n for (let j = content.length - 1; j >= 0; j--) {\n const block = content[j] as MessageContentComplex;\n const type = (block as { type?: string }).type;\n if (type === ContentTypes.TEXT || type === 'text') {\n const text = (block as { text?: string }).text;\n if (text === '' || text === undefined) {\n continue;\n }\n content.splice(j + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n content.push({\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n }\n messagesModified++;\n }\n }\n\n return updatedMessages;\n}\n"],"names":["ContentTypes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cache.cjs","sources":["../../../src/messages/cache.ts"],"sourcesContent":["import { BaseMessage, MessageContentComplex } from '@langchain/core/messages';\nimport type { AnthropicMessage } from '@/types/messages';\nimport type Anthropic from '@anthropic-ai/sdk';\nimport { ContentTypes } from '@/common/enum';\n\ntype MessageWithContent = {\n content?: string | MessageContentComplex[];\n};\n\n/**\n * Anthropic API: Adds cache control to the appropriate user messages in the payload.\n * Strips ALL existing cache control (both Anthropic and Bedrock formats) from all messages,\n * then adds fresh cache control to the last 2 user messages in a single backward pass.\n * This ensures we don't accumulate stale cache points across multiple turns.\n * @param messages - The array of message objects.\n * @returns - The updated array of message objects with cache control added.\n */\nexport function addCacheControl<T extends AnthropicMessage | BaseMessage>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages = [...messages];\n let userMessagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const message = updatedMessages[i];\n const isUserMessage =\n ('getType' in message && message.getType() === 'human') ||\n ('role' in message && message.role === 'user');\n\n if (Array.isArray(message.content)) {\n message.content = message.content.filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof message.content;\n\n for (let j = 0; j < message.content.length; j++) {\n const block = message.content[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n if (userMessagesModified >= 2 || !isUserMessage) {\n continue;\n }\n\n if (typeof message.content === 'string') {\n message.content = [\n {\n type: 'text',\n text: message.content,\n cache_control: { type: 'ephemeral' },\n },\n ];\n userMessagesModified++;\n } else if (Array.isArray(message.content)) {\n for (let j = message.content.length - 1; j >= 0; j--) {\n const contentPart = message.content[j];\n if ('type' in contentPart && contentPart.type === 'text') {\n (contentPart as Anthropic.TextBlockParam).cache_control = {\n type: 'ephemeral',\n };\n userMessagesModified++;\n break;\n }\n }\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a content block is a cache point\n */\nfunction isCachePoint(block: MessageContentComplex): boolean {\n return 'cachePoint' in block && !('type' in block);\n}\n\n/**\n * Removes all Anthropic cache_control fields from messages\n * Used when switching from Anthropic to Bedrock provider\n */\nexport function stripAnthropicCacheControl<T extends MessageWithContent>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages)) {\n return messages;\n }\n\n const updatedMessages = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const message = updatedMessages[i];\n const content = message.content;\n\n if (Array.isArray(content)) {\n for (let j = 0; j < content.length; j++) {\n const block = content[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Removes all Bedrock cachePoint blocks from messages\n * Used when switching from Bedrock to Anthropic provider\n */\nexport function stripBedrockCacheControl<T extends MessageWithContent>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages)) {\n return messages;\n }\n\n const updatedMessages = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const message = updatedMessages[i];\n const content = message.content;\n\n if (Array.isArray(content)) {\n message.content = content.filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof content;\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Adds Bedrock Converse API cache points to the last two messages.\n * Inserts `{ cachePoint: { type: 'default' } }` as a separate content block\n * immediately after the last text block in each targeted message.\n * Strips ALL existing cache control (both Bedrock and Anthropic formats) from all messages,\n * then adds fresh cache points to the last 2 messages in a single backward pass.\n * This ensures we don't accumulate stale cache points across multiple turns.\n * @param messages - The array of message objects.\n * @returns - The updated array of message objects with cache points added.\n */\nexport function addBedrockCacheControl<\n T extends Partial<BaseMessage> & MessageWithContent,\n>(messages: T[]): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages: T[] = messages.slice();\n let messagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const message = updatedMessages[i];\n const isToolMessage =\n 'getType' in message &&\n typeof message.getType === 'function' &&\n message.getType() === 'tool';\n\n const content = message.content;\n\n if (Array.isArray(content)) {\n message.content = content.filter(\n (block) => !isCachePoint(block)\n ) as typeof content;\n\n for (let j = 0; j < message.content.length; j++) {\n const block = message.content[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n if (messagesModified >= 2 || isToolMessage) {\n continue;\n }\n\n if (typeof content === 'string' && content === '') {\n continue;\n }\n\n if (typeof content === 'string') {\n message.content = [\n { type: ContentTypes.TEXT, text: content },\n { cachePoint: { type: 'default' } },\n ] as MessageContentComplex[];\n messagesModified++;\n continue;\n }\n\n if (Array.isArray(message.content)) {\n let hasCacheableContent = false;\n for (const block of message.content) {\n if (block.type === ContentTypes.TEXT) {\n if (typeof block.text === 'string' && block.text !== '') {\n hasCacheableContent = true;\n break;\n }\n }\n }\n\n if (!hasCacheableContent) {\n continue;\n }\n\n let inserted = false;\n for (let j = message.content.length - 1; j >= 0; j--) {\n const block = message.content[j] as MessageContentComplex;\n const type = (block as { type?: string }).type;\n if (type === ContentTypes.TEXT || type === 'text') {\n const text = (block as { text?: string }).text;\n if (text === '' || text === undefined) {\n continue;\n }\n message.content.splice(j + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n message.content.push({\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n }\n messagesModified++;\n }\n }\n\n return updatedMessages;\n}\n"],"names":["ContentTypes"],"mappings":"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"}
|
|
@@ -182,19 +182,20 @@ function formatAssistantMessage(message) {
|
|
|
182
182
|
}
|
|
183
183
|
// Create a new AIMessage with this text and prepare for tool calls
|
|
184
184
|
lastAIMessage = new messages.AIMessage({
|
|
185
|
-
content: part.text
|
|
185
|
+
content: part.text != null ? part.text : '',
|
|
186
186
|
});
|
|
187
187
|
formattedMessages.push(lastAIMessage);
|
|
188
188
|
}
|
|
189
189
|
else if (part.type === _enum.ContentTypes.TOOL_CALL) {
|
|
190
190
|
// Skip malformed tool call entries without tool_call property
|
|
191
|
-
if (
|
|
191
|
+
if (part.tool_call == null) {
|
|
192
192
|
continue;
|
|
193
193
|
}
|
|
194
194
|
// Note: `tool_calls` list is defined when constructed by `AIMessage` class, and outputs should be excluded from it
|
|
195
195
|
const { output, args: _args, ..._tool_call } = part.tool_call;
|
|
196
196
|
// Skip invalid tool calls that have no name AND no output
|
|
197
|
-
if (
|
|
197
|
+
if (_tool_call.name == null ||
|
|
198
|
+
(_tool_call.name === '' && (output == null || output === ''))) {
|
|
198
199
|
continue;
|
|
199
200
|
}
|
|
200
201
|
if (!lastAIMessage) {
|
|
@@ -223,7 +224,7 @@ function formatAssistantMessage(message) {
|
|
|
223
224
|
formattedMessages.push(new messages.ToolMessage({
|
|
224
225
|
tool_call_id: tool_call.id ?? '',
|
|
225
226
|
name: tool_call.name,
|
|
226
|
-
content: output
|
|
227
|
+
content: output != null ? output : '',
|
|
227
228
|
}));
|
|
228
229
|
}
|
|
229
230
|
else if (part.type === _enum.ContentTypes.THINK) {
|
|
@@ -257,6 +258,177 @@ function formatAssistantMessage(message) {
|
|
|
257
258
|
}
|
|
258
259
|
return formattedMessages;
|
|
259
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Labels all agent content for parallel patterns (fan-out/fan-in)
|
|
263
|
+
* Groups consecutive content by agent and wraps with clear labels
|
|
264
|
+
*/
|
|
265
|
+
function labelAllAgentContent(contentParts, agentIdMap, agentNames) {
|
|
266
|
+
const result = [];
|
|
267
|
+
let currentAgentId;
|
|
268
|
+
let agentContentBuffer = [];
|
|
269
|
+
const flushAgentBuffer = () => {
|
|
270
|
+
if (agentContentBuffer.length === 0) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (currentAgentId != null && currentAgentId !== '') {
|
|
274
|
+
const agentName = (agentNames?.[currentAgentId] ?? '') || currentAgentId;
|
|
275
|
+
const formattedParts = [];
|
|
276
|
+
formattedParts.push(`--- ${agentName} ---`);
|
|
277
|
+
for (const part of agentContentBuffer) {
|
|
278
|
+
if (part.type === _enum.ContentTypes.THINK) {
|
|
279
|
+
const thinkContent = part.think || '';
|
|
280
|
+
if (thinkContent) {
|
|
281
|
+
formattedParts.push(`${agentName}: ${JSON.stringify({
|
|
282
|
+
type: 'think',
|
|
283
|
+
think: thinkContent,
|
|
284
|
+
})}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
else if (part.type === _enum.ContentTypes.TEXT) {
|
|
288
|
+
const textContent = part.text ?? '';
|
|
289
|
+
if (textContent) {
|
|
290
|
+
formattedParts.push(`${agentName}: ${textContent}`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
else if (part.type === _enum.ContentTypes.TOOL_CALL) {
|
|
294
|
+
formattedParts.push(`${agentName}: ${JSON.stringify({
|
|
295
|
+
type: 'tool_call',
|
|
296
|
+
tool_call: part.tool_call,
|
|
297
|
+
})}`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
formattedParts.push(`--- End of ${agentName} ---`);
|
|
301
|
+
// Create a single text content part with all agent content
|
|
302
|
+
result.push({
|
|
303
|
+
type: _enum.ContentTypes.TEXT,
|
|
304
|
+
text: formattedParts.join('\n\n'),
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
// No agent ID, pass through as-is
|
|
309
|
+
result.push(...agentContentBuffer);
|
|
310
|
+
}
|
|
311
|
+
agentContentBuffer = [];
|
|
312
|
+
};
|
|
313
|
+
for (let i = 0; i < contentParts.length; i++) {
|
|
314
|
+
const part = contentParts[i];
|
|
315
|
+
const agentId = agentIdMap[i];
|
|
316
|
+
// If agent changed, flush previous buffer
|
|
317
|
+
if (agentId !== currentAgentId && currentAgentId !== undefined) {
|
|
318
|
+
flushAgentBuffer();
|
|
319
|
+
}
|
|
320
|
+
currentAgentId = agentId;
|
|
321
|
+
agentContentBuffer.push(part);
|
|
322
|
+
}
|
|
323
|
+
// Flush any remaining content
|
|
324
|
+
flushAgentBuffer();
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Groups content parts by agent and formats them with agent labels
|
|
329
|
+
* This preprocesses multi-agent content to prevent identity confusion
|
|
330
|
+
*
|
|
331
|
+
* @param contentParts - The content parts from a run
|
|
332
|
+
* @param agentIdMap - Map of content part index to agent ID
|
|
333
|
+
* @param agentNames - Optional map of agent ID to display name
|
|
334
|
+
* @param options - Configuration options
|
|
335
|
+
* @param options.labelNonTransferContent - If true, labels all agent transitions (for parallel patterns)
|
|
336
|
+
* @returns Modified content parts with agent labels where appropriate
|
|
337
|
+
*/
|
|
338
|
+
const labelContentByAgent = (contentParts, agentIdMap, agentNames, options) => {
|
|
339
|
+
if (!agentIdMap || Object.keys(agentIdMap).length === 0) {
|
|
340
|
+
return contentParts;
|
|
341
|
+
}
|
|
342
|
+
// If labelNonTransferContent is true, use a different strategy for parallel patterns
|
|
343
|
+
if (options?.labelNonTransferContent === true) {
|
|
344
|
+
return labelAllAgentContent(contentParts, agentIdMap, agentNames);
|
|
345
|
+
}
|
|
346
|
+
const result = [];
|
|
347
|
+
let currentAgentId;
|
|
348
|
+
let agentContentBuffer = [];
|
|
349
|
+
let transferToolCallIndex;
|
|
350
|
+
let transferToolCallId;
|
|
351
|
+
const flushAgentBuffer = () => {
|
|
352
|
+
if (agentContentBuffer.length === 0) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
// If this is content from a transferred agent, format it specially
|
|
356
|
+
if (currentAgentId != null &&
|
|
357
|
+
currentAgentId !== '' &&
|
|
358
|
+
transferToolCallIndex !== undefined) {
|
|
359
|
+
const agentName = (agentNames?.[currentAgentId] ?? '') || currentAgentId;
|
|
360
|
+
const formattedParts = [];
|
|
361
|
+
formattedParts.push(`--- Transfer to ${agentName} ---`);
|
|
362
|
+
for (const part of agentContentBuffer) {
|
|
363
|
+
if (part.type === _enum.ContentTypes.THINK) {
|
|
364
|
+
formattedParts.push(`${agentName}: ${JSON.stringify({
|
|
365
|
+
type: 'think',
|
|
366
|
+
think: part.think,
|
|
367
|
+
})}`);
|
|
368
|
+
}
|
|
369
|
+
else if ('text' in part && part.type === _enum.ContentTypes.TEXT) {
|
|
370
|
+
const textContent = part.text ?? '';
|
|
371
|
+
if (textContent) {
|
|
372
|
+
formattedParts.push(`${agentName}: ${JSON.stringify({
|
|
373
|
+
type: 'text',
|
|
374
|
+
text: textContent,
|
|
375
|
+
})}`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
else if (part.type === _enum.ContentTypes.TOOL_CALL) {
|
|
379
|
+
formattedParts.push(`${agentName}: ${JSON.stringify({
|
|
380
|
+
type: 'tool_call',
|
|
381
|
+
tool_call: part.tool_call,
|
|
382
|
+
})}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
formattedParts.push(`--- End of ${agentName} response ---`);
|
|
386
|
+
// Find the tool call that triggered this transfer and update its output
|
|
387
|
+
if (transferToolCallIndex < result.length) {
|
|
388
|
+
const transferToolCall = result[transferToolCallIndex];
|
|
389
|
+
if (transferToolCall.type === _enum.ContentTypes.TOOL_CALL &&
|
|
390
|
+
transferToolCall.tool_call?.id === transferToolCallId) {
|
|
391
|
+
transferToolCall.tool_call.output = formattedParts.join('\n\n');
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
// Not from a transfer, add as-is
|
|
397
|
+
result.push(...agentContentBuffer);
|
|
398
|
+
}
|
|
399
|
+
agentContentBuffer = [];
|
|
400
|
+
transferToolCallIndex = undefined;
|
|
401
|
+
transferToolCallId = undefined;
|
|
402
|
+
};
|
|
403
|
+
for (let i = 0; i < contentParts.length; i++) {
|
|
404
|
+
const part = contentParts[i];
|
|
405
|
+
const agentId = agentIdMap[i];
|
|
406
|
+
// Check if this is a transfer tool call
|
|
407
|
+
const isTransferTool = (part.type === _enum.ContentTypes.TOOL_CALL &&
|
|
408
|
+
part.tool_call?.name?.startsWith('lc_transfer_to_')) ??
|
|
409
|
+
false;
|
|
410
|
+
// If agent changed, flush previous buffer
|
|
411
|
+
if (agentId !== currentAgentId && currentAgentId !== undefined) {
|
|
412
|
+
flushAgentBuffer();
|
|
413
|
+
}
|
|
414
|
+
currentAgentId = agentId;
|
|
415
|
+
if (isTransferTool) {
|
|
416
|
+
// Flush any existing buffer first
|
|
417
|
+
flushAgentBuffer();
|
|
418
|
+
// Add the transfer tool call to result
|
|
419
|
+
result.push(part);
|
|
420
|
+
// Mark that the next agent's content should be captured
|
|
421
|
+
transferToolCallIndex = result.length - 1;
|
|
422
|
+
transferToolCallId = part.tool_call?.id;
|
|
423
|
+
currentAgentId = undefined; // Reset to capture the next agent
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
agentContentBuffer.push(part);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
flushAgentBuffer();
|
|
430
|
+
return result;
|
|
431
|
+
};
|
|
260
432
|
/**
|
|
261
433
|
* Formats an array of messages for LangChain, handling tool calls and creating ToolMessage instances.
|
|
262
434
|
*
|
|
@@ -307,7 +479,7 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools) => {
|
|
|
307
479
|
break;
|
|
308
480
|
}
|
|
309
481
|
// Protect against malformed tool call entries
|
|
310
|
-
if (
|
|
482
|
+
if (part.tool_call == null ||
|
|
311
483
|
part.tool_call.name == null ||
|
|
312
484
|
part.tool_call.name === '') {
|
|
313
485
|
hasInvalidTool = true;
|
|
@@ -334,7 +506,7 @@ const formatAgentMessages = (payload, indexTokenCountMap, tools) => {
|
|
|
334
506
|
// Check if this is a continuation of the tool sequence
|
|
335
507
|
let isToolResponse = false;
|
|
336
508
|
const content = payload[j].content;
|
|
337
|
-
if (content && Array.isArray(content)) {
|
|
509
|
+
if (content != null && Array.isArray(content)) {
|
|
338
510
|
for (const part of content) {
|
|
339
511
|
if (part.type === _enum.ContentTypes.TOOL_CALL) {
|
|
340
512
|
isToolResponse = true;
|
|
@@ -435,9 +607,15 @@ function shiftIndexTokenCountMap(indexTokenCountMap, instructionsTokenCount) {
|
|
|
435
607
|
}
|
|
436
608
|
/**
|
|
437
609
|
* Ensures compatibility when switching from a non-thinking agent to a thinking-enabled agent.
|
|
438
|
-
* Converts AI messages with tool calls (that lack thinking blocks) into buffer strings,
|
|
610
|
+
* Converts AI messages with tool calls (that lack thinking/reasoning blocks) into buffer strings,
|
|
439
611
|
* avoiding the thinking block signature requirement.
|
|
440
612
|
*
|
|
613
|
+
* Recognizes the following as valid thinking/reasoning blocks:
|
|
614
|
+
* - ContentTypes.THINKING (Anthropic)
|
|
615
|
+
* - ContentTypes.REASONING_CONTENT (Bedrock)
|
|
616
|
+
* - ContentTypes.REASONING (VertexAI / Google)
|
|
617
|
+
* - 'redacted_thinking'
|
|
618
|
+
*
|
|
441
619
|
* @param messages - Array of messages to process
|
|
442
620
|
* @param provider - The provider being used (unused but kept for future compatibility)
|
|
443
621
|
* @returns The messages array with tool sequences converted to buffer strings if necessary
|
|
@@ -469,6 +647,8 @@ function ensureThinkingBlockInMessages(messages$1, _provider) {
|
|
|
469
647
|
// If message has tool use but no thinking block, convert to buffer string
|
|
470
648
|
if (hasToolUse &&
|
|
471
649
|
firstContentType !== _enum.ContentTypes.THINKING &&
|
|
650
|
+
firstContentType !== _enum.ContentTypes.REASONING_CONTENT &&
|
|
651
|
+
firstContentType !== _enum.ContentTypes.REASONING &&
|
|
472
652
|
firstContentType !== 'redacted_thinking') {
|
|
473
653
|
// Collect the AI message and any following tool messages
|
|
474
654
|
const toolSequence = [msg];
|
|
@@ -502,5 +682,6 @@ exports.formatFromLangChain = formatFromLangChain;
|
|
|
502
682
|
exports.formatLangChainMessages = formatLangChainMessages;
|
|
503
683
|
exports.formatMediaMessage = formatMediaMessage;
|
|
504
684
|
exports.formatMessage = formatMessage;
|
|
685
|
+
exports.labelContentByAgent = labelContentByAgent;
|
|
505
686
|
exports.shiftIndexTokenCountMap = shiftIndexTokenCountMap;
|
|
506
687
|
//# sourceMappingURL=format.cjs.map
|