@librechat/agents 3.0.774 → 3.0.776
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/messages/cache.cjs +51 -94
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/esm/messages/cache.mjs +51 -94
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/package.json +3 -3
- package/src/messages/cache.test.ts +51 -6
- package/src/messages/cache.ts +75 -130
- package/src/specs/cache.simple.test.ts +396 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var messages = require('@langchain/core/messages');
|
|
4
3
|
var _enum = require('../common/enum.cjs');
|
|
5
4
|
|
|
6
5
|
/**
|
|
@@ -16,61 +15,24 @@ function deepCloneContent(content) {
|
|
|
16
15
|
return content;
|
|
17
16
|
}
|
|
18
17
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* Clones a message with deep-cloned content, explicitly excluding LangChain
|
|
19
|
+
* serialization metadata to prevent coercion issues.
|
|
21
20
|
*/
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const msgType = baseMsg.getType();
|
|
36
|
-
const baseFields = {
|
|
37
|
-
content,
|
|
38
|
-
name: baseMsg.name,
|
|
39
|
-
additional_kwargs: { ...baseMsg.additional_kwargs },
|
|
40
|
-
response_metadata: { ...baseMsg.response_metadata },
|
|
41
|
-
id: baseMsg.id,
|
|
21
|
+
function cloneMessage(message, content) {
|
|
22
|
+
const { lc_kwargs: _lc_kwargs, lc_serializable: _lc_serializable, lc_namespace: _lc_namespace, ...rest } = message;
|
|
23
|
+
const cloned = { ...rest, content };
|
|
24
|
+
// LangChain messages don't have a direct 'role' property - derive it from getType()
|
|
25
|
+
if ('getType' in message &&
|
|
26
|
+
typeof message.getType === 'function' &&
|
|
27
|
+
!('role' in cloned)) {
|
|
28
|
+
const msgType = message.getType();
|
|
29
|
+
const roleMap = {
|
|
30
|
+
human: 'user',
|
|
31
|
+
ai: 'assistant',
|
|
32
|
+
system: 'system',
|
|
33
|
+
tool: 'tool',
|
|
42
34
|
};
|
|
43
|
-
|
|
44
|
-
case 'human':
|
|
45
|
-
return new messages.HumanMessage(baseFields);
|
|
46
|
-
case 'ai': {
|
|
47
|
-
const aiMsg = baseMsg;
|
|
48
|
-
return new messages.AIMessage({
|
|
49
|
-
...baseFields,
|
|
50
|
-
tool_calls: aiMsg.tool_calls ? [...aiMsg.tool_calls] : [],
|
|
51
|
-
invalid_tool_calls: aiMsg.invalid_tool_calls
|
|
52
|
-
? [...aiMsg.invalid_tool_calls]
|
|
53
|
-
: [],
|
|
54
|
-
usage_metadata: aiMsg.usage_metadata,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
case 'system':
|
|
58
|
-
return new messages.SystemMessage(baseFields);
|
|
59
|
-
case 'tool': {
|
|
60
|
-
const toolMsg = baseMsg;
|
|
61
|
-
return new messages.ToolMessage({
|
|
62
|
-
...baseFields,
|
|
63
|
-
tool_call_id: toolMsg.tool_call_id,
|
|
64
|
-
status: toolMsg.status,
|
|
65
|
-
artifact: toolMsg.artifact,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
const cloned = { ...message, content };
|
|
71
|
-
const lcKwargs = cloned.lc_kwargs;
|
|
72
|
-
if (lcKwargs != null) {
|
|
73
|
-
cloned.lc_kwargs = { ...lcKwargs, content };
|
|
35
|
+
cloned.role = roleMap[msgType] || msgType;
|
|
74
36
|
}
|
|
75
37
|
return cloned;
|
|
76
38
|
}
|
|
@@ -105,53 +67,51 @@ function addCacheControl(messages) {
|
|
|
105
67
|
let userMessagesModified = 0;
|
|
106
68
|
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
107
69
|
const originalMessage = updatedMessages[i];
|
|
70
|
+
const content = originalMessage.content;
|
|
108
71
|
const isUserMessage = ('getType' in originalMessage && originalMessage.getType() === 'human') ||
|
|
109
72
|
('role' in originalMessage && originalMessage.role === 'user');
|
|
110
|
-
const hasArrayContent = Array.isArray(
|
|
73
|
+
const hasArrayContent = Array.isArray(content);
|
|
111
74
|
const needsStripping = hasArrayContent &&
|
|
112
|
-
needsCacheStripping(
|
|
75
|
+
needsCacheStripping(content);
|
|
113
76
|
const needsCacheAdd = userMessagesModified < 2 &&
|
|
114
77
|
isUserMessage &&
|
|
115
|
-
(typeof
|
|
78
|
+
(typeof content === 'string' || hasArrayContent);
|
|
116
79
|
if (!needsStripping && !needsCacheAdd) {
|
|
117
80
|
continue;
|
|
118
81
|
}
|
|
119
|
-
|
|
120
|
-
updatedMessages[i] = message;
|
|
82
|
+
let workingContent;
|
|
121
83
|
if (hasArrayContent) {
|
|
122
|
-
|
|
123
|
-
for (let j = 0; j <
|
|
124
|
-
const block =
|
|
84
|
+
workingContent = deepCloneContent(content).filter((block) => !isCachePoint(block));
|
|
85
|
+
for (let j = 0; j < workingContent.length; j++) {
|
|
86
|
+
const block = workingContent[j];
|
|
125
87
|
if ('cache_control' in block) {
|
|
126
88
|
delete block.cache_control;
|
|
127
89
|
}
|
|
128
90
|
}
|
|
129
91
|
}
|
|
92
|
+
else if (typeof content === 'string') {
|
|
93
|
+
workingContent = [
|
|
94
|
+
{ type: 'text', text: content },
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
workingContent = [];
|
|
99
|
+
}
|
|
130
100
|
if (userMessagesModified >= 2 || !isUserMessage) {
|
|
101
|
+
updatedMessages[i] = cloneMessage(originalMessage, workingContent);
|
|
131
102
|
continue;
|
|
132
103
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
userMessagesModified++;
|
|
142
|
-
}
|
|
143
|
-
else if (Array.isArray(message.content)) {
|
|
144
|
-
for (let j = message.content.length - 1; j >= 0; j--) {
|
|
145
|
-
const contentPart = message.content[j];
|
|
146
|
-
if ('type' in contentPart && contentPart.type === 'text') {
|
|
147
|
-
contentPart.cache_control = {
|
|
148
|
-
type: 'ephemeral',
|
|
149
|
-
};
|
|
150
|
-
userMessagesModified++;
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
104
|
+
for (let j = workingContent.length - 1; j >= 0; j--) {
|
|
105
|
+
const contentPart = workingContent[j];
|
|
106
|
+
if ('type' in contentPart && contentPart.type === 'text') {
|
|
107
|
+
contentPart.cache_control = {
|
|
108
|
+
type: 'ephemeral',
|
|
109
|
+
};
|
|
110
|
+
userMessagesModified++;
|
|
111
|
+
break;
|
|
153
112
|
}
|
|
154
113
|
}
|
|
114
|
+
updatedMessages[i] = cloneMessage(originalMessage, workingContent);
|
|
155
115
|
}
|
|
156
116
|
return updatedMessages;
|
|
157
117
|
}
|
|
@@ -187,14 +147,14 @@ function stripAnthropicCacheControl(messages) {
|
|
|
187
147
|
if (!Array.isArray(content) || !hasAnthropicCacheControl(content)) {
|
|
188
148
|
continue;
|
|
189
149
|
}
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const block = message.content[j];
|
|
150
|
+
const clonedContent = deepCloneContent(content);
|
|
151
|
+
for (let j = 0; j < clonedContent.length; j++) {
|
|
152
|
+
const block = clonedContent[j];
|
|
194
153
|
if ('cache_control' in block) {
|
|
195
154
|
delete block.cache_control;
|
|
196
155
|
}
|
|
197
156
|
}
|
|
157
|
+
updatedMessages[i] = cloneMessage(originalMessage, clonedContent);
|
|
198
158
|
}
|
|
199
159
|
return updatedMessages;
|
|
200
160
|
}
|
|
@@ -224,9 +184,8 @@ function stripBedrockCacheControl(messages) {
|
|
|
224
184
|
if (!Array.isArray(content) || !hasBedrockCachePoint(content)) {
|
|
225
185
|
continue;
|
|
226
186
|
}
|
|
227
|
-
const
|
|
228
|
-
updatedMessages[i] =
|
|
229
|
-
message.content = message.content.filter((block) => !isCachePoint(block));
|
|
187
|
+
const clonedContent = deepCloneContent(content).filter((block) => !isCachePoint(block));
|
|
188
|
+
updatedMessages[i] = cloneMessage(originalMessage, clonedContent);
|
|
230
189
|
}
|
|
231
190
|
return updatedMessages;
|
|
232
191
|
}
|
|
@@ -281,8 +240,7 @@ function addBedrockCacheControl(messages) {
|
|
|
281
240
|
workingContent = [];
|
|
282
241
|
}
|
|
283
242
|
if (messagesModified >= 2 || isToolMessage || isEmptyString) {
|
|
284
|
-
updatedMessages[i] =
|
|
285
|
-
updatedMessages[i].content = workingContent;
|
|
243
|
+
updatedMessages[i] = cloneMessage(originalMessage, workingContent);
|
|
286
244
|
continue;
|
|
287
245
|
}
|
|
288
246
|
if (workingContent.length === 0) {
|
|
@@ -298,8 +256,7 @@ function addBedrockCacheControl(messages) {
|
|
|
298
256
|
}
|
|
299
257
|
}
|
|
300
258
|
if (!hasCacheableContent) {
|
|
301
|
-
updatedMessages[i] =
|
|
302
|
-
updatedMessages[i].content = workingContent;
|
|
259
|
+
updatedMessages[i] = cloneMessage(originalMessage, workingContent);
|
|
303
260
|
continue;
|
|
304
261
|
}
|
|
305
262
|
let inserted = false;
|
|
@@ -323,7 +280,7 @@ function addBedrockCacheControl(messages) {
|
|
|
323
280
|
cachePoint: { type: 'default' },
|
|
324
281
|
});
|
|
325
282
|
}
|
|
326
|
-
updatedMessages[i] =
|
|
283
|
+
updatedMessages[i] = cloneMessage(originalMessage, workingContent);
|
|
327
284
|
messagesModified++;
|
|
328
285
|
}
|
|
329
286
|
return updatedMessages;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.cjs","sources":["../../../src/messages/cache.ts"],"sourcesContent":["import {\n BaseMessage,\n MessageContentComplex,\n AIMessage,\n HumanMessage,\n SystemMessage,\n ToolMessage,\n} 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 * Deep clones a message's content to prevent mutation of the original.\n */\nfunction deepCloneContent<T extends string | MessageContentComplex[]>(\n content: T\n): T {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content.map((block) => ({ ...block })) as T;\n }\n return content;\n}\n\n/**\n * Simple shallow clone with deep-cloned content.\n * Used for stripping cache control where we don't need proper LangChain instances.\n */\nfunction shallowCloneMessage<T extends MessageWithContent>(message: T): T {\n return {\n ...message,\n content: deepCloneContent(message.content ?? ''),\n } as T;\n}\n\n/**\n * Creates a new LangChain message instance with the given content.\n * Required when adding cache points to ensure proper serialization.\n */\nfunction createNewMessage<T extends MessageWithContent>(\n message: T,\n content: MessageContentComplex[]\n): T {\n if ('getType' in message && typeof message.getType === 'function') {\n const baseMsg = message as unknown as BaseMessage;\n const msgType = baseMsg.getType();\n\n const baseFields = {\n content,\n name: baseMsg.name,\n additional_kwargs: { ...baseMsg.additional_kwargs },\n response_metadata: { ...baseMsg.response_metadata },\n id: baseMsg.id,\n };\n\n switch (msgType) {\n case 'human':\n return new HumanMessage(baseFields) as unknown as T;\n case 'ai': {\n const aiMsg = baseMsg as AIMessage;\n return new AIMessage({\n ...baseFields,\n tool_calls: aiMsg.tool_calls ? [...aiMsg.tool_calls] : [],\n invalid_tool_calls: aiMsg.invalid_tool_calls\n ? [...aiMsg.invalid_tool_calls]\n : [],\n usage_metadata: aiMsg.usage_metadata,\n }) as unknown as T;\n }\n case 'system':\n return new SystemMessage(baseFields) as unknown as T;\n case 'tool': {\n const toolMsg = baseMsg as ToolMessage;\n return new ToolMessage({\n ...baseFields,\n tool_call_id: toolMsg.tool_call_id,\n status: toolMsg.status,\n artifact: toolMsg.artifact,\n }) as unknown as T;\n }\n default:\n break;\n }\n }\n\n const cloned = { ...message, content } as T;\n const lcKwargs = (cloned as Record<string, unknown>).lc_kwargs as\n | Record<string, unknown>\n | undefined;\n if (lcKwargs != null) {\n (cloned as Record<string, unknown>).lc_kwargs = { ...lcKwargs, content };\n }\n return cloned;\n}\n\n/**\n * Checks if a message's content needs cache control stripping.\n * Returns true if content has cachePoint blocks or cache_control fields.\n */\nfunction needsCacheStripping(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n const block = content[i];\n if (isCachePoint(block)) return true;\n if ('cache_control' in block) return true;\n }\n return false;\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 * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new 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: T[] = [...messages];\n let userMessagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isUserMessage =\n ('getType' in originalMessage && originalMessage.getType() === 'human') ||\n ('role' in originalMessage && originalMessage.role === 'user');\n\n const hasArrayContent = Array.isArray(originalMessage.content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(originalMessage.content as MessageContentComplex[]);\n const needsCacheAdd =\n userMessagesModified < 2 &&\n isUserMessage &&\n (typeof originalMessage.content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n const message = shallowCloneMessage(\n originalMessage as MessageWithContent\n ) as T;\n updatedMessages[i] = message;\n\n if (hasArrayContent) {\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof message.content;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\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 * Checks if a message's content has Anthropic cache_control fields.\n */\nfunction hasAnthropicCacheControl(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if ('cache_control' in content[i]) return true;\n }\n return false;\n}\n\n/**\n * Removes all Anthropic cache_control fields from messages\n * Used when switching from Anthropic to Bedrock provider\n * Returns a new array - only clones messages that require modification.\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: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasAnthropicCacheControl(content)) {\n continue;\n }\n\n const message = shallowCloneMessage(originalMessage);\n updatedMessages[i] = message;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a message's content has Bedrock cachePoint blocks.\n */\nfunction hasBedrockCachePoint(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if (isCachePoint(content[i])) return true;\n }\n return false;\n}\n\n/**\n * Removes all Bedrock cachePoint blocks from messages\n * Used when switching from Bedrock to Anthropic provider\n * Returns a new array - only clones messages that require modification.\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: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasBedrockCachePoint(content)) {\n continue;\n }\n\n const message = shallowCloneMessage(originalMessage);\n updatedMessages[i] = message;\n\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof content;\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 * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new 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];\n let messagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isToolMessage =\n 'getType' in originalMessage &&\n typeof originalMessage.getType === 'function' &&\n originalMessage.getType() === 'tool';\n\n const content = originalMessage.content;\n const hasArrayContent = Array.isArray(content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(content as MessageContentComplex[]);\n const isEmptyString = typeof content === 'string' && content === '';\n const needsCacheAdd =\n messagesModified < 2 &&\n !isToolMessage &&\n !isEmptyString &&\n (typeof content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n let workingContent: MessageContentComplex[];\n\n if (hasArrayContent) {\n workingContent = deepCloneContent(\n content as MessageContentComplex[]\n ).filter((block) => !isCachePoint(block));\n\n for (let j = 0; j < workingContent.length; j++) {\n const block = workingContent[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n } else if (typeof content === 'string') {\n workingContent = [{ type: ContentTypes.TEXT, text: content }];\n } else {\n workingContent = [];\n }\n\n if (messagesModified >= 2 || isToolMessage || isEmptyString) {\n updatedMessages[i] = shallowCloneMessage(originalMessage);\n (updatedMessages[i] as MessageWithContent).content = workingContent;\n continue;\n }\n\n if (workingContent.length === 0) {\n continue;\n }\n\n let hasCacheableContent = false;\n for (const block of workingContent) {\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 updatedMessages[i] = shallowCloneMessage(originalMessage);\n (updatedMessages[i] as MessageWithContent).content = workingContent;\n continue;\n }\n\n let inserted = false;\n for (let j = workingContent.length - 1; j >= 0; j--) {\n const block = workingContent[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 workingContent.splice(j + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n workingContent.push({\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n }\n\n updatedMessages[i] = createNewMessage(originalMessage, workingContent);\n messagesModified++;\n }\n\n return updatedMessages;\n}\n"],"names":["HumanMessage","AIMessage","SystemMessage","ToolMessage","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 * Deep clones a message's content to prevent mutation of the original.\n */\nfunction deepCloneContent<T extends string | MessageContentComplex[]>(\n content: T\n): T {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content.map((block) => ({ ...block })) as T;\n }\n return content;\n}\n\n/**\n * Clones a message with deep-cloned content, explicitly excluding LangChain\n * serialization metadata to prevent coercion issues.\n */\nfunction cloneMessage<T extends MessageWithContent>(\n message: T,\n content: string | MessageContentComplex[]\n): T {\n const {\n lc_kwargs: _lc_kwargs,\n lc_serializable: _lc_serializable,\n lc_namespace: _lc_namespace,\n ...rest\n } = message as T & {\n lc_kwargs?: unknown;\n lc_serializable?: unknown;\n lc_namespace?: unknown;\n };\n\n const cloned = { ...rest, content } as T;\n\n // LangChain messages don't have a direct 'role' property - derive it from getType()\n if (\n 'getType' in message &&\n typeof message.getType === 'function' &&\n !('role' in cloned)\n ) {\n const msgType = (message as unknown as BaseMessage).getType();\n const roleMap: Record<string, string> = {\n human: 'user',\n ai: 'assistant',\n system: 'system',\n tool: 'tool',\n };\n (cloned as Record<string, unknown>).role = roleMap[msgType] || msgType;\n }\n\n return cloned;\n}\n\n/**\n * Checks if a message's content needs cache control stripping.\n * Returns true if content has cachePoint blocks or cache_control fields.\n */\nfunction needsCacheStripping(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n const block = content[i];\n if (isCachePoint(block)) return true;\n if ('cache_control' in block) return true;\n }\n return false;\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 * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new 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: T[] = [...messages];\n let userMessagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n const isUserMessage =\n ('getType' in originalMessage && originalMessage.getType() === 'human') ||\n ('role' in originalMessage && originalMessage.role === 'user');\n\n const hasArrayContent = Array.isArray(content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(content as MessageContentComplex[]);\n const needsCacheAdd =\n userMessagesModified < 2 &&\n isUserMessage &&\n (typeof content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n let workingContent: MessageContentComplex[];\n\n if (hasArrayContent) {\n workingContent = deepCloneContent(\n content as MessageContentComplex[]\n ).filter((block) => !isCachePoint(block as MessageContentComplex));\n\n for (let j = 0; j < workingContent.length; j++) {\n const block = workingContent[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n } else if (typeof content === 'string') {\n workingContent = [\n { type: 'text', text: content },\n ] as MessageContentComplex[];\n } else {\n workingContent = [];\n }\n\n if (userMessagesModified >= 2 || !isUserMessage) {\n updatedMessages[i] = cloneMessage(\n originalMessage as MessageWithContent,\n workingContent\n ) as T;\n continue;\n }\n\n for (let j = workingContent.length - 1; j >= 0; j--) {\n const contentPart = workingContent[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 updatedMessages[i] = cloneMessage(\n originalMessage as MessageWithContent,\n workingContent\n ) as T;\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 * Checks if a message's content has Anthropic cache_control fields.\n */\nfunction hasAnthropicCacheControl(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if ('cache_control' in content[i]) return true;\n }\n return false;\n}\n\n/**\n * Removes all Anthropic cache_control fields from messages\n * Used when switching from Anthropic to Bedrock provider\n * Returns a new array - only clones messages that require modification.\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: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasAnthropicCacheControl(content)) {\n continue;\n }\n\n const clonedContent = deepCloneContent(content);\n for (let j = 0; j < clonedContent.length; j++) {\n const block = clonedContent[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n updatedMessages[i] = cloneMessage(originalMessage, clonedContent);\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a message's content has Bedrock cachePoint blocks.\n */\nfunction hasBedrockCachePoint(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if (isCachePoint(content[i])) return true;\n }\n return false;\n}\n\n/**\n * Removes all Bedrock cachePoint blocks from messages\n * Used when switching from Bedrock to Anthropic provider\n * Returns a new array - only clones messages that require modification.\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: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasBedrockCachePoint(content)) {\n continue;\n }\n\n const clonedContent = deepCloneContent(content).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n );\n updatedMessages[i] = cloneMessage(originalMessage, clonedContent);\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 * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new 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];\n let messagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isToolMessage =\n 'getType' in originalMessage &&\n typeof originalMessage.getType === 'function' &&\n originalMessage.getType() === 'tool';\n\n const content = originalMessage.content;\n const hasArrayContent = Array.isArray(content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(content as MessageContentComplex[]);\n const isEmptyString = typeof content === 'string' && content === '';\n const needsCacheAdd =\n messagesModified < 2 &&\n !isToolMessage &&\n !isEmptyString &&\n (typeof content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n let workingContent: MessageContentComplex[];\n\n if (hasArrayContent) {\n workingContent = deepCloneContent(\n content as MessageContentComplex[]\n ).filter((block) => !isCachePoint(block));\n\n for (let j = 0; j < workingContent.length; j++) {\n const block = workingContent[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n } else if (typeof content === 'string') {\n workingContent = [{ type: ContentTypes.TEXT, text: content }];\n } else {\n workingContent = [];\n }\n\n if (messagesModified >= 2 || isToolMessage || isEmptyString) {\n updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n continue;\n }\n\n if (workingContent.length === 0) {\n continue;\n }\n\n let hasCacheableContent = false;\n for (const block of workingContent) {\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 updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n continue;\n }\n\n let inserted = false;\n for (let j = workingContent.length - 1; j >= 0; j--) {\n const block = workingContent[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 workingContent.splice(j + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n workingContent.push({\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n }\n\n updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n messagesModified++;\n }\n\n return updatedMessages;\n}\n"],"names":["ContentTypes"],"mappings":"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"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ToolMessage, SystemMessage, AIMessage, HumanMessage } from '@langchain/core/messages';
|
|
2
1
|
import { ContentTypes } from '../common/enum.mjs';
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -14,61 +13,24 @@ function deepCloneContent(content) {
|
|
|
14
13
|
return content;
|
|
15
14
|
}
|
|
16
15
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* Clones a message with deep-cloned content, explicitly excluding LangChain
|
|
17
|
+
* serialization metadata to prevent coercion issues.
|
|
19
18
|
*/
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const msgType = baseMsg.getType();
|
|
34
|
-
const baseFields = {
|
|
35
|
-
content,
|
|
36
|
-
name: baseMsg.name,
|
|
37
|
-
additional_kwargs: { ...baseMsg.additional_kwargs },
|
|
38
|
-
response_metadata: { ...baseMsg.response_metadata },
|
|
39
|
-
id: baseMsg.id,
|
|
19
|
+
function cloneMessage(message, content) {
|
|
20
|
+
const { lc_kwargs: _lc_kwargs, lc_serializable: _lc_serializable, lc_namespace: _lc_namespace, ...rest } = message;
|
|
21
|
+
const cloned = { ...rest, content };
|
|
22
|
+
// LangChain messages don't have a direct 'role' property - derive it from getType()
|
|
23
|
+
if ('getType' in message &&
|
|
24
|
+
typeof message.getType === 'function' &&
|
|
25
|
+
!('role' in cloned)) {
|
|
26
|
+
const msgType = message.getType();
|
|
27
|
+
const roleMap = {
|
|
28
|
+
human: 'user',
|
|
29
|
+
ai: 'assistant',
|
|
30
|
+
system: 'system',
|
|
31
|
+
tool: 'tool',
|
|
40
32
|
};
|
|
41
|
-
|
|
42
|
-
case 'human':
|
|
43
|
-
return new HumanMessage(baseFields);
|
|
44
|
-
case 'ai': {
|
|
45
|
-
const aiMsg = baseMsg;
|
|
46
|
-
return new AIMessage({
|
|
47
|
-
...baseFields,
|
|
48
|
-
tool_calls: aiMsg.tool_calls ? [...aiMsg.tool_calls] : [],
|
|
49
|
-
invalid_tool_calls: aiMsg.invalid_tool_calls
|
|
50
|
-
? [...aiMsg.invalid_tool_calls]
|
|
51
|
-
: [],
|
|
52
|
-
usage_metadata: aiMsg.usage_metadata,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
case 'system':
|
|
56
|
-
return new SystemMessage(baseFields);
|
|
57
|
-
case 'tool': {
|
|
58
|
-
const toolMsg = baseMsg;
|
|
59
|
-
return new ToolMessage({
|
|
60
|
-
...baseFields,
|
|
61
|
-
tool_call_id: toolMsg.tool_call_id,
|
|
62
|
-
status: toolMsg.status,
|
|
63
|
-
artifact: toolMsg.artifact,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
const cloned = { ...message, content };
|
|
69
|
-
const lcKwargs = cloned.lc_kwargs;
|
|
70
|
-
if (lcKwargs != null) {
|
|
71
|
-
cloned.lc_kwargs = { ...lcKwargs, content };
|
|
33
|
+
cloned.role = roleMap[msgType] || msgType;
|
|
72
34
|
}
|
|
73
35
|
return cloned;
|
|
74
36
|
}
|
|
@@ -103,53 +65,51 @@ function addCacheControl(messages) {
|
|
|
103
65
|
let userMessagesModified = 0;
|
|
104
66
|
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
105
67
|
const originalMessage = updatedMessages[i];
|
|
68
|
+
const content = originalMessage.content;
|
|
106
69
|
const isUserMessage = ('getType' in originalMessage && originalMessage.getType() === 'human') ||
|
|
107
70
|
('role' in originalMessage && originalMessage.role === 'user');
|
|
108
|
-
const hasArrayContent = Array.isArray(
|
|
71
|
+
const hasArrayContent = Array.isArray(content);
|
|
109
72
|
const needsStripping = hasArrayContent &&
|
|
110
|
-
needsCacheStripping(
|
|
73
|
+
needsCacheStripping(content);
|
|
111
74
|
const needsCacheAdd = userMessagesModified < 2 &&
|
|
112
75
|
isUserMessage &&
|
|
113
|
-
(typeof
|
|
76
|
+
(typeof content === 'string' || hasArrayContent);
|
|
114
77
|
if (!needsStripping && !needsCacheAdd) {
|
|
115
78
|
continue;
|
|
116
79
|
}
|
|
117
|
-
|
|
118
|
-
updatedMessages[i] = message;
|
|
80
|
+
let workingContent;
|
|
119
81
|
if (hasArrayContent) {
|
|
120
|
-
|
|
121
|
-
for (let j = 0; j <
|
|
122
|
-
const block =
|
|
82
|
+
workingContent = deepCloneContent(content).filter((block) => !isCachePoint(block));
|
|
83
|
+
for (let j = 0; j < workingContent.length; j++) {
|
|
84
|
+
const block = workingContent[j];
|
|
123
85
|
if ('cache_control' in block) {
|
|
124
86
|
delete block.cache_control;
|
|
125
87
|
}
|
|
126
88
|
}
|
|
127
89
|
}
|
|
90
|
+
else if (typeof content === 'string') {
|
|
91
|
+
workingContent = [
|
|
92
|
+
{ type: 'text', text: content },
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
workingContent = [];
|
|
97
|
+
}
|
|
128
98
|
if (userMessagesModified >= 2 || !isUserMessage) {
|
|
99
|
+
updatedMessages[i] = cloneMessage(originalMessage, workingContent);
|
|
129
100
|
continue;
|
|
130
101
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
userMessagesModified++;
|
|
140
|
-
}
|
|
141
|
-
else if (Array.isArray(message.content)) {
|
|
142
|
-
for (let j = message.content.length - 1; j >= 0; j--) {
|
|
143
|
-
const contentPart = message.content[j];
|
|
144
|
-
if ('type' in contentPart && contentPart.type === 'text') {
|
|
145
|
-
contentPart.cache_control = {
|
|
146
|
-
type: 'ephemeral',
|
|
147
|
-
};
|
|
148
|
-
userMessagesModified++;
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
102
|
+
for (let j = workingContent.length - 1; j >= 0; j--) {
|
|
103
|
+
const contentPart = workingContent[j];
|
|
104
|
+
if ('type' in contentPart && contentPart.type === 'text') {
|
|
105
|
+
contentPart.cache_control = {
|
|
106
|
+
type: 'ephemeral',
|
|
107
|
+
};
|
|
108
|
+
userMessagesModified++;
|
|
109
|
+
break;
|
|
151
110
|
}
|
|
152
111
|
}
|
|
112
|
+
updatedMessages[i] = cloneMessage(originalMessage, workingContent);
|
|
153
113
|
}
|
|
154
114
|
return updatedMessages;
|
|
155
115
|
}
|
|
@@ -185,14 +145,14 @@ function stripAnthropicCacheControl(messages) {
|
|
|
185
145
|
if (!Array.isArray(content) || !hasAnthropicCacheControl(content)) {
|
|
186
146
|
continue;
|
|
187
147
|
}
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const block = message.content[j];
|
|
148
|
+
const clonedContent = deepCloneContent(content);
|
|
149
|
+
for (let j = 0; j < clonedContent.length; j++) {
|
|
150
|
+
const block = clonedContent[j];
|
|
192
151
|
if ('cache_control' in block) {
|
|
193
152
|
delete block.cache_control;
|
|
194
153
|
}
|
|
195
154
|
}
|
|
155
|
+
updatedMessages[i] = cloneMessage(originalMessage, clonedContent);
|
|
196
156
|
}
|
|
197
157
|
return updatedMessages;
|
|
198
158
|
}
|
|
@@ -222,9 +182,8 @@ function stripBedrockCacheControl(messages) {
|
|
|
222
182
|
if (!Array.isArray(content) || !hasBedrockCachePoint(content)) {
|
|
223
183
|
continue;
|
|
224
184
|
}
|
|
225
|
-
const
|
|
226
|
-
updatedMessages[i] =
|
|
227
|
-
message.content = message.content.filter((block) => !isCachePoint(block));
|
|
185
|
+
const clonedContent = deepCloneContent(content).filter((block) => !isCachePoint(block));
|
|
186
|
+
updatedMessages[i] = cloneMessage(originalMessage, clonedContent);
|
|
228
187
|
}
|
|
229
188
|
return updatedMessages;
|
|
230
189
|
}
|
|
@@ -279,8 +238,7 @@ function addBedrockCacheControl(messages) {
|
|
|
279
238
|
workingContent = [];
|
|
280
239
|
}
|
|
281
240
|
if (messagesModified >= 2 || isToolMessage || isEmptyString) {
|
|
282
|
-
updatedMessages[i] =
|
|
283
|
-
updatedMessages[i].content = workingContent;
|
|
241
|
+
updatedMessages[i] = cloneMessage(originalMessage, workingContent);
|
|
284
242
|
continue;
|
|
285
243
|
}
|
|
286
244
|
if (workingContent.length === 0) {
|
|
@@ -296,8 +254,7 @@ function addBedrockCacheControl(messages) {
|
|
|
296
254
|
}
|
|
297
255
|
}
|
|
298
256
|
if (!hasCacheableContent) {
|
|
299
|
-
updatedMessages[i] =
|
|
300
|
-
updatedMessages[i].content = workingContent;
|
|
257
|
+
updatedMessages[i] = cloneMessage(originalMessage, workingContent);
|
|
301
258
|
continue;
|
|
302
259
|
}
|
|
303
260
|
let inserted = false;
|
|
@@ -321,7 +278,7 @@ function addBedrockCacheControl(messages) {
|
|
|
321
278
|
cachePoint: { type: 'default' },
|
|
322
279
|
});
|
|
323
280
|
}
|
|
324
|
-
updatedMessages[i] =
|
|
281
|
+
updatedMessages[i] = cloneMessage(originalMessage, workingContent);
|
|
325
282
|
messagesModified++;
|
|
326
283
|
}
|
|
327
284
|
return updatedMessages;
|