@librechat/agents 3.3.4 → 3.3.5

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 (159) hide show
  1. package/dist/cjs/common/constants.cjs +21 -0
  2. package/dist/cjs/common/constants.cjs.map +1 -1
  3. package/dist/cjs/events.cjs +10 -1
  4. package/dist/cjs/events.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +456 -7
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/hooks/HookRegistry.cjs +25 -0
  8. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  9. package/dist/cjs/hooks/index.cjs +12 -0
  10. package/dist/cjs/hooks/index.cjs.map +1 -1
  11. package/dist/cjs/hooks/types.cjs +1 -0
  12. package/dist/cjs/hooks/types.cjs.map +1 -1
  13. package/dist/cjs/langfuse.cjs +8 -0
  14. package/dist/cjs/langfuse.cjs.map +1 -1
  15. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +1 -3
  16. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  17. package/dist/cjs/llm/invoke.cjs +268 -3
  18. package/dist/cjs/llm/invoke.cjs.map +1 -1
  19. package/dist/cjs/llm/preempt.cjs +132 -0
  20. package/dist/cjs/llm/preempt.cjs.map +1 -0
  21. package/dist/cjs/main.cjs +17 -3
  22. package/dist/cjs/messages/alternation.cjs +92 -0
  23. package/dist/cjs/messages/alternation.cjs.map +1 -0
  24. package/dist/cjs/messages/format.cjs +72 -0
  25. package/dist/cjs/messages/format.cjs.map +1 -1
  26. package/dist/cjs/messages/handoffCue.cjs +63 -0
  27. package/dist/cjs/messages/handoffCue.cjs.map +1 -0
  28. package/dist/cjs/messages/index.cjs +3 -0
  29. package/dist/cjs/messages/injected.cjs +60 -0
  30. package/dist/cjs/messages/injected.cjs.map +1 -0
  31. package/dist/cjs/run.cjs +80 -7
  32. package/dist/cjs/run.cjs.map +1 -1
  33. package/dist/cjs/session/handlers.cjs +18 -9
  34. package/dist/cjs/session/handlers.cjs.map +1 -1
  35. package/dist/cjs/stream.cjs +28 -7
  36. package/dist/cjs/stream.cjs.map +1 -1
  37. package/dist/cjs/tools/ToolNode.cjs +3 -23
  38. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  39. package/dist/cjs/tools/search/keenable-scraper.cjs +90 -0
  40. package/dist/cjs/tools/search/keenable-scraper.cjs.map +1 -0
  41. package/dist/cjs/tools/search/tool.cjs +9 -1
  42. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  43. package/dist/esm/common/constants.mjs +19 -1
  44. package/dist/esm/common/constants.mjs.map +1 -1
  45. package/dist/esm/events.mjs +10 -1
  46. package/dist/esm/events.mjs.map +1 -1
  47. package/dist/esm/graphs/Graph.mjs +455 -6
  48. package/dist/esm/graphs/Graph.mjs.map +1 -1
  49. package/dist/esm/hooks/HookRegistry.mjs +25 -0
  50. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  51. package/dist/esm/hooks/index.mjs +12 -1
  52. package/dist/esm/hooks/index.mjs.map +1 -1
  53. package/dist/esm/hooks/types.mjs +1 -0
  54. package/dist/esm/hooks/types.mjs.map +1 -1
  55. package/dist/esm/langfuse.mjs +9 -1
  56. package/dist/esm/langfuse.mjs.map +1 -1
  57. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +1 -3
  58. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  59. package/dist/esm/llm/invoke.mjs +270 -6
  60. package/dist/esm/llm/invoke.mjs.map +1 -1
  61. package/dist/esm/llm/preempt.mjs +131 -0
  62. package/dist/esm/llm/preempt.mjs.map +1 -0
  63. package/dist/esm/main.mjs +8 -5
  64. package/dist/esm/messages/alternation.mjs +91 -0
  65. package/dist/esm/messages/alternation.mjs.map +1 -0
  66. package/dist/esm/messages/format.mjs +72 -0
  67. package/dist/esm/messages/format.mjs.map +1 -1
  68. package/dist/esm/messages/handoffCue.mjs +61 -0
  69. package/dist/esm/messages/handoffCue.mjs.map +1 -0
  70. package/dist/esm/messages/index.mjs +3 -0
  71. package/dist/esm/messages/injected.mjs +60 -0
  72. package/dist/esm/messages/injected.mjs.map +1 -0
  73. package/dist/esm/run.mjs +80 -7
  74. package/dist/esm/run.mjs.map +1 -1
  75. package/dist/esm/session/handlers.mjs +19 -10
  76. package/dist/esm/session/handlers.mjs.map +1 -1
  77. package/dist/esm/stream.mjs +27 -8
  78. package/dist/esm/stream.mjs.map +1 -1
  79. package/dist/esm/tools/ToolNode.mjs +3 -23
  80. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  81. package/dist/esm/tools/search/keenable-scraper.mjs +88 -0
  82. package/dist/esm/tools/search/keenable-scraper.mjs.map +1 -0
  83. package/dist/esm/tools/search/tool.mjs +9 -1
  84. package/dist/esm/tools/search/tool.mjs.map +1 -1
  85. package/dist/types/common/constants.d.ts +18 -0
  86. package/dist/types/graphs/Graph.d.ts +138 -1
  87. package/dist/types/hooks/HookRegistry.d.ts +15 -0
  88. package/dist/types/hooks/index.d.ts +12 -1
  89. package/dist/types/hooks/types.d.ts +45 -6
  90. package/dist/types/index.d.ts +1 -1
  91. package/dist/types/llm/invoke.d.ts +7 -0
  92. package/dist/types/llm/preempt.d.ts +40 -0
  93. package/dist/types/messages/alternation.d.ts +23 -0
  94. package/dist/types/messages/handoffCue.d.ts +40 -0
  95. package/dist/types/messages/index.d.ts +3 -0
  96. package/dist/types/messages/injected.d.ts +3 -0
  97. package/dist/types/run.d.ts +7 -0
  98. package/dist/types/stream.d.ts +14 -0
  99. package/dist/types/tools/ToolNode.d.ts +0 -7
  100. package/dist/types/tools/search/keenable-scraper.d.ts +15 -0
  101. package/dist/types/tools/search/types.d.ts +31 -2
  102. package/dist/types/types/graph.d.ts +8 -1
  103. package/dist/types/types/run.d.ts +65 -0
  104. package/dist/types/types/stream.d.ts +0 -25
  105. package/package.json +1 -1
  106. package/src/{splitStream.test.ts → aggregator.test.ts} +59 -666
  107. package/src/common/constants.ts +21 -0
  108. package/src/events.ts +15 -1
  109. package/src/graphs/Graph.ts +568 -3
  110. package/src/graphs/__tests__/Graph.contextOverflow.test.ts +18 -7
  111. package/src/graphs/__tests__/Graph.preemptSignal.test.ts +126 -0
  112. package/src/hooks/HookRegistry.ts +40 -0
  113. package/src/hooks/__tests__/preemptBoundary.test.ts +152 -0
  114. package/src/hooks/index.ts +16 -2
  115. package/src/hooks/types.ts +47 -3
  116. package/src/index.ts +1 -1
  117. package/src/langfuse.ts +26 -1
  118. package/src/llm/bedrock/utils/message_inputs.test.ts +82 -0
  119. package/src/llm/bedrock/utils/message_inputs.ts +14 -11
  120. package/src/llm/bedrock/utils/toolResultCachePoint.test.ts +15 -0
  121. package/src/llm/invoke.alternation.test.ts +87 -0
  122. package/src/llm/invoke.handoffCue.test.ts +112 -0
  123. package/src/llm/invoke.ts +417 -8
  124. package/src/llm/preempt.test.ts +323 -0
  125. package/src/llm/preempt.ts +178 -0
  126. package/src/messages/alternation.test.ts +212 -0
  127. package/src/messages/alternation.ts +112 -0
  128. package/src/messages/format.ts +91 -0
  129. package/src/messages/formatAgentMessages.steer.test.ts +267 -0
  130. package/src/messages/handoffCue.test.ts +96 -0
  131. package/src/messages/handoffCue.ts +78 -0
  132. package/src/messages/index.ts +3 -0
  133. package/src/messages/injected.test.ts +90 -0
  134. package/src/messages/injected.ts +74 -0
  135. package/src/run.ts +91 -6
  136. package/src/scripts/preempt-probe.ts +330 -0
  137. package/src/scripts/preempt-scenarios.ts +388 -0
  138. package/src/session/handlers.ts +32 -12
  139. package/src/specs/handoffCue.test.ts +165 -0
  140. package/src/specs/langfuse-callbacks.test.ts +352 -2
  141. package/src/specs/preemptSeal.test.ts +309 -0
  142. package/src/stream.dispatch.test.ts +63 -0
  143. package/src/stream.ts +36 -8
  144. package/src/tools/ToolNode.ts +3 -31
  145. package/src/tools/search/keenable-scraper.test.ts +153 -0
  146. package/src/tools/search/keenable-scraper.ts +137 -0
  147. package/src/tools/search/tool.ts +13 -2
  148. package/src/tools/search/types.ts +50 -3
  149. package/src/types/graph.ts +12 -1
  150. package/src/types/run.ts +67 -0
  151. package/src/types/stream.ts +0 -41
  152. package/dist/cjs/splitStream.cjs +0 -151
  153. package/dist/cjs/splitStream.cjs.map +0 -1
  154. package/dist/esm/splitStream.mjs +0 -150
  155. package/dist/esm/splitStream.mjs.map +0 -1
  156. package/dist/types/mockStream.d.ts +0 -32
  157. package/dist/types/splitStream.d.ts +0 -37
  158. package/src/mockStream.ts +0 -99
  159. package/src/splitStream.ts +0 -234
@@ -12,8 +12,29 @@ const ANTHROPIC_TOOL_TOKEN_MULTIPLIER = 2.6;
12
12
  * Empirically calibrated at ~1.4× the raw JSON token count.
13
13
  */
14
14
  const DEFAULT_TOOL_TOKEN_MULTIPLIER = 1.4;
15
+ /**
16
+ * Default ceiling on cooperative stream seals per run. Each seal costs one
17
+ * extra superstep, so this also sizes the recursion-limit headroom a
18
+ * preemption-enabled run reserves.
19
+ */
20
+ const DEFAULT_MAX_SEALS = 8;
21
+ /**
22
+ * Per-hook timeout for `PreemptBoundary`, deliberately far above
23
+ * `DEFAULT_HOOK_TIMEOUT_MS`. A host drain has already popped its queue and
24
+ * persisted content by the time this fires, so a timeout does not cancel the
25
+ * work — it only loses the messages the run was about to inject.
26
+ */
27
+ const PREEMPT_BOUNDARY_HOOK_TIMEOUT_MS = 12e4;
28
+ /**
29
+ * Default LangGraph recursion limit for a run. Callers may override it via
30
+ * the stream config; a preemption-enabled run adds its seal budget on top.
31
+ */
32
+ const DEFAULT_RECURSION_LIMIT = 50;
15
33
  //#endregion
16
34
  exports.ANTHROPIC_TOOL_TOKEN_MULTIPLIER = ANTHROPIC_TOOL_TOKEN_MULTIPLIER;
35
+ exports.DEFAULT_MAX_SEALS = DEFAULT_MAX_SEALS;
36
+ exports.DEFAULT_RECURSION_LIMIT = DEFAULT_RECURSION_LIMIT;
17
37
  exports.DEFAULT_TOOL_TOKEN_MULTIPLIER = DEFAULT_TOOL_TOKEN_MULTIPLIER;
38
+ exports.PREEMPT_BOUNDARY_HOOK_TIMEOUT_MS = PREEMPT_BOUNDARY_HOOK_TIMEOUT_MS;
18
39
 
19
40
  //# sourceMappingURL=constants.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.cjs","names":[],"sources":["../../../src/common/constants.ts"],"sourcesContent":["/**\n * Anthropic direct API tool schema overhead multiplier.\n * Empirically calibrated against real MCP tool sets (29 tools).\n * Accounts for Anthropic's internal XML-like tool encoding plus\n * a ~300-token hidden tool-system preamble.\n */\nexport const ANTHROPIC_TOOL_TOKEN_MULTIPLIER = 2.6;\n\n/**\n * Default tool schema overhead multiplier for all non-Anthropic providers.\n * Covers OpenAI function-calling format, Bedrock, and other providers.\n * Empirically calibrated at ~1.4× the raw JSON token count.\n */\nexport const DEFAULT_TOOL_TOKEN_MULTIPLIER = 1.4;\n"],"mappings":";;;;;;;AAMA,MAAa,kCAAkC;;;;;;AAO/C,MAAa,gCAAgC"}
1
+ {"version":3,"file":"constants.cjs","names":[],"sources":["../../../src/common/constants.ts"],"sourcesContent":["/**\n * Anthropic direct API tool schema overhead multiplier.\n * Empirically calibrated against real MCP tool sets (29 tools).\n * Accounts for Anthropic's internal XML-like tool encoding plus\n * a ~300-token hidden tool-system preamble.\n */\nexport const ANTHROPIC_TOOL_TOKEN_MULTIPLIER = 2.6;\n\n/**\n * Default tool schema overhead multiplier for all non-Anthropic providers.\n * Covers OpenAI function-calling format, Bedrock, and other providers.\n * Empirically calibrated at ~1.4× the raw JSON token count.\n */\nexport const DEFAULT_TOOL_TOKEN_MULTIPLIER = 1.4;\n\n/**\n * Default ceiling on cooperative stream seals per run. Each seal costs one\n * extra superstep, so this also sizes the recursion-limit headroom a\n * preemption-enabled run reserves.\n */\nexport const DEFAULT_MAX_SEALS = 8;\n\n/**\n * Per-hook timeout for `PreemptBoundary`, deliberately far above\n * `DEFAULT_HOOK_TIMEOUT_MS`. A host drain has already popped its queue and\n * persisted content by the time this fires, so a timeout does not cancel the\n * work — it only loses the messages the run was about to inject.\n */\nexport const PREEMPT_BOUNDARY_HOOK_TIMEOUT_MS = 120_000;\n\n/**\n * Default LangGraph recursion limit for a run. Callers may override it via\n * the stream config; a preemption-enabled run adds its seal budget on top.\n */\nexport const DEFAULT_RECURSION_LIMIT = 50;\n"],"mappings":";;;;;;;AAMA,MAAa,kCAAkC;;;;;;AAO/C,MAAa,gCAAgC;;;;;;AAO7C,MAAa,oBAAoB;;;;;;;AAQjC,MAAa,mCAAmC;;;;;AAMhD,MAAa,0BAA0B"}
@@ -1,5 +1,6 @@
1
1
  require("./common/enum.cjs");
2
2
  require("./common/index.cjs");
3
+ const require_stream = require("./stream.cjs");
3
4
  //#region src/events.ts
4
5
  var HandlerRegistry = class {
5
6
  handlers = /* @__PURE__ */ new Map();
@@ -20,10 +21,18 @@ function composeEventHandlers(...handlerSets) {
20
21
  composed[eventType] = handler;
21
22
  continue;
22
23
  }
23
- composed[eventType] = { handle: async (...args) => {
24
+ const wrapper = { handle: async (...args) => {
24
25
  await previous.handle(...args);
25
26
  await handler.handle(...args);
26
27
  } };
28
+ /**
29
+ * Carry the stream-dispatch brand across the wrapper. Without this a
30
+ * composed handler fails every capability check made about it — notably
31
+ * the one deciding whether a run may seal — even though it still drives
32
+ * the SDK's content-part dispatch.
33
+ */
34
+ if (require_stream.dispatchesChatModelStream(previous) || require_stream.dispatchesChatModelStream(handler)) Object.defineProperty(wrapper, require_stream.SDK_STREAM_DISPATCH, { value: true });
35
+ composed[eventType] = wrapper;
27
36
  }
28
37
  }
29
38
  return composed;
@@ -1 +1 @@
1
- {"version":3,"file":"events.cjs","names":[],"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 { Logger } from 'winston';\nimport type { MultiAgentGraph, StandardGraph } from '@/graphs';\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"],"mappings":"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"}
1
+ {"version":3,"file":"events.cjs","names":["dispatchesChatModelStream","SDK_STREAM_DISPATCH"],"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 { Logger } from 'winston';\nimport type { MultiAgentGraph, StandardGraph } from '@/graphs';\nimport type * as t from '@/types';\nimport { dispatchesChatModelStream, SDK_STREAM_DISPATCH } from '@/stream';\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 const wrapper: t.EventHandler = {\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 * Carry the stream-dispatch brand across the wrapper. Without this a\n * composed handler fails every capability check made about it — notably\n * the one deciding whether a run may seal — even though it still drives\n * the SDK's content-part dispatch.\n */\n if (\n dispatchesChatModelStream(previous) ||\n dispatchesChatModelStream(handler)\n ) {\n Object.defineProperty(wrapper, SDK_STREAM_DISPATCH, { value: true });\n }\n composed[eventType] = wrapper;\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"],"mappings":"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"}