@librechat/agents 3.1.39 → 3.1.41
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/agents/AgentContext.cjs +20 -1
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +4 -4
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +68 -17
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/run.cjs +6 -1
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +20 -1
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +4 -4
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +68 -17
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/run.mjs +6 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/types/agents/AgentContext.d.ts +2 -0
- package/package.json +2 -2
- package/src/agents/AgentContext.ts +22 -1
- package/src/agents/__tests__/AgentContext.test.ts +25 -4
- package/src/graphs/MultiAgentGraph.ts +6 -4
- package/src/messages/format.ts +75 -18
- package/src/messages/formatAgentMessages.test.ts +993 -4
- package/src/run.ts +7 -1
- package/src/specs/custom-event-await.test.ts +215 -0
|
@@ -7,10 +7,11 @@ describe('AgentContext', () => {
|
|
|
7
7
|
type ContextOptions = {
|
|
8
8
|
agentConfig?: Partial<t.AgentInputs>;
|
|
9
9
|
tokenCounter?: t.TokenCounter;
|
|
10
|
+
indexTokenCountMap?: Record<string, number>;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
const createBasicContext = (options: ContextOptions = {}): AgentContext => {
|
|
13
|
-
const { agentConfig = {}, tokenCounter } = options;
|
|
14
|
+
const { agentConfig = {}, tokenCounter, indexTokenCountMap } = options;
|
|
14
15
|
return AgentContext.fromConfig(
|
|
15
16
|
{
|
|
16
17
|
agentId: 'test-agent',
|
|
@@ -18,7 +19,8 @@ describe('AgentContext', () => {
|
|
|
18
19
|
instructions: 'Test instructions',
|
|
19
20
|
...agentConfig,
|
|
20
21
|
},
|
|
21
|
-
tokenCounter
|
|
22
|
+
tokenCounter,
|
|
23
|
+
indexTokenCountMap
|
|
22
24
|
);
|
|
23
25
|
};
|
|
24
26
|
|
|
@@ -393,6 +395,23 @@ describe('AgentContext', () => {
|
|
|
393
395
|
expect(ctx.currentUsage).toBeUndefined();
|
|
394
396
|
});
|
|
395
397
|
|
|
398
|
+
it('rebuilds indexTokenCountMap from base map after reset', async () => {
|
|
399
|
+
const tokenCounter = jest.fn(() => 5);
|
|
400
|
+
const ctx = createBasicContext({
|
|
401
|
+
tokenCounter,
|
|
402
|
+
indexTokenCountMap: { '0': 10, '1': 20 },
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
await ctx.tokenCalculationPromise;
|
|
406
|
+
ctx.indexTokenCountMap = {};
|
|
407
|
+
|
|
408
|
+
ctx.reset();
|
|
409
|
+
await ctx.tokenCalculationPromise;
|
|
410
|
+
|
|
411
|
+
expect(ctx.indexTokenCountMap['1']).toBe(20);
|
|
412
|
+
expect(ctx.indexTokenCountMap['0'] ?? 0).toBeGreaterThanOrEqual(10);
|
|
413
|
+
});
|
|
414
|
+
|
|
396
415
|
it('forces rebuild on next systemRunnable access', () => {
|
|
397
416
|
const ctx = createBasicContext({ agentConfig: { instructions: 'Test' } });
|
|
398
417
|
|
|
@@ -780,8 +799,9 @@ describe('AgentContext', () => {
|
|
|
780
799
|
|
|
781
800
|
// Verify state is cleared
|
|
782
801
|
expect(ctx.discoveredToolNames.size).toBe(0);
|
|
783
|
-
|
|
784
|
-
expect(
|
|
802
|
+
const resetTokens = ctx.instructionTokens;
|
|
803
|
+
expect(resetTokens).toBeGreaterThan(0);
|
|
804
|
+
expect(resetTokens).toBeLessThan(run1Tokens);
|
|
785
805
|
|
|
786
806
|
// ========== RUN 2 ==========
|
|
787
807
|
// Re-initialize (as fromConfig would do)
|
|
@@ -790,6 +810,7 @@ describe('AgentContext', () => {
|
|
|
790
810
|
// System runnable should NOT include the previously discovered tool
|
|
791
811
|
// (because discoveredToolNames was cleared)
|
|
792
812
|
const run2Tokens = ctx.instructionTokens;
|
|
813
|
+
expect(run2Tokens).toBe(resetTokens);
|
|
793
814
|
|
|
794
815
|
// Token count should be lower than run 1 (no discovered tool in system message)
|
|
795
816
|
expect(run2Tokens).toBeLessThan(run1Tokens);
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
getCurrentTaskInput,
|
|
16
16
|
messagesStateReducer,
|
|
17
17
|
} from '@langchain/langgraph';
|
|
18
|
+
import type { LangGraphRunnableConfig } from '@langchain/langgraph';
|
|
18
19
|
import type { BaseMessage, AIMessageChunk } from '@langchain/core/messages';
|
|
19
20
|
import type { ToolRunnableConfig } from '@langchain/core/tools';
|
|
20
21
|
import type * as t from '@/types';
|
|
@@ -745,7 +746,8 @@ export class MultiAgentGraph extends StandardGraph {
|
|
|
745
746
|
|
|
746
747
|
/** Wrapper function that handles agentMessages channel, handoff reception, and conditional routing */
|
|
747
748
|
const agentWrapper = async (
|
|
748
|
-
state: t.MultiAgentGraphState
|
|
749
|
+
state: t.MultiAgentGraphState,
|
|
750
|
+
config?: LangGraphRunnableConfig
|
|
749
751
|
): Promise<t.MultiAgentGraphState | Command> => {
|
|
750
752
|
let result: t.MultiAgentGraphState;
|
|
751
753
|
|
|
@@ -817,7 +819,7 @@ export class MultiAgentGraph extends StandardGraph {
|
|
|
817
819
|
...state,
|
|
818
820
|
messages: messagesForAgent,
|
|
819
821
|
};
|
|
820
|
-
result = await agentSubgraph.invoke(transformedState);
|
|
822
|
+
result = await agentSubgraph.invoke(transformedState, config);
|
|
821
823
|
result = {
|
|
822
824
|
...result,
|
|
823
825
|
agentMessages: [],
|
|
@@ -863,14 +865,14 @@ export class MultiAgentGraph extends StandardGraph {
|
|
|
863
865
|
...state,
|
|
864
866
|
messages: state.agentMessages,
|
|
865
867
|
};
|
|
866
|
-
result = await agentSubgraph.invoke(transformedState);
|
|
868
|
+
result = await agentSubgraph.invoke(transformedState, config);
|
|
867
869
|
result = {
|
|
868
870
|
...result,
|
|
869
871
|
/** Clear agentMessages for next agent */
|
|
870
872
|
agentMessages: [],
|
|
871
873
|
};
|
|
872
874
|
} else {
|
|
873
|
-
result = await agentSubgraph.invoke(state);
|
|
875
|
+
result = await agentSubgraph.invoke(state, config);
|
|
874
876
|
}
|
|
875
877
|
|
|
876
878
|
/** If agent has both handoff and direct edges, use Command for exclusive routing */
|
package/src/messages/format.ts
CHANGED
|
@@ -288,7 +288,12 @@ function formatAssistantMessage(
|
|
|
288
288
|
let hasReasoning = false;
|
|
289
289
|
|
|
290
290
|
if (Array.isArray(message.content)) {
|
|
291
|
-
for (const part of message.content
|
|
291
|
+
for (const part of message.content as Array<
|
|
292
|
+
MessageContentComplex | undefined | null
|
|
293
|
+
>) {
|
|
294
|
+
if (part == null) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
292
297
|
if (part.type === ContentTypes.TEXT && part.tool_call_ids) {
|
|
293
298
|
/*
|
|
294
299
|
If there's pending content, it needs to be aggregated as a single string to prepare for tool calls.
|
|
@@ -865,7 +870,6 @@ export const formatAgentMessages = (
|
|
|
865
870
|
indexMapping[i] = resultIndices;
|
|
866
871
|
}
|
|
867
872
|
|
|
868
|
-
// Update the token count map if it was provided
|
|
869
873
|
if (indexTokenCountMap) {
|
|
870
874
|
for (
|
|
871
875
|
let originalIndex = 0;
|
|
@@ -875,24 +879,77 @@ export const formatAgentMessages = (
|
|
|
875
879
|
const resultIndices = indexMapping[originalIndex] || [];
|
|
876
880
|
const tokenCount = indexTokenCountMap[originalIndex];
|
|
877
881
|
|
|
878
|
-
if (tokenCount
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
882
|
+
if (tokenCount === undefined) {
|
|
883
|
+
continue;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
const msgCount = resultIndices.length;
|
|
887
|
+
if (msgCount === 1) {
|
|
888
|
+
updatedIndexTokenCountMap[resultIndices[0]] = tokenCount;
|
|
889
|
+
continue;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
if (msgCount < 2) {
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
let totalLength = 0;
|
|
897
|
+
const lastIdx = msgCount - 1;
|
|
898
|
+
const lengths = new Array<number>(msgCount);
|
|
899
|
+
for (let k = 0; k < msgCount; k++) {
|
|
900
|
+
const msg = messages[resultIndices[k]];
|
|
901
|
+
const { content } = msg;
|
|
902
|
+
let len = 0;
|
|
903
|
+
if (typeof content === 'string') {
|
|
904
|
+
len = content.length;
|
|
905
|
+
} else if (Array.isArray(content)) {
|
|
906
|
+
for (const part of content as Array<
|
|
907
|
+
Record<string, unknown> | string | undefined
|
|
908
|
+
>) {
|
|
909
|
+
if (typeof part === 'string') {
|
|
910
|
+
len += part.length;
|
|
911
|
+
} else if (part != null && typeof part === 'object') {
|
|
912
|
+
const val = part.text ?? part.content;
|
|
913
|
+
if (typeof val === 'string') {
|
|
914
|
+
len += val.length;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
const toolCalls = (msg as AIMessage).tool_calls;
|
|
920
|
+
if (Array.isArray(toolCalls)) {
|
|
921
|
+
for (const tc of toolCalls as Array<Record<string, unknown>>) {
|
|
922
|
+
if (typeof tc.name === 'string') {
|
|
923
|
+
len += tc.name.length;
|
|
924
|
+
}
|
|
925
|
+
const { args } = tc;
|
|
926
|
+
if (typeof args === 'string') {
|
|
927
|
+
len += args.length;
|
|
928
|
+
} else if (args != null) {
|
|
929
|
+
len += JSON.stringify(args).length;
|
|
893
930
|
}
|
|
894
|
-
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
lengths[k] = len;
|
|
934
|
+
totalLength += len;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
if (totalLength === 0) {
|
|
938
|
+
const countPerMessage = Math.floor(tokenCount / msgCount);
|
|
939
|
+
for (let k = 0; k < lastIdx; k++) {
|
|
940
|
+
updatedIndexTokenCountMap[resultIndices[k]] = countPerMessage;
|
|
941
|
+
}
|
|
942
|
+
updatedIndexTokenCountMap[resultIndices[lastIdx]] =
|
|
943
|
+
tokenCount - countPerMessage * lastIdx;
|
|
944
|
+
} else {
|
|
945
|
+
let distributed = 0;
|
|
946
|
+
for (let k = 0; k < lastIdx; k++) {
|
|
947
|
+
const share = Math.floor((lengths[k] / totalLength) * tokenCount);
|
|
948
|
+
updatedIndexTokenCountMap[resultIndices[k]] = share;
|
|
949
|
+
distributed += share;
|
|
895
950
|
}
|
|
951
|
+
updatedIndexTokenCountMap[resultIndices[lastIdx]] =
|
|
952
|
+
tokenCount - distributed;
|
|
896
953
|
}
|
|
897
954
|
}
|
|
898
955
|
}
|