@librechat/agents 3.0.774 → 3.0.775
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.
|
@@ -105,53 +105,60 @@ function addCacheControl(messages) {
|
|
|
105
105
|
let userMessagesModified = 0;
|
|
106
106
|
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
107
107
|
const originalMessage = updatedMessages[i];
|
|
108
|
+
const content = originalMessage.content;
|
|
108
109
|
const isUserMessage = ('getType' in originalMessage && originalMessage.getType() === 'human') ||
|
|
109
110
|
('role' in originalMessage && originalMessage.role === 'user');
|
|
110
|
-
const hasArrayContent = Array.isArray(
|
|
111
|
+
const hasArrayContent = Array.isArray(content);
|
|
111
112
|
const needsStripping = hasArrayContent &&
|
|
112
|
-
needsCacheStripping(
|
|
113
|
+
needsCacheStripping(content);
|
|
113
114
|
const needsCacheAdd = userMessagesModified < 2 &&
|
|
114
115
|
isUserMessage &&
|
|
115
|
-
(typeof
|
|
116
|
+
(typeof content === 'string' || hasArrayContent);
|
|
116
117
|
if (!needsStripping && !needsCacheAdd) {
|
|
117
118
|
continue;
|
|
118
119
|
}
|
|
119
|
-
|
|
120
|
-
updatedMessages[i] = message;
|
|
120
|
+
let workingContent;
|
|
121
121
|
if (hasArrayContent) {
|
|
122
|
-
|
|
123
|
-
for (let j = 0; j <
|
|
124
|
-
const block =
|
|
122
|
+
workingContent = deepCloneContent(content).filter((block) => !isCachePoint(block));
|
|
123
|
+
for (let j = 0; j < workingContent.length; j++) {
|
|
124
|
+
const block = workingContent[j];
|
|
125
125
|
if ('cache_control' in block) {
|
|
126
126
|
delete block.cache_control;
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
+
else if (typeof content === 'string') {
|
|
131
|
+
workingContent = [
|
|
132
|
+
{ type: 'text', text: content },
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
workingContent = [];
|
|
137
|
+
}
|
|
130
138
|
if (userMessagesModified >= 2 || !isUserMessage) {
|
|
139
|
+
updatedMessages[i] = shallowCloneMessage(originalMessage);
|
|
140
|
+
updatedMessages[i].content = workingContent;
|
|
131
141
|
continue;
|
|
132
142
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
}
|
|
143
|
+
let cacheAdded = false;
|
|
144
|
+
for (let j = workingContent.length - 1; j >= 0; j--) {
|
|
145
|
+
const contentPart = workingContent[j];
|
|
146
|
+
if ('type' in contentPart && contentPart.type === 'text') {
|
|
147
|
+
contentPart.cache_control = {
|
|
148
|
+
type: 'ephemeral',
|
|
149
|
+
};
|
|
150
|
+
cacheAdded = true;
|
|
151
|
+
userMessagesModified++;
|
|
152
|
+
break;
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
|
+
if (cacheAdded) {
|
|
156
|
+
updatedMessages[i] = createNewMessage(originalMessage, workingContent);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
updatedMessages[i] = shallowCloneMessage(originalMessage);
|
|
160
|
+
updatedMessages[i].content = workingContent;
|
|
161
|
+
}
|
|
155
162
|
}
|
|
156
163
|
return updatedMessages;
|
|
157
164
|
}
|
|
@@ -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":";;;;;AAgBA;;AAEG;AACH,SAAS,gBAAgB,CACvB,OAAU,EAAA;AAEV,IAAA,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;AAC/B,QAAA,OAAO,OAAO;;AAEhB,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AAC1B,QAAA,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,CAAM;;AAEpD,IAAA,OAAO,OAAO;AAChB;AAEA;;;AAGG;AACH,SAAS,mBAAmB,CAA+B,OAAU,EAAA;IACnE,OAAO;AACL,QAAA,GAAG,OAAO;QACV,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;KAC5C;AACR;AAEA;;;AAGG;AACH,SAAS,gBAAgB,CACvB,OAAU,EACV,OAAgC,EAAA;IAEhC,IAAI,SAAS,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU,EAAE;QACjE,MAAM,OAAO,GAAG,OAAiC;AACjD,QAAA,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE;AAEjC,QAAA,MAAM,UAAU,GAAG;YACjB,OAAO;YACP,IAAI,EAAE,OAAO,CAAC,IAAI;AAClB,YAAA,iBAAiB,EAAE,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE;AACnD,YAAA,iBAAiB,EAAE,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE;YACnD,EAAE,EAAE,OAAO,CAAC,EAAE;SACf;QAED,QAAQ,OAAO;AACf,YAAA,KAAK,OAAO;AACV,gBAAA,OAAO,IAAIA,qBAAY,CAAC,UAAU,CAAiB;YACrD,KAAK,IAAI,EAAE;gBACT,MAAM,KAAK,GAAG,OAAoB;gBAClC,OAAO,IAAIC,kBAAS,CAAC;AACnB,oBAAA,GAAG,UAAU;AACb,oBAAA,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE;oBACzD,kBAAkB,EAAE,KAAK,CAAC;AACxB,0BAAE,CAAC,GAAG,KAAK,CAAC,kBAAkB;AAC9B,0BAAE,EAAE;oBACN,cAAc,EAAE,KAAK,CAAC,cAAc;AACrC,iBAAA,CAAiB;;AAEpB,YAAA,KAAK,QAAQ;AACX,gBAAA,OAAO,IAAIC,sBAAa,CAAC,UAAU,CAAiB;YACtD,KAAK,MAAM,EAAE;gBACX,MAAM,OAAO,GAAG,OAAsB;gBACtC,OAAO,IAAIC,oBAAW,CAAC;AACrB,oBAAA,GAAG,UAAU;oBACb,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ;AAC3B,iBAAA,CAAiB;;;;IAOtB,MAAM,MAAM,GAAG,EAAE,GAAG,OAAO,EAAE,OAAO,EAAO;AAC3C,IAAA,MAAM,QAAQ,GAAI,MAAkC,CAAC,SAExC;AACb,IAAA,IAAI,QAAQ,IAAI,IAAI,EAAE;QACnB,MAAkC,CAAC,SAAS,GAAG,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE;;AAE1E,IAAA,OAAO,MAAM;AACf;AAEA;;;AAGG;AACH,SAAS,mBAAmB,CAAC,OAAgC,EAAA;AAC3D,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACvC,QAAA,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC;QACxB,IAAI,YAAY,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;QACpC,IAAI,eAAe,IAAI,KAAK;AAAE,YAAA,OAAO,IAAI;;AAE3C,IAAA,OAAO,KAAK;AACd;AAEA;;;;;;;;AAQG;AACG,SAAU,eAAe,CAC7B,QAAa,EAAA;AAEb,IAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;AACnD,QAAA,OAAO,QAAQ;;AAGjB,IAAA,MAAM,eAAe,GAAQ,CAAC,GAAG,QAAQ,CAAC;IAC1C,IAAI,oBAAoB,GAAG,CAAC;AAE5B,IAAA,KAAK,IAAI,CAAC,GAAG,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;AACpD,QAAA,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC;AAC1C,QAAA,MAAM,aAAa,GACjB,CAAC,SAAS,IAAI,eAAe,IAAI,eAAe,CAAC,OAAO,EAAE,KAAK,OAAO;aACrE,MAAM,IAAI,eAAe,IAAI,eAAe,CAAC,IAAI,KAAK,MAAM,CAAC;QAEhE,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC;QAC9D,MAAM,cAAc,GAClB,eAAe;AACf,YAAA,mBAAmB,CAAC,eAAe,CAAC,OAAkC,CAAC;AACzE,QAAA,MAAM,aAAa,GACjB,oBAAoB,GAAG,CAAC;YACxB,aAAa;aACZ,OAAO,eAAe,CAAC,OAAO,KAAK,QAAQ,IAAI,eAAe,CAAC;AAElE,QAAA,IAAI,CAAC,cAAc,IAAI,CAAC,aAAa,EAAE;YACrC;;AAGF,QAAA,MAAM,OAAO,GAAG,mBAAmB,CACjC,eAAqC,CACjC;AACN,QAAA,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO;QAE5B,IAAI,eAAe,EAAE;YACnB,OAAO,CAAC,OAAO,GAAI,OAAO,CAAC,OAAmC,CAAC,MAAM,CACnE,CAAC,KAAK,KAAK,CAAC,YAAY,CAAC,KAA8B,CAAC,CAC/B;AAE3B,YAAA,KACE,IAAI,CAAC,GAAG,CAAC,EACT,CAAC,GAAI,OAAO,CAAC,OAAmC,CAAC,MAAM,EACvD,CAAC,EAAE,EACH;gBACA,MAAM,KAAK,GAAI,OAAO,CAAC,OAAmC,CAAC,CAAC,CAG3D;AACD,gBAAA,IAAI,eAAe,IAAI,KAAK,EAAE;oBAC5B,OAAO,KAAK,CAAC,aAAa;;;;AAKhC,QAAA,IAAI,oBAAoB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YAC/C;;AAGF,QAAA,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE;YACvC,OAAO,CAAC,OAAO,GAAG;AAChB,gBAAA;AACE,oBAAA,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,OAAO,CAAC,OAAO;AACrB,oBAAA,aAAa,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;AACrC,iBAAA;aACF;AACD,YAAA,oBAAoB,EAAE;;aACjB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACzC,YAAA,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;gBACpD,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;gBACtC,IAAI,MAAM,IAAI,WAAW,IAAI,WAAW,CAAC,IAAI,KAAK,MAAM,EAAE;oBACvD,WAAwC,CAAC,aAAa,GAAG;AACxD,wBAAA,IAAI,EAAE,WAAW;qBAClB;AACD,oBAAA,oBAAoB,EAAE;oBACtB;;;;;AAMR,IAAA,OAAO,eAAe;AACxB;AAEA;;AAEG;AACH,SAAS,YAAY,CAAC,KAA4B,EAAA;IAChD,OAAO,YAAY,IAAI,KAAK,IAAI,EAAE,MAAM,IAAI,KAAK,CAAC;AACpD;AAEA;;AAEG;AACH,SAAS,wBAAwB,CAAC,OAAgC,EAAA;AAChE,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACvC,QAAA,IAAI,eAAe,IAAI,OAAO,CAAC,CAAC,CAAC;AAAE,YAAA,OAAO,IAAI;;AAEhD,IAAA,OAAO,KAAK;AACd;AAEA;;;;AAIG;AACG,SAAU,0BAA0B,CACxC,QAAa,EAAA;IAEb,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;AAC5B,QAAA,OAAO,QAAQ;;AAGjB,IAAA,MAAM,eAAe,GAAQ,CAAC,GAAG,QAAQ,CAAC;AAE1C,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC/C,QAAA,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC;AAC1C,QAAA,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO;AAEvC,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE;YACjE;;AAGF,QAAA,MAAM,OAAO,GAAG,mBAAmB,CAAC,eAAe,CAAC;AACpD,QAAA,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO;AAE5B,QAAA,KACE,IAAI,CAAC,GAAG,CAAC,EACT,CAAC,GAAI,OAAO,CAAC,OAAmC,CAAC,MAAM,EACvD,CAAC,EAAE,EACH;YACA,MAAM,KAAK,GAAI,OAAO,CAAC,OAAmC,CAAC,CAAC,CAG3D;AACD,YAAA,IAAI,eAAe,IAAI,KAAK,EAAE;gBAC5B,OAAO,KAAK,CAAC,aAAa;;;;AAKhC,IAAA,OAAO,eAAe;AACxB;AAEA;;AAEG;AACH,SAAS,oBAAoB,CAAC,OAAgC,EAAA;AAC5D,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACvC,QAAA,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAAE,YAAA,OAAO,IAAI;;AAE3C,IAAA,OAAO,KAAK;AACd;AAEA;;;;AAIG;AACG,SAAU,wBAAwB,CACtC,QAAa,EAAA;IAEb,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;AAC5B,QAAA,OAAO,QAAQ;;AAGjB,IAAA,MAAM,eAAe,GAAQ,CAAC,GAAG,QAAQ,CAAC;AAE1C,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC/C,QAAA,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC;AAC1C,QAAA,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO;AAEvC,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE;YAC7D;;AAGF,QAAA,MAAM,OAAO,GAAG,mBAAmB,CAAC,eAAe,CAAC;AACpD,QAAA,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO;QAE5B,OAAO,CAAC,OAAO,GAAI,OAAO,CAAC,OAAmC,CAAC,MAAM,CACnE,CAAC,KAAK,KAAK,CAAC,YAAY,CAAC,KAA8B,CAAC,CACvC;;AAGrB,IAAA,OAAO,eAAe;AACxB;AAEA;;;;;;;;;;AAUG;AACG,SAAU,sBAAsB,CAEpC,QAAa,EAAA;AACb,IAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;AACnD,QAAA,OAAO,QAAQ;;AAGjB,IAAA,MAAM,eAAe,GAAQ,CAAC,GAAG,QAAQ,CAAC;IAC1C,IAAI,gBAAgB,GAAG,CAAC;AAExB,IAAA,KAAK,IAAI,CAAC,GAAG,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;AACpD,QAAA,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC;AAC1C,QAAA,MAAM,aAAa,GACjB,SAAS,IAAI,eAAe;AAC5B,YAAA,OAAO,eAAe,CAAC,OAAO,KAAK,UAAU;AAC7C,YAAA,eAAe,CAAC,OAAO,EAAE,KAAK,MAAM;AAEtC,QAAA,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO;QACvC,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAC9C,MAAM,cAAc,GAClB,eAAe;YACf,mBAAmB,CAAC,OAAkC,CAAC;QACzD,MAAM,aAAa,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,EAAE;AACnE,QAAA,MAAM,aAAa,GACjB,gBAAgB,GAAG,CAAC;AACpB,YAAA,CAAC,aAAa;AACd,YAAA,CAAC,aAAa;AACd,aAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,eAAe,CAAC;AAElD,QAAA,IAAI,CAAC,cAAc,IAAI,CAAC,aAAa,EAAE;YACrC;;AAGF,QAAA,IAAI,cAAuC;QAE3C,IAAI,eAAe,EAAE;AACnB,YAAA,cAAc,GAAG,gBAAgB,CAC/B,OAAkC,CACnC,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;AAEzC,YAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC9C,gBAAA,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAA4B;AAC1D,gBAAA,IAAI,eAAe,IAAI,KAAK,EAAE;oBAC5B,OAAO,KAAK,CAAC,aAAa;;;;AAGzB,aAAA,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;AACtC,YAAA,cAAc,GAAG,CAAC,EAAE,IAAI,EAAEC,kBAAY,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;;aACxD;YACL,cAAc,GAAG,EAAE;;QAGrB,IAAI,gBAAgB,IAAI,CAAC,IAAI,aAAa,IAAI,aAAa,EAAE;YAC3D,eAAe,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,eAAe,CAAC;AACxD,YAAA,eAAe,CAAC,CAAC,CAAwB,CAAC,OAAO,GAAG,cAAc;YACnE;;AAGF,QAAA,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE;YAC/B;;QAGF,IAAI,mBAAmB,GAAG,KAAK;AAC/B,QAAA,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE;YAClC,IAAI,KAAK,CAAC,IAAI,KAAKA,kBAAY,CAAC,IAAI,EAAE;AACpC,gBAAA,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,EAAE,EAAE;oBACvD,mBAAmB,GAAG,IAAI;oBAC1B;;;;QAKN,IAAI,CAAC,mBAAmB,EAAE;YACxB,eAAe,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,eAAe,CAAC;AACxD,YAAA,eAAe,CAAC,CAAC,CAAwB,CAAC,OAAO,GAAG,cAAc;YACnE;;QAGF,IAAI,QAAQ,GAAG,KAAK;AACpB,QAAA,KAAK,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;AACnD,YAAA,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAA0B;AACxD,YAAA,MAAM,IAAI,GAAI,KAA2B,CAAC,IAAI;YAC9C,IAAI,IAAI,KAAKA,kBAAY,CAAC,IAAI,IAAI,IAAI,KAAK,MAAM,EAAE;AACjD,gBAAA,MAAM,IAAI,GAAI,KAA2B,CAAC,IAAI;gBAC9C,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,SAAS,EAAE;oBACrC;;gBAEF,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AAC9B,oBAAA,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;AACP,iBAAA,CAAC;gBAC3B,QAAQ,GAAG,IAAI;gBACf;;;QAGJ,IAAI,CAAC,QAAQ,EAAE;YACb,cAAc,CAAC,IAAI,CAAC;AAClB,gBAAA,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;AACP,aAAA,CAAC;;QAG7B,eAAe,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,eAAe,EAAE,cAAc,CAAC;AACtE,QAAA,gBAAgB,EAAE;;AAGpB,IAAA,OAAO,eAAe;AACxB;;;;;;;"}
|
|
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 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] = shallowCloneMessage(\n originalMessage as MessageWithContent\n ) as T;\n (updatedMessages[i] as MessageWithContent).content = workingContent;\n continue;\n }\n\n let cacheAdded = false;\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 cacheAdded = true;\n userMessagesModified++;\n break;\n }\n }\n\n if (cacheAdded) {\n updatedMessages[i] = createNewMessage(\n originalMessage as MessageWithContent,\n workingContent\n ) as T;\n } else {\n updatedMessages[i] = shallowCloneMessage(\n originalMessage as MessageWithContent\n ) as T;\n (updatedMessages[i] as MessageWithContent).content = workingContent;\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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"}
|
|
@@ -103,53 +103,60 @@ function addCacheControl(messages) {
|
|
|
103
103
|
let userMessagesModified = 0;
|
|
104
104
|
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
105
105
|
const originalMessage = updatedMessages[i];
|
|
106
|
+
const content = originalMessage.content;
|
|
106
107
|
const isUserMessage = ('getType' in originalMessage && originalMessage.getType() === 'human') ||
|
|
107
108
|
('role' in originalMessage && originalMessage.role === 'user');
|
|
108
|
-
const hasArrayContent = Array.isArray(
|
|
109
|
+
const hasArrayContent = Array.isArray(content);
|
|
109
110
|
const needsStripping = hasArrayContent &&
|
|
110
|
-
needsCacheStripping(
|
|
111
|
+
needsCacheStripping(content);
|
|
111
112
|
const needsCacheAdd = userMessagesModified < 2 &&
|
|
112
113
|
isUserMessage &&
|
|
113
|
-
(typeof
|
|
114
|
+
(typeof content === 'string' || hasArrayContent);
|
|
114
115
|
if (!needsStripping && !needsCacheAdd) {
|
|
115
116
|
continue;
|
|
116
117
|
}
|
|
117
|
-
|
|
118
|
-
updatedMessages[i] = message;
|
|
118
|
+
let workingContent;
|
|
119
119
|
if (hasArrayContent) {
|
|
120
|
-
|
|
121
|
-
for (let j = 0; j <
|
|
122
|
-
const block =
|
|
120
|
+
workingContent = deepCloneContent(content).filter((block) => !isCachePoint(block));
|
|
121
|
+
for (let j = 0; j < workingContent.length; j++) {
|
|
122
|
+
const block = workingContent[j];
|
|
123
123
|
if ('cache_control' in block) {
|
|
124
124
|
delete block.cache_control;
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
+
else if (typeof content === 'string') {
|
|
129
|
+
workingContent = [
|
|
130
|
+
{ type: 'text', text: content },
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
workingContent = [];
|
|
135
|
+
}
|
|
128
136
|
if (userMessagesModified >= 2 || !isUserMessage) {
|
|
137
|
+
updatedMessages[i] = shallowCloneMessage(originalMessage);
|
|
138
|
+
updatedMessages[i].content = workingContent;
|
|
129
139
|
continue;
|
|
130
140
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
}
|
|
141
|
+
let cacheAdded = false;
|
|
142
|
+
for (let j = workingContent.length - 1; j >= 0; j--) {
|
|
143
|
+
const contentPart = workingContent[j];
|
|
144
|
+
if ('type' in contentPart && contentPart.type === 'text') {
|
|
145
|
+
contentPart.cache_control = {
|
|
146
|
+
type: 'ephemeral',
|
|
147
|
+
};
|
|
148
|
+
cacheAdded = true;
|
|
149
|
+
userMessagesModified++;
|
|
150
|
+
break;
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
+
if (cacheAdded) {
|
|
154
|
+
updatedMessages[i] = createNewMessage(originalMessage, workingContent);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
updatedMessages[i] = shallowCloneMessage(originalMessage);
|
|
158
|
+
updatedMessages[i].content = workingContent;
|
|
159
|
+
}
|
|
153
160
|
}
|
|
154
161
|
return updatedMessages;
|
|
155
162
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.mjs","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":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cache.mjs","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 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] = shallowCloneMessage(\n originalMessage as MessageWithContent\n ) as T;\n (updatedMessages[i] as MessageWithContent).content = workingContent;\n continue;\n }\n\n let cacheAdded = false;\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 cacheAdded = true;\n userMessagesModified++;\n break;\n }\n }\n\n if (cacheAdded) {\n updatedMessages[i] = createNewMessage(\n originalMessage as MessageWithContent,\n workingContent\n ) as T;\n } else {\n updatedMessages[i] = shallowCloneMessage(\n originalMessage as MessageWithContent\n ) as T;\n (updatedMessages[i] as MessageWithContent).content = workingContent;\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":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -920,6 +920,57 @@ describe('Immutability - addCacheControl does not mutate original messages', ()
|
|
|
920
920
|
|
|
921
921
|
expect('cache_control' in originalFirstBlock).toBe(true);
|
|
922
922
|
});
|
|
923
|
+
|
|
924
|
+
it('should keep lc_kwargs.content in sync with content for LangChain messages', () => {
|
|
925
|
+
type LangChainLikeMsg = TestMsg & {
|
|
926
|
+
lc_kwargs?: { content?: MessageContentComplex[] };
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
const messagesWithLcKwargs: LangChainLikeMsg[] = [
|
|
930
|
+
{
|
|
931
|
+
role: 'user',
|
|
932
|
+
content: [{ type: ContentTypes.TEXT, text: 'First user message' }],
|
|
933
|
+
lc_kwargs: {
|
|
934
|
+
content: [{ type: ContentTypes.TEXT, text: 'First user message' }],
|
|
935
|
+
},
|
|
936
|
+
},
|
|
937
|
+
{
|
|
938
|
+
role: 'assistant',
|
|
939
|
+
content: [{ type: ContentTypes.TEXT, text: 'Assistant response' }],
|
|
940
|
+
lc_kwargs: {
|
|
941
|
+
content: [{ type: ContentTypes.TEXT, text: 'Assistant response' }],
|
|
942
|
+
},
|
|
943
|
+
},
|
|
944
|
+
{
|
|
945
|
+
role: 'user',
|
|
946
|
+
content: [{ type: ContentTypes.TEXT, text: 'Second user message' }],
|
|
947
|
+
lc_kwargs: {
|
|
948
|
+
content: [{ type: ContentTypes.TEXT, text: 'Second user message' }],
|
|
949
|
+
},
|
|
950
|
+
},
|
|
951
|
+
];
|
|
952
|
+
|
|
953
|
+
const result = addCacheControl(messagesWithLcKwargs as never);
|
|
954
|
+
|
|
955
|
+
const resultFirst = result[0] as LangChainLikeMsg;
|
|
956
|
+
const resultThird = result[2] as LangChainLikeMsg;
|
|
957
|
+
|
|
958
|
+
expect(resultFirst.content).toEqual(resultFirst.lc_kwargs?.content);
|
|
959
|
+
expect(resultThird.content).toEqual(resultThird.lc_kwargs?.content);
|
|
960
|
+
|
|
961
|
+
const firstContent = resultFirst.content as MessageContentComplex[];
|
|
962
|
+
const firstLcContent = resultFirst.lc_kwargs
|
|
963
|
+
?.content as MessageContentComplex[];
|
|
964
|
+
expect('cache_control' in firstContent[0]).toBe(true);
|
|
965
|
+
expect('cache_control' in firstLcContent[0]).toBe(true);
|
|
966
|
+
|
|
967
|
+
const originalFirst = messagesWithLcKwargs[0];
|
|
968
|
+
const originalContent = originalFirst.content as MessageContentComplex[];
|
|
969
|
+
const originalLcContent = originalFirst.lc_kwargs
|
|
970
|
+
?.content as MessageContentComplex[];
|
|
971
|
+
expect('cache_control' in originalContent[0]).toBe(false);
|
|
972
|
+
expect('cache_control' in originalLcContent[0]).toBe(false);
|
|
973
|
+
});
|
|
923
974
|
});
|
|
924
975
|
|
|
925
976
|
describe('Immutability - addBedrockCacheControl does not mutate original messages', () => {
|
package/src/messages/cache.ts
CHANGED
|
@@ -134,73 +134,77 @@ export function addCacheControl<T extends AnthropicMessage | BaseMessage>(
|
|
|
134
134
|
|
|
135
135
|
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
136
136
|
const originalMessage = updatedMessages[i];
|
|
137
|
+
const content = originalMessage.content;
|
|
137
138
|
const isUserMessage =
|
|
138
139
|
('getType' in originalMessage && originalMessage.getType() === 'human') ||
|
|
139
140
|
('role' in originalMessage && originalMessage.role === 'user');
|
|
140
141
|
|
|
141
|
-
const hasArrayContent = Array.isArray(
|
|
142
|
+
const hasArrayContent = Array.isArray(content);
|
|
142
143
|
const needsStripping =
|
|
143
144
|
hasArrayContent &&
|
|
144
|
-
needsCacheStripping(
|
|
145
|
+
needsCacheStripping(content as MessageContentComplex[]);
|
|
145
146
|
const needsCacheAdd =
|
|
146
147
|
userMessagesModified < 2 &&
|
|
147
148
|
isUserMessage &&
|
|
148
|
-
(typeof
|
|
149
|
+
(typeof content === 'string' || hasArrayContent);
|
|
149
150
|
|
|
150
151
|
if (!needsStripping && !needsCacheAdd) {
|
|
151
152
|
continue;
|
|
152
153
|
}
|
|
153
154
|
|
|
154
|
-
|
|
155
|
-
originalMessage as MessageWithContent
|
|
156
|
-
) as T;
|
|
157
|
-
updatedMessages[i] = message;
|
|
155
|
+
let workingContent: MessageContentComplex[];
|
|
158
156
|
|
|
159
157
|
if (hasArrayContent) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
) as
|
|
163
|
-
|
|
164
|
-
for (
|
|
165
|
-
|
|
166
|
-
j < (message.content as MessageContentComplex[]).length;
|
|
167
|
-
j++
|
|
168
|
-
) {
|
|
169
|
-
const block = (message.content as MessageContentComplex[])[j] as Record<
|
|
170
|
-
string,
|
|
171
|
-
unknown
|
|
172
|
-
>;
|
|
158
|
+
workingContent = deepCloneContent(
|
|
159
|
+
content as MessageContentComplex[]
|
|
160
|
+
).filter((block) => !isCachePoint(block as MessageContentComplex));
|
|
161
|
+
|
|
162
|
+
for (let j = 0; j < workingContent.length; j++) {
|
|
163
|
+
const block = workingContent[j] as Record<string, unknown>;
|
|
173
164
|
if ('cache_control' in block) {
|
|
174
165
|
delete block.cache_control;
|
|
175
166
|
}
|
|
176
167
|
}
|
|
168
|
+
} else if (typeof content === 'string') {
|
|
169
|
+
workingContent = [
|
|
170
|
+
{ type: 'text', text: content },
|
|
171
|
+
] as MessageContentComplex[];
|
|
172
|
+
} else {
|
|
173
|
+
workingContent = [];
|
|
177
174
|
}
|
|
178
175
|
|
|
179
176
|
if (userMessagesModified >= 2 || !isUserMessage) {
|
|
177
|
+
updatedMessages[i] = shallowCloneMessage(
|
|
178
|
+
originalMessage as MessageWithContent
|
|
179
|
+
) as T;
|
|
180
|
+
(updatedMessages[i] as MessageWithContent).content = workingContent;
|
|
180
181
|
continue;
|
|
181
182
|
}
|
|
182
183
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
for (let j = message.content.length - 1; j >= 0; j--) {
|
|
194
|
-
const contentPart = message.content[j];
|
|
195
|
-
if ('type' in contentPart && contentPart.type === 'text') {
|
|
196
|
-
(contentPart as Anthropic.TextBlockParam).cache_control = {
|
|
197
|
-
type: 'ephemeral',
|
|
198
|
-
};
|
|
199
|
-
userMessagesModified++;
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
184
|
+
let cacheAdded = false;
|
|
185
|
+
for (let j = workingContent.length - 1; j >= 0; j--) {
|
|
186
|
+
const contentPart = workingContent[j];
|
|
187
|
+
if ('type' in contentPart && contentPart.type === 'text') {
|
|
188
|
+
(contentPart as Anthropic.TextBlockParam).cache_control = {
|
|
189
|
+
type: 'ephemeral',
|
|
190
|
+
};
|
|
191
|
+
cacheAdded = true;
|
|
192
|
+
userMessagesModified++;
|
|
193
|
+
break;
|
|
202
194
|
}
|
|
203
195
|
}
|
|
196
|
+
|
|
197
|
+
if (cacheAdded) {
|
|
198
|
+
updatedMessages[i] = createNewMessage(
|
|
199
|
+
originalMessage as MessageWithContent,
|
|
200
|
+
workingContent
|
|
201
|
+
) as T;
|
|
202
|
+
} else {
|
|
203
|
+
updatedMessages[i] = shallowCloneMessage(
|
|
204
|
+
originalMessage as MessageWithContent
|
|
205
|
+
) as T;
|
|
206
|
+
(updatedMessages[i] as MessageWithContent).content = workingContent;
|
|
207
|
+
}
|
|
204
208
|
}
|
|
205
209
|
|
|
206
210
|
return updatedMessages;
|