@librechat/agents 3.0.19 → 3.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/events.cjs +34 -10
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/main.cjs +2 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +87 -14
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/esm/events.mjs +34 -10
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -1
- package/dist/esm/messages/cache.mjs +86 -15
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/types/events.d.ts +3 -1
- package/dist/types/messages/cache.d.ts +16 -0
- package/dist/types/types/stream.d.ts +1 -1
- package/package.json +1 -1
- package/src/events.ts +37 -15
- package/src/messages/cache.test.ts +499 -3
- package/src/messages/cache.ts +115 -25
- package/src/types/stream.ts +1 -1
package/src/messages/cache.ts
CHANGED
|
@@ -9,6 +9,9 @@ type MessageWithContent = {
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Anthropic API: Adds cache control to the appropriate user messages in the payload.
|
|
12
|
+
* Strips ALL existing cache control (both Anthropic and Bedrock formats) from all messages,
|
|
13
|
+
* then adds fresh cache control to the last 2 user messages in a single backward pass.
|
|
14
|
+
* This ensures we don't accumulate stale cache points across multiple turns.
|
|
12
15
|
* @param messages - The array of message objects.
|
|
13
16
|
* @returns - The updated array of message objects with cache control added.
|
|
14
17
|
*/
|
|
@@ -22,15 +25,26 @@ export function addCacheControl<T extends AnthropicMessage | BaseMessage>(
|
|
|
22
25
|
const updatedMessages = [...messages];
|
|
23
26
|
let userMessagesModified = 0;
|
|
24
27
|
|
|
25
|
-
for (
|
|
26
|
-
let i = updatedMessages.length - 1;
|
|
27
|
-
i >= 0 && userMessagesModified < 2;
|
|
28
|
-
i--
|
|
29
|
-
) {
|
|
28
|
+
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
30
29
|
const message = updatedMessages[i];
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
const isUserMessage =
|
|
31
|
+
('getType' in message && message.getType() === 'human') ||
|
|
32
|
+
('role' in message && message.role === 'user');
|
|
33
|
+
|
|
34
|
+
if (Array.isArray(message.content)) {
|
|
35
|
+
message.content = message.content.filter(
|
|
36
|
+
(block) => !isCachePoint(block as MessageContentComplex)
|
|
37
|
+
) as typeof message.content;
|
|
38
|
+
|
|
39
|
+
for (let j = 0; j < message.content.length; j++) {
|
|
40
|
+
const block = message.content[j] as Record<string, unknown>;
|
|
41
|
+
if ('cache_control' in block) {
|
|
42
|
+
delete block.cache_control;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (userMessagesModified >= 2 || !isUserMessage) {
|
|
34
48
|
continue;
|
|
35
49
|
}
|
|
36
50
|
|
|
@@ -60,10 +74,77 @@ export function addCacheControl<T extends AnthropicMessage | BaseMessage>(
|
|
|
60
74
|
return updatedMessages;
|
|
61
75
|
}
|
|
62
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Checks if a content block is a cache point
|
|
79
|
+
*/
|
|
80
|
+
function isCachePoint(block: MessageContentComplex): boolean {
|
|
81
|
+
return 'cachePoint' in block && !('type' in block);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Removes all Anthropic cache_control fields from messages
|
|
86
|
+
* Used when switching from Anthropic to Bedrock provider
|
|
87
|
+
*/
|
|
88
|
+
export function stripAnthropicCacheControl<T extends MessageWithContent>(
|
|
89
|
+
messages: T[]
|
|
90
|
+
): T[] {
|
|
91
|
+
if (!Array.isArray(messages)) {
|
|
92
|
+
return messages;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const updatedMessages = [...messages];
|
|
96
|
+
|
|
97
|
+
for (let i = 0; i < updatedMessages.length; i++) {
|
|
98
|
+
const message = updatedMessages[i];
|
|
99
|
+
const content = message.content;
|
|
100
|
+
|
|
101
|
+
if (Array.isArray(content)) {
|
|
102
|
+
for (let j = 0; j < content.length; j++) {
|
|
103
|
+
const block = content[j] as Record<string, unknown>;
|
|
104
|
+
if ('cache_control' in block) {
|
|
105
|
+
delete block.cache_control;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return updatedMessages;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Removes all Bedrock cachePoint blocks from messages
|
|
116
|
+
* Used when switching from Bedrock to Anthropic provider
|
|
117
|
+
*/
|
|
118
|
+
export function stripBedrockCacheControl<T extends MessageWithContent>(
|
|
119
|
+
messages: T[]
|
|
120
|
+
): T[] {
|
|
121
|
+
if (!Array.isArray(messages)) {
|
|
122
|
+
return messages;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const updatedMessages = [...messages];
|
|
126
|
+
|
|
127
|
+
for (let i = 0; i < updatedMessages.length; i++) {
|
|
128
|
+
const message = updatedMessages[i];
|
|
129
|
+
const content = message.content;
|
|
130
|
+
|
|
131
|
+
if (Array.isArray(content)) {
|
|
132
|
+
message.content = content.filter(
|
|
133
|
+
(block) => !isCachePoint(block as MessageContentComplex)
|
|
134
|
+
) as typeof content;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return updatedMessages;
|
|
139
|
+
}
|
|
140
|
+
|
|
63
141
|
/**
|
|
64
142
|
* Adds Bedrock Converse API cache points to the last two messages.
|
|
65
143
|
* Inserts `{ cachePoint: { type: 'default' } }` as a separate content block
|
|
66
144
|
* immediately after the last text block in each targeted message.
|
|
145
|
+
* Strips ALL existing cache control (both Bedrock and Anthropic formats) from all messages,
|
|
146
|
+
* then adds fresh cache points to the last 2 messages in a single backward pass.
|
|
147
|
+
* This ensures we don't accumulate stale cache points across multiple turns.
|
|
67
148
|
* @param messages - The array of message objects.
|
|
68
149
|
* @returns - The updated array of message objects with cache points added.
|
|
69
150
|
*/
|
|
@@ -77,23 +158,32 @@ export function addBedrockCacheControl<
|
|
|
77
158
|
const updatedMessages: T[] = messages.slice();
|
|
78
159
|
let messagesModified = 0;
|
|
79
160
|
|
|
80
|
-
for (
|
|
81
|
-
let i = updatedMessages.length - 1;
|
|
82
|
-
i >= 0 && messagesModified < 2;
|
|
83
|
-
i--
|
|
84
|
-
) {
|
|
161
|
+
for (let i = updatedMessages.length - 1; i >= 0; i--) {
|
|
85
162
|
const message = updatedMessages[i];
|
|
86
|
-
|
|
87
|
-
if (
|
|
163
|
+
const isToolMessage =
|
|
88
164
|
'getType' in message &&
|
|
89
165
|
typeof message.getType === 'function' &&
|
|
90
|
-
message.getType() === 'tool'
|
|
91
|
-
) {
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
166
|
+
message.getType() === 'tool';
|
|
94
167
|
|
|
95
168
|
const content = message.content;
|
|
96
169
|
|
|
170
|
+
if (Array.isArray(content)) {
|
|
171
|
+
message.content = content.filter(
|
|
172
|
+
(block) => !isCachePoint(block)
|
|
173
|
+
) as typeof content;
|
|
174
|
+
|
|
175
|
+
for (let j = 0; j < message.content.length; j++) {
|
|
176
|
+
const block = message.content[j] as Record<string, unknown>;
|
|
177
|
+
if ('cache_control' in block) {
|
|
178
|
+
delete block.cache_control;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (messagesModified >= 2 || isToolMessage) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
|
|
97
187
|
if (typeof content === 'string' && content === '') {
|
|
98
188
|
continue;
|
|
99
189
|
}
|
|
@@ -107,9 +197,9 @@ export function addBedrockCacheControl<
|
|
|
107
197
|
continue;
|
|
108
198
|
}
|
|
109
199
|
|
|
110
|
-
if (Array.isArray(content)) {
|
|
200
|
+
if (Array.isArray(message.content)) {
|
|
111
201
|
let hasCacheableContent = false;
|
|
112
|
-
for (const block of content) {
|
|
202
|
+
for (const block of message.content) {
|
|
113
203
|
if (block.type === ContentTypes.TEXT) {
|
|
114
204
|
if (typeof block.text === 'string' && block.text !== '') {
|
|
115
205
|
hasCacheableContent = true;
|
|
@@ -123,15 +213,15 @@ export function addBedrockCacheControl<
|
|
|
123
213
|
}
|
|
124
214
|
|
|
125
215
|
let inserted = false;
|
|
126
|
-
for (let j = content.length - 1; j >= 0; j--) {
|
|
127
|
-
const block = content[j] as MessageContentComplex;
|
|
216
|
+
for (let j = message.content.length - 1; j >= 0; j--) {
|
|
217
|
+
const block = message.content[j] as MessageContentComplex;
|
|
128
218
|
const type = (block as { type?: string }).type;
|
|
129
219
|
if (type === ContentTypes.TEXT || type === 'text') {
|
|
130
220
|
const text = (block as { text?: string }).text;
|
|
131
221
|
if (text === '' || text === undefined) {
|
|
132
222
|
continue;
|
|
133
223
|
}
|
|
134
|
-
content.splice(j + 1, 0, {
|
|
224
|
+
message.content.splice(j + 1, 0, {
|
|
135
225
|
cachePoint: { type: 'default' },
|
|
136
226
|
} as MessageContentComplex);
|
|
137
227
|
inserted = true;
|
|
@@ -139,7 +229,7 @@ export function addBedrockCacheControl<
|
|
|
139
229
|
}
|
|
140
230
|
}
|
|
141
231
|
if (!inserted) {
|
|
142
|
-
content.push({
|
|
232
|
+
message.content.push({
|
|
143
233
|
cachePoint: { type: 'default' },
|
|
144
234
|
} as MessageContentComplex);
|
|
145
235
|
}
|
package/src/types/stream.ts
CHANGED