@librechat/agents 2.3.1 → 2.3.3
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/graphs/Graph.cjs +6 -6
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/llm.cjs +7 -7
- package/dist/cjs/llm/anthropic/llm.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +6 -6
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +24 -24
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/fake.cjs.map +1 -1
- package/dist/cjs/llm/text.cjs.map +1 -1
- package/dist/cjs/main.cjs +3 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +6 -6
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +11 -9
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs +155 -205
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +7 -7
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +1 -1
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +3 -3
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +6 -6
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/llm/anthropic/llm.mjs +7 -7
- package/dist/esm/llm/anthropic/llm.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +6 -6
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +24 -24
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/fake.mjs.map +1 -1
- package/dist/esm/llm/text.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -1
- package/dist/esm/messages/core.mjs +6 -6
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +11 -9
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs +153 -206
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +7 -7
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +1 -1
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +3 -3
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/types/messages/format.d.ts +1 -2
- package/dist/types/messages/prune.d.ts +31 -2
- package/dist/types/types/stream.d.ts +2 -2
- package/dist/types/utils/tokens.d.ts +1 -1
- package/package.json +4 -3
- package/src/graphs/Graph.ts +8 -8
- package/src/llm/anthropic/llm.ts +7 -8
- package/src/llm/anthropic/types.ts +4 -4
- package/src/llm/anthropic/utils/message_inputs.ts +6 -6
- package/src/llm/anthropic/utils/message_outputs.ts +39 -39
- package/src/llm/fake.ts +2 -2
- package/src/llm/text.ts +1 -1
- package/src/messages/core.ts +9 -9
- package/src/messages/format.ts +43 -42
- package/src/messages/formatAgentMessages.test.ts +35 -35
- package/src/messages/formatAgentMessages.tools.test.ts +30 -30
- package/src/messages/prune.ts +182 -255
- package/src/messages/shiftIndexTokenCountMap.test.ts +18 -18
- package/src/mockStream.ts +1 -1
- package/src/run.ts +2 -2
- package/src/specs/prune.test.ts +89 -89
- package/src/specs/reasoning.test.ts +1 -1
- package/src/specs/thinking-prune.test.ts +265 -261
- package/src/specs/tool-error.test.ts +16 -17
- package/src/stream.ts +21 -18
- package/src/tools/ToolNode.ts +1 -1
- package/src/types/stream.ts +4 -3
- package/src/utils/tokens.ts +12 -12
|
@@ -362,14 +362,14 @@ describe('formatAgentMessages', () => {
|
|
|
362
362
|
{ role: 'user', content: 'Hello' },
|
|
363
363
|
{ role: 'assistant', content: 'Hi there!' },
|
|
364
364
|
];
|
|
365
|
-
|
|
365
|
+
|
|
366
366
|
const indexTokenCountMap = {
|
|
367
367
|
0: 5, // 5 tokens for "Hello"
|
|
368
368
|
1: 10, // 10 tokens for "Hi there!"
|
|
369
369
|
};
|
|
370
|
-
|
|
370
|
+
|
|
371
371
|
const result = formatAgentMessages(payload, indexTokenCountMap);
|
|
372
|
-
|
|
372
|
+
|
|
373
373
|
expect(result.messages).toHaveLength(2);
|
|
374
374
|
expect(result.indexTokenCountMap).toBeDefined();
|
|
375
375
|
expect(result.indexTokenCountMap?.[0]).toBe(5);
|
|
@@ -399,23 +399,23 @@ describe('formatAgentMessages', () => {
|
|
|
399
399
|
],
|
|
400
400
|
},
|
|
401
401
|
];
|
|
402
|
-
|
|
402
|
+
|
|
403
403
|
const indexTokenCountMap = {
|
|
404
404
|
0: 10, // 10 tokens for "What's the weather?"
|
|
405
405
|
1: 50, // 50 tokens for the assistant message with tool call
|
|
406
406
|
};
|
|
407
|
-
|
|
407
|
+
|
|
408
408
|
const result = formatAgentMessages(payload, indexTokenCountMap);
|
|
409
|
-
|
|
409
|
+
|
|
410
410
|
// The original message at index 1 should be split into two messages
|
|
411
411
|
expect(result.messages).toHaveLength(3);
|
|
412
412
|
expect(result.indexTokenCountMap).toBeDefined();
|
|
413
413
|
expect(result.indexTokenCountMap?.[0]).toBe(10); // User message stays the same
|
|
414
|
-
|
|
414
|
+
|
|
415
415
|
// The assistant message tokens should be distributed across the resulting messages
|
|
416
416
|
const totalAssistantTokens = Object.values(result.indexTokenCountMap || {})
|
|
417
417
|
.reduce((sum, count) => sum + count, 0) - 10; // Subtract user message tokens
|
|
418
|
-
|
|
418
|
+
|
|
419
419
|
expect(totalAssistantTokens).toBe(50); // Should match the original token count
|
|
420
420
|
});
|
|
421
421
|
|
|
@@ -460,23 +460,23 @@ describe('formatAgentMessages', () => {
|
|
|
460
460
|
],
|
|
461
461
|
},
|
|
462
462
|
];
|
|
463
|
-
|
|
463
|
+
|
|
464
464
|
const indexTokenCountMap = {
|
|
465
465
|
0: 100, // 100 tokens for the complex assistant message
|
|
466
466
|
};
|
|
467
|
-
|
|
467
|
+
|
|
468
468
|
const result = formatAgentMessages(payload, indexTokenCountMap);
|
|
469
|
-
|
|
469
|
+
|
|
470
470
|
// One message expands to 5 messages (2 tool calls + text before, between, and after)
|
|
471
471
|
expect(result.messages).toHaveLength(5);
|
|
472
472
|
expect(result.indexTokenCountMap).toBeDefined();
|
|
473
|
-
|
|
473
|
+
|
|
474
474
|
// The sum of all token counts should equal the original
|
|
475
475
|
const totalTokens = Object.values(result.indexTokenCountMap || {})
|
|
476
476
|
.reduce((sum, count) => sum + count, 0);
|
|
477
|
-
|
|
477
|
+
|
|
478
478
|
expect(totalTokens).toBe(100);
|
|
479
|
-
|
|
479
|
+
|
|
480
480
|
// Check that each resulting message has a token count
|
|
481
481
|
for (let i = 0; i < result.messages.length; i++) {
|
|
482
482
|
expect(result.indexTokenCountMap?.[i]).toBeDefined();
|
|
@@ -495,17 +495,17 @@ describe('formatAgentMessages', () => {
|
|
|
495
495
|
],
|
|
496
496
|
},
|
|
497
497
|
];
|
|
498
|
-
|
|
498
|
+
|
|
499
499
|
const indexTokenCountMap = {
|
|
500
500
|
0: 60, // 60 tokens for the message with filtered content
|
|
501
501
|
};
|
|
502
|
-
|
|
502
|
+
|
|
503
503
|
const result = formatAgentMessages(payload, indexTokenCountMap);
|
|
504
|
-
|
|
504
|
+
|
|
505
505
|
// Only one message should remain after filtering
|
|
506
506
|
expect(result.messages).toHaveLength(1);
|
|
507
507
|
expect(result.indexTokenCountMap).toBeDefined();
|
|
508
|
-
|
|
508
|
+
|
|
509
509
|
// All tokens should be assigned to the remaining message
|
|
510
510
|
expect(result.indexTokenCountMap?.[0]).toBe(60);
|
|
511
511
|
});
|
|
@@ -522,17 +522,17 @@ describe('formatAgentMessages', () => {
|
|
|
522
522
|
],
|
|
523
523
|
},
|
|
524
524
|
];
|
|
525
|
-
|
|
525
|
+
|
|
526
526
|
const indexTokenCountMap = {
|
|
527
527
|
0: 40, // 40 tokens for the message with filtered content
|
|
528
528
|
};
|
|
529
|
-
|
|
529
|
+
|
|
530
530
|
const result = formatAgentMessages(payload, indexTokenCountMap);
|
|
531
|
-
|
|
531
|
+
|
|
532
532
|
// No messages should remain after filtering
|
|
533
533
|
expect(result.messages).toHaveLength(0);
|
|
534
534
|
expect(result.indexTokenCountMap).toBeDefined();
|
|
535
|
-
|
|
535
|
+
|
|
536
536
|
// The token count map should be empty since there are no messages
|
|
537
537
|
expect(Object.keys(result.indexTokenCountMap || {})).toHaveLength(0);
|
|
538
538
|
});
|
|
@@ -561,29 +561,29 @@ describe('formatAgentMessages', () => {
|
|
|
561
561
|
],
|
|
562
562
|
},
|
|
563
563
|
];
|
|
564
|
-
|
|
564
|
+
|
|
565
565
|
const indexTokenCountMap = {
|
|
566
566
|
0: 15, // 15 tokens for the user message
|
|
567
567
|
1: 45, // 45 tokens for the assistant message with tool call
|
|
568
568
|
};
|
|
569
|
-
|
|
569
|
+
|
|
570
570
|
const result = formatAgentMessages(payload, indexTokenCountMap);
|
|
571
|
-
|
|
571
|
+
|
|
572
572
|
// 2 input messages become 3 output messages (user + assistant + tool)
|
|
573
573
|
expect(payload).toHaveLength(2);
|
|
574
574
|
expect(result.messages).toHaveLength(3);
|
|
575
575
|
expect(result.indexTokenCountMap).toBeDefined();
|
|
576
576
|
expect(Object.keys(result.indexTokenCountMap ?? {}).length).toBe(3);
|
|
577
|
-
|
|
577
|
+
|
|
578
578
|
// Check message types
|
|
579
579
|
expect(result.messages[0]).toBeInstanceOf(HumanMessage);
|
|
580
580
|
expect(result.messages[1]).toBeInstanceOf(AIMessage);
|
|
581
581
|
expect(result.messages[2]).toBeInstanceOf(ToolMessage);
|
|
582
|
-
|
|
582
|
+
|
|
583
583
|
// The sum of all token counts should equal the original total
|
|
584
584
|
const totalTokens = Object.values(result.indexTokenCountMap || {})
|
|
585
585
|
.reduce((sum, count) => sum + count, 0);
|
|
586
|
-
|
|
586
|
+
|
|
587
587
|
expect(totalTokens).toBe(60); // 15 + 45
|
|
588
588
|
});
|
|
589
589
|
|
|
@@ -600,30 +600,30 @@ describe('formatAgentMessages', () => {
|
|
|
600
600
|
],
|
|
601
601
|
},
|
|
602
602
|
];
|
|
603
|
-
|
|
603
|
+
|
|
604
604
|
const indexTokenCountMap = {
|
|
605
605
|
0: 10, // 10 tokens for the user message
|
|
606
606
|
1: 30, // 30 tokens for the assistant message that will be filtered out
|
|
607
607
|
};
|
|
608
|
-
|
|
608
|
+
|
|
609
609
|
const result = formatAgentMessages(payload, indexTokenCountMap);
|
|
610
|
-
|
|
610
|
+
|
|
611
611
|
// 2 input messages become 1 output message (only the user message remains)
|
|
612
612
|
expect(payload).toHaveLength(2);
|
|
613
613
|
expect(result.messages).toHaveLength(1);
|
|
614
614
|
expect(result.indexTokenCountMap).toBeDefined();
|
|
615
615
|
expect(Object.keys(result.indexTokenCountMap ?? {}).length).toBe(1);
|
|
616
|
-
|
|
616
|
+
|
|
617
617
|
// Check message type
|
|
618
618
|
expect(result.messages[0]).toBeInstanceOf(HumanMessage);
|
|
619
|
-
|
|
619
|
+
|
|
620
620
|
// Only the user message tokens should remain
|
|
621
621
|
expect(result.indexTokenCountMap?.[0]).toBe(10);
|
|
622
|
-
|
|
622
|
+
|
|
623
623
|
// The total tokens should be just the user message tokens
|
|
624
624
|
const totalTokens = Object.values(result.indexTokenCountMap || {})
|
|
625
625
|
.reduce((sum, count) => sum + count, 0);
|
|
626
|
-
|
|
626
|
+
|
|
627
627
|
expect(totalTokens).toBe(10);
|
|
628
628
|
});
|
|
629
629
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HumanMessage, AIMessage,
|
|
1
|
+
import { HumanMessage, AIMessage, ToolMessage } from '@langchain/core/messages';
|
|
2
2
|
import type { TPayload } from '@/types';
|
|
3
3
|
import { formatAgentMessages } from './format';
|
|
4
4
|
import { ContentTypes } from '@/common';
|
|
@@ -27,9 +27,9 @@ describe('formatAgentMessages with tools parameter', () => {
|
|
|
27
27
|
],
|
|
28
28
|
},
|
|
29
29
|
];
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
const result = formatAgentMessages(payload);
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
expect(result.messages).toHaveLength(3);
|
|
34
34
|
expect(result.messages[0]).toBeInstanceOf(HumanMessage);
|
|
35
35
|
expect(result.messages[1]).toBeInstanceOf(AIMessage);
|
|
@@ -61,17 +61,17 @@ describe('formatAgentMessages with tools parameter', () => {
|
|
|
61
61
|
],
|
|
62
62
|
},
|
|
63
63
|
];
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
// Provide an empty set of allowed tools
|
|
66
66
|
const allowedTools = new Set<string>();
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
const result = formatAgentMessages(payload, undefined, allowedTools);
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
// Should convert to a single AIMessage with string content
|
|
71
71
|
expect(result.messages).toHaveLength(2);
|
|
72
72
|
expect(result.messages[0]).toBeInstanceOf(HumanMessage);
|
|
73
73
|
expect(result.messages[1]).toBeInstanceOf(AIMessage);
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
// The content should be a string representation of both messages
|
|
76
76
|
expect(typeof result.messages[1].content).toBe('string');
|
|
77
77
|
expect(result.messages[1].content).toEqual('AI: Let me check the weather for you.\nTool: check_weather, Sunny, 75°F');
|
|
@@ -100,17 +100,17 @@ describe('formatAgentMessages with tools parameter', () => {
|
|
|
100
100
|
],
|
|
101
101
|
},
|
|
102
102
|
];
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
// Provide a set of allowed tools that doesn't include 'check_weather'
|
|
105
105
|
const allowedTools = new Set(['search', 'calculator']);
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
const result = formatAgentMessages(payload, undefined, allowedTools);
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
// Should convert to a single AIMessage with string content
|
|
110
110
|
expect(result.messages).toHaveLength(2);
|
|
111
111
|
expect(result.messages[0]).toBeInstanceOf(HumanMessage);
|
|
112
112
|
expect(result.messages[1]).toBeInstanceOf(AIMessage);
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
// The content should be a string representation of both messages
|
|
115
115
|
expect(typeof result.messages[1].content).toBe('string');
|
|
116
116
|
expect(result.messages[1].content).toEqual('AI: Let me check the weather for you.\nTool: check_weather, Sunny, 75°F');
|
|
@@ -139,12 +139,12 @@ describe('formatAgentMessages with tools parameter', () => {
|
|
|
139
139
|
],
|
|
140
140
|
},
|
|
141
141
|
];
|
|
142
|
-
|
|
142
|
+
|
|
143
143
|
// Provide a set of allowed tools that includes 'check_weather'
|
|
144
144
|
const allowedTools = new Set(['check_weather', 'search']);
|
|
145
|
-
|
|
145
|
+
|
|
146
146
|
const result = formatAgentMessages(payload, undefined, allowedTools);
|
|
147
|
-
|
|
147
|
+
|
|
148
148
|
// Should keep the original structure
|
|
149
149
|
expect(result.messages).toHaveLength(3);
|
|
150
150
|
expect(result.messages[0]).toBeInstanceOf(HumanMessage);
|
|
@@ -189,17 +189,17 @@ describe('formatAgentMessages with tools parameter', () => {
|
|
|
189
189
|
],
|
|
190
190
|
},
|
|
191
191
|
];
|
|
192
|
-
|
|
192
|
+
|
|
193
193
|
// Allow calculator but not check_weather
|
|
194
194
|
const allowedTools = new Set(['calculator', 'search']);
|
|
195
|
-
|
|
195
|
+
|
|
196
196
|
const result = formatAgentMessages(payload, undefined, allowedTools);
|
|
197
|
-
|
|
197
|
+
|
|
198
198
|
// Should convert the entire sequence to a single AIMessage
|
|
199
199
|
expect(result.messages).toHaveLength(2);
|
|
200
200
|
expect(result.messages[0]).toBeInstanceOf(HumanMessage);
|
|
201
201
|
expect(result.messages[1]).toBeInstanceOf(AIMessage);
|
|
202
|
-
|
|
202
|
+
|
|
203
203
|
// The content should include all parts
|
|
204
204
|
expect(typeof result.messages[1].content).toBe('string');
|
|
205
205
|
expect(result.messages[1].content).toContain('Let me check the weather first.');
|
|
@@ -231,24 +231,24 @@ describe('formatAgentMessages with tools parameter', () => {
|
|
|
231
231
|
],
|
|
232
232
|
},
|
|
233
233
|
];
|
|
234
|
-
|
|
234
|
+
|
|
235
235
|
const indexTokenCountMap = {
|
|
236
236
|
0: 10, // 10 tokens for user message
|
|
237
237
|
1: 40, // 40 tokens for assistant message with tool call
|
|
238
238
|
};
|
|
239
|
-
|
|
239
|
+
|
|
240
240
|
// Provide a set of allowed tools that doesn't include 'check_weather'
|
|
241
241
|
const allowedTools = new Set(['search', 'calculator']);
|
|
242
|
-
|
|
242
|
+
|
|
243
243
|
const result = formatAgentMessages(payload, indexTokenCountMap, allowedTools);
|
|
244
|
-
|
|
244
|
+
|
|
245
245
|
// Should have 2 messages and 2 entries in the token count map
|
|
246
246
|
expect(result.messages).toHaveLength(2);
|
|
247
247
|
expect(Object.keys(result.indexTokenCountMap || {}).length).toBe(2);
|
|
248
|
-
|
|
248
|
+
|
|
249
249
|
// User message token count should be unchanged
|
|
250
250
|
expect(result.indexTokenCountMap?.[0]).toBe(10);
|
|
251
|
-
|
|
251
|
+
|
|
252
252
|
// All assistant message tokens should be assigned to the single AIMessage
|
|
253
253
|
expect(result.indexTokenCountMap?.[1]).toBe(40);
|
|
254
254
|
});
|
|
@@ -315,27 +315,27 @@ describe('formatAgentMessages with tools parameter', () => {
|
|
|
315
315
|
},
|
|
316
316
|
{ role: 'assistant', content: 'Here\'s your answer based on all that information.' },
|
|
317
317
|
];
|
|
318
|
-
|
|
318
|
+
|
|
319
319
|
// Allow search and calculator but not check_weather
|
|
320
320
|
const allowedTools = new Set(['search', 'calculator']);
|
|
321
|
-
|
|
321
|
+
|
|
322
322
|
const result = formatAgentMessages(payload, undefined, allowedTools);
|
|
323
|
-
|
|
323
|
+
|
|
324
324
|
// Should have the user message, search tool sequence (2 messages),
|
|
325
325
|
// a combined message for weather and calculator (since one has an invalid tool),
|
|
326
326
|
// and final message
|
|
327
327
|
expect(result.messages).toHaveLength(5);
|
|
328
|
-
|
|
328
|
+
|
|
329
329
|
// Check the types of messages
|
|
330
330
|
expect(result.messages[0]).toBeInstanceOf(HumanMessage);
|
|
331
331
|
expect(result.messages[1]).toBeInstanceOf(AIMessage); // Search message
|
|
332
332
|
expect(result.messages[2]).toBeInstanceOf(ToolMessage); // Search tool response
|
|
333
333
|
expect(result.messages[3]).toBeInstanceOf(AIMessage); // Converted weather+calculator message
|
|
334
334
|
expect(result.messages[4]).toBeInstanceOf(AIMessage); // Final message
|
|
335
|
-
|
|
335
|
+
|
|
336
336
|
// Check that the combined message was converted to a string
|
|
337
337
|
expect(typeof result.messages[3].content).toBe('string');
|
|
338
|
-
|
|
338
|
+
|
|
339
339
|
// The format might vary based on the getBufferString implementation
|
|
340
340
|
// but we should check that all the key information is present
|
|
341
341
|
const content = result.messages[3].content as string;
|