@librechat/agents 2.4.322 → 3.0.0-rc10
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 +218 -0
- package/dist/cjs/agents/AgentContext.cjs.map +1 -0
- package/dist/cjs/common/enum.cjs +15 -5
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/events.cjs +10 -6
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +309 -213
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +507 -0
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -0
- package/dist/cjs/llm/anthropic/index.cjs +54 -9
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +52 -6
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +22 -2
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/tools.cjs +29 -0
- package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -0
- package/dist/cjs/llm/google/index.cjs +144 -0
- package/dist/cjs/llm/google/index.cjs.map +1 -0
- package/dist/cjs/llm/google/utils/common.cjs +477 -0
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -0
- package/dist/cjs/llm/ollama/index.cjs +67 -0
- package/dist/cjs/llm/ollama/index.cjs.map +1 -0
- package/dist/cjs/llm/ollama/utils.cjs +158 -0
- package/dist/cjs/llm/ollama/utils.cjs.map +1 -0
- package/dist/cjs/llm/openai/index.cjs +422 -3
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +672 -0
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -0
- package/dist/cjs/llm/providers.cjs +15 -15
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/llm/text.cjs +14 -3
- package/dist/cjs/llm/text.cjs.map +1 -1
- package/dist/cjs/llm/vertexai/index.cjs +330 -0
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -0
- package/dist/cjs/main.cjs +11 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/run.cjs +137 -85
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +86 -52
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +10 -4
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +119 -13
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/search/anthropic.cjs +40 -0
- package/dist/cjs/tools/search/anthropic.cjs.map +1 -0
- package/dist/cjs/tools/search/firecrawl.cjs +55 -9
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/format.cjs +6 -6
- package/dist/cjs/tools/search/format.cjs.map +1 -1
- package/dist/cjs/tools/search/rerankers.cjs +7 -29
- package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +86 -16
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +4 -2
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +1 -1
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/cjs/utils/events.cjs +31 -0
- package/dist/cjs/utils/events.cjs.map +1 -0
- package/dist/cjs/utils/title.cjs +57 -21
- package/dist/cjs/utils/title.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +54 -7
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +216 -0
- package/dist/esm/agents/AgentContext.mjs.map +1 -0
- package/dist/esm/common/enum.mjs +16 -6
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/events.mjs +10 -6
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +311 -215
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +505 -0
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -0
- package/dist/esm/llm/anthropic/index.mjs +54 -9
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/anthropic/types.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +52 -6
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +22 -2
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/tools.mjs +27 -0
- package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -0
- package/dist/esm/llm/google/index.mjs +142 -0
- package/dist/esm/llm/google/index.mjs.map +1 -0
- package/dist/esm/llm/google/utils/common.mjs +471 -0
- package/dist/esm/llm/google/utils/common.mjs.map +1 -0
- package/dist/esm/llm/ollama/index.mjs +65 -0
- package/dist/esm/llm/ollama/index.mjs.map +1 -0
- package/dist/esm/llm/ollama/utils.mjs +155 -0
- package/dist/esm/llm/ollama/utils.mjs.map +1 -0
- package/dist/esm/llm/openai/index.mjs +421 -4
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +666 -0
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -0
- package/dist/esm/llm/providers.mjs +5 -5
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/llm/text.mjs +14 -3
- package/dist/esm/llm/text.mjs.map +1 -1
- package/dist/esm/llm/vertexai/index.mjs +328 -0
- package/dist/esm/llm/vertexai/index.mjs.map +1 -0
- package/dist/esm/main.mjs +6 -5
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/run.mjs +138 -87
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +88 -55
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +10 -4
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +119 -15
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/search/anthropic.mjs +37 -0
- package/dist/esm/tools/search/anthropic.mjs.map +1 -0
- package/dist/esm/tools/search/firecrawl.mjs +55 -9
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/format.mjs +7 -7
- package/dist/esm/tools/search/format.mjs.map +1 -1
- package/dist/esm/tools/search/rerankers.mjs +7 -29
- package/dist/esm/tools/search/rerankers.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +86 -16
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +4 -2
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +1 -1
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/esm/utils/events.mjs +29 -0
- package/dist/esm/utils/events.mjs.map +1 -0
- package/dist/esm/utils/title.mjs +57 -22
- package/dist/esm/utils/title.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +54 -8
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/types/agents/AgentContext.d.ts +91 -0
- package/dist/types/common/enum.d.ts +17 -7
- package/dist/types/events.d.ts +5 -4
- package/dist/types/graphs/Graph.d.ts +64 -67
- package/dist/types/graphs/MultiAgentGraph.d.ts +47 -0
- package/dist/types/graphs/index.d.ts +1 -0
- package/dist/types/llm/anthropic/index.d.ts +11 -0
- package/dist/types/llm/anthropic/types.d.ts +9 -3
- package/dist/types/llm/anthropic/utils/message_inputs.d.ts +1 -1
- package/dist/types/llm/anthropic/utils/output_parsers.d.ts +4 -4
- package/dist/types/llm/anthropic/utils/tools.d.ts +3 -0
- package/dist/types/llm/google/index.d.ts +13 -0
- package/dist/types/llm/google/types.d.ts +32 -0
- package/dist/types/llm/google/utils/common.d.ts +19 -0
- package/dist/types/llm/google/utils/tools.d.ts +10 -0
- package/dist/types/llm/google/utils/zod_to_genai_parameters.d.ts +14 -0
- package/dist/types/llm/ollama/index.d.ts +7 -0
- package/dist/types/llm/ollama/utils.d.ts +7 -0
- package/dist/types/llm/openai/index.d.ts +82 -3
- package/dist/types/llm/openai/types.d.ts +10 -0
- package/dist/types/llm/openai/utils/index.d.ts +20 -0
- package/dist/types/llm/text.d.ts +1 -1
- package/dist/types/llm/vertexai/index.d.ts +293 -0
- package/dist/types/messages/reducer.d.ts +9 -0
- package/dist/types/run.d.ts +19 -12
- package/dist/types/stream.d.ts +10 -3
- package/dist/types/tools/CodeExecutor.d.ts +2 -2
- package/dist/types/tools/ToolNode.d.ts +1 -1
- package/dist/types/tools/handlers.d.ts +17 -4
- package/dist/types/tools/search/anthropic.d.ts +16 -0
- package/dist/types/tools/search/firecrawl.d.ts +15 -0
- package/dist/types/tools/search/rerankers.d.ts +0 -1
- package/dist/types/tools/search/types.d.ts +30 -9
- package/dist/types/types/graph.d.ts +129 -15
- package/dist/types/types/llm.d.ts +25 -10
- package/dist/types/types/run.d.ts +50 -8
- package/dist/types/types/stream.d.ts +16 -2
- package/dist/types/types/tools.d.ts +1 -1
- package/dist/types/utils/events.d.ts +6 -0
- package/dist/types/utils/title.d.ts +2 -1
- package/dist/types/utils/tokens.d.ts +24 -0
- package/package.json +41 -17
- package/src/agents/AgentContext.ts +315 -0
- package/src/common/enum.ts +15 -5
- package/src/events.ts +24 -13
- package/src/graphs/Graph.ts +495 -313
- package/src/graphs/MultiAgentGraph.ts +598 -0
- package/src/graphs/index.ts +2 -1
- package/src/llm/anthropic/Jacob_Lee_Resume_2023.pdf +0 -0
- package/src/llm/anthropic/index.ts +78 -13
- package/src/llm/anthropic/llm.spec.ts +491 -115
- package/src/llm/anthropic/types.ts +39 -3
- package/src/llm/anthropic/utils/message_inputs.ts +67 -11
- package/src/llm/anthropic/utils/message_outputs.ts +21 -2
- package/src/llm/anthropic/utils/output_parsers.ts +25 -6
- package/src/llm/anthropic/utils/tools.ts +29 -0
- package/src/llm/google/index.ts +218 -0
- package/src/llm/google/types.ts +43 -0
- package/src/llm/google/utils/common.ts +646 -0
- package/src/llm/google/utils/tools.ts +160 -0
- package/src/llm/google/utils/zod_to_genai_parameters.ts +86 -0
- package/src/llm/ollama/index.ts +89 -0
- package/src/llm/ollama/utils.ts +193 -0
- package/src/llm/openai/index.ts +641 -14
- package/src/llm/openai/types.ts +24 -0
- package/src/llm/openai/utils/index.ts +912 -0
- package/src/llm/openai/utils/isReasoningModel.test.ts +90 -0
- package/src/llm/providers.ts +10 -9
- package/src/llm/text.ts +26 -7
- package/src/llm/vertexai/index.ts +360 -0
- package/src/messages/reducer.ts +80 -0
- package/src/run.ts +196 -116
- package/src/scripts/ant_web_search.ts +158 -0
- package/src/scripts/args.ts +12 -8
- package/src/scripts/cli4.ts +29 -21
- package/src/scripts/cli5.ts +29 -21
- package/src/scripts/code_exec.ts +54 -23
- package/src/scripts/code_exec_files.ts +48 -17
- package/src/scripts/code_exec_simple.ts +46 -27
- package/src/scripts/handoff-test.ts +135 -0
- package/src/scripts/image.ts +52 -20
- package/src/scripts/multi-agent-chain.ts +278 -0
- package/src/scripts/multi-agent-conditional.ts +220 -0
- package/src/scripts/multi-agent-document-review-chain.ts +197 -0
- package/src/scripts/multi-agent-hybrid-flow.ts +310 -0
- package/src/scripts/multi-agent-parallel.ts +341 -0
- package/src/scripts/multi-agent-sequence.ts +212 -0
- package/src/scripts/multi-agent-supervisor.ts +362 -0
- package/src/scripts/multi-agent-test.ts +186 -0
- package/src/scripts/search.ts +1 -9
- package/src/scripts/simple.ts +25 -10
- package/src/scripts/test-custom-prompt-key.ts +145 -0
- package/src/scripts/test-handoff-input.ts +170 -0
- package/src/scripts/test-multi-agent-list-handoff.ts +261 -0
- package/src/scripts/test-tools-before-handoff.ts +233 -0
- package/src/scripts/tools.ts +48 -18
- package/src/specs/anthropic.simple.test.ts +150 -34
- package/src/specs/azure.simple.test.ts +325 -0
- package/src/specs/openai.simple.test.ts +140 -33
- package/src/specs/openrouter.simple.test.ts +107 -0
- package/src/specs/prune.test.ts +4 -9
- package/src/specs/reasoning.test.ts +80 -44
- package/src/specs/token-memoization.test.ts +39 -0
- package/src/stream.test.ts +94 -0
- package/src/stream.ts +143 -61
- package/src/tools/ToolNode.ts +21 -7
- package/src/tools/handlers.ts +192 -18
- package/src/tools/search/anthropic.ts +51 -0
- package/src/tools/search/firecrawl.ts +69 -20
- package/src/tools/search/format.ts +6 -8
- package/src/tools/search/rerankers.ts +7 -40
- package/src/tools/search/search.ts +97 -16
- package/src/tools/search/tool.ts +5 -2
- package/src/tools/search/types.ts +30 -10
- package/src/tools/search/utils.ts +1 -1
- package/src/types/graph.ts +318 -103
- package/src/types/llm.ts +26 -12
- package/src/types/run.ts +56 -13
- package/src/types/stream.ts +22 -1
- package/src/types/tools.ts +16 -10
- package/src/utils/events.ts +32 -0
- package/src/utils/llmConfig.ts +19 -7
- package/src/utils/title.ts +104 -30
- package/src/utils/tokens.ts +69 -10
- package/dist/types/scripts/abort.d.ts +0 -1
- package/dist/types/scripts/args.d.ts +0 -6
- package/dist/types/scripts/caching.d.ts +0 -1
- package/dist/types/scripts/cli.d.ts +0 -1
- package/dist/types/scripts/cli2.d.ts +0 -1
- package/dist/types/scripts/cli3.d.ts +0 -1
- package/dist/types/scripts/cli4.d.ts +0 -1
- package/dist/types/scripts/cli5.d.ts +0 -1
- package/dist/types/scripts/code_exec.d.ts +0 -1
- package/dist/types/scripts/code_exec_files.d.ts +0 -1
- package/dist/types/scripts/code_exec_simple.d.ts +0 -1
- package/dist/types/scripts/content.d.ts +0 -1
- package/dist/types/scripts/empty_input.d.ts +0 -1
- package/dist/types/scripts/image.d.ts +0 -1
- package/dist/types/scripts/memory.d.ts +0 -1
- package/dist/types/scripts/search.d.ts +0 -1
- package/dist/types/scripts/simple.d.ts +0 -1
- package/dist/types/scripts/stream.d.ts +0 -1
- package/dist/types/scripts/thinking.d.ts +0 -1
- package/dist/types/scripts/tools.d.ts +0 -1
- package/dist/types/specs/spec.utils.d.ts +0 -1
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
import { nanoid } from 'nanoid';
|
|
2
2
|
import { concat } from '@langchain/core/utils/stream';
|
|
3
3
|
import { ChatVertexAI } from '@langchain/google-vertexai';
|
|
4
|
-
import { StateGraph, START, END } from '@langchain/langgraph';
|
|
5
|
-
import {
|
|
4
|
+
import { Annotation, messagesStateReducer, StateGraph, START, END } from '@langchain/langgraph';
|
|
5
|
+
import { RunnableLambda } from '@langchain/core/runnables';
|
|
6
6
|
import { SystemMessage, AIMessageChunk, ToolMessage } from '@langchain/core/messages';
|
|
7
7
|
import { GraphNodeKeys, ContentTypes, Providers, GraphEvents, StepTypes } from '../common/enum.mjs';
|
|
8
|
-
import {
|
|
9
|
-
import { ToolNode, toolsCondition } from '../tools/ToolNode.mjs';
|
|
10
|
-
import { convertMessagesToContent, formatAnthropicArtifactContent, formatArtifactPayload, modifyDeltaProperties } from '../messages/core.mjs';
|
|
8
|
+
import { convertMessagesToContent, modifyDeltaProperties, formatAnthropicArtifactContent, formatArtifactPayload } from '../messages/core.mjs';
|
|
11
9
|
import { createPruneMessages } from '../messages/prune.mjs';
|
|
12
10
|
import { resetIfNotEmpty, joinKeys } from '../utils/graph.mjs';
|
|
13
11
|
import { isOpenAILike, isGoogleLike } from '../utils/llm.mjs';
|
|
14
12
|
import { sleep } from '../utils/run.mjs';
|
|
15
13
|
import 'js-tiktoken/lite';
|
|
14
|
+
import { getChatModelClass, manualToolStreamProviders } from '../llm/providers.mjs';
|
|
15
|
+
import { ToolNode, toolsCondition } from '../tools/ToolNode.mjs';
|
|
16
16
|
import { ChatOpenAI, AzureChatOpenAI } from '../llm/openai/index.mjs';
|
|
17
|
+
import { safeDispatchCustomEvent } from '../utils/events.mjs';
|
|
18
|
+
import { AgentContext } from '../agents/AgentContext.mjs';
|
|
17
19
|
import { createFakeStreamingLLM } from '../llm/fake.mjs';
|
|
18
20
|
|
|
19
21
|
/* eslint-disable no-console */
|
|
20
22
|
// src/graphs/Graph.ts
|
|
21
23
|
const { AGENT, TOOLS } = GraphNodeKeys;
|
|
22
24
|
class Graph {
|
|
23
|
-
lastToken;
|
|
24
|
-
tokenTypeSwitch;
|
|
25
|
-
reasoningKey = 'reasoning_content';
|
|
26
|
-
currentTokenType = ContentTypes.TEXT;
|
|
27
25
|
messageStepHasToolCalls = new Map();
|
|
28
26
|
messageIdsByStepKey = new Map();
|
|
29
27
|
prelimMessageIdsByStepKey = new Map();
|
|
@@ -32,71 +30,37 @@ class Graph {
|
|
|
32
30
|
stepKeyIds = new Map();
|
|
33
31
|
contentIndexMap = new Map();
|
|
34
32
|
toolCallStepIds = new Map();
|
|
35
|
-
currentUsage;
|
|
36
|
-
indexTokenCountMap = {};
|
|
37
|
-
maxContextTokens;
|
|
38
|
-
pruneMessages;
|
|
39
|
-
/** The amount of time that should pass before another consecutive API call */
|
|
40
|
-
streamBuffer;
|
|
41
|
-
tokenCounter;
|
|
42
33
|
signal;
|
|
34
|
+
/** Set of invoked tool call IDs from non-message run steps completed mid-run, if any */
|
|
35
|
+
invokedToolIds;
|
|
36
|
+
handlerRegistry;
|
|
43
37
|
}
|
|
44
38
|
class StandardGraph extends Graph {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
/** The last recorded timestamp that a stream API call was invoked */
|
|
49
|
-
lastStreamCall;
|
|
50
|
-
handlerRegistry;
|
|
51
|
-
systemMessage;
|
|
39
|
+
overrideModel;
|
|
40
|
+
/** Optional compile options passed into workflow.compile() */
|
|
41
|
+
compileOptions;
|
|
52
42
|
messages = [];
|
|
53
43
|
runId;
|
|
54
|
-
tools;
|
|
55
|
-
toolMap;
|
|
56
44
|
startIndex = 0;
|
|
57
|
-
provider;
|
|
58
|
-
toolEnd;
|
|
59
45
|
signal;
|
|
60
|
-
|
|
46
|
+
/** Map of agent contexts by agent ID */
|
|
47
|
+
agentContexts = new Map();
|
|
48
|
+
/** Default agent ID to use */
|
|
49
|
+
defaultAgentId;
|
|
50
|
+
constructor({
|
|
51
|
+
// parent-level graph inputs
|
|
52
|
+
runId, signal, agents, tokenCounter, indexTokenCountMap, }) {
|
|
61
53
|
super();
|
|
62
54
|
this.runId = runId;
|
|
63
|
-
this.tools = tools;
|
|
64
55
|
this.signal = signal;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
this.provider = provider;
|
|
68
|
-
this.streamBuffer = streamBuffer;
|
|
69
|
-
this.clientOptions = clientOptions;
|
|
70
|
-
this.graphState = this.createGraphState();
|
|
71
|
-
this.boundModel = this.initializeModel();
|
|
72
|
-
if (reasoningKey) {
|
|
73
|
-
this.reasoningKey = reasoningKey;
|
|
56
|
+
if (agents.length === 0) {
|
|
57
|
+
throw new Error('At least one agent configuration is required');
|
|
74
58
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
finalInstructions != null && finalInstructions
|
|
79
|
-
? `${finalInstructions}\n\n${additional_instructions}`
|
|
80
|
-
: additional_instructions;
|
|
81
|
-
}
|
|
82
|
-
if (finalInstructions != null &&
|
|
83
|
-
finalInstructions &&
|
|
84
|
-
provider === Providers.ANTHROPIC &&
|
|
85
|
-
(clientOptions.clientOptions?.defaultHeaders?.['anthropic-beta']?.includes('prompt-caching') ??
|
|
86
|
-
false)) {
|
|
87
|
-
finalInstructions = {
|
|
88
|
-
content: [
|
|
89
|
-
{
|
|
90
|
-
type: 'text',
|
|
91
|
-
text: instructions,
|
|
92
|
-
cache_control: { type: 'ephemeral' },
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
if (finalInstructions != null && finalInstructions !== '') {
|
|
98
|
-
this.systemMessage = new SystemMessage(finalInstructions);
|
|
59
|
+
for (const agentConfig of agents) {
|
|
60
|
+
const agentContext = AgentContext.fromConfig(agentConfig, tokenCounter, indexTokenCountMap);
|
|
61
|
+
this.agentContexts.set(agentConfig.agentId, agentContext);
|
|
99
62
|
}
|
|
63
|
+
this.defaultAgentId = agents[0].agentId;
|
|
100
64
|
}
|
|
101
65
|
/* Init */
|
|
102
66
|
resetValues(keepContent) {
|
|
@@ -109,15 +73,12 @@ class StandardGraph extends Graph {
|
|
|
109
73
|
this.stepKeyIds = resetIfNotEmpty(this.stepKeyIds, new Map());
|
|
110
74
|
this.toolCallStepIds = resetIfNotEmpty(this.toolCallStepIds, new Map());
|
|
111
75
|
this.messageIdsByStepKey = resetIfNotEmpty(this.messageIdsByStepKey, new Map());
|
|
112
|
-
this.messageStepHasToolCalls = resetIfNotEmpty(this.
|
|
76
|
+
this.messageStepHasToolCalls = resetIfNotEmpty(this.messageStepHasToolCalls, new Map());
|
|
113
77
|
this.prelimMessageIdsByStepKey = resetIfNotEmpty(this.prelimMessageIdsByStepKey, new Map());
|
|
114
|
-
this.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
this.currentUsage = resetIfNotEmpty(this.currentUsage, undefined);
|
|
119
|
-
this.tokenCounter = resetIfNotEmpty(this.tokenCounter, undefined);
|
|
120
|
-
this.maxContextTokens = resetIfNotEmpty(this.maxContextTokens, undefined);
|
|
78
|
+
this.invokedToolIds = resetIfNotEmpty(this.invokedToolIds, undefined);
|
|
79
|
+
for (const context of this.agentContexts.values()) {
|
|
80
|
+
context.reset();
|
|
81
|
+
}
|
|
121
82
|
}
|
|
122
83
|
/* Run Step Processing */
|
|
123
84
|
getRunStep(stepId) {
|
|
@@ -127,6 +88,27 @@ class StandardGraph extends Graph {
|
|
|
127
88
|
}
|
|
128
89
|
return undefined;
|
|
129
90
|
}
|
|
91
|
+
getAgentContext(metadata) {
|
|
92
|
+
if (!metadata) {
|
|
93
|
+
throw new Error('No metadata provided to retrieve agent context');
|
|
94
|
+
}
|
|
95
|
+
const currentNode = metadata.langgraph_node;
|
|
96
|
+
if (!currentNode) {
|
|
97
|
+
throw new Error('No langgraph_node in metadata to retrieve agent context');
|
|
98
|
+
}
|
|
99
|
+
let agentId;
|
|
100
|
+
if (currentNode.startsWith(AGENT)) {
|
|
101
|
+
agentId = currentNode.substring(AGENT.length);
|
|
102
|
+
}
|
|
103
|
+
else if (currentNode.startsWith(TOOLS)) {
|
|
104
|
+
agentId = currentNode.substring(TOOLS.length);
|
|
105
|
+
}
|
|
106
|
+
const agentContext = this.agentContexts.get(agentId ?? '');
|
|
107
|
+
if (!agentContext) {
|
|
108
|
+
throw new Error(`No agent context found for agent ID ${agentId}`);
|
|
109
|
+
}
|
|
110
|
+
return agentContext;
|
|
111
|
+
}
|
|
130
112
|
getStepKey(metadata) {
|
|
131
113
|
if (!metadata)
|
|
132
114
|
return '';
|
|
@@ -172,10 +154,14 @@ class StandardGraph extends Graph {
|
|
|
172
154
|
metadata.langgraph_step,
|
|
173
155
|
metadata.checkpoint_ns,
|
|
174
156
|
];
|
|
175
|
-
|
|
176
|
-
|
|
157
|
+
const agentContext = this.getAgentContext(metadata);
|
|
158
|
+
if (agentContext.currentTokenType === ContentTypes.THINK ||
|
|
159
|
+
agentContext.currentTokenType === 'think_and_text') {
|
|
177
160
|
keyList.push('reasoning');
|
|
178
161
|
}
|
|
162
|
+
if (this.invokedToolIds != null && this.invokedToolIds.size > 0) {
|
|
163
|
+
keyList.push(this.invokedToolIds.size + '');
|
|
164
|
+
}
|
|
179
165
|
return keyList;
|
|
180
166
|
}
|
|
181
167
|
checkKeyList(keyList) {
|
|
@@ -189,113 +175,158 @@ class StandardGraph extends Graph {
|
|
|
189
175
|
return convertMessagesToContent(this.messages.slice(this.startIndex));
|
|
190
176
|
}
|
|
191
177
|
/* Graph */
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
178
|
+
createSystemRunnable({ provider, clientOptions, instructions, additional_instructions, }) {
|
|
179
|
+
let finalInstructions = instructions;
|
|
180
|
+
if (additional_instructions != null && additional_instructions !== '') {
|
|
181
|
+
finalInstructions =
|
|
182
|
+
finalInstructions != null && finalInstructions
|
|
183
|
+
? `${finalInstructions}\n\n${additional_instructions}`
|
|
184
|
+
: additional_instructions;
|
|
185
|
+
}
|
|
186
|
+
if (finalInstructions != null &&
|
|
187
|
+
finalInstructions &&
|
|
188
|
+
provider === Providers.ANTHROPIC &&
|
|
189
|
+
(clientOptions.clientOptions
|
|
190
|
+
?.defaultHeaders?.['anthropic-beta']?.includes('prompt-caching') ??
|
|
191
|
+
false)) {
|
|
192
|
+
finalInstructions = {
|
|
193
|
+
content: [
|
|
194
|
+
{
|
|
195
|
+
type: 'text',
|
|
196
|
+
text: instructions,
|
|
197
|
+
cache_control: { type: 'ephemeral' },
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
if (finalInstructions != null && finalInstructions !== '') {
|
|
203
|
+
const systemMessage = new SystemMessage(finalInstructions);
|
|
204
|
+
return RunnableLambda.from((messages) => {
|
|
205
|
+
return [systemMessage, ...messages];
|
|
206
|
+
}).withConfig({ runName: 'prompt' });
|
|
207
|
+
}
|
|
209
208
|
}
|
|
210
|
-
initializeTools() {
|
|
211
|
-
// return new ToolNode<t.BaseGraphState>(this.tools);
|
|
209
|
+
initializeTools({ currentTools, currentToolMap, }) {
|
|
212
210
|
return new ToolNode({
|
|
213
|
-
tools:
|
|
214
|
-
toolMap:
|
|
211
|
+
tools: currentTools ?? [],
|
|
212
|
+
toolMap: currentToolMap,
|
|
215
213
|
toolCallStepIds: this.toolCallStepIds,
|
|
216
214
|
errorHandler: (data, metadata) => StandardGraph.handleToolCallErrorStatic(this, data, metadata),
|
|
217
215
|
});
|
|
218
216
|
}
|
|
219
|
-
initializeModel() {
|
|
220
|
-
const ChatModelClass = getChatModelClass(
|
|
221
|
-
const model = new ChatModelClass(
|
|
222
|
-
if (isOpenAILike(
|
|
217
|
+
initializeModel({ provider, tools, clientOptions, }) {
|
|
218
|
+
const ChatModelClass = getChatModelClass(provider);
|
|
219
|
+
const model = new ChatModelClass(clientOptions ?? {});
|
|
220
|
+
if (isOpenAILike(provider) &&
|
|
223
221
|
(model instanceof ChatOpenAI || model instanceof AzureChatOpenAI)) {
|
|
224
|
-
model.temperature =
|
|
222
|
+
model.temperature = clientOptions
|
|
225
223
|
.temperature;
|
|
226
|
-
model.topP =
|
|
227
|
-
model.frequencyPenalty =
|
|
224
|
+
model.topP = clientOptions.topP;
|
|
225
|
+
model.frequencyPenalty = clientOptions
|
|
228
226
|
.frequencyPenalty;
|
|
229
|
-
model.presencePenalty =
|
|
227
|
+
model.presencePenalty = clientOptions
|
|
230
228
|
.presencePenalty;
|
|
231
|
-
model.n =
|
|
229
|
+
model.n = clientOptions.n;
|
|
232
230
|
}
|
|
233
|
-
else if (
|
|
231
|
+
else if (provider === Providers.VERTEXAI &&
|
|
234
232
|
model instanceof ChatVertexAI) {
|
|
235
|
-
model.temperature =
|
|
233
|
+
model.temperature = clientOptions
|
|
236
234
|
.temperature;
|
|
237
|
-
model.topP =
|
|
238
|
-
|
|
239
|
-
model.
|
|
240
|
-
.topK;
|
|
241
|
-
model.topLogprobs = this.clientOptions
|
|
235
|
+
model.topP = clientOptions.topP;
|
|
236
|
+
model.topK = clientOptions.topK;
|
|
237
|
+
model.topLogprobs = clientOptions
|
|
242
238
|
.topLogprobs;
|
|
243
|
-
model.frequencyPenalty =
|
|
239
|
+
model.frequencyPenalty = clientOptions
|
|
244
240
|
.frequencyPenalty;
|
|
245
|
-
model.presencePenalty =
|
|
241
|
+
model.presencePenalty = clientOptions
|
|
246
242
|
.presencePenalty;
|
|
247
|
-
model.maxOutputTokens =
|
|
243
|
+
model.maxOutputTokens = clientOptions
|
|
248
244
|
.maxOutputTokens;
|
|
249
245
|
}
|
|
250
|
-
if (!
|
|
246
|
+
if (!tools || tools.length === 0) {
|
|
251
247
|
return model;
|
|
252
248
|
}
|
|
253
|
-
return model.bindTools(
|
|
249
|
+
return model.bindTools(tools);
|
|
254
250
|
}
|
|
255
251
|
overrideTestModel(responses, sleep, toolCalls) {
|
|
256
|
-
this.
|
|
252
|
+
this.overrideModel = createFakeStreamingLLM({
|
|
257
253
|
responses,
|
|
258
254
|
sleep,
|
|
259
255
|
toolCalls,
|
|
260
256
|
});
|
|
261
257
|
}
|
|
262
|
-
getNewModel({
|
|
263
|
-
const ChatModelClass = getChatModelClass(
|
|
264
|
-
|
|
265
|
-
? Object.fromEntries(Object.entries(this.clientOptions).filter(([key]) => !omitOriginalOptions.has(key)))
|
|
266
|
-
: this.clientOptions;
|
|
267
|
-
const options = Object.assign(_options, clientOptions);
|
|
268
|
-
return new ChatModelClass(options);
|
|
258
|
+
getNewModel({ provider, clientOptions, }) {
|
|
259
|
+
const ChatModelClass = getChatModelClass(provider);
|
|
260
|
+
return new ChatModelClass(clientOptions ?? {});
|
|
269
261
|
}
|
|
270
|
-
|
|
262
|
+
getUsageMetadata(finalMessage) {
|
|
271
263
|
if (finalMessage &&
|
|
272
264
|
'usage_metadata' in finalMessage &&
|
|
273
265
|
finalMessage.usage_metadata != null) {
|
|
274
|
-
|
|
266
|
+
return finalMessage.usage_metadata;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/** Execute model invocation with streaming support */
|
|
270
|
+
async attemptInvoke({ currentModel, finalMessages, provider, tools, }, config) {
|
|
271
|
+
const model = this.overrideModel ?? currentModel;
|
|
272
|
+
if (!model) {
|
|
273
|
+
throw new Error('No model found');
|
|
274
|
+
}
|
|
275
|
+
if ((tools?.length ?? 0) > 0 && manualToolStreamProviders.has(provider)) {
|
|
276
|
+
if (!model.stream) {
|
|
277
|
+
throw new Error('Model does not support stream');
|
|
278
|
+
}
|
|
279
|
+
const stream = await model.stream(finalMessages, config);
|
|
280
|
+
let finalChunk;
|
|
281
|
+
for await (const chunk of stream) {
|
|
282
|
+
await safeDispatchCustomEvent(GraphEvents.CHAT_MODEL_STREAM, { chunk, emitted: true }, config);
|
|
283
|
+
finalChunk = finalChunk ? concat(finalChunk, chunk) : chunk;
|
|
284
|
+
}
|
|
285
|
+
finalChunk = modifyDeltaProperties(provider, finalChunk);
|
|
286
|
+
return { messages: [finalChunk] };
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
const finalMessage = await model.invoke(finalMessages, config);
|
|
290
|
+
if ((finalMessage.tool_calls?.length ?? 0) > 0) {
|
|
291
|
+
finalMessage.tool_calls = finalMessage.tool_calls?.filter((tool_call) => !!tool_call.name);
|
|
292
|
+
}
|
|
293
|
+
return { messages: [finalMessage] };
|
|
275
294
|
}
|
|
276
295
|
}
|
|
277
|
-
cleanupSignalListener() {
|
|
296
|
+
cleanupSignalListener(currentModel) {
|
|
278
297
|
if (!this.signal) {
|
|
279
298
|
return;
|
|
280
299
|
}
|
|
281
|
-
|
|
300
|
+
const model = this.overrideModel ?? currentModel;
|
|
301
|
+
if (!model) {
|
|
282
302
|
return;
|
|
283
303
|
}
|
|
284
|
-
const client =
|
|
304
|
+
const client = model?.exposedClient;
|
|
285
305
|
if (!client?.abortHandler) {
|
|
286
306
|
return;
|
|
287
307
|
}
|
|
288
308
|
this.signal.removeEventListener('abort', client.abortHandler);
|
|
289
309
|
client.abortHandler = undefined;
|
|
290
310
|
}
|
|
291
|
-
createCallModel() {
|
|
311
|
+
createCallModel(agentId = 'default', currentModel) {
|
|
292
312
|
return async (state, config) => {
|
|
293
|
-
|
|
294
|
-
|
|
313
|
+
/**
|
|
314
|
+
* Get agent context - it must exist by this point
|
|
315
|
+
*/
|
|
316
|
+
const agentContext = this.agentContexts.get(agentId);
|
|
317
|
+
if (!agentContext) {
|
|
318
|
+
throw new Error(`Agent context not found for agentId: ${agentId}`);
|
|
319
|
+
}
|
|
320
|
+
const model = this.overrideModel ?? currentModel;
|
|
321
|
+
if (!model) {
|
|
295
322
|
throw new Error('No Graph model found');
|
|
296
323
|
}
|
|
297
|
-
if (!config
|
|
298
|
-
throw new Error(
|
|
324
|
+
if (!config) {
|
|
325
|
+
throw new Error('No config provided');
|
|
326
|
+
}
|
|
327
|
+
// Ensure token calculations are complete before proceeding
|
|
328
|
+
if (agentContext.tokenCalculationPromise) {
|
|
329
|
+
await agentContext.tokenCalculationPromise;
|
|
299
330
|
}
|
|
300
331
|
if (!config.signal) {
|
|
301
332
|
config.signal = this.signal;
|
|
@@ -303,32 +334,32 @@ class StandardGraph extends Graph {
|
|
|
303
334
|
this.config = config;
|
|
304
335
|
const { messages } = state;
|
|
305
336
|
let messagesToUse = messages;
|
|
306
|
-
if (!
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
const isAnthropicWithThinking = (
|
|
311
|
-
|
|
337
|
+
if (!agentContext.pruneMessages &&
|
|
338
|
+
agentContext.tokenCounter &&
|
|
339
|
+
agentContext.maxContextTokens != null &&
|
|
340
|
+
agentContext.indexTokenCountMap[0] != null) {
|
|
341
|
+
const isAnthropicWithThinking = (agentContext.provider === Providers.ANTHROPIC &&
|
|
342
|
+
agentContext.clientOptions.thinking !=
|
|
312
343
|
null) ||
|
|
313
|
-
(
|
|
314
|
-
|
|
344
|
+
(agentContext.provider === Providers.BEDROCK &&
|
|
345
|
+
agentContext.clientOptions
|
|
315
346
|
.additionalModelRequestFields?.['thinking'] != null);
|
|
316
|
-
|
|
317
|
-
provider: this.provider,
|
|
318
|
-
indexTokenCountMap: this.indexTokenCountMap,
|
|
319
|
-
maxTokens: this.maxContextTokens,
|
|
320
|
-
tokenCounter: this.tokenCounter,
|
|
347
|
+
agentContext.pruneMessages = createPruneMessages({
|
|
321
348
|
startIndex: this.startIndex,
|
|
349
|
+
provider: agentContext.provider,
|
|
350
|
+
tokenCounter: agentContext.tokenCounter,
|
|
351
|
+
maxTokens: agentContext.maxContextTokens,
|
|
322
352
|
thinkingEnabled: isAnthropicWithThinking,
|
|
353
|
+
indexTokenCountMap: agentContext.indexTokenCountMap,
|
|
323
354
|
});
|
|
324
355
|
}
|
|
325
|
-
if (
|
|
326
|
-
const { context, indexTokenCountMap } =
|
|
356
|
+
if (agentContext.pruneMessages) {
|
|
357
|
+
const { context, indexTokenCountMap } = agentContext.pruneMessages({
|
|
327
358
|
messages,
|
|
328
|
-
usageMetadata:
|
|
359
|
+
usageMetadata: agentContext.currentUsage,
|
|
329
360
|
// startOnMessageType: 'human',
|
|
330
361
|
});
|
|
331
|
-
|
|
362
|
+
agentContext.indexTokenCountMap = indexTokenCountMap;
|
|
332
363
|
messagesToUse = context;
|
|
333
364
|
}
|
|
334
365
|
const finalMessages = messagesToUse;
|
|
@@ -338,87 +369,145 @@ class StandardGraph extends Graph {
|
|
|
338
369
|
const lastMessageY = finalMessages.length >= 1
|
|
339
370
|
? finalMessages[finalMessages.length - 1]
|
|
340
371
|
: null;
|
|
341
|
-
if (provider === Providers.BEDROCK &&
|
|
372
|
+
if (agentContext.provider === Providers.BEDROCK &&
|
|
342
373
|
lastMessageX instanceof AIMessageChunk &&
|
|
343
374
|
lastMessageY instanceof ToolMessage &&
|
|
344
375
|
typeof lastMessageX.content === 'string') {
|
|
345
376
|
finalMessages[finalMessages.length - 2].content = '';
|
|
346
377
|
}
|
|
347
378
|
const isLatestToolMessage = lastMessageY instanceof ToolMessage;
|
|
348
|
-
if (isLatestToolMessage &&
|
|
379
|
+
if (isLatestToolMessage &&
|
|
380
|
+
agentContext.provider === Providers.ANTHROPIC) {
|
|
349
381
|
formatAnthropicArtifactContent(finalMessages);
|
|
350
382
|
}
|
|
351
383
|
else if (isLatestToolMessage &&
|
|
352
|
-
(isOpenAILike(provider) ||
|
|
384
|
+
(isOpenAILike(agentContext.provider) ||
|
|
385
|
+
isGoogleLike(agentContext.provider))) {
|
|
353
386
|
formatArtifactPayload(finalMessages);
|
|
354
387
|
}
|
|
355
|
-
if (
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
388
|
+
if (agentContext.lastStreamCall != null &&
|
|
389
|
+
agentContext.streamBuffer != null) {
|
|
390
|
+
const timeSinceLastCall = Date.now() - agentContext.lastStreamCall;
|
|
391
|
+
if (timeSinceLastCall < agentContext.streamBuffer) {
|
|
392
|
+
const timeToWait = Math.ceil((agentContext.streamBuffer - timeSinceLastCall) / 1000) *
|
|
393
|
+
1000;
|
|
359
394
|
await sleep(timeToWait);
|
|
360
395
|
}
|
|
361
396
|
}
|
|
362
|
-
|
|
397
|
+
agentContext.lastStreamCall = Date.now();
|
|
363
398
|
let result;
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
399
|
+
const fallbacks = agentContext.clientOptions?.fallbacks ??
|
|
400
|
+
[];
|
|
401
|
+
try {
|
|
402
|
+
result = await this.attemptInvoke({
|
|
403
|
+
currentModel: model,
|
|
404
|
+
finalMessages,
|
|
405
|
+
provider: agentContext.provider,
|
|
406
|
+
tools: agentContext.tools,
|
|
407
|
+
}, config);
|
|
408
|
+
}
|
|
409
|
+
catch (primaryError) {
|
|
410
|
+
let lastError = primaryError;
|
|
411
|
+
for (const fb of fallbacks) {
|
|
412
|
+
try {
|
|
413
|
+
let model = this.getNewModel({
|
|
414
|
+
provider: fb.provider,
|
|
415
|
+
clientOptions: fb.clientOptions,
|
|
416
|
+
});
|
|
417
|
+
const bindableTools = agentContext.tools;
|
|
418
|
+
model = (!bindableTools || bindableTools.length === 0
|
|
419
|
+
? model
|
|
420
|
+
: model.bindTools(bindableTools));
|
|
421
|
+
result = await this.attemptInvoke({
|
|
422
|
+
currentModel: model,
|
|
423
|
+
finalMessages,
|
|
424
|
+
provider: fb.provider,
|
|
425
|
+
tools: agentContext.tools,
|
|
426
|
+
}, config);
|
|
427
|
+
lastError = undefined;
|
|
428
|
+
break;
|
|
372
429
|
}
|
|
373
|
-
|
|
374
|
-
|
|
430
|
+
catch (e) {
|
|
431
|
+
lastError = e;
|
|
432
|
+
continue;
|
|
375
433
|
}
|
|
376
434
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
const finalMessage = (await this.boundModel.invoke(finalMessages, config));
|
|
382
|
-
if ((finalMessage.tool_calls?.length ?? 0) > 0) {
|
|
383
|
-
finalMessage.tool_calls = finalMessage.tool_calls?.filter((tool_call) => {
|
|
384
|
-
if (!tool_call.name) {
|
|
385
|
-
return false;
|
|
386
|
-
}
|
|
387
|
-
return true;
|
|
388
|
-
});
|
|
435
|
+
if (lastError !== undefined) {
|
|
436
|
+
throw lastError;
|
|
389
437
|
}
|
|
390
|
-
result = { messages: [finalMessage] };
|
|
391
438
|
}
|
|
392
|
-
|
|
439
|
+
if (!result) {
|
|
440
|
+
throw new Error('No result after model invocation');
|
|
441
|
+
}
|
|
442
|
+
agentContext.currentUsage = this.getUsageMetadata(result.messages?.[0]);
|
|
393
443
|
this.cleanupSignalListener();
|
|
394
444
|
return result;
|
|
395
445
|
};
|
|
396
446
|
}
|
|
397
|
-
|
|
447
|
+
createAgentNode(agentId) {
|
|
448
|
+
const agentContext = this.agentContexts.get(agentId);
|
|
449
|
+
if (!agentContext) {
|
|
450
|
+
throw new Error(`Agent context not found for agentId: ${agentId}`);
|
|
451
|
+
}
|
|
452
|
+
let currentModel = this.initializeModel({
|
|
453
|
+
tools: agentContext.tools,
|
|
454
|
+
provider: agentContext.provider,
|
|
455
|
+
clientOptions: agentContext.clientOptions,
|
|
456
|
+
});
|
|
457
|
+
if (agentContext.systemRunnable) {
|
|
458
|
+
currentModel = agentContext.systemRunnable.pipe(currentModel);
|
|
459
|
+
}
|
|
460
|
+
const agentNode = `${AGENT}${agentId}`;
|
|
461
|
+
const toolNode = `${TOOLS}${agentId}`;
|
|
398
462
|
const routeMessage = (state, config) => {
|
|
399
463
|
this.config = config;
|
|
400
|
-
|
|
401
|
-
// if (!lastMessage?.tool_calls?.length) {
|
|
402
|
-
// return END;
|
|
403
|
-
// }
|
|
404
|
-
// return TOOLS;
|
|
405
|
-
return toolsCondition(state);
|
|
464
|
+
return toolsCondition(state, toolNode, this.invokedToolIds);
|
|
406
465
|
};
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
.
|
|
415
|
-
|
|
466
|
+
const StateAnnotation = Annotation.Root({
|
|
467
|
+
messages: Annotation({
|
|
468
|
+
reducer: messagesStateReducer,
|
|
469
|
+
default: () => [],
|
|
470
|
+
}),
|
|
471
|
+
});
|
|
472
|
+
const workflow = new StateGraph(StateAnnotation)
|
|
473
|
+
.addNode(agentNode, this.createCallModel(agentId, currentModel))
|
|
474
|
+
.addNode(toolNode, this.initializeTools({
|
|
475
|
+
currentTools: agentContext.tools,
|
|
476
|
+
currentToolMap: agentContext.toolMap,
|
|
477
|
+
}))
|
|
478
|
+
.addEdge(START, agentNode)
|
|
479
|
+
.addConditionalEdges(agentNode, routeMessage)
|
|
480
|
+
.addEdge(toolNode, agentContext.toolEnd ? END : agentNode);
|
|
481
|
+
// Cast to unknown to avoid tight coupling to external types; options are opt-in
|
|
482
|
+
return workflow.compile(this.compileOptions);
|
|
483
|
+
}
|
|
484
|
+
createWorkflow() {
|
|
485
|
+
/** Use the default (first) agent for now */
|
|
486
|
+
const agentNode = this.createAgentNode(this.defaultAgentId);
|
|
487
|
+
const StateAnnotation = Annotation.Root({
|
|
488
|
+
messages: Annotation({
|
|
489
|
+
reducer: (a, b) => {
|
|
490
|
+
if (!a.length) {
|
|
491
|
+
this.startIndex = a.length + b.length;
|
|
492
|
+
}
|
|
493
|
+
const result = messagesStateReducer(a, b);
|
|
494
|
+
this.messages = result;
|
|
495
|
+
return result;
|
|
496
|
+
},
|
|
497
|
+
default: () => [],
|
|
498
|
+
}),
|
|
499
|
+
});
|
|
500
|
+
const workflow = new StateGraph(StateAnnotation)
|
|
501
|
+
.addNode(this.defaultAgentId, agentNode, { ends: [END] })
|
|
502
|
+
.addEdge(START, this.defaultAgentId)
|
|
503
|
+
.compile();
|
|
504
|
+
return workflow;
|
|
416
505
|
}
|
|
417
506
|
/* Dispatchers */
|
|
418
507
|
/**
|
|
419
508
|
* Dispatches a run step to the client, returns the step ID
|
|
420
509
|
*/
|
|
421
|
-
dispatchRunStep(stepKey, stepDetails) {
|
|
510
|
+
async dispatchRunStep(stepKey, stepDetails) {
|
|
422
511
|
if (!this.config) {
|
|
423
512
|
throw new Error('No config provided');
|
|
424
513
|
}
|
|
@@ -446,17 +535,21 @@ class StandardGraph extends Graph {
|
|
|
446
535
|
}
|
|
447
536
|
this.contentData.push(runStep);
|
|
448
537
|
this.contentIndexMap.set(stepId, runStep.index);
|
|
449
|
-
|
|
538
|
+
await safeDispatchCustomEvent(GraphEvents.ON_RUN_STEP, runStep, this.config);
|
|
450
539
|
return stepId;
|
|
451
540
|
}
|
|
452
|
-
handleToolCallCompleted(data, metadata) {
|
|
541
|
+
async handleToolCallCompleted(data, metadata, omitOutput) {
|
|
453
542
|
if (!this.config) {
|
|
454
543
|
throw new Error('No config provided');
|
|
455
544
|
}
|
|
456
545
|
if (!data.output) {
|
|
457
546
|
return;
|
|
458
547
|
}
|
|
459
|
-
const { input, output } = data;
|
|
548
|
+
const { input, output: _output } = data;
|
|
549
|
+
if (_output?.lg_name === 'Command') {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
const output = _output;
|
|
460
553
|
const { tool_call_id } = output;
|
|
461
554
|
const stepId = this.toolCallStepIds.get(tool_call_id) ?? '';
|
|
462
555
|
if (!stepId) {
|
|
@@ -466,17 +559,20 @@ class StandardGraph extends Graph {
|
|
|
466
559
|
if (!runStep) {
|
|
467
560
|
throw new Error(`No run step found for stepId ${stepId}`);
|
|
468
561
|
}
|
|
562
|
+
const dispatchedOutput = typeof output.content === 'string'
|
|
563
|
+
? output.content
|
|
564
|
+
: JSON.stringify(output.content);
|
|
469
565
|
const args = typeof input === 'string' ? input : input.input;
|
|
470
566
|
const tool_call = {
|
|
471
567
|
args: typeof args === 'string' ? args : JSON.stringify(args),
|
|
472
568
|
name: output.name ?? '',
|
|
473
569
|
id: output.tool_call_id,
|
|
474
|
-
output:
|
|
475
|
-
? output.content
|
|
476
|
-
: JSON.stringify(output.content),
|
|
570
|
+
output: omitOutput === true ? '' : dispatchedOutput,
|
|
477
571
|
progress: 1,
|
|
478
572
|
};
|
|
479
|
-
this.handlerRegistry
|
|
573
|
+
await this.handlerRegistry
|
|
574
|
+
?.getHandler(GraphEvents.ON_RUN_STEP_COMPLETED)
|
|
575
|
+
?.handle(GraphEvents.ON_RUN_STEP_COMPLETED, {
|
|
480
576
|
result: {
|
|
481
577
|
id: stepId,
|
|
482
578
|
index: runStep.index,
|
|
@@ -489,7 +585,7 @@ class StandardGraph extends Graph {
|
|
|
489
585
|
* Static version of handleToolCallError to avoid creating strong references
|
|
490
586
|
* that prevent garbage collection
|
|
491
587
|
*/
|
|
492
|
-
static handleToolCallErrorStatic(graph, data, metadata) {
|
|
588
|
+
static async handleToolCallErrorStatic(graph, data, metadata) {
|
|
493
589
|
if (!graph.config) {
|
|
494
590
|
throw new Error('No config provided');
|
|
495
591
|
}
|
|
@@ -513,7 +609,7 @@ class StandardGraph extends Graph {
|
|
|
513
609
|
output: `Error processing tool${error?.message != null ? `: ${error.message}` : ''}`,
|
|
514
610
|
progress: 1,
|
|
515
611
|
};
|
|
516
|
-
graph.handlerRegistry
|
|
612
|
+
await graph.handlerRegistry
|
|
517
613
|
?.getHandler(GraphEvents.ON_RUN_STEP_COMPLETED)
|
|
518
614
|
?.handle(GraphEvents.ON_RUN_STEP_COMPLETED, {
|
|
519
615
|
result: {
|
|
@@ -528,10 +624,10 @@ class StandardGraph extends Graph {
|
|
|
528
624
|
* Instance method that delegates to the static method
|
|
529
625
|
* Kept for backward compatibility
|
|
530
626
|
*/
|
|
531
|
-
handleToolCallError(data, metadata) {
|
|
532
|
-
StandardGraph.handleToolCallErrorStatic(this, data, metadata);
|
|
627
|
+
async handleToolCallError(data, metadata) {
|
|
628
|
+
await StandardGraph.handleToolCallErrorStatic(this, data, metadata);
|
|
533
629
|
}
|
|
534
|
-
dispatchRunStepDelta(id, delta) {
|
|
630
|
+
async dispatchRunStepDelta(id, delta) {
|
|
535
631
|
if (!this.config) {
|
|
536
632
|
throw new Error('No config provided');
|
|
537
633
|
}
|
|
@@ -542,9 +638,9 @@ class StandardGraph extends Graph {
|
|
|
542
638
|
id,
|
|
543
639
|
delta,
|
|
544
640
|
};
|
|
545
|
-
|
|
641
|
+
await safeDispatchCustomEvent(GraphEvents.ON_RUN_STEP_DELTA, runStepDelta, this.config);
|
|
546
642
|
}
|
|
547
|
-
dispatchMessageDelta(id, delta) {
|
|
643
|
+
async dispatchMessageDelta(id, delta) {
|
|
548
644
|
if (!this.config) {
|
|
549
645
|
throw new Error('No config provided');
|
|
550
646
|
}
|
|
@@ -552,9 +648,9 @@ class StandardGraph extends Graph {
|
|
|
552
648
|
id,
|
|
553
649
|
delta,
|
|
554
650
|
};
|
|
555
|
-
|
|
651
|
+
await safeDispatchCustomEvent(GraphEvents.ON_MESSAGE_DELTA, messageDelta, this.config);
|
|
556
652
|
}
|
|
557
|
-
dispatchReasoningDelta = (stepId, delta) => {
|
|
653
|
+
dispatchReasoningDelta = async (stepId, delta) => {
|
|
558
654
|
if (!this.config) {
|
|
559
655
|
throw new Error('No config provided');
|
|
560
656
|
}
|
|
@@ -562,7 +658,7 @@ class StandardGraph extends Graph {
|
|
|
562
658
|
id: stepId,
|
|
563
659
|
delta,
|
|
564
660
|
};
|
|
565
|
-
|
|
661
|
+
await safeDispatchCustomEvent(GraphEvents.ON_REASONING_DELTA, reasoningDelta, this.config);
|
|
566
662
|
};
|
|
567
663
|
}
|
|
568
664
|
|