@librechat/agents 3.1.86 → 3.1.88

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 (160) hide show
  1. package/README.md +69 -0
  2. package/dist/cjs/events.cjs +23 -0
  3. package/dist/cjs/events.cjs.map +1 -1
  4. package/dist/cjs/graphs/Graph.cjs +133 -18
  5. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  6. package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
  7. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  8. package/dist/cjs/llm/anthropic/index.cjs +251 -53
  9. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  10. package/dist/cjs/llm/init.cjs +1 -5
  11. package/dist/cjs/llm/init.cjs.map +1 -1
  12. package/dist/cjs/llm/openai/index.cjs +113 -24
  13. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  14. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  15. package/dist/cjs/llm/openrouter/index.cjs +3 -1
  16. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  17. package/dist/cjs/main.cjs +18 -5
  18. package/dist/cjs/main.cjs.map +1 -1
  19. package/dist/cjs/openai/index.cjs +253 -0
  20. package/dist/cjs/openai/index.cjs.map +1 -0
  21. package/dist/cjs/responses/index.cjs +448 -0
  22. package/dist/cjs/responses/index.cjs.map +1 -0
  23. package/dist/cjs/run.cjs +108 -7
  24. package/dist/cjs/run.cjs.map +1 -1
  25. package/dist/cjs/session/AgentSession.cjs +1057 -0
  26. package/dist/cjs/session/AgentSession.cjs.map +1 -0
  27. package/dist/cjs/session/JsonlSessionStore.cjs +425 -0
  28. package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -0
  29. package/dist/cjs/session/handlers.cjs +221 -0
  30. package/dist/cjs/session/handlers.cjs.map +1 -0
  31. package/dist/cjs/session/ids.cjs +22 -0
  32. package/dist/cjs/session/ids.cjs.map +1 -0
  33. package/dist/cjs/session/messageSerialization.cjs +179 -0
  34. package/dist/cjs/session/messageSerialization.cjs.map +1 -0
  35. package/dist/cjs/stream.cjs +475 -11
  36. package/dist/cjs/stream.cjs.map +1 -1
  37. package/dist/cjs/summarization/node.cjs +1 -1
  38. package/dist/cjs/summarization/node.cjs.map +1 -1
  39. package/dist/cjs/tools/ToolNode.cjs +177 -59
  40. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  41. package/dist/cjs/tools/eagerEventExecution.cjs +113 -0
  42. package/dist/cjs/tools/eagerEventExecution.cjs.map +1 -0
  43. package/dist/cjs/tools/handlers.cjs +1 -1
  44. package/dist/cjs/tools/handlers.cjs.map +1 -1
  45. package/dist/cjs/tools/streamedToolCallSeals.cjs +42 -0
  46. package/dist/cjs/tools/streamedToolCallSeals.cjs.map +1 -0
  47. package/dist/esm/events.mjs +23 -1
  48. package/dist/esm/events.mjs.map +1 -1
  49. package/dist/esm/graphs/Graph.mjs +133 -18
  50. package/dist/esm/graphs/Graph.mjs.map +1 -1
  51. package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
  52. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  53. package/dist/esm/llm/anthropic/index.mjs +251 -53
  54. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  55. package/dist/esm/llm/init.mjs +1 -5
  56. package/dist/esm/llm/init.mjs.map +1 -1
  57. package/dist/esm/llm/openai/index.mjs +113 -25
  58. package/dist/esm/llm/openai/index.mjs.map +1 -1
  59. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  60. package/dist/esm/llm/openrouter/index.mjs +4 -2
  61. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  62. package/dist/esm/main.mjs +5 -1
  63. package/dist/esm/main.mjs.map +1 -1
  64. package/dist/esm/openai/index.mjs +246 -0
  65. package/dist/esm/openai/index.mjs.map +1 -0
  66. package/dist/esm/responses/index.mjs +440 -0
  67. package/dist/esm/responses/index.mjs.map +1 -0
  68. package/dist/esm/run.mjs +108 -7
  69. package/dist/esm/run.mjs.map +1 -1
  70. package/dist/esm/session/AgentSession.mjs +1054 -0
  71. package/dist/esm/session/AgentSession.mjs.map +1 -0
  72. package/dist/esm/session/JsonlSessionStore.mjs +422 -0
  73. package/dist/esm/session/JsonlSessionStore.mjs.map +1 -0
  74. package/dist/esm/session/handlers.mjs +219 -0
  75. package/dist/esm/session/handlers.mjs.map +1 -0
  76. package/dist/esm/session/ids.mjs +17 -0
  77. package/dist/esm/session/ids.mjs.map +1 -0
  78. package/dist/esm/session/messageSerialization.mjs +173 -0
  79. package/dist/esm/session/messageSerialization.mjs.map +1 -0
  80. package/dist/esm/stream.mjs +476 -12
  81. package/dist/esm/stream.mjs.map +1 -1
  82. package/dist/esm/summarization/node.mjs +1 -1
  83. package/dist/esm/summarization/node.mjs.map +1 -1
  84. package/dist/esm/tools/ToolNode.mjs +177 -59
  85. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  86. package/dist/esm/tools/eagerEventExecution.mjs +107 -0
  87. package/dist/esm/tools/eagerEventExecution.mjs.map +1 -0
  88. package/dist/esm/tools/handlers.mjs +1 -1
  89. package/dist/esm/tools/handlers.mjs.map +1 -1
  90. package/dist/esm/tools/streamedToolCallSeals.mjs +36 -0
  91. package/dist/esm/tools/streamedToolCallSeals.mjs.map +1 -0
  92. package/dist/types/events.d.ts +1 -0
  93. package/dist/types/graphs/Graph.d.ts +24 -9
  94. package/dist/types/index.d.ts +1 -0
  95. package/dist/types/llm/openai/index.d.ts +1 -0
  96. package/dist/types/openai/index.d.ts +75 -0
  97. package/dist/types/responses/index.d.ts +97 -0
  98. package/dist/types/run.d.ts +2 -0
  99. package/dist/types/session/AgentSession.d.ts +32 -0
  100. package/dist/types/session/JsonlSessionStore.d.ts +67 -0
  101. package/dist/types/session/handlers.d.ts +8 -0
  102. package/dist/types/session/ids.d.ts +4 -0
  103. package/dist/types/session/index.d.ts +5 -0
  104. package/dist/types/session/messageSerialization.d.ts +7 -0
  105. package/dist/types/session/types.d.ts +191 -0
  106. package/dist/types/tools/ToolNode.d.ts +12 -1
  107. package/dist/types/tools/eagerEventExecution.d.ts +23 -0
  108. package/dist/types/tools/streamedToolCallSeals.d.ts +13 -0
  109. package/dist/types/types/hitl.d.ts +4 -0
  110. package/dist/types/types/run.d.ts +11 -1
  111. package/dist/types/types/tools.d.ts +36 -0
  112. package/package.json +19 -2
  113. package/src/__tests__/stream.eagerEventExecution.test.ts +2571 -0
  114. package/src/events.ts +29 -0
  115. package/src/graphs/Graph.ts +224 -50
  116. package/src/graphs/MultiAgentGraph.ts +1 -1
  117. package/src/graphs/__tests__/composition.smoke.test.ts +30 -0
  118. package/src/index.ts +3 -0
  119. package/src/llm/anthropic/index.ts +356 -84
  120. package/src/llm/anthropic/llm.spec.ts +64 -0
  121. package/src/llm/custom-chat-models.smoke.test.ts +175 -4
  122. package/src/llm/openai/contentBlocks.test.ts +35 -0
  123. package/src/llm/openai/deepseek.test.ts +201 -2
  124. package/src/llm/openai/index.ts +171 -26
  125. package/src/llm/openai/utils/index.ts +22 -0
  126. package/src/llm/openrouter/index.ts +4 -2
  127. package/src/openai/__tests__/openai.test.ts +337 -0
  128. package/src/openai/index.ts +404 -0
  129. package/src/responses/__tests__/responses.test.ts +652 -0
  130. package/src/responses/index.ts +677 -0
  131. package/src/run.ts +158 -8
  132. package/src/scripts/compare_pi_vs_ours.ts +592 -173
  133. package/src/scripts/session_live.ts +548 -0
  134. package/src/session/AgentSession.ts +1432 -0
  135. package/src/session/JsonlSessionStore.ts +572 -0
  136. package/src/session/__tests__/JsonlSessionStore.test.ts +1410 -0
  137. package/src/session/__tests__/handlers.test.ts +161 -0
  138. package/src/session/handlers.ts +272 -0
  139. package/src/session/ids.ts +17 -0
  140. package/src/session/index.ts +44 -0
  141. package/src/session/messageSerialization.ts +207 -0
  142. package/src/session/types.ts +275 -0
  143. package/src/specs/custom-event-await.test.ts +89 -0
  144. package/src/specs/summarization.test.ts +1 -1
  145. package/src/stream.ts +756 -48
  146. package/src/summarization/node.ts +1 -1
  147. package/src/tools/ToolNode.ts +299 -126
  148. package/src/tools/__tests__/ToolNode.eagerEventExecution.test.ts +373 -0
  149. package/src/tools/__tests__/handlers.test.ts +2 -1
  150. package/src/tools/__tests__/hitl.test.ts +206 -110
  151. package/src/tools/eagerEventExecution.ts +153 -0
  152. package/src/tools/handlers.ts +8 -4
  153. package/src/tools/streamedToolCallSeals.ts +57 -0
  154. package/src/types/hitl.ts +4 -0
  155. package/src/types/run.ts +11 -0
  156. package/src/types/tools.ts +36 -0
  157. package/dist/cjs/llm/text.cjs +0 -69
  158. package/dist/cjs/llm/text.cjs.map +0 -1
  159. package/dist/esm/llm/text.mjs +0 -67
  160. package/dist/esm/llm/text.mjs.map +0 -1
package/README.md CHANGED
@@ -46,6 +46,75 @@ const content = await run.processStream(
46
46
  );
47
47
  ```
48
48
 
49
+ ## Programmatic Sessions
50
+
51
+ For scripts, CI, and programmatic integrations, use the session facade. It
52
+ keeps a JSONL session tree by default, so runs can be resumed, cloned, forked,
53
+ branched in place, compacted, and inspected later.
54
+
55
+ ```typescript
56
+ import { Providers, createAgentSession } from '@librechat/agents';
57
+
58
+ const session = await createAgentSession({
59
+ checkpointing: true,
60
+ graphConfig: {
61
+ type: 'standard',
62
+ instructions: 'You are a concise coding assistant.',
63
+ llmConfig: {
64
+ provider: Providers.OPENAI,
65
+ model: 'gpt-4o-mini',
66
+ apiKey: process.env.OPENAI_API_KEY,
67
+ },
68
+ },
69
+ });
70
+
71
+ const result = await session.run('Summarize this repository.');
72
+ console.log(result.text);
73
+ console.log(session.sessionPath); // durable .jsonl session file
74
+ ```
75
+
76
+ When `checkpointing` is enabled, the session injects a shared LangGraph
77
+ checkpointer into `compileOptions`, records checkpoint IDs in JSONL, and uses
78
+ checkpoint state for later turns on the same `thread_id`. When HITL is enabled
79
+ (`humanInTheLoop: { enabled: true }`), sessions also get a `MemorySaver` by
80
+ default so `resumeInterrupt()` can reuse the same saver instead of relying on a
81
+ per-run fallback. JSONL still owns portable replay, clone, fork, and audit
82
+ records.
83
+
84
+ Sessions expose tree operations inspired by Pi-style workflows:
85
+
86
+ ```typescript
87
+ const store = session.getSessionStore();
88
+ const forkPoint = store?.getForkPoints()[0];
89
+
90
+ if (forkPoint) {
91
+ const forked = await session.fork(forkPoint.id, { position: 'before' });
92
+ await forked.run('Try a different approach from here.');
93
+ }
94
+
95
+ const cloned = await session.clone();
96
+ await cloned.compact({ instructions: 'Keep only implementation decisions.' });
97
+ ```
98
+
99
+ `session.stream()` projects the SDK's existing graph events, and
100
+ `session.compact()` uses the same summarization node, hooks, and provider
101
+ logic as normal runs. JSONL is the durable journal; the graph remains the
102
+ execution engine.
103
+
104
+ OpenAI-compatible streaming helpers are available as experimental subpaths:
105
+
106
+ ```typescript
107
+ import { composeEventHandlers } from '@librechat/agents';
108
+ import { createOpenAIHandlers } from '@librechat/agents/openai';
109
+ import { createResponsesEventHandlers } from '@librechat/agents/responses';
110
+
111
+ const customHandlers = composeEventHandlers(
112
+ createOpenAIHandlers(openAIConfig),
113
+ createResponsesEventHandlers(responsesConfig),
114
+ hostHandlers
115
+ );
116
+ ```
117
+
49
118
  ## Development
50
119
 
51
120
  ```bash
@@ -11,6 +11,28 @@ class HandlerRegistry {
11
11
  return this.handlers.get(eventType);
12
12
  }
13
13
  }
14
+ function composeEventHandlers(...handlerSets) {
15
+ const composed = {};
16
+ for (const handlerSet of handlerSets) {
17
+ if (!handlerSet) {
18
+ continue;
19
+ }
20
+ for (const [eventType, handler] of Object.entries(handlerSet)) {
21
+ const previous = composed[eventType];
22
+ if (previous === undefined) {
23
+ composed[eventType] = handler;
24
+ continue;
25
+ }
26
+ composed[eventType] = {
27
+ handle: async (...args) => {
28
+ await previous.handle(...args);
29
+ await handler.handle(...args);
30
+ },
31
+ };
32
+ }
33
+ }
34
+ return composed;
35
+ }
14
36
  class ModelEndHandler {
15
37
  collectedUsage;
16
38
  constructor(collectedUsage) {
@@ -154,5 +176,6 @@ exports.ModelEndHandler = ModelEndHandler;
154
176
  exports.TestChatStreamHandler = TestChatStreamHandler;
155
177
  exports.TestLLMStreamHandler = TestLLMStreamHandler;
156
178
  exports.ToolEndHandler = ToolEndHandler;
179
+ exports.composeEventHandlers = composeEventHandlers;
157
180
  exports.createMetadataAggregator = createMetadataAggregator;
158
181
  //# sourceMappingURL=events.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.cjs","sources":["../../src/events.ts"],"sourcesContent":["/* eslint-disable no-console */\n// src/events.ts\nimport type {\n BaseMessageFields,\n UsageMetadata,\n} from '@langchain/core/messages';\nimport type { MultiAgentGraph, StandardGraph } from '@/graphs';\nimport type { Logger } from 'winston';\nimport type * as t from '@/types';\nimport { Constants } from '@/common';\n\nexport class HandlerRegistry {\n private handlers: Map<string, t.EventHandler> = new Map();\n\n register(eventType: string, handler: t.EventHandler): void {\n this.handlers.set(eventType, handler);\n }\n\n getHandler(eventType: string): t.EventHandler | undefined {\n return this.handlers.get(eventType);\n }\n}\n\nexport class ModelEndHandler implements t.EventHandler {\n collectedUsage?: UsageMetadata[];\n constructor(collectedUsage?: UsageMetadata[]) {\n if (collectedUsage && !Array.isArray(collectedUsage)) {\n throw new Error('collectedUsage must be an array');\n }\n this.collectedUsage = collectedUsage;\n }\n\n async handle(\n event: string,\n data: t.ModelEndData,\n metadata?: Record<string, unknown>,\n graph?: StandardGraph | MultiAgentGraph\n ): Promise<void> {\n if (!graph || !metadata) {\n console.warn(`Graph or metadata not found in ${event} event`);\n return;\n }\n\n const usage = data?.output?.usage_metadata;\n if (usage != null && this.collectedUsage != null) {\n this.collectedUsage.push(usage);\n }\n }\n}\n\nexport class ToolEndHandler implements t.EventHandler {\n private callback?: t.ToolEndCallback;\n private logger?: Logger;\n constructor(callback?: t.ToolEndCallback, logger?: Logger) {\n this.callback = callback;\n this.logger = logger;\n }\n\n /**\n * Handles on_tool_end events from the for-await stream consumer.\n *\n * This handler is now purely a consumer callback — tool completion\n * (ON_RUN_STEP_COMPLETED dispatch + session context storage) is handled\n * in graph context by ToolNode directly, eliminating the race between\n * the stream consumer and graph execution.\n */\n async handle(\n event: string,\n data: t.StreamEventData | undefined,\n metadata?: Record<string, unknown>,\n graph?: StandardGraph | MultiAgentGraph\n ): Promise<void> {\n try {\n if (!graph || !metadata) {\n if (this.logger) {\n this.logger.warn(`Graph or metadata not found in ${event} event`);\n } else {\n console.warn(`Graph or metadata not found in ${event} event`);\n }\n return;\n }\n\n const toolEndData = data as t.ToolEndData | undefined;\n if (!toolEndData?.output) {\n if (this.logger) {\n this.logger.warn('No output found in tool_end event');\n } else {\n console.warn('No output found in tool_end event');\n }\n return;\n }\n\n if (\n metadata[Constants.PROGRAMMATIC_TOOL_CALLING] === true ||\n metadata[Constants.BASH_PROGRAMMATIC_TOOL_CALLING] === true\n ) {\n return;\n }\n\n if (this.callback) {\n await this.callback(toolEndData, metadata);\n }\n } catch (error) {\n if (this.logger) {\n this.logger.error('Error handling tool_end event:', error);\n } else {\n console.error('Error handling tool_end event:', error);\n }\n }\n }\n}\n\nexport class TestLLMStreamHandler implements t.EventHandler {\n handle(event: string, data: t.StreamEventData | undefined): void {\n const chunk = data?.chunk;\n const isMessageChunk = !!(chunk && 'message' in chunk);\n const msg = isMessageChunk ? chunk.message : undefined;\n if (msg && msg.tool_call_chunks && msg.tool_call_chunks.length > 0) {\n console.log(msg.tool_call_chunks);\n } else if (msg && typeof msg.content === 'string') {\n process.stdout.write(msg.content);\n }\n }\n}\n\nexport class TestChatStreamHandler implements t.EventHandler {\n handle(event: string, data: t.StreamEventData | undefined): void {\n const chunk = data?.chunk;\n const isContentChunk = !!(chunk && 'content' in chunk);\n if (!isContentChunk) {\n return;\n }\n\n const content = chunk.content;\n\n if (chunk.tool_call_chunks && chunk.tool_call_chunks.length > 0) {\n console.dir(chunk.tool_call_chunks, { depth: null });\n }\n\n if (typeof content === 'string') {\n process.stdout.write(content);\n } else {\n console.dir(content, { depth: null });\n }\n }\n}\n\nexport class LLMStreamHandler implements t.EventHandler {\n handle(\n event: string,\n data: t.StreamEventData | undefined,\n metadata?: Record<string, unknown>\n ): void {\n const chunk = data?.chunk;\n const isMessageChunk = !!(chunk && 'message' in chunk);\n const msg = isMessageChunk ? chunk.message : undefined;\n if (metadata) {\n console.log(metadata);\n }\n if (msg && msg.tool_call_chunks && msg.tool_call_chunks.length > 0) {\n console.log(msg.tool_call_chunks);\n } else if (msg && typeof msg.content === 'string') {\n process.stdout.write(msg.content);\n }\n }\n}\n\nexport const createMetadataAggregator = (\n _collected?: Record<\n string,\n NonNullable<BaseMessageFields['response_metadata']>\n >[]\n): t.MetadataAggregatorResult => {\n const collected = _collected || [];\n\n const handleLLMEnd: t.HandleLLMEnd = (output) => {\n const { generations } = output;\n const lastMessageOutput = (\n generations[generations.length - 1] as\n | (t.StreamGeneration | undefined)[]\n | undefined\n )?.[0];\n if (!lastMessageOutput) {\n return;\n }\n const { message } = lastMessageOutput;\n if (message?.response_metadata) {\n collected.push(message.response_metadata);\n }\n };\n\n return { handleLLMEnd, collected };\n};\n"],"names":["Constants"],"mappings":"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"}
1
+ {"version":3,"file":"events.cjs","sources":["../../src/events.ts"],"sourcesContent":["/* eslint-disable no-console */\n// src/events.ts\nimport type {\n BaseMessageFields,\n UsageMetadata,\n} from '@langchain/core/messages';\nimport type { MultiAgentGraph, StandardGraph } from '@/graphs';\nimport type { Logger } from 'winston';\nimport type * as t from '@/types';\nimport { Constants } from '@/common';\n\nexport class HandlerRegistry {\n private handlers: Map<string, t.EventHandler> = new Map();\n\n register(eventType: string, handler: t.EventHandler): void {\n this.handlers.set(eventType, handler);\n }\n\n getHandler(eventType: string): t.EventHandler | undefined {\n return this.handlers.get(eventType);\n }\n}\n\nexport function composeEventHandlers(\n ...handlerSets: Array<Record<string, t.EventHandler> | undefined>\n): Record<string, t.EventHandler> {\n const composed: Partial<Record<string, t.EventHandler>> = {};\n\n for (const handlerSet of handlerSets) {\n if (!handlerSet) {\n continue;\n }\n for (const [eventType, handler] of Object.entries(handlerSet)) {\n const previous = composed[eventType];\n if (previous === undefined) {\n composed[eventType] = handler;\n continue;\n }\n composed[eventType] = {\n handle: async (\n ...args: Parameters<t.EventHandler['handle']>\n ): Promise<void> => {\n await previous.handle(...args);\n await handler.handle(...args);\n },\n };\n }\n }\n\n return composed as Record<string, t.EventHandler>;\n}\n\nexport class ModelEndHandler implements t.EventHandler {\n collectedUsage?: UsageMetadata[];\n constructor(collectedUsage?: UsageMetadata[]) {\n if (collectedUsage && !Array.isArray(collectedUsage)) {\n throw new Error('collectedUsage must be an array');\n }\n this.collectedUsage = collectedUsage;\n }\n\n async handle(\n event: string,\n data: t.ModelEndData,\n metadata?: Record<string, unknown>,\n graph?: StandardGraph | MultiAgentGraph\n ): Promise<void> {\n if (!graph || !metadata) {\n console.warn(`Graph or metadata not found in ${event} event`);\n return;\n }\n\n const usage = data?.output?.usage_metadata;\n if (usage != null && this.collectedUsage != null) {\n this.collectedUsage.push(usage);\n }\n }\n}\n\nexport class ToolEndHandler implements t.EventHandler {\n private callback?: t.ToolEndCallback;\n private logger?: Logger;\n constructor(callback?: t.ToolEndCallback, logger?: Logger) {\n this.callback = callback;\n this.logger = logger;\n }\n\n /**\n * Handles on_tool_end events from the for-await stream consumer.\n *\n * This handler is now purely a consumer callback — tool completion\n * (ON_RUN_STEP_COMPLETED dispatch + session context storage) is handled\n * in graph context by ToolNode directly, eliminating the race between\n * the stream consumer and graph execution.\n */\n async handle(\n event: string,\n data: t.StreamEventData | undefined,\n metadata?: Record<string, unknown>,\n graph?: StandardGraph | MultiAgentGraph\n ): Promise<void> {\n try {\n if (!graph || !metadata) {\n if (this.logger) {\n this.logger.warn(`Graph or metadata not found in ${event} event`);\n } else {\n console.warn(`Graph or metadata not found in ${event} event`);\n }\n return;\n }\n\n const toolEndData = data as t.ToolEndData | undefined;\n if (!toolEndData?.output) {\n if (this.logger) {\n this.logger.warn('No output found in tool_end event');\n } else {\n console.warn('No output found in tool_end event');\n }\n return;\n }\n\n if (\n metadata[Constants.PROGRAMMATIC_TOOL_CALLING] === true ||\n metadata[Constants.BASH_PROGRAMMATIC_TOOL_CALLING] === true\n ) {\n return;\n }\n\n if (this.callback) {\n await this.callback(toolEndData, metadata);\n }\n } catch (error) {\n if (this.logger) {\n this.logger.error('Error handling tool_end event:', error);\n } else {\n console.error('Error handling tool_end event:', error);\n }\n }\n }\n}\n\nexport class TestLLMStreamHandler implements t.EventHandler {\n handle(event: string, data: t.StreamEventData | undefined): void {\n const chunk = data?.chunk;\n const isMessageChunk = !!(chunk && 'message' in chunk);\n const msg = isMessageChunk ? chunk.message : undefined;\n if (msg && msg.tool_call_chunks && msg.tool_call_chunks.length > 0) {\n console.log(msg.tool_call_chunks);\n } else if (msg && typeof msg.content === 'string') {\n process.stdout.write(msg.content);\n }\n }\n}\n\nexport class TestChatStreamHandler implements t.EventHandler {\n handle(event: string, data: t.StreamEventData | undefined): void {\n const chunk = data?.chunk;\n const isContentChunk = !!(chunk && 'content' in chunk);\n if (!isContentChunk) {\n return;\n }\n\n const content = chunk.content;\n\n if (chunk.tool_call_chunks && chunk.tool_call_chunks.length > 0) {\n console.dir(chunk.tool_call_chunks, { depth: null });\n }\n\n if (typeof content === 'string') {\n process.stdout.write(content);\n } else {\n console.dir(content, { depth: null });\n }\n }\n}\n\nexport class LLMStreamHandler implements t.EventHandler {\n handle(\n event: string,\n data: t.StreamEventData | undefined,\n metadata?: Record<string, unknown>\n ): void {\n const chunk = data?.chunk;\n const isMessageChunk = !!(chunk && 'message' in chunk);\n const msg = isMessageChunk ? chunk.message : undefined;\n if (metadata) {\n console.log(metadata);\n }\n if (msg && msg.tool_call_chunks && msg.tool_call_chunks.length > 0) {\n console.log(msg.tool_call_chunks);\n } else if (msg && typeof msg.content === 'string') {\n process.stdout.write(msg.content);\n }\n }\n}\n\nexport const createMetadataAggregator = (\n _collected?: Record<\n string,\n NonNullable<BaseMessageFields['response_metadata']>\n >[]\n): t.MetadataAggregatorResult => {\n const collected = _collected || [];\n\n const handleLLMEnd: t.HandleLLMEnd = (output) => {\n const { generations } = output;\n const lastMessageOutput = (\n generations[generations.length - 1] as\n | (t.StreamGeneration | undefined)[]\n | undefined\n )?.[0];\n if (!lastMessageOutput) {\n return;\n }\n const { message } = lastMessageOutput;\n if (message?.response_metadata) {\n collected.push(message.response_metadata);\n }\n };\n\n return { handleLLMEnd, collected };\n};\n"],"names":["Constants"],"mappings":"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"}
@@ -16,7 +16,7 @@ var reducer = require('../messages/reducer.cjs');
16
16
  var _enum = require('../common/enum.cjs');
17
17
  var graph = require('../utils/graph.cjs');
18
18
  var llm = require('../utils/llm.cjs');
19
- var handlers = require('../tools/handlers.cjs');
19
+ require('../stream.cjs');
20
20
  var run = require('../utils/run.cjs');
21
21
  require('ai-tokenizer');
22
22
  require('zod-to-json-schema');
@@ -31,6 +31,7 @@ var node = require('../summarization/node.cjs');
31
31
  var schema = require('../tools/schema.cjs');
32
32
  var AgentContext = require('../agents/AgentContext.cjs');
33
33
  var fake = require('../llm/fake.cjs');
34
+ var handlers = require('../tools/handlers.cjs');
34
35
  require('../tools/local/CompileCheckTool.cjs');
35
36
  require('path');
36
37
  require('fs/promises');
@@ -53,6 +54,9 @@ var toolCache = require('../llm/openrouter/toolCache.cjs');
53
54
  const { AGENT, TOOLS, SUMMARIZE } = _enum.GraphNodeKeys;
54
55
  /** Minimum relative variance before calibrated toolSchemaTokens overrides current value. */
55
56
  const CALIBRATION_VARIANCE_THRESHOLD = 0.15;
57
+ function getHandlerDispatchedEventKey(eventName, stepId) {
58
+ return `${eventName}:${stepId}`;
59
+ }
56
60
  class Graph {
57
61
  messageStepHasToolCalls = new Map();
58
62
  messageIdsByStepKey = new Map();
@@ -63,11 +67,12 @@ class Graph {
63
67
  contentIndexMap = new Map();
64
68
  toolCallStepIds = new Map();
65
69
  /**
66
- * Step IDs that have been dispatched via handler registry directly
67
- * (in dispatchRunStep). Used by the custom event callback to skip
68
- * duplicate dispatch through the LangGraph callback chain.
70
+ * Step IDs dispatched through the handler registry during this run.
71
+ * Event echo suppression is tracked separately so repeated deltas for
72
+ * the same step are scoped to the active custom event dispatch.
69
73
  */
70
74
  handlerDispatchedStepIds = new Set();
75
+ handlerDispatchedEventCounts = new Map();
71
76
  signal;
72
77
  /** Set of invoked tool call IDs from non-message run steps completed mid-run, if any */
73
78
  invokedToolIds;
@@ -86,6 +91,16 @@ class Graph {
86
91
  * graph compiles.
87
92
  */
88
93
  toolOutputReferences;
94
+ /**
95
+ * Run-scoped opt-in for eager event-driven tool execution. The stream
96
+ * handler may prestart eligible event-driven tools; ToolNode later
97
+ * consumes the settled promises while preserving final ToolMessage order.
98
+ */
99
+ eagerEventToolExecution;
100
+ eagerEventToolExecutions = new Map();
101
+ eagerEventToolUsageCount = new Map();
102
+ eagerEventToolUsageCountsByAgentId = new Map();
103
+ eagerEventToolCallChunks = new Map();
89
104
  /**
90
105
  * Run-scoped execution backend for built-in code tools. Defaults to the
91
106
  * remote Code API sandbox when unset.
@@ -124,7 +139,12 @@ class Graph {
124
139
  this.hookRegistry = undefined;
125
140
  this.humanInTheLoop = undefined;
126
141
  this.toolOutputReferences = undefined;
142
+ this.eagerEventToolExecution = undefined;
143
+ this.eagerEventToolExecutions.clear();
144
+ this.clearEagerEventToolUsageCounts();
145
+ this.eagerEventToolCallChunks.clear();
127
146
  this.toolExecution = undefined;
147
+ this.handlerDispatchedEventCounts.clear();
128
148
  /**
129
149
  * ToolNodes compiled from this graph captured the registry
130
150
  * instance at construction time, so simply dropping the Graph's
@@ -154,6 +174,39 @@ class Graph {
154
174
  this._compiledToolNodes.clear();
155
175
  this.sessions.clear();
156
176
  }
177
+ getEagerEventToolUsageCount(agentId) {
178
+ if (agentId == null || agentId === '') {
179
+ return this.eagerEventToolUsageCount;
180
+ }
181
+ let usageCount = this.eagerEventToolUsageCountsByAgentId.get(agentId);
182
+ if (usageCount == null) {
183
+ usageCount = new Map();
184
+ this.eagerEventToolUsageCountsByAgentId.set(agentId, usageCount);
185
+ }
186
+ return usageCount;
187
+ }
188
+ clearEagerEventToolUsageCounts() {
189
+ this.eagerEventToolUsageCount.clear();
190
+ for (const usageCount of this.eagerEventToolUsageCountsByAgentId.values()) {
191
+ usageCount.clear();
192
+ }
193
+ }
194
+ markHandlerDispatchedEvent(eventName, stepId) {
195
+ const key = getHandlerDispatchedEventKey(eventName, stepId);
196
+ this.handlerDispatchedEventCounts.set(key, (this.handlerDispatchedEventCounts.get(key) ?? 0) + 1);
197
+ return () => {
198
+ const count = this.handlerDispatchedEventCounts.get(key) ?? 0;
199
+ if (count <= 1) {
200
+ this.handlerDispatchedEventCounts.delete(key);
201
+ return;
202
+ }
203
+ this.handlerDispatchedEventCounts.set(key, count - 1);
204
+ };
205
+ }
206
+ hasHandlerDispatchedEvent(eventName, stepId) {
207
+ const key = getHandlerDispatchedEventKey(eventName, stepId);
208
+ return (this.handlerDispatchedEventCounts.get(key) ?? 0) > 0;
209
+ }
157
210
  /**
158
211
  * Subclass hook to register a freshly compiled ToolNode so
159
212
  * `clearHeavyState` can flush its per-Run direct-path turn cache
@@ -284,7 +337,11 @@ class StandardGraph extends Graph {
284
337
  * a stale reference on 2nd+ processStream calls.
285
338
  */
286
339
  this.toolCallStepIds.clear();
340
+ this.eagerEventToolExecutions.clear();
341
+ this.clearEagerEventToolUsageCounts();
342
+ this.eagerEventToolCallChunks.clear();
287
343
  this.handlerDispatchedStepIds = graph.resetIfNotEmpty(this.handlerDispatchedStepIds, new Set());
344
+ this.handlerDispatchedEventCounts = graph.resetIfNotEmpty(this.handlerDispatchedEventCounts, new Map());
288
345
  this.messageIdsByStepKey = graph.resetIfNotEmpty(this.messageIdsByStepKey, new Map());
289
346
  this.messageStepHasToolCalls = graph.resetIfNotEmpty(this.messageStepHasToolCalls, new Map());
290
347
  this.prelimMessageIdsByStepKey = graph.resetIfNotEmpty(this.prelimMessageIdsByStepKey, new Map());
@@ -508,6 +565,9 @@ class StandardGraph extends Graph {
508
565
  toolRegistry: agentContext?.toolRegistry,
509
566
  hookRegistry: this.hookRegistry,
510
567
  humanInTheLoop: this.humanInTheLoop,
568
+ eagerEventToolExecution: this.eagerEventToolExecution,
569
+ eagerEventToolExecutions: this.eagerEventToolExecutions,
570
+ eagerEventToolUsageCount: this.getEagerEventToolUsageCount(agentContext?.agentId),
511
571
  toolExecution: this.toolExecution,
512
572
  directToolNames: directToolNames.size > 0 ? directToolNames : undefined,
513
573
  maxContextTokens: agentContext?.maxContextTokens,
@@ -958,7 +1018,7 @@ class StandardGraph extends Graph {
958
1018
  if (typeof content === 'string') {
959
1019
  await this.dispatchMessageDelta(stepId, {
960
1020
  content: [{ type: _enum.ContentTypes.TEXT, text: content }],
961
- });
1021
+ }, metadata);
962
1022
  }
963
1023
  else if (Array.isArray(content) &&
964
1024
  content.every((c) => typeof c === 'object' &&
@@ -967,7 +1027,7 @@ class StandardGraph extends Graph {
967
1027
  c.type.startsWith('text'))) {
968
1028
  await this.dispatchMessageDelta(stepId, {
969
1029
  content: content,
970
- });
1030
+ }, metadata);
971
1031
  }
972
1032
  }
973
1033
  }
@@ -997,7 +1057,7 @@ class StandardGraph extends Graph {
997
1057
  if (typeof content === 'string') {
998
1058
  await this.dispatchMessageDelta(stepId, {
999
1059
  content: [{ type: _enum.ContentTypes.TEXT, text: content }],
1000
- });
1060
+ }, metadata);
1001
1061
  }
1002
1062
  else if (Array.isArray(content) &&
1003
1063
  content.every((c) => typeof c === 'object' &&
@@ -1006,7 +1066,7 @@ class StandardGraph extends Graph {
1006
1066
  c.type.startsWith('text'))) {
1007
1067
  await this.dispatchMessageDelta(stepId, {
1008
1068
  content: content,
1009
- });
1069
+ }, metadata);
1010
1070
  }
1011
1071
  }
1012
1072
  }
@@ -1176,8 +1236,16 @@ class StandardGraph extends Graph {
1176
1236
  await handler.handle(_enum.GraphEvents.ON_RUN_STEP, runStep, resolvedConfig?.configurable, this);
1177
1237
  this.handlerDispatchedStepIds.add(runStep.id);
1178
1238
  }
1179
- if (resolvedConfig) {
1180
- await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_RUN_STEP, runStep, resolvedConfig);
1239
+ const unmarkHandlerDispatchedEvent = handler
1240
+ ? this.markHandlerDispatchedEvent(_enum.GraphEvents.ON_RUN_STEP, runStep.id)
1241
+ : undefined;
1242
+ try {
1243
+ if (resolvedConfig) {
1244
+ await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_RUN_STEP, runStep, resolvedConfig);
1245
+ }
1246
+ }
1247
+ finally {
1248
+ unmarkHandlerDispatchedEvent?.();
1181
1249
  }
1182
1250
  },
1183
1251
  dispatchRunStepCompleted: async (stepId, result, nodeConfig) => {
@@ -1208,7 +1276,7 @@ class StandardGraph extends Graph {
1208
1276
  const StateAnnotation = langgraph.Annotation.Root({
1209
1277
  messages: langgraph.Annotation({
1210
1278
  reducer: (a, b) => {
1211
- if (!a.length) {
1279
+ if (!this.messages.length) {
1212
1280
  this.startIndex = a.length + b.length;
1213
1281
  }
1214
1282
  const result = reducer.messagesStateReducer(a, b);
@@ -1305,7 +1373,15 @@ class StandardGraph extends Graph {
1305
1373
  // but the primary dispatch above guarantees the event reaches the handler.
1306
1374
  // The customEventCallback in run.ts skips events already dispatched above
1307
1375
  // to prevent double handling.
1308
- await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_RUN_STEP, runStep, this.config);
1376
+ const unmarkHandlerDispatchedEvent = handler
1377
+ ? this.markHandlerDispatchedEvent(_enum.GraphEvents.ON_RUN_STEP, stepId)
1378
+ : undefined;
1379
+ try {
1380
+ await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_RUN_STEP, runStep, this.config);
1381
+ }
1382
+ finally {
1383
+ unmarkHandlerDispatchedEvent?.();
1384
+ }
1309
1385
  return stepId;
1310
1386
  }
1311
1387
  /**
@@ -1354,7 +1430,7 @@ class StandardGraph extends Graph {
1354
1430
  async handleToolCallError(data, metadata) {
1355
1431
  await StandardGraph.handleToolCallErrorStatic(this, data, metadata);
1356
1432
  }
1357
- async dispatchRunStepDelta(id, delta) {
1433
+ async dispatchRunStepDelta(id, delta, metadata) {
1358
1434
  if (!this.config) {
1359
1435
  throw new Error('No config provided');
1360
1436
  }
@@ -1365,9 +1441,22 @@ class StandardGraph extends Graph {
1365
1441
  id,
1366
1442
  delta,
1367
1443
  };
1368
- await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_RUN_STEP_DELTA, runStepDelta, this.config);
1444
+ const handler = this.handlerRegistry?.getHandler(_enum.GraphEvents.ON_RUN_STEP_DELTA);
1445
+ if (handler) {
1446
+ await handler.handle(_enum.GraphEvents.ON_RUN_STEP_DELTA, runStepDelta, metadata, this);
1447
+ this.handlerDispatchedStepIds.add(id);
1448
+ }
1449
+ const unmarkHandlerDispatchedEvent = handler
1450
+ ? this.markHandlerDispatchedEvent(_enum.GraphEvents.ON_RUN_STEP_DELTA, id)
1451
+ : undefined;
1452
+ try {
1453
+ await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_RUN_STEP_DELTA, runStepDelta, this.config);
1454
+ }
1455
+ finally {
1456
+ unmarkHandlerDispatchedEvent?.();
1457
+ }
1369
1458
  }
1370
- async dispatchMessageDelta(id, delta) {
1459
+ async dispatchMessageDelta(id, delta, metadata) {
1371
1460
  if (!this.config) {
1372
1461
  throw new Error('No config provided');
1373
1462
  }
@@ -1375,9 +1464,22 @@ class StandardGraph extends Graph {
1375
1464
  id,
1376
1465
  delta,
1377
1466
  };
1378
- await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_MESSAGE_DELTA, messageDelta, this.config);
1467
+ const handler = this.handlerRegistry?.getHandler(_enum.GraphEvents.ON_MESSAGE_DELTA);
1468
+ if (handler) {
1469
+ await handler.handle(_enum.GraphEvents.ON_MESSAGE_DELTA, messageDelta, metadata, this);
1470
+ this.handlerDispatchedStepIds.add(id);
1471
+ }
1472
+ const unmarkHandlerDispatchedEvent = handler
1473
+ ? this.markHandlerDispatchedEvent(_enum.GraphEvents.ON_MESSAGE_DELTA, id)
1474
+ : undefined;
1475
+ try {
1476
+ await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_MESSAGE_DELTA, messageDelta, this.config);
1477
+ }
1478
+ finally {
1479
+ unmarkHandlerDispatchedEvent?.();
1480
+ }
1379
1481
  }
1380
- dispatchReasoningDelta = async (stepId, delta) => {
1482
+ dispatchReasoningDelta = async (stepId, delta, metadata) => {
1381
1483
  if (!this.config) {
1382
1484
  throw new Error('No config provided');
1383
1485
  }
@@ -1385,7 +1487,20 @@ class StandardGraph extends Graph {
1385
1487
  id: stepId,
1386
1488
  delta,
1387
1489
  };
1388
- await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_REASONING_DELTA, reasoningDelta, this.config);
1490
+ const handler = this.handlerRegistry?.getHandler(_enum.GraphEvents.ON_REASONING_DELTA);
1491
+ if (handler) {
1492
+ await handler.handle(_enum.GraphEvents.ON_REASONING_DELTA, reasoningDelta, metadata, this);
1493
+ this.handlerDispatchedStepIds.add(stepId);
1494
+ }
1495
+ const unmarkHandlerDispatchedEvent = handler
1496
+ ? this.markHandlerDispatchedEvent(_enum.GraphEvents.ON_REASONING_DELTA, stepId)
1497
+ : undefined;
1498
+ try {
1499
+ await events.safeDispatchCustomEvent(_enum.GraphEvents.ON_REASONING_DELTA, reasoningDelta, this.config);
1500
+ }
1501
+ finally {
1502
+ unmarkHandlerDispatchedEvent?.();
1503
+ }
1389
1504
  };
1390
1505
  }
1391
1506