@librechat/agents 3.1.57 → 3.1.61

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 (214) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +326 -62
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/common/enum.cjs +13 -0
  4. package/dist/cjs/common/enum.cjs.map +1 -1
  5. package/dist/cjs/events.cjs +7 -27
  6. package/dist/cjs/events.cjs.map +1 -1
  7. package/dist/cjs/graphs/Graph.cjs +303 -222
  8. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  9. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +4 -4
  10. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  11. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +6 -2
  12. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  13. package/dist/cjs/llm/init.cjs +60 -0
  14. package/dist/cjs/llm/init.cjs.map +1 -0
  15. package/dist/cjs/llm/invoke.cjs +90 -0
  16. package/dist/cjs/llm/invoke.cjs.map +1 -0
  17. package/dist/cjs/llm/openai/index.cjs +2 -0
  18. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  19. package/dist/cjs/llm/request.cjs +41 -0
  20. package/dist/cjs/llm/request.cjs.map +1 -0
  21. package/dist/cjs/main.cjs +40 -0
  22. package/dist/cjs/main.cjs.map +1 -1
  23. package/dist/cjs/messages/cache.cjs +76 -89
  24. package/dist/cjs/messages/cache.cjs.map +1 -1
  25. package/dist/cjs/messages/contextPruning.cjs +156 -0
  26. package/dist/cjs/messages/contextPruning.cjs.map +1 -0
  27. package/dist/cjs/messages/contextPruningSettings.cjs +53 -0
  28. package/dist/cjs/messages/contextPruningSettings.cjs.map +1 -0
  29. package/dist/cjs/messages/core.cjs +23 -37
  30. package/dist/cjs/messages/core.cjs.map +1 -1
  31. package/dist/cjs/messages/format.cjs +156 -11
  32. package/dist/cjs/messages/format.cjs.map +1 -1
  33. package/dist/cjs/messages/prune.cjs +1161 -49
  34. package/dist/cjs/messages/prune.cjs.map +1 -1
  35. package/dist/cjs/messages/reducer.cjs +87 -0
  36. package/dist/cjs/messages/reducer.cjs.map +1 -0
  37. package/dist/cjs/run.cjs +81 -42
  38. package/dist/cjs/run.cjs.map +1 -1
  39. package/dist/cjs/stream.cjs +54 -7
  40. package/dist/cjs/stream.cjs.map +1 -1
  41. package/dist/cjs/summarization/index.cjs +75 -0
  42. package/dist/cjs/summarization/index.cjs.map +1 -0
  43. package/dist/cjs/summarization/node.cjs +663 -0
  44. package/dist/cjs/summarization/node.cjs.map +1 -0
  45. package/dist/cjs/tools/ToolNode.cjs +16 -8
  46. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  47. package/dist/cjs/tools/handlers.cjs +2 -0
  48. package/dist/cjs/tools/handlers.cjs.map +1 -1
  49. package/dist/cjs/utils/errors.cjs +115 -0
  50. package/dist/cjs/utils/errors.cjs.map +1 -0
  51. package/dist/cjs/utils/events.cjs +17 -0
  52. package/dist/cjs/utils/events.cjs.map +1 -1
  53. package/dist/cjs/utils/handlers.cjs +16 -0
  54. package/dist/cjs/utils/handlers.cjs.map +1 -1
  55. package/dist/cjs/utils/llm.cjs +10 -0
  56. package/dist/cjs/utils/llm.cjs.map +1 -1
  57. package/dist/cjs/utils/tokens.cjs +247 -14
  58. package/dist/cjs/utils/tokens.cjs.map +1 -1
  59. package/dist/cjs/utils/truncation.cjs +107 -0
  60. package/dist/cjs/utils/truncation.cjs.map +1 -0
  61. package/dist/esm/agents/AgentContext.mjs +325 -61
  62. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  63. package/dist/esm/common/enum.mjs +13 -0
  64. package/dist/esm/common/enum.mjs.map +1 -1
  65. package/dist/esm/events.mjs +8 -28
  66. package/dist/esm/events.mjs.map +1 -1
  67. package/dist/esm/graphs/Graph.mjs +307 -226
  68. package/dist/esm/graphs/Graph.mjs.map +1 -1
  69. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +4 -4
  70. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  71. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +6 -2
  72. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  73. package/dist/esm/llm/init.mjs +58 -0
  74. package/dist/esm/llm/init.mjs.map +1 -0
  75. package/dist/esm/llm/invoke.mjs +87 -0
  76. package/dist/esm/llm/invoke.mjs.map +1 -0
  77. package/dist/esm/llm/openai/index.mjs +2 -0
  78. package/dist/esm/llm/openai/index.mjs.map +1 -1
  79. package/dist/esm/llm/request.mjs +38 -0
  80. package/dist/esm/llm/request.mjs.map +1 -0
  81. package/dist/esm/main.mjs +13 -3
  82. package/dist/esm/main.mjs.map +1 -1
  83. package/dist/esm/messages/cache.mjs +76 -89
  84. package/dist/esm/messages/cache.mjs.map +1 -1
  85. package/dist/esm/messages/contextPruning.mjs +154 -0
  86. package/dist/esm/messages/contextPruning.mjs.map +1 -0
  87. package/dist/esm/messages/contextPruningSettings.mjs +50 -0
  88. package/dist/esm/messages/contextPruningSettings.mjs.map +1 -0
  89. package/dist/esm/messages/core.mjs +23 -37
  90. package/dist/esm/messages/core.mjs.map +1 -1
  91. package/dist/esm/messages/format.mjs +156 -11
  92. package/dist/esm/messages/format.mjs.map +1 -1
  93. package/dist/esm/messages/prune.mjs +1158 -52
  94. package/dist/esm/messages/prune.mjs.map +1 -1
  95. package/dist/esm/messages/reducer.mjs +83 -0
  96. package/dist/esm/messages/reducer.mjs.map +1 -0
  97. package/dist/esm/run.mjs +82 -43
  98. package/dist/esm/run.mjs.map +1 -1
  99. package/dist/esm/stream.mjs +54 -7
  100. package/dist/esm/stream.mjs.map +1 -1
  101. package/dist/esm/summarization/index.mjs +73 -0
  102. package/dist/esm/summarization/index.mjs.map +1 -0
  103. package/dist/esm/summarization/node.mjs +659 -0
  104. package/dist/esm/summarization/node.mjs.map +1 -0
  105. package/dist/esm/tools/ToolNode.mjs +16 -8
  106. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  107. package/dist/esm/tools/handlers.mjs +2 -0
  108. package/dist/esm/tools/handlers.mjs.map +1 -1
  109. package/dist/esm/utils/errors.mjs +111 -0
  110. package/dist/esm/utils/errors.mjs.map +1 -0
  111. package/dist/esm/utils/events.mjs +17 -1
  112. package/dist/esm/utils/events.mjs.map +1 -1
  113. package/dist/esm/utils/handlers.mjs +16 -0
  114. package/dist/esm/utils/handlers.mjs.map +1 -1
  115. package/dist/esm/utils/llm.mjs +10 -1
  116. package/dist/esm/utils/llm.mjs.map +1 -1
  117. package/dist/esm/utils/tokens.mjs +245 -15
  118. package/dist/esm/utils/tokens.mjs.map +1 -1
  119. package/dist/esm/utils/truncation.mjs +102 -0
  120. package/dist/esm/utils/truncation.mjs.map +1 -0
  121. package/dist/types/agents/AgentContext.d.ts +124 -6
  122. package/dist/types/common/enum.d.ts +14 -1
  123. package/dist/types/graphs/Graph.d.ts +22 -27
  124. package/dist/types/index.d.ts +5 -0
  125. package/dist/types/llm/init.d.ts +18 -0
  126. package/dist/types/llm/invoke.d.ts +48 -0
  127. package/dist/types/llm/request.d.ts +14 -0
  128. package/dist/types/messages/contextPruning.d.ts +42 -0
  129. package/dist/types/messages/contextPruningSettings.d.ts +44 -0
  130. package/dist/types/messages/core.d.ts +1 -1
  131. package/dist/types/messages/format.d.ts +17 -1
  132. package/dist/types/messages/index.d.ts +3 -0
  133. package/dist/types/messages/prune.d.ts +162 -1
  134. package/dist/types/messages/reducer.d.ts +18 -0
  135. package/dist/types/run.d.ts +12 -1
  136. package/dist/types/summarization/index.d.ts +20 -0
  137. package/dist/types/summarization/node.d.ts +29 -0
  138. package/dist/types/tools/ToolNode.d.ts +3 -1
  139. package/dist/types/types/graph.d.ts +44 -6
  140. package/dist/types/types/index.d.ts +1 -0
  141. package/dist/types/types/run.d.ts +30 -0
  142. package/dist/types/types/stream.d.ts +31 -4
  143. package/dist/types/types/summarize.d.ts +47 -0
  144. package/dist/types/types/tools.d.ts +7 -0
  145. package/dist/types/utils/errors.d.ts +28 -0
  146. package/dist/types/utils/events.d.ts +13 -0
  147. package/dist/types/utils/index.d.ts +2 -0
  148. package/dist/types/utils/llm.d.ts +4 -0
  149. package/dist/types/utils/tokens.d.ts +14 -1
  150. package/dist/types/utils/truncation.d.ts +49 -0
  151. package/package.json +3 -3
  152. package/src/agents/AgentContext.ts +388 -58
  153. package/src/agents/__tests__/AgentContext.test.ts +265 -5
  154. package/src/common/enum.ts +13 -0
  155. package/src/events.ts +9 -39
  156. package/src/graphs/Graph.ts +468 -331
  157. package/src/index.ts +7 -0
  158. package/src/llm/anthropic/llm.spec.ts +3 -3
  159. package/src/llm/anthropic/utils/message_inputs.ts +6 -4
  160. package/src/llm/bedrock/llm.spec.ts +1 -1
  161. package/src/llm/bedrock/utils/message_inputs.ts +6 -2
  162. package/src/llm/init.ts +63 -0
  163. package/src/llm/invoke.ts +144 -0
  164. package/src/llm/request.ts +55 -0
  165. package/src/messages/__tests__/observationMasking.test.ts +221 -0
  166. package/src/messages/cache.ts +77 -102
  167. package/src/messages/contextPruning.ts +191 -0
  168. package/src/messages/contextPruningSettings.ts +90 -0
  169. package/src/messages/core.ts +32 -53
  170. package/src/messages/ensureThinkingBlock.test.ts +39 -39
  171. package/src/messages/format.ts +227 -15
  172. package/src/messages/formatAgentMessages.test.ts +511 -1
  173. package/src/messages/index.ts +3 -0
  174. package/src/messages/prune.ts +1548 -62
  175. package/src/messages/reducer.ts +22 -0
  176. package/src/run.ts +104 -51
  177. package/src/scripts/bedrock-merge-test.ts +1 -1
  178. package/src/scripts/test-thinking-handoff-bedrock.ts +1 -1
  179. package/src/scripts/test-thinking-handoff.ts +1 -1
  180. package/src/scripts/thinking-bedrock.ts +1 -1
  181. package/src/scripts/thinking.ts +1 -1
  182. package/src/specs/anthropic.simple.test.ts +1 -1
  183. package/src/specs/multi-agent-summarization.test.ts +396 -0
  184. package/src/specs/prune.test.ts +1196 -23
  185. package/src/specs/summarization-unit.test.ts +868 -0
  186. package/src/specs/summarization.test.ts +3827 -0
  187. package/src/specs/summarize-prune.test.ts +376 -0
  188. package/src/specs/thinking-handoff.test.ts +10 -10
  189. package/src/specs/thinking-prune.test.ts +7 -4
  190. package/src/specs/token-accounting-e2e.test.ts +1034 -0
  191. package/src/specs/token-accounting-pipeline.test.ts +882 -0
  192. package/src/specs/token-distribution-edge-case.test.ts +25 -26
  193. package/src/splitStream.test.ts +42 -33
  194. package/src/stream.ts +64 -11
  195. package/src/summarization/__tests__/aggregator.test.ts +153 -0
  196. package/src/summarization/__tests__/node.test.ts +708 -0
  197. package/src/summarization/__tests__/trigger.test.ts +50 -0
  198. package/src/summarization/index.ts +102 -0
  199. package/src/summarization/node.ts +982 -0
  200. package/src/tools/ToolNode.ts +25 -3
  201. package/src/types/graph.ts +62 -7
  202. package/src/types/index.ts +1 -0
  203. package/src/types/run.ts +32 -0
  204. package/src/types/stream.ts +45 -5
  205. package/src/types/summarize.ts +58 -0
  206. package/src/types/tools.ts +7 -0
  207. package/src/utils/errors.ts +117 -0
  208. package/src/utils/events.ts +31 -0
  209. package/src/utils/handlers.ts +18 -0
  210. package/src/utils/index.ts +2 -0
  211. package/src/utils/llm.ts +12 -0
  212. package/src/utils/tokens.ts +336 -18
  213. package/src/utils/truncation.ts +124 -0
  214. package/src/scripts/image.ts +0 -180
@@ -1,6 +1,7 @@
1
1
  import { AIMessage, ToolMessage, BaseMessage, HumanMessage, SystemMessage } from '@langchain/core/messages';
2
2
  import type { MessageContentImageUrl } from '@langchain/core/messages';
3
3
  import type { MessageContentComplex, TPayload } from '@/types';
4
+ import type { RunnableConfig } from '@langchain/core/runnables';
4
5
  import { Providers } from '@/common';
5
6
  interface MediaMessageParams {
6
7
  message: {
@@ -108,6 +109,20 @@ export declare const labelContentByAgent: (contentParts: MessageContentComplex[]
108
109
  export declare const formatAgentMessages: (payload: TPayload, indexTokenCountMap?: Record<number, number | undefined>, tools?: Set<string>) => {
109
110
  messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;
110
111
  indexTokenCountMap?: Record<number, number>;
112
+ /** Cross-run summary extracted from the payload. Should be forwarded to the
113
+ * agent run so it can be included in the system message via AgentContext. */
114
+ summary?: {
115
+ text: string;
116
+ tokenCount: number;
117
+ };
118
+ /** When a summary boundary sliced content from a message, the token count
119
+ * was proportionally reduced. Returned so the caller can log it. */
120
+ boundaryTokenAdjustment?: {
121
+ original: number;
122
+ adjusted: number;
123
+ remainingChars: number;
124
+ totalChars: number;
125
+ };
111
126
  };
112
127
  /**
113
128
  * Adds a value at key 0 for system messages and shifts all key indices by one in an indexTokenCountMap.
@@ -131,7 +146,8 @@ export declare function shiftIndexTokenCountMap(indexTokenCountMap: Record<numbe
131
146
  *
132
147
  * @param messages - Array of messages to process
133
148
  * @param provider - The provider being used (unused but kept for future compatibility)
149
+ * @param config - Optional RunnableConfig for structured agent logging
134
150
  * @returns The messages array with tool sequences converted to buffer strings if necessary
135
151
  */
136
- export declare function ensureThinkingBlockInMessages(messages: BaseMessage[], _provider: Providers): BaseMessage[];
152
+ export declare function ensureThinkingBlockInMessages(messages: BaseMessage[], _provider: Providers, config?: RunnableConfig): BaseMessage[];
137
153
  export {};
@@ -5,3 +5,6 @@ export * from './format';
5
5
  export * from './cache';
6
6
  export * from './content';
7
7
  export * from './tools';
8
+ export * from './contextPruning';
9
+ export * from './contextPruningSettings';
10
+ export * from './reducer';
@@ -1,6 +1,9 @@
1
1
  import { BaseMessage, UsageMetadata } from '@langchain/core/messages';
2
2
  import type { TokenCounter } from '@/types/run';
3
+ import type { ContextPruningConfig } from '@/types/graph';
3
4
  import { ContentTypes, Providers } from '@/common';
5
+ /** Default fraction of the token budget reserved as headroom (5 %). */
6
+ export declare const DEFAULT_RESERVE_RATIO = 0.05;
4
7
  export type PruneMessagesFactoryParams = {
5
8
  provider?: Providers;
6
9
  maxTokens: number;
@@ -8,12 +11,90 @@ export type PruneMessagesFactoryParams = {
8
11
  tokenCounter: TokenCounter;
9
12
  indexTokenCountMap: Record<string, number | undefined>;
10
13
  thinkingEnabled?: boolean;
14
+ /** Context pruning configuration for position-based tool result degradation. */
15
+ contextPruningConfig?: ContextPruningConfig;
16
+ /**
17
+ * When true, context pressure fading (pre-flight tool result truncation)
18
+ * is skipped. Summarization replaces pruning as the primary context
19
+ * management strategy — the summarizer needs full un-truncated tool results
20
+ * to produce an accurate summary. Hard pruning still runs as a fallback
21
+ * when summarization is skipped or capped.
22
+ */
23
+ summarizationEnabled?: boolean;
24
+ /**
25
+ * Returns the current instruction-token overhead (system message + tool schemas + summary).
26
+ * Called on each prune invocation so the budget reflects dynamic changes
27
+ * (e.g. summary added between turns). When messages don't include a leading
28
+ * SystemMessage, these tokens are subtracted from the available budget so
29
+ * the pruner correctly reserves space for the system prompt that will be
30
+ * prepended later by `buildSystemRunnable`.
31
+ */
32
+ getInstructionTokens?: () => number;
33
+ /**
34
+ * Fraction of the effective token budget to reserve as headroom (0–1).
35
+ * When set, pruning triggers at `effectiveMax * (1 - reserveRatio)` instead of
36
+ * filling the context window to 100%. Defaults to 5 % (0.05) when omitted.
37
+ */
38
+ reserveRatio?: number;
39
+ /**
40
+ * Initial calibration ratio from a previous run's persisted contextMeta.
41
+ * Seeds the running EMA so new messages are scaled immediately instead
42
+ * of waiting for the first provider response. Ignored when <= 0.
43
+ */
44
+ calibrationRatio?: number;
45
+ /** Optional diagnostic log callback wired by the graph for observability. */
46
+ log?: (level: 'debug' | 'info' | 'warn' | 'error', message: string, data?: Record<string, unknown>) => void;
11
47
  };
12
48
  export type PruneMessagesParams = {
13
49
  messages: BaseMessage[];
14
50
  usageMetadata?: Partial<UsageMetadata>;
15
51
  startType?: ReturnType<BaseMessage['getType']>;
52
+ /**
53
+ * Usage from the most recent LLM call only (not accumulated).
54
+ * When provided, calibration uses this instead of usageMetadata
55
+ * to avoid inflated ratios from N×cacheRead accumulation.
56
+ */
57
+ lastCallUsage?: {
58
+ totalTokens: number;
59
+ inputTokens?: number;
60
+ };
61
+ /**
62
+ * Whether the token data is fresh (from a just-completed LLM call).
63
+ * When false, provider calibration is skipped to avoid applying
64
+ * stale ratios.
65
+ */
66
+ totalTokensFresh?: boolean;
16
67
  };
68
+ export declare function repairOrphanedToolMessages({ context, allMessages, tokenCounter, indexTokenCountMap, }: {
69
+ context: BaseMessage[];
70
+ allMessages: BaseMessage[];
71
+ tokenCounter: TokenCounter;
72
+ indexTokenCountMap: Record<string, number | undefined>;
73
+ }): {
74
+ context: BaseMessage[];
75
+ reclaimedTokens: number;
76
+ droppedOrphanCount: number;
77
+ /** Messages removed from context during orphan repair. These should be
78
+ * appended to `messagesToRefine` so that summarization can still see them
79
+ * (e.g. a ToolMessage whose parent AI was pruned). */
80
+ droppedMessages: BaseMessage[];
81
+ };
82
+ /**
83
+ * Lightweight structural cleanup: strips orphan tool_use blocks from AI messages
84
+ * and drops orphan ToolMessages whose AI counterpart is missing.
85
+ *
86
+ * Unlike `repairOrphanedToolMessages`, this does NOT track tokens — it is
87
+ * intended as a final safety net in Graph.ts right before model invocation
88
+ * to prevent Anthropic/Bedrock structural validation errors.
89
+ *
90
+ * Uses duck-typing instead of `getType()` because messages at this stage
91
+ * may be plain objects (from LangGraph state serialization) rather than
92
+ * proper BaseMessage class instances.
93
+ *
94
+ * Includes a fast-path: if every tool_call has a matching tool_result and
95
+ * vice-versa, the original array is returned immediately with zero allocation.
96
+ */
97
+ export declare function sanitizeOrphanToolBlocks(messages: BaseMessage[]): BaseMessage[];
17
98
  /**
18
99
  * Calculates the total tokens from a single usage object
19
100
  *
@@ -34,7 +115,7 @@ export type PruningResult = {
34
115
  * @param options Configuration options for processing messages
35
116
  * @returns Object containing the message context, remaining tokens, messages not included, and summary index
36
117
  */
37
- export declare function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, indexTokenCountMap, startType: _startType, thinkingEnabled, tokenCounter, thinkingStartIndex: _thinkingStartIndex, reasoningType, }: {
118
+ export declare function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, indexTokenCountMap, startType: _startType, thinkingEnabled, tokenCounter, thinkingStartIndex: _thinkingStartIndex, reasoningType, instructionTokens: _instructionTokens, }: {
38
119
  messages: BaseMessage[];
39
120
  maxContextTokens: number;
40
121
  indexTokenCountMap: Record<string, number | undefined>;
@@ -43,9 +124,89 @@ export declare function getMessagesWithinTokenLimit({ messages: _messages, maxCo
43
124
  tokenCounter: TokenCounter;
44
125
  thinkingStartIndex?: number;
45
126
  reasoningType?: ContentTypes.THINKING | ContentTypes.REASONING_CONTENT;
127
+ /**
128
+ * Token overhead for instructions (system message + tool schemas + summary)
129
+ * that are NOT included in `messages`. When messages[0] is already a
130
+ * SystemMessage the budget is deducted from its indexTokenCountMap entry
131
+ * as before; otherwise this value is subtracted from the available budget.
132
+ */
133
+ instructionTokens?: number;
46
134
  }): PruningResult;
47
135
  export declare function checkValidNumber(value: unknown): value is number;
136
+ /**
137
+ * Observation masking: replaces consumed ToolMessage content with tight
138
+ * head+tail truncations that serve as informative placeholders.
139
+ *
140
+ * A ToolMessage is "consumed" when a subsequent AI message exists that is NOT
141
+ * purely tool calls — meaning the model has already read and acted on the
142
+ * result. Unconsumed results (the latest tool outputs the model hasn't
143
+ * responded to yet) are left intact so the model can still use them.
144
+ *
145
+ * AI messages are never masked — they contain the model's own reasoning and
146
+ * conclusions, which is what prevents the model from repeating work after
147
+ * its tool results are masked.
148
+ *
149
+ * @returns The number of tool messages that were masked.
150
+ */
151
+ export declare function maskConsumedToolResults(params: {
152
+ messages: BaseMessage[];
153
+ indexTokenCountMap: Record<string, number | undefined>;
154
+ tokenCounter: TokenCounter;
155
+ /** Raw-space token budget available for all consumed tool results combined.
156
+ * When provided, the budget is distributed across consumed results weighted
157
+ * by recency (newest get the most, oldest get MASKED_RESULT_MAX_CHARS min).
158
+ * When omitted, falls back to a flat MASKED_RESULT_MAX_CHARS per result. */
159
+ availableRawBudget?: number;
160
+ /** When provided, original (pre-masking) content is stored here keyed by
161
+ * message index — only for entries that actually get truncated. */
162
+ originalContentStore?: Map<number, string>;
163
+ /** Called after storing content with the char length of the stored entry. */
164
+ onContentStored?: (charLength: number) => void;
165
+ }): number;
166
+ /**
167
+ * Pre-flight truncation: truncates oversized ToolMessage content before the
168
+ * main backward-iteration pruning runs. Unlike the ingestion guard (which caps
169
+ * at tool-execution time), pre-flight truncation applies per-turn based on the
170
+ * current context window budget (which may have shrunk due to growing conversation).
171
+ *
172
+ * After truncation, recounts tokens via tokenCounter and updates indexTokenCountMap
173
+ * so subsequent pruning works with accurate counts.
174
+ *
175
+ * @returns The number of tool messages that were truncated.
176
+ */
177
+ export declare function preFlightTruncateToolResults(params: {
178
+ messages: BaseMessage[];
179
+ maxContextTokens: number;
180
+ indexTokenCountMap: Record<string, number | undefined>;
181
+ tokenCounter: TokenCounter;
182
+ }): number;
183
+ /**
184
+ * Pre-flight truncation: truncates oversized `tool_use` input fields in AI messages.
185
+ *
186
+ * Tool call inputs (arguments) can be very large — e.g., code evaluation payloads from
187
+ * MCP tools like chrome-devtools. Since these tool calls have already been executed,
188
+ * the model only needs a summary of what was called, not the full arguments. Truncating
189
+ * them before pruning can prevent entire messages from being dropped.
190
+ *
191
+ * Uses 15% of the context window (in estimated characters, ~4 chars/token) as the
192
+ * per-input cap, capped at 200K chars.
193
+ *
194
+ * @returns The number of AI messages that had tool_use inputs truncated.
195
+ */
196
+ export declare function preFlightTruncateToolCallInputs(params: {
197
+ messages: BaseMessage[];
198
+ maxContextTokens: number;
199
+ indexTokenCountMap: Record<string, number | undefined>;
200
+ tokenCounter: TokenCounter;
201
+ }): number;
48
202
  export declare function createPruneMessages(factoryParams: PruneMessagesFactoryParams): (params: PruneMessagesParams) => {
49
203
  context: BaseMessage[];
50
204
  indexTokenCountMap: Record<string, number | undefined>;
205
+ messagesToRefine?: BaseMessage[];
206
+ prePruneContextTokens?: number;
207
+ remainingContextTokens?: number;
208
+ contextPressure?: number;
209
+ originalToolContent?: Map<number, string>;
210
+ calibrationRatio?: number;
211
+ resolvedInstructionOverhead?: number;
51
212
  };
@@ -1,5 +1,23 @@
1
1
  import { BaseMessage, BaseMessageLike } from '@langchain/core/messages';
2
2
  export declare const REMOVE_ALL_MESSAGES = "__remove_all__";
3
+ /**
4
+ * Creates a message that instructs messagesStateReducer to remove ALL
5
+ * existing messages from state. Messages appearing after this one in
6
+ * the array become the new state.
7
+ *
8
+ * Usage (in a node return value):
9
+ * ```ts
10
+ * return { messages: [createRemoveAllMessage(), ...survivingMessages] };
11
+ * ```
12
+ *
13
+ * This works because the reducer checks for `getType() === 'remove'`
14
+ * with `id === REMOVE_ALL_MESSAGES` and discards everything before it.
15
+ *
16
+ * NOTE: Uses RemoveMessage from @langchain/core with a sentinel id so
17
+ * the reducer can distinguish a "remove-all" marker from a single-message
18
+ * removal.
19
+ */
20
+ export declare function createRemoveAllMessage(): BaseMessage;
3
21
  export type Messages = Array<BaseMessage | BaseMessageLike> | BaseMessage | BaseMessageLike;
4
22
  /**
5
23
  * Prebuilt reducer that combines returned messages.
@@ -10,21 +10,32 @@ export declare class Run<_T extends t.BaseGraphState> {
10
10
  private tokenCounter?;
11
11
  private handlerRegistry?;
12
12
  private indexTokenCountMap?;
13
+ calibrationRatio: number;
13
14
  graphRunnable?: t.CompiledStateWorkflow;
14
15
  Graph: StandardGraph | MultiAgentGraph | undefined;
15
16
  returnContent: boolean;
16
17
  private skipCleanup;
18
+ private _streamResult;
17
19
  private constructor();
18
20
  private createLegacyGraph;
19
21
  private createMultiAgentGraph;
20
22
  static create<T extends t.BaseGraphState>(config: t.RunConfig): Promise<Run<T>>;
21
23
  getRunMessages(): BaseMessage[] | undefined;
24
+ /**
25
+ * Returns the current calibration ratio (EMA of provider-vs-estimate token ratios).
26
+ * Hosts should persist this value and pass it back as `RunConfig.calibrationRatio`
27
+ * on the next run for the same conversation so the pruner starts with an accurate
28
+ * scaling factor instead of the default (1).
29
+ */
30
+ getCalibrationRatio(): number;
31
+ getResolvedInstructionOverhead(): number | undefined;
32
+ getToolCount(): number;
22
33
  /**
23
34
  * Creates a custom event callback handler that intercepts custom events
24
35
  * and processes them through our handler registry instead of EventStreamCallbackHandler
25
36
  */
26
37
  private createCustomEventCallback;
27
- processStream(inputs: t.IState, config: Partial<RunnableConfig> & {
38
+ processStream(inputs: t.IState, callerConfig: Partial<RunnableConfig> & {
28
39
  version: 'v1' | 'v2';
29
40
  run_id?: string;
30
41
  }, streamOptions?: t.EventStreamOptions): Promise<MessageContentComplex[] | undefined>;
@@ -0,0 +1,20 @@
1
+ import type { SummarizationTrigger } from '@/types';
2
+ /**
3
+ * Determines whether summarization should be triggered based on the configured trigger
4
+ * and current context state.
5
+ *
6
+ * Default behavior (no trigger configured): returns `true` whenever messages were pruned.
7
+ * This is intentional — when an admin enables summarization without specifying a trigger,
8
+ * summarization fires on any context overflow that causes pruning.
9
+ *
10
+ * When a trigger IS configured but required runtime data is missing (e.g., maxContextTokens
11
+ * unavailable for a token_ratio trigger), returns `false` — we cannot evaluate the condition,
12
+ * so we do not fire.
13
+ */
14
+ export declare function shouldTriggerSummarization(params: {
15
+ trigger?: SummarizationTrigger;
16
+ maxContextTokens?: number;
17
+ prePruneContextTokens?: number;
18
+ remainingContextTokens?: number;
19
+ messagesToRefineCount: number;
20
+ }): boolean;
@@ -0,0 +1,29 @@
1
+ import type { RunnableConfig } from '@langchain/core/runnables';
2
+ import type { BaseMessage } from '@langchain/core/messages';
3
+ import type { AgentContext } from '@/agents/AgentContext';
4
+ import type * as t from '@/types';
5
+ /** Structured checkpoint prompt for fresh summarization (no prior summary). */
6
+ export declare const DEFAULT_SUMMARIZATION_PROMPT = "Hold on, before you continue I need you to write me a checkpoint of everything so far. Your context window is filling up and this checkpoint replaces the messages above, so capture everything you need to pick right back up.\n\nDon't second-guess or fact-check anything you did, your tool results reflect exactly what happened. Just record what you did and what you observed. Only the checkpoint, don't respond to me or continue the conversation.\n\n## Checkpoint\n\n## Goal\nWhat I asked you to do and any sub-goals you identified.\n\n## Constraints & Preferences\nAny rules, preferences, or configuration I established.\n\n## Progress\n### Done\n- What you completed and the outcomes\n\n### In Progress\n- What you're currently working on\n\n## Key Decisions\nDecisions you made and why.\n\n## Next Steps\nConcrete task actions remaining, in priority order.\n\n## Critical Context\nExact identifiers, names, error messages, URLs, and details you need to preserve verbatim.\n\nRules:\n- Record what you did and observed, don't judge or re-evaluate it\n- For each tool call: the tool name, key inputs, and the outcome\n- Preserve exact identifiers, names, errors, and references verbatim\n- Short declarative sentences\n- Skip empty sections";
7
+ /** Prompt for re-compaction when a prior summary exists. */
8
+ export declare const DEFAULT_UPDATE_SUMMARIZATION_PROMPT = "Hold on again, update your checkpoint. Merge the new messages into your existing checkpoint and give me a single consolidated replacement.\n\nKeep it roughly the same length as your last checkpoint. Compress older details to make room for what's new, don't just append. Give recent actions more detail, compress older items to one-liners.\n\nDon't fact-check or second-guess anything, your tool results are ground truth. Only the checkpoint, don't respond to me or continue the conversation.\n\nRules:\n- Merge new progress into existing sections, don't duplicate headers\n- Compress older completed items into one-line entries\n- Move items from \"In Progress\" to \"Done\" when you completed them\n- Update \"Next Steps\" to reflect current task priorities.\n- For each new tool call: the tool name, key inputs, and the outcome\n- Preserve exact identifiers, names, errors, and references verbatim\n- Skip empty sections";
9
+ interface CreateSummarizeNodeParams {
10
+ agentContext: AgentContext;
11
+ graph: {
12
+ contentData: t.RunStep[];
13
+ contentIndexMap: Map<string, number>;
14
+ config?: RunnableConfig;
15
+ runId?: string;
16
+ isMultiAgent: boolean;
17
+ dispatchRunStep: (runStep: t.RunStep, config?: RunnableConfig) => Promise<void>;
18
+ dispatchRunStepCompleted: (stepId: string, result: t.StepCompleted, config?: RunnableConfig) => Promise<void>;
19
+ };
20
+ generateStepId: (stepKey: string) => [string, number];
21
+ }
22
+ export declare function createSummarizeNode({ agentContext, graph, generateStepId, }: CreateSummarizeNodeParams): (state: {
23
+ messages: BaseMessage[];
24
+ summarizationRequest?: t.SummarizationNodeInput;
25
+ }, config?: RunnableConfig) => Promise<{
26
+ summarizationRequest: undefined;
27
+ messages?: BaseMessage[];
28
+ }>;
29
+ export {};
@@ -26,7 +26,9 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
26
26
  private agentId?;
27
27
  /** Tool names that bypass event dispatch and execute directly (e.g., graph-managed handoff tools) */
28
28
  private directToolNames?;
29
- constructor({ tools, toolMap, name, tags, errorHandler, toolCallStepIds, handleToolErrors, loadRuntimeTools, toolRegistry, sessions, eventDrivenMode, agentId, directToolNames, }: t.ToolNodeConstructorParams);
29
+ /** Maximum characters allowed in a single tool result before truncation. */
30
+ private maxToolResultChars;
31
+ constructor({ tools, toolMap, name, tags, errorHandler, toolCallStepIds, handleToolErrors, loadRuntimeTools, toolRegistry, sessions, eventDrivenMode, agentId, directToolNames, maxContextTokens, maxToolResultChars, }: t.ToolNodeConstructorParams);
30
32
  /**
31
33
  * Returns cached programmatic tools, computing once on first access.
32
34
  * Single iteration builds both toolMap and toolDefs simultaneously.
@@ -8,6 +8,7 @@ import type { ToolMap, ToolEndEvent, GenericTool, LCTool } from '@/types/tools';
8
8
  import type { Providers, Callback, GraphNodeKeys } from '@/common';
9
9
  import type { StandardGraph, MultiAgentGraph } from '@/graphs';
10
10
  import type { ClientOptions } from '@/types/llm';
11
+ import type { SummarizationNodeInput, SummarizeCompleteEvent, SummarizationConfig, SummarizeStartEvent, SummarizeDeltaEvent } from '@/types/summarize';
11
12
  import type { RunStep, RunStepDeltaEvent, MessageDeltaEvent, ReasoningDeltaEvent } from '@/types/stream';
12
13
  import type { TokenCounter } from '@/types/run';
13
14
  /** Interface for bound model with stream and invoke methods */
@@ -28,12 +29,23 @@ export type SystemCallbacks = {
28
29
  export type BaseGraphState = {
29
30
  messages: BaseMessage[];
30
31
  };
32
+ export type AgentSubgraphState = BaseGraphState & {
33
+ summarizationRequest?: SummarizationNodeInput;
34
+ };
31
35
  export type MultiAgentGraphState = BaseGraphState & {
32
36
  agentMessages?: BaseMessage[];
33
37
  };
34
38
  export type IState = BaseGraphState;
39
+ export interface AgentLogEvent {
40
+ level: 'debug' | 'info' | 'warn' | 'error';
41
+ scope: 'prune' | 'summarize' | 'graph' | 'sanitize' | (string & {});
42
+ message: string;
43
+ data?: Record<string, unknown>;
44
+ runId?: string;
45
+ agentId?: string;
46
+ }
35
47
  export interface EventHandler {
36
- handle(event: string, data: StreamEventData | ModelEndData | RunStep | RunStepDeltaEvent | MessageDeltaEvent | ReasoningDeltaEvent | {
48
+ handle(event: string, data: StreamEventData | ModelEndData | RunStep | RunStepDeltaEvent | MessageDeltaEvent | ReasoningDeltaEvent | SummarizeStartEvent | SummarizeDeltaEvent | SummarizeCompleteEvent | AgentLogEvent | {
37
49
  result: ToolEndEvent;
38
50
  }, metadata?: Record<string, unknown>, graph?: StandardGraph | MultiAgentGraph): void | Promise<void>;
39
51
  }
@@ -62,17 +74,16 @@ export type CompiledMultiAgentWorkflow = CompiledStateGraph<StateType<{
62
74
  messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
63
75
  agentMessages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
64
76
  }, StateDefinition>;
65
- export type CompiledAgentWorfklow = CompiledStateGraph<{
66
- messages: BaseMessage[];
67
- }, {
68
- messages?: BaseMessage[] | undefined;
69
- }, '__start__' | `agent=${string}` | `tools=${string}`, {
77
+ export type CompiledAgentWorfklow = CompiledStateGraph<AgentSubgraphState, Partial<AgentSubgraphState>, '__start__' | `agent=${string}` | `tools=${string}` | `summarize=${string}`, {
70
78
  messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
79
+ summarizationRequest: BinaryOperatorAggregate<SummarizationNodeInput | undefined, SummarizationNodeInput | undefined>;
71
80
  }, {
72
81
  messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
82
+ summarizationRequest: BinaryOperatorAggregate<SummarizationNodeInput | undefined, SummarizationNodeInput | undefined>;
73
83
  }, StateDefinition, {
74
84
  [x: `agent=${string}`]: Partial<BaseGraphState>;
75
85
  [x: `tools=${string}`]: any;
86
+ [x: `summarize=${string}`]: any;
76
87
  }>;
77
88
  export type SystemRunnable = Runnable<BaseMessage[], (BaseMessage | SystemMessage)[], RunnableConfig<Record<string, unknown>>> | undefined;
78
89
  /**
@@ -201,6 +212,7 @@ export type StandardGraphInput = {
201
212
  agents: AgentInputs[];
202
213
  tokenCounter?: TokenCounter;
203
214
  indexTokenCountMap?: Record<string, number>;
215
+ calibrationRatio?: number;
204
216
  };
205
217
  export type GraphEdge = {
206
218
  /** Agent ID, use a list for multiple sources */
@@ -270,4 +282,30 @@ export interface AgentInputs {
270
282
  * in tool binding without requiring tool_search.
271
283
  */
272
284
  discoveredTools?: string[];
285
+ summarizationEnabled?: boolean;
286
+ summarizationConfig?: SummarizationConfig;
287
+ /** Cross-run summary from a previous run, forwarded from formatAgentMessages.
288
+ * Injected into the system message via AgentContext.buildInstructionsString(). */
289
+ initialSummary?: {
290
+ text: string;
291
+ tokenCount: number;
292
+ };
293
+ contextPruningConfig?: ContextPruningConfig;
294
+ maxToolResultChars?: number;
295
+ }
296
+ export interface ContextPruningConfig {
297
+ enabled?: boolean;
298
+ keepLastAssistants?: number;
299
+ softTrimRatio?: number;
300
+ hardClearRatio?: number;
301
+ minPrunableToolChars?: number;
302
+ softTrim?: {
303
+ maxChars?: number;
304
+ headChars?: number;
305
+ tailChars?: number;
306
+ };
307
+ hardClear?: {
308
+ enabled?: boolean;
309
+ placeholder?: string;
310
+ };
273
311
  }
@@ -3,3 +3,4 @@ export * from './llm';
3
3
  export * from './run';
4
4
  export * from './stream';
5
5
  export * from './tools';
6
+ export * from './summarize';
@@ -103,11 +103,41 @@ export type RunConfig = {
103
103
  returnContent?: boolean;
104
104
  tokenCounter?: TokenCounter;
105
105
  indexTokenCountMap?: Record<string, number>;
106
+ /**
107
+ * Calibration ratio from a previous run's contextMeta.
108
+ * Seeds the pruner's EMA so new messages are scaled immediately.
109
+ *
110
+ * Hosts should persist the value returned by `Run.getCalibrationRatio()`
111
+ * after each run and pass it back here on subsequent runs for the same
112
+ * conversation. Without this, the EMA resets to 1 on every new Run instance.
113
+ */
114
+ calibrationRatio?: number;
106
115
  /** Skip post-stream cleanup (clearHeavyState) — useful for tests that inspect graph state after processStream */
107
116
  skipCleanup?: boolean;
108
117
  };
109
118
  export type ProvidedCallbacks = (BaseCallbackHandler | CallbackHandlerMethods)[] | undefined;
110
119
  export type TokenCounter = (message: BaseMessage) => number;
120
+ /** Structured breakdown of how context token budget is consumed. */
121
+ export type TokenBudgetBreakdown = {
122
+ /** Total context window budget (maxContextTokens). */
123
+ maxContextTokens: number;
124
+ /** Total instruction tokens (system + tools + summary). */
125
+ instructionTokens: number;
126
+ /** Tokens from the system message text alone. */
127
+ systemMessageTokens: number;
128
+ /** Tokens from tool schema definitions. */
129
+ toolSchemaTokens: number;
130
+ /** Tokens from the conversation summary. */
131
+ summaryTokens: number;
132
+ /** Number of registered tools. */
133
+ toolCount: number;
134
+ /** Number of messages in the conversation. */
135
+ messageCount: number;
136
+ /** Total tokens consumed by messages (excluding system). */
137
+ messageTokens: number;
138
+ /** Tokens available for messages after instructions. */
139
+ availableForMessages: number;
140
+ };
111
141
  export type EventStreamOptions = {
112
142
  callbacks?: g.ClientCallbacks;
113
143
  keepContent?: boolean;
@@ -4,6 +4,7 @@ import type { ToolCall, ToolCallChunk } from '@langchain/core/messages/tool';
4
4
  import type { LLMResult, Generation } from '@langchain/core/outputs';
5
5
  import type { AnthropicContentBlock } from '@/llm/anthropic/types';
6
6
  import type { Command } from '@langchain/langgraph';
7
+ import type { SummarizeCompleteEvent } from '@/types/summarize';
7
8
  import type { ToolEndEvent } from '@/types/tools';
8
9
  import { StepTypes, ContentTypes, GraphEvents } from '@/common/enum';
9
10
  export type HandleLLMEnd = (output: LLMResult, runId: string, parentRunId?: string, tags?: string[]) => void;
@@ -52,6 +53,7 @@ export type RunStep = {
52
53
  index: number;
53
54
  stepIndex?: number;
54
55
  stepDetails: StepDetails;
56
+ summary?: SummaryContentBlock;
55
57
  usage?: null | object;
56
58
  };
57
59
  /**
@@ -69,7 +71,11 @@ export interface RunStepDeltaEvent {
69
71
  delta: ToolCallDelta;
70
72
  }
71
73
  export type StepDetails = MessageCreationDetails | ToolCallsDetails;
72
- export type StepCompleted = ToolCallCompleted;
74
+ export type SummaryCompleted = {
75
+ type: 'summary';
76
+ summary: SummaryContentBlock;
77
+ };
78
+ export type StepCompleted = ToolCallCompleted | SummaryCompleted;
73
79
  export type MessageCreationDetails = {
74
80
  type: StepTypes.MESSAGE_CREATION;
75
81
  message_creation: {
@@ -116,6 +122,7 @@ export type ToolCallsDetails = {
116
122
  export type ToolCallDelta = {
117
123
  type: StepTypes;
118
124
  tool_calls?: ToolCallChunk[];
125
+ summary?: SummaryContentBlock;
119
126
  auth?: string;
120
127
  expires_at?: number;
121
128
  };
@@ -202,11 +209,25 @@ export type ReasoningDeltaUpdate = {
202
209
  type: ContentTypes.THINK;
203
210
  think: string;
204
211
  };
205
- export type ContentType = 'text' | 'image_url' | 'tool_call' | 'think' | string;
212
+ export type ContentType = 'text' | 'image_url' | 'tool_call' | 'think' | 'summary' | string;
206
213
  export type ReasoningContentText = {
207
214
  type: ContentTypes.THINK;
208
215
  think: string;
209
216
  };
217
+ export type SummaryBoundary = {
218
+ messageId: string;
219
+ contentIndex: number;
220
+ };
221
+ export type SummaryContentBlock = {
222
+ type: ContentTypes.SUMMARY;
223
+ content?: MessageContentComplex[];
224
+ tokenCount?: number;
225
+ boundary?: SummaryBoundary;
226
+ summaryVersion?: number;
227
+ model?: string;
228
+ provider?: string;
229
+ createdAt?: string;
230
+ };
210
231
  /** Vertex AI / Google Common - Reasoning Content Block Format */
211
232
  export type GoogleReasoningContentText = {
212
233
  type: ContentTypes.REASONING;
@@ -258,7 +279,7 @@ export type ToolResultContent = {
258
279
  input?: string | Record<string, unknown>;
259
280
  index?: number;
260
281
  };
261
- export type MessageContentComplex = (ToolResultContent | ThinkingContentText | AgentUpdate | ToolCallContent | ReasoningContentText | MessageContentText | MessageContentImageUrl | (Record<string, any> & {
282
+ export type MessageContentComplex = (ToolResultContent | ThinkingContentText | SummaryContentBlock | AgentUpdate | ToolCallContent | ReasoningContentText | MessageContentText | MessageContentImageUrl | (Record<string, any> & {
262
283
  type?: 'text' | 'image_url' | 'think' | 'thinking' | string;
263
284
  }) | (Record<string, any> & {
264
285
  type?: never;
@@ -297,9 +318,15 @@ export type SplitStreamHandlers = Partial<{
297
318
  data: ReasoningDeltaEvent;
298
319
  }) => void;
299
320
  }>;
321
+ export type SummarizeDeltaData = {
322
+ id: string;
323
+ delta: {
324
+ summary: SummaryContentBlock;
325
+ };
326
+ };
300
327
  export type ContentAggregator = ({ event, data, }: {
301
328
  event: GraphEvents;
302
- data: RunStep | MessageDeltaEvent | RunStepDeltaEvent | {
329
+ data: RunStep | AgentUpdate | MessageDeltaEvent | ReasoningDeltaEvent | RunStepDeltaEvent | SummarizeDeltaData | SummarizeCompleteEvent | {
303
330
  result: ToolEndEvent;
304
331
  };
305
332
  }) => void;
@@ -0,0 +1,47 @@
1
+ import type { SummaryContentBlock } from '@/types/stream';
2
+ import type { Providers } from '@/common';
3
+ export type SummarizationTrigger = {
4
+ type: 'token_ratio' | 'remaining_tokens' | 'messages_to_refine' | (string & {});
5
+ value: number;
6
+ };
7
+ export type SummarizationConfig = {
8
+ provider?: Providers;
9
+ model?: string;
10
+ parameters?: Record<string, unknown>;
11
+ prompt?: string;
12
+ updatePrompt?: string;
13
+ trigger?: SummarizationTrigger;
14
+ maxSummaryTokens?: number;
15
+ /** Fraction of the token budget reserved as headroom (0–1). Defaults to 0.05. */
16
+ reserveRatio?: number;
17
+ };
18
+ export interface SummarizeResult {
19
+ text: string;
20
+ tokenCount: number;
21
+ model?: string;
22
+ provider?: string;
23
+ }
24
+ export interface SummarizationNodeInput {
25
+ remainingContextTokens: number;
26
+ agentId: string;
27
+ }
28
+ export interface SummarizeStartEvent {
29
+ agentId: string;
30
+ provider: string;
31
+ model?: string;
32
+ messagesToRefineCount: number;
33
+ /** Which summarization cycle this is (1-based, increments each time summarization fires) */
34
+ summaryVersion: number;
35
+ }
36
+ export interface SummarizeDeltaEvent {
37
+ id: string;
38
+ delta: {
39
+ summary: SummaryContentBlock;
40
+ };
41
+ }
42
+ export interface SummarizeCompleteEvent {
43
+ id: string;
44
+ agentId: string;
45
+ summary?: SummaryContentBlock;
46
+ error?: string;
47
+ }
@@ -39,6 +39,13 @@ export type ToolNodeOptions = {
39
39
  agentId?: string;
40
40
  /** Tool names that must be executed directly (via runTool) even in event-driven mode (e.g., graph-managed handoff tools) */
41
41
  directToolNames?: Set<string>;
42
+ /** Max context tokens for the agent — used to compute tool result truncation limits. */
43
+ maxContextTokens?: number;
44
+ /**
45
+ * Maximum characters allowed in a single tool result before truncation.
46
+ * When provided, takes precedence over the value computed from maxContextTokens.
47
+ */
48
+ maxToolResultChars?: number;
42
49
  };
43
50
  export type ToolNodeConstructorParams = ToolRefs & ToolNodeOptions;
44
51
  export type ToolEndEvent = {