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.
Files changed (225) hide show
  1. package/LICENSE +25 -21
  2. package/dist/cjs/agents/AgentContext.cjs +222 -0
  3. package/dist/cjs/agents/AgentContext.cjs.map +1 -0
  4. package/dist/cjs/common/enum.cjs +5 -4
  5. package/dist/cjs/common/enum.cjs.map +1 -1
  6. package/dist/cjs/events.cjs +7 -5
  7. package/dist/cjs/events.cjs.map +1 -1
  8. package/dist/cjs/graphs/Graph.cjs +328 -207
  9. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  10. package/dist/cjs/graphs/MultiAgentGraph.cjs +507 -0
  11. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -0
  12. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  13. package/dist/cjs/llm/google/index.cjs.map +1 -1
  14. package/dist/cjs/llm/ollama/index.cjs.map +1 -1
  15. package/dist/cjs/llm/openai/index.cjs +35 -0
  16. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  17. package/dist/cjs/llm/openai/utils/index.cjs +3 -1
  18. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  19. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  20. package/dist/cjs/llm/providers.cjs +0 -2
  21. package/dist/cjs/llm/providers.cjs.map +1 -1
  22. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  23. package/dist/cjs/main.cjs +12 -1
  24. package/dist/cjs/main.cjs.map +1 -1
  25. package/dist/cjs/messages/cache.cjs +123 -0
  26. package/dist/cjs/messages/cache.cjs.map +1 -0
  27. package/dist/cjs/messages/content.cjs +53 -0
  28. package/dist/cjs/messages/content.cjs.map +1 -0
  29. package/dist/cjs/messages/format.cjs +17 -29
  30. package/dist/cjs/messages/format.cjs.map +1 -1
  31. package/dist/cjs/run.cjs +119 -74
  32. package/dist/cjs/run.cjs.map +1 -1
  33. package/dist/cjs/stream.cjs +77 -73
  34. package/dist/cjs/stream.cjs.map +1 -1
  35. package/dist/cjs/tools/Calculator.cjs +45 -0
  36. package/dist/cjs/tools/Calculator.cjs.map +1 -0
  37. package/dist/cjs/tools/CodeExecutor.cjs +22 -22
  38. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  39. package/dist/cjs/tools/ToolNode.cjs +5 -3
  40. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  41. package/dist/cjs/tools/handlers.cjs +20 -20
  42. package/dist/cjs/tools/handlers.cjs.map +1 -1
  43. package/dist/cjs/utils/events.cjs +31 -0
  44. package/dist/cjs/utils/events.cjs.map +1 -0
  45. package/dist/cjs/utils/handlers.cjs +70 -0
  46. package/dist/cjs/utils/handlers.cjs.map +1 -0
  47. package/dist/cjs/utils/tokens.cjs +54 -7
  48. package/dist/cjs/utils/tokens.cjs.map +1 -1
  49. package/dist/esm/agents/AgentContext.mjs +220 -0
  50. package/dist/esm/agents/AgentContext.mjs.map +1 -0
  51. package/dist/esm/common/enum.mjs +5 -4
  52. package/dist/esm/common/enum.mjs.map +1 -1
  53. package/dist/esm/events.mjs +7 -5
  54. package/dist/esm/events.mjs.map +1 -1
  55. package/dist/esm/graphs/Graph.mjs +330 -209
  56. package/dist/esm/graphs/Graph.mjs.map +1 -1
  57. package/dist/esm/graphs/MultiAgentGraph.mjs +505 -0
  58. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -0
  59. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  60. package/dist/esm/llm/google/index.mjs.map +1 -1
  61. package/dist/esm/llm/ollama/index.mjs.map +1 -1
  62. package/dist/esm/llm/openai/index.mjs +35 -0
  63. package/dist/esm/llm/openai/index.mjs.map +1 -1
  64. package/dist/esm/llm/openai/utils/index.mjs +3 -1
  65. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  66. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  67. package/dist/esm/llm/providers.mjs +0 -2
  68. package/dist/esm/llm/providers.mjs.map +1 -1
  69. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  70. package/dist/esm/main.mjs +7 -2
  71. package/dist/esm/main.mjs.map +1 -1
  72. package/dist/esm/messages/cache.mjs +120 -0
  73. package/dist/esm/messages/cache.mjs.map +1 -0
  74. package/dist/esm/messages/content.mjs +51 -0
  75. package/dist/esm/messages/content.mjs.map +1 -0
  76. package/dist/esm/messages/format.mjs +18 -29
  77. package/dist/esm/messages/format.mjs.map +1 -1
  78. package/dist/esm/run.mjs +119 -74
  79. package/dist/esm/run.mjs.map +1 -1
  80. package/dist/esm/stream.mjs +77 -73
  81. package/dist/esm/stream.mjs.map +1 -1
  82. package/dist/esm/tools/Calculator.mjs +24 -0
  83. package/dist/esm/tools/Calculator.mjs.map +1 -0
  84. package/dist/esm/tools/CodeExecutor.mjs +22 -22
  85. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  86. package/dist/esm/tools/ToolNode.mjs +5 -3
  87. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  88. package/dist/esm/tools/handlers.mjs +20 -20
  89. package/dist/esm/tools/handlers.mjs.map +1 -1
  90. package/dist/esm/utils/events.mjs +29 -0
  91. package/dist/esm/utils/events.mjs.map +1 -0
  92. package/dist/esm/utils/handlers.mjs +68 -0
  93. package/dist/esm/utils/handlers.mjs.map +1 -0
  94. package/dist/esm/utils/tokens.mjs +54 -8
  95. package/dist/esm/utils/tokens.mjs.map +1 -1
  96. package/dist/types/agents/AgentContext.d.ts +94 -0
  97. package/dist/types/common/enum.d.ts +7 -5
  98. package/dist/types/events.d.ts +3 -3
  99. package/dist/types/graphs/Graph.d.ts +60 -66
  100. package/dist/types/graphs/MultiAgentGraph.d.ts +47 -0
  101. package/dist/types/graphs/index.d.ts +1 -0
  102. package/dist/types/index.d.ts +1 -0
  103. package/dist/types/llm/openai/index.d.ts +10 -0
  104. package/dist/types/messages/cache.d.ts +20 -0
  105. package/dist/types/messages/content.d.ts +7 -0
  106. package/dist/types/messages/format.d.ts +1 -7
  107. package/dist/types/messages/index.d.ts +2 -0
  108. package/dist/types/messages/reducer.d.ts +9 -0
  109. package/dist/types/run.d.ts +16 -10
  110. package/dist/types/stream.d.ts +4 -3
  111. package/dist/types/tools/Calculator.d.ts +8 -0
  112. package/dist/types/tools/ToolNode.d.ts +1 -1
  113. package/dist/types/tools/handlers.d.ts +9 -7
  114. package/dist/types/tools/search/tool.d.ts +4 -4
  115. package/dist/types/types/graph.d.ts +124 -11
  116. package/dist/types/types/llm.d.ts +13 -9
  117. package/dist/types/types/messages.d.ts +4 -0
  118. package/dist/types/types/run.d.ts +46 -8
  119. package/dist/types/types/stream.d.ts +3 -2
  120. package/dist/types/utils/events.d.ts +6 -0
  121. package/dist/types/utils/handlers.d.ts +34 -0
  122. package/dist/types/utils/index.d.ts +1 -0
  123. package/dist/types/utils/tokens.d.ts +24 -0
  124. package/package.json +162 -145
  125. package/src/agents/AgentContext.ts +323 -0
  126. package/src/common/enum.ts +177 -176
  127. package/src/events.ts +197 -191
  128. package/src/graphs/Graph.ts +1058 -846
  129. package/src/graphs/MultiAgentGraph.ts +598 -0
  130. package/src/graphs/index.ts +2 -1
  131. package/src/index.ts +25 -24
  132. package/src/llm/anthropic/index.ts +413 -413
  133. package/src/llm/google/index.ts +222 -222
  134. package/src/llm/google/utils/zod_to_genai_parameters.ts +86 -88
  135. package/src/llm/ollama/index.ts +92 -92
  136. package/src/llm/openai/index.ts +894 -853
  137. package/src/llm/openai/utils/index.ts +920 -918
  138. package/src/llm/openrouter/index.ts +60 -60
  139. package/src/llm/providers.ts +55 -57
  140. package/src/llm/vertexai/index.ts +360 -360
  141. package/src/messages/cache.test.ts +461 -0
  142. package/src/messages/cache.ts +151 -0
  143. package/src/messages/content.test.ts +362 -0
  144. package/src/messages/content.ts +63 -0
  145. package/src/messages/format.ts +611 -625
  146. package/src/messages/formatAgentMessages.test.ts +1144 -917
  147. package/src/messages/index.ts +6 -4
  148. package/src/messages/reducer.ts +80 -0
  149. package/src/run.ts +447 -381
  150. package/src/scripts/abort.ts +157 -138
  151. package/src/scripts/ant_web_search.ts +158 -158
  152. package/src/scripts/cli.ts +172 -167
  153. package/src/scripts/cli2.ts +133 -125
  154. package/src/scripts/cli3.ts +184 -178
  155. package/src/scripts/cli4.ts +191 -184
  156. package/src/scripts/cli5.ts +191 -184
  157. package/src/scripts/code_exec.ts +213 -214
  158. package/src/scripts/code_exec_simple.ts +147 -129
  159. package/src/scripts/content.ts +138 -120
  160. package/src/scripts/handoff-test.ts +135 -0
  161. package/src/scripts/multi-agent-chain.ts +278 -0
  162. package/src/scripts/multi-agent-conditional.ts +220 -0
  163. package/src/scripts/multi-agent-document-review-chain.ts +197 -0
  164. package/src/scripts/multi-agent-hybrid-flow.ts +310 -0
  165. package/src/scripts/multi-agent-parallel.ts +343 -0
  166. package/src/scripts/multi-agent-sequence.ts +212 -0
  167. package/src/scripts/multi-agent-supervisor.ts +364 -0
  168. package/src/scripts/multi-agent-test.ts +186 -0
  169. package/src/scripts/search.ts +146 -150
  170. package/src/scripts/simple.ts +225 -225
  171. package/src/scripts/stream.ts +140 -122
  172. package/src/scripts/test-custom-prompt-key.ts +145 -0
  173. package/src/scripts/test-handoff-input.ts +170 -0
  174. package/src/scripts/test-multi-agent-list-handoff.ts +261 -0
  175. package/src/scripts/test-tools-before-handoff.ts +222 -0
  176. package/src/scripts/tools.ts +153 -155
  177. package/src/specs/agent-handoffs.test.ts +889 -0
  178. package/src/specs/anthropic.simple.test.ts +320 -317
  179. package/src/specs/azure.simple.test.ts +325 -316
  180. package/src/specs/openai.simple.test.ts +311 -316
  181. package/src/specs/openrouter.simple.test.ts +107 -0
  182. package/src/specs/prune.test.ts +758 -763
  183. package/src/specs/reasoning.test.ts +201 -165
  184. package/src/specs/thinking-prune.test.ts +769 -703
  185. package/src/specs/token-memoization.test.ts +39 -0
  186. package/src/stream.ts +664 -651
  187. package/src/tools/Calculator.test.ts +278 -0
  188. package/src/tools/Calculator.ts +25 -0
  189. package/src/tools/CodeExecutor.ts +220 -220
  190. package/src/tools/ToolNode.ts +170 -170
  191. package/src/tools/handlers.ts +341 -336
  192. package/src/types/graph.ts +372 -185
  193. package/src/types/llm.ts +141 -140
  194. package/src/types/messages.ts +4 -0
  195. package/src/types/run.ts +128 -89
  196. package/src/types/stream.ts +401 -400
  197. package/src/utils/events.ts +32 -0
  198. package/src/utils/handlers.ts +107 -0
  199. package/src/utils/index.ts +6 -5
  200. package/src/utils/llmConfig.ts +183 -183
  201. package/src/utils/tokens.ts +129 -70
  202. package/dist/types/scripts/abort.d.ts +0 -1
  203. package/dist/types/scripts/ant_web_search.d.ts +0 -1
  204. package/dist/types/scripts/args.d.ts +0 -7
  205. package/dist/types/scripts/caching.d.ts +0 -1
  206. package/dist/types/scripts/cli.d.ts +0 -1
  207. package/dist/types/scripts/cli2.d.ts +0 -1
  208. package/dist/types/scripts/cli3.d.ts +0 -1
  209. package/dist/types/scripts/cli4.d.ts +0 -1
  210. package/dist/types/scripts/cli5.d.ts +0 -1
  211. package/dist/types/scripts/code_exec.d.ts +0 -1
  212. package/dist/types/scripts/code_exec_files.d.ts +0 -1
  213. package/dist/types/scripts/code_exec_simple.d.ts +0 -1
  214. package/dist/types/scripts/content.d.ts +0 -1
  215. package/dist/types/scripts/empty_input.d.ts +0 -1
  216. package/dist/types/scripts/image.d.ts +0 -1
  217. package/dist/types/scripts/memory.d.ts +0 -1
  218. package/dist/types/scripts/search.d.ts +0 -1
  219. package/dist/types/scripts/simple.d.ts +0 -1
  220. package/dist/types/scripts/stream.d.ts +0 -1
  221. package/dist/types/scripts/thinking.d.ts +0 -1
  222. package/dist/types/scripts/tools.d.ts +0 -1
  223. package/dist/types/specs/spec.utils.d.ts +0 -1
  224. package/dist/types/tools/example.d.ts +0 -78
  225. 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 { dispatchCustomEvent } from '@langchain/core/callbacks/dispatch';
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 { getChatModelClass, manualToolStreamProviders } from '../llm/providers.mjs';
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
- graphState;
49
- clientOptions;
50
- boundModel;
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
- constructor({ runId, tools, signal, toolMap, provider, streamBuffer, instructions, reasoningKey, clientOptions, toolEnd = false, additional_instructions = '', }) {
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
- this.toolEnd = toolEnd;
68
- this.toolMap = toolMap;
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
- let finalInstructions = instructions;
78
- if (additional_instructions) {
79
- finalInstructions =
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.prelimMessageIdsByStepKey, new Map());
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
- if (this.currentTokenType === ContentTypes.THINK ||
180
- this.currentTokenType === 'think_and_text') {
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 (this.tokenTypeSwitch === 'content') {
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
- createGraphState() {
203
- return {
204
- messages: {
205
- value: (x, y) => {
206
- if (!x.length) {
207
- if (this.systemMessage) {
208
- x.push(this.systemMessage);
209
- }
210
- this.startIndex = x.length + y.length;
211
- }
212
- const current = x.concat(y);
213
- this.messages = current;
214
- return current;
215
- },
216
- default: () => [],
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: this.tools || [],
224
- toolMap: this.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(this.provider);
231
- const model = new ChatModelClass(this.clientOptions);
232
- if (isOpenAILike(this.provider) &&
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 = this.clientOptions
227
+ model.temperature = clientOptions
235
228
  .temperature;
236
- model.topP = this.clientOptions.topP;
237
- model.frequencyPenalty = this.clientOptions
229
+ model.topP = clientOptions.topP;
230
+ model.frequencyPenalty = clientOptions
238
231
  .frequencyPenalty;
239
- model.presencePenalty = this.clientOptions
232
+ model.presencePenalty = clientOptions
240
233
  .presencePenalty;
241
- model.n = this.clientOptions.n;
234
+ model.n = clientOptions.n;
242
235
  }
243
- else if (this.provider === Providers.VERTEXAI &&
236
+ else if (provider === Providers.VERTEXAI &&
244
237
  model instanceof ChatVertexAI) {
245
- model.temperature = this.clientOptions
238
+ model.temperature = clientOptions
246
239
  .temperature;
247
- model.topP = this.clientOptions
248
- .topP;
249
- model.topK = this.clientOptions
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 = this.clientOptions
244
+ model.frequencyPenalty = clientOptions
254
245
  .frequencyPenalty;
255
- model.presencePenalty = this.clientOptions
246
+ model.presencePenalty = clientOptions
256
247
  .presencePenalty;
257
- model.maxOutputTokens = this.clientOptions
248
+ model.maxOutputTokens = clientOptions
258
249
  .maxOutputTokens;
259
250
  }
260
- if (!this.tools || this.tools.length === 0) {
251
+ if (!tools || tools.length === 0) {
261
252
  return model;
262
253
  }
263
- return model.bindTools(this.tools);
254
+ return model.bindTools(tools);
264
255
  }
265
256
  overrideTestModel(responses, sleep, toolCalls) {
266
- this.boundModel = createFakeStreamingLLM({
257
+ this.overrideModel = createFakeStreamingLLM({
267
258
  responses,
268
259
  sleep,
269
260
  toolCalls,
270
261
  });
271
262
  }
272
- getNewModel({ provider, clientOptions, omitOptions, }) {
263
+ getNewModel({ provider, clientOptions, }) {
273
264
  const ChatModelClass = getChatModelClass(provider);
274
- const options = omitOptions && clientOptions == null
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
- storeUsageMetadata(finalMessage) {
267
+ getUsageMetadata(finalMessage) {
280
268
  if (finalMessage &&
281
269
  'usage_metadata' in finalMessage &&
282
270
  finalMessage.usage_metadata != null) {
283
- this.currentUsage = finalMessage.usage_metadata;
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
- if (!this.boundModel) {
305
+ const model = this.overrideModel ?? currentModel;
306
+ if (!model) {
291
307
  return;
292
308
  }
293
- const client = this.boundModel?.exposedClient;
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
- const { provider = '' } = config?.configurable ?? {};
303
- if (this.boundModel == null) {
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 || !provider) {
307
- throw new Error(`No ${config ? 'provider' : 'config'} provided`);
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 (!this.pruneMessages &&
316
- this.tokenCounter &&
317
- this.maxContextTokens != null &&
318
- this.indexTokenCountMap[0] != null) {
319
- const isAnthropicWithThinking = (this.provider === Providers.ANTHROPIC &&
320
- this.clientOptions.thinking !=
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
- (this.provider === Providers.BEDROCK &&
323
- this.clientOptions
349
+ (agentContext.provider === Providers.BEDROCK &&
350
+ agentContext.clientOptions
324
351
  .additionalModelRequestFields?.['thinking'] != null) ||
325
- (this.provider === Providers.OPENAI &&
326
- this.clientOptions.modelKwargs
352
+ (agentContext.provider === Providers.OPENAI &&
353
+ agentContext.clientOptions.modelKwargs
327
354
  ?.thinking?.type === 'enabled');
328
- this.pruneMessages = createPruneMessages({
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 (this.pruneMessages) {
338
- const { context, indexTokenCountMap } = this.pruneMessages({
364
+ if (agentContext.pruneMessages) {
365
+ const { context, indexTokenCountMap } = agentContext.pruneMessages({
339
366
  messages,
340
- usageMetadata: this.currentUsage,
367
+ usageMetadata: agentContext.currentUsage,
341
368
  // startOnMessageType: 'human',
342
369
  });
343
- this.indexTokenCountMap = indexTokenCountMap;
370
+ agentContext.indexTokenCountMap = indexTokenCountMap;
344
371
  messagesToUse = context;
345
372
  }
346
- const finalMessages = messagesToUse;
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 && provider === Providers.ANTHROPIC) {
390
+ if (isLatestToolMessage &&
391
+ agentContext.provider === Providers.ANTHROPIC) {
361
392
  formatAnthropicArtifactContent(finalMessages);
362
393
  }
363
394
  else if (isLatestToolMessage &&
364
- (isOpenAILike(provider) || isGoogleLike(provider))) {
395
+ (isOpenAILike(agentContext.provider) ||
396
+ isGoogleLike(agentContext.provider))) {
365
397
  formatArtifactPayload(finalMessages);
366
398
  }
367
- if (this.lastStreamCall != null && this.streamBuffer != null) {
368
- const timeSinceLastCall = Date.now() - this.lastStreamCall;
369
- if (timeSinceLastCall < this.streamBuffer) {
370
- const timeToWait = Math.ceil((this.streamBuffer - timeSinceLastCall) / 1000) * 1000;
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
- this.lastStreamCall = Date.now();
424
+ agentContext.lastStreamCall = Date.now();
375
425
  let result;
376
- if ((this.tools?.length ?? 0) > 0 &&
377
- manualToolStreamProviders.has(provider)) {
378
- const stream = await this.boundModel.stream(finalMessages, config);
379
- let finalChunk;
380
- for await (const chunk of stream) {
381
- dispatchCustomEvent(GraphEvents.CHAT_MODEL_STREAM, { chunk }, config);
382
- if (!finalChunk) {
383
- finalChunk = chunk;
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
- else {
386
- finalChunk = concat(finalChunk, chunk);
463
+ catch (e) {
464
+ lastError = e;
465
+ continue;
387
466
  }
388
467
  }
389
- finalChunk = modifyDeltaProperties(this.provider, finalChunk);
390
- result = { messages: [finalChunk] };
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
- this.storeUsageMetadata(result.messages?.[0]);
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
- createWorkflow() {
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 workflow = new StateGraph({
415
- channels: this.graphState,
416
- })
417
- .addNode(AGENT, this.createCallModel())
418
- .addNode(TOOLS, this.initializeTools())
419
- .addEdge(START, AGENT)
420
- .addConditionalEdges(AGENT, routeMessage)
421
- .addEdge(TOOLS, this.toolEnd ? END : AGENT);
422
- return workflow.compile();
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
- dispatchCustomEvent(GraphEvents.ON_RUN_STEP, runStep, this.config);
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?.getHandler(GraphEvents.ON_RUN_STEP_COMPLETED)?.handle(GraphEvents.ON_RUN_STEP_COMPLETED, {
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
- dispatchCustomEvent(GraphEvents.ON_RUN_STEP_DELTA, runStepDelta, this.config);
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
- dispatchCustomEvent(GraphEvents.ON_MESSAGE_DELTA, messageDelta, this.config);
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
- dispatchCustomEvent(GraphEvents.ON_REASONING_DELTA, reasoningDelta, this.config);
694
+ await safeDispatchCustomEvent(GraphEvents.ON_REASONING_DELTA, reasoningDelta, this.config);
574
695
  };
575
696
  }
576
697