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