@librechat/agents 3.2.32 → 3.2.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/cjs/agents/AgentContext.cjs +844 -1046
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/constants.cjs +13 -13
- package/dist/cjs/common/constants.cjs.map +1 -1
- package/dist/cjs/common/enum.cjs +233 -240
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/common/index.cjs +2 -0
- package/dist/cjs/events.cjs +121 -169
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +1389 -1807
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +713 -945
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/graphs/index.cjs +2 -0
- package/dist/cjs/hitl/askUserQuestion.cjs +60 -62
- package/dist/cjs/hitl/askUserQuestion.cjs.map +1 -1
- package/dist/cjs/hitl/index.cjs +1 -0
- package/dist/cjs/hooks/HookRegistry.cjs +176 -202
- package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
- package/dist/cjs/hooks/createToolPolicyHook.cjs +71 -101
- package/dist/cjs/hooks/createToolPolicyHook.cjs.map +1 -1
- package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +170 -273
- package/dist/cjs/hooks/createWorkspacePolicyHook.cjs.map +1 -1
- package/dist/cjs/hooks/executeHooks.cjs +227 -282
- package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
- package/dist/cjs/hooks/index.cjs +6 -0
- package/dist/cjs/hooks/matchers.cjs +196 -230
- package/dist/cjs/hooks/matchers.cjs.map +1 -1
- package/dist/cjs/hooks/types.cjs +24 -24
- package/dist/cjs/hooks/types.cjs.map +1 -1
- package/dist/cjs/instrumentation.cjs +110 -137
- package/dist/cjs/instrumentation.cjs.map +1 -1
- package/dist/cjs/langchain/google-common.cjs +0 -3
- package/dist/cjs/langchain/index.cjs +80 -43
- package/dist/cjs/langchain/language_models/chat_models.cjs +0 -3
- package/dist/cjs/langchain/messages/tool.cjs +0 -3
- package/dist/cjs/langchain/messages.cjs +35 -18
- package/dist/cjs/langchain/openai.cjs +0 -3
- package/dist/cjs/langchain/prompts.cjs +5 -8
- package/dist/cjs/langchain/runnables.cjs +11 -10
- package/dist/cjs/langchain/tools.cjs +14 -11
- package/dist/cjs/langchain/utils/env.cjs +5 -8
- package/dist/cjs/langfuse.cjs +60 -79
- package/dist/cjs/langfuse.cjs.map +1 -1
- package/dist/cjs/langfuseToolOutputTracing.cjs +267 -399
- package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/index.cjs +432 -562
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/types.cjs +23 -47
- package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +441 -731
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +171 -256
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/output_parsers.cjs +2 -0
- package/dist/cjs/llm/anthropic/utils/tools.cjs +12 -26
- package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +214 -240
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/toolCache.cjs +84 -106
- package/dist/cjs/llm/bedrock/toolCache.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/index.cjs +2 -0
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +357 -620
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_outputs.cjs +141 -149
- package/dist/cjs/llm/bedrock/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/fake.cjs +86 -96
- package/dist/cjs/llm/fake.cjs.map +1 -1
- package/dist/cjs/llm/google/index.cjs +183 -237
- package/dist/cjs/llm/google/index.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/common.cjs +404 -674
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/zod_to_genai_parameters.cjs +2 -0
- package/dist/cjs/llm/init.cjs +44 -53
- package/dist/cjs/llm/init.cjs.map +1 -1
- package/dist/cjs/llm/invoke.cjs +142 -182
- package/dist/cjs/llm/invoke.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +1035 -1273
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +189 -316
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs +102 -153
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/toolCache.cjs +35 -44
- package/dist/cjs/llm/openrouter/toolCache.cjs.map +1 -1
- package/dist/cjs/llm/providers.cjs +29 -37
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/llm/request.cjs +20 -33
- package/dist/cjs/llm/request.cjs.map +1 -1
- package/dist/cjs/llm/vertexai/index.cjs +446 -453
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +547 -528
- package/dist/cjs/messages/anthropicToolCache.cjs +68 -119
- package/dist/cjs/messages/anthropicToolCache.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +305 -418
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/content.cjs +36 -49
- package/dist/cjs/messages/content.cjs.map +1 -1
- package/dist/cjs/messages/contextPruning.cjs +112 -145
- package/dist/cjs/messages/contextPruning.cjs.map +1 -1
- package/dist/cjs/messages/contextPruningSettings.cjs +36 -46
- package/dist/cjs/messages/contextPruningSettings.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +256 -397
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +904 -1387
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/ids.cjs +16 -20
- package/dist/cjs/messages/ids.cjs.map +1 -1
- package/dist/cjs/messages/index.cjs +12 -0
- package/dist/cjs/messages/langchain.cjs +18 -18
- package/dist/cjs/messages/langchain.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs +1054 -1517
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/messages/recency.cjs +77 -95
- package/dist/cjs/messages/recency.cjs.map +1 -1
- package/dist/cjs/messages/reducer.cjs +63 -78
- package/dist/cjs/messages/reducer.cjs.map +1 -1
- package/dist/cjs/messages/tools.cjs +51 -79
- package/dist/cjs/messages/tools.cjs.map +1 -1
- package/dist/cjs/openai/index.cjs +171 -217
- package/dist/cjs/openai/index.cjs.map +1 -1
- package/dist/cjs/responses/index.cjs +302 -391
- package/dist/cjs/responses/index.cjs.map +1 -1
- package/dist/cjs/run.cjs +903 -1113
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/AgentSession.cjs +805 -986
- package/dist/cjs/session/AgentSession.cjs.map +1 -1
- package/dist/cjs/session/JsonlSessionStore.cjs +327 -410
- package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -1
- package/dist/cjs/session/handlers.cjs +192 -208
- package/dist/cjs/session/handlers.cjs.map +1 -1
- package/dist/cjs/session/ids.cjs +9 -10
- package/dist/cjs/session/ids.cjs.map +1 -1
- package/dist/cjs/session/index.cjs +4 -0
- package/dist/cjs/session/messageSerialization.cjs +94 -156
- package/dist/cjs/session/messageSerialization.cjs.map +1 -1
- package/dist/cjs/splitStream.cjs +147 -206
- package/dist/cjs/splitStream.cjs.map +1 -1
- package/dist/cjs/stream.cjs +874 -1344
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/index.cjs +57 -101
- package/dist/cjs/summarization/index.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +643 -796
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/BashExecutor.cjs +110 -136
- package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +165 -245
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/Calculator.cjs +36 -57
- package/dist/cjs/tools/Calculator.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +126 -168
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/CodeSessionFileSummary.cjs +36 -46
- package/dist/cjs/tools/CodeSessionFileSummary.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +459 -649
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ReadFile.cjs +17 -20
- package/dist/cjs/tools/ReadFile.cjs.map +1 -1
- package/dist/cjs/tools/SkillTool.cjs +26 -27
- package/dist/cjs/tools/SkillTool.cjs.map +1 -1
- package/dist/cjs/tools/SubagentTool.cjs +59 -61
- package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +2146 -2686
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/ToolSearch.cjs +663 -825
- package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
- package/dist/cjs/tools/cloudflare/CloudflareBridgeRuntime.cjs +248 -340
- package/dist/cjs/tools/cloudflare/CloudflareBridgeRuntime.cjs.map +1 -1
- package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs +170 -197
- package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs +425 -520
- package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs.map +1 -1
- package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs +91 -124
- package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs.map +1 -1
- package/dist/cjs/tools/cloudflare/index.cjs +4 -0
- package/dist/cjs/tools/eagerEventExecution.cjs +75 -99
- package/dist/cjs/tools/eagerEventExecution.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +200 -262
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/local/CompileCheckTool.cjs +150 -212
- package/dist/cjs/tools/local/CompileCheckTool.cjs.map +1 -1
- package/dist/cjs/tools/local/FileCheckpointer.cjs +77 -85
- package/dist/cjs/tools/local/FileCheckpointer.cjs.map +1 -1
- package/dist/cjs/tools/local/LocalCodingTools.cjs +763 -1022
- package/dist/cjs/tools/local/LocalCodingTools.cjs.map +1 -1
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs +666 -941
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs.map +1 -1
- package/dist/cjs/tools/local/LocalExecutionTools.cjs +49 -92
- package/dist/cjs/tools/local/LocalExecutionTools.cjs.map +1 -1
- package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +286 -354
- package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/local/attachments.cjs +108 -165
- package/dist/cjs/tools/local/attachments.cjs.map +1 -1
- package/dist/cjs/tools/local/bashAst.cjs +99 -113
- package/dist/cjs/tools/local/bashAst.cjs.map +1 -1
- package/dist/cjs/tools/local/editStrategies.cjs +126 -169
- package/dist/cjs/tools/local/editStrategies.cjs.map +1 -1
- package/dist/cjs/tools/local/index.cjs +12 -0
- package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs +136 -218
- package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -1
- package/dist/cjs/tools/local/syntaxCheck.cjs +142 -161
- package/dist/cjs/tools/local/syntaxCheck.cjs.map +1 -1
- package/dist/cjs/tools/local/textEncoding.cjs +25 -23
- package/dist/cjs/tools/local/textEncoding.cjs.map +1 -1
- package/dist/cjs/tools/local/workspaceFS.cjs +38 -46
- package/dist/cjs/tools/local/workspaceFS.cjs.map +1 -1
- package/dist/cjs/tools/ptcTimeout.cjs +27 -47
- package/dist/cjs/tools/ptcTimeout.cjs.map +1 -1
- package/dist/cjs/tools/schema.cjs +24 -23
- package/dist/cjs/tools/schema.cjs.map +1 -1
- package/dist/cjs/tools/search/anthropic.cjs +24 -33
- package/dist/cjs/tools/search/anthropic.cjs.map +1 -1
- package/dist/cjs/tools/search/content.cjs +95 -137
- package/dist/cjs/tools/search/content.cjs.map +1 -1
- package/dist/cjs/tools/search/firecrawl.cjs +141 -172
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/format.cjs +128 -196
- package/dist/cjs/tools/search/format.cjs.map +1 -1
- package/dist/cjs/tools/search/highlights.cjs +165 -232
- package/dist/cjs/tools/search/highlights.cjs.map +1 -1
- package/dist/cjs/tools/search/index.cjs +2 -0
- package/dist/cjs/tools/search/rerankers.cjs +151 -174
- package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
- package/dist/cjs/tools/search/schema.cjs +40 -39
- package/dist/cjs/tools/search/schema.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +428 -530
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/serper-scraper.cjs +106 -127
- package/dist/cjs/tools/search/serper-scraper.cjs.map +1 -1
- package/dist/cjs/tools/search/tavily-scraper.cjs +129 -181
- package/dist/cjs/tools/search/tavily-scraper.cjs.map +1 -1
- package/dist/cjs/tools/search/tavily-search.cjs +295 -359
- package/dist/cjs/tools/search/tavily-search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +260 -299
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +74 -117
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/cjs/tools/skillCatalog.cjs +54 -72
- package/dist/cjs/tools/skillCatalog.cjs.map +1 -1
- package/dist/cjs/tools/streamedToolCallSeals.cjs +46 -34
- package/dist/cjs/tools/streamedToolCallSeals.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +612 -771
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/tools/subagent/index.cjs +1 -0
- package/dist/cjs/tools/toolOutputReferences.cjs +523 -630
- package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
- package/dist/cjs/utils/callbacks.cjs +11 -21
- package/dist/cjs/utils/callbacks.cjs.map +1 -1
- package/dist/cjs/utils/errors.cjs +70 -95
- package/dist/cjs/utils/errors.cjs.map +1 -1
- package/dist/cjs/utils/events.cjs +32 -42
- package/dist/cjs/utils/events.cjs.map +1 -1
- package/dist/cjs/utils/graph.cjs +8 -12
- package/dist/cjs/utils/graph.cjs.map +1 -1
- package/dist/cjs/utils/handlers.cjs +60 -82
- package/dist/cjs/utils/handlers.cjs.map +1 -1
- package/dist/cjs/utils/index.cjs +9 -0
- package/dist/cjs/utils/llm.cjs +19 -27
- package/dist/cjs/utils/llm.cjs.map +1 -1
- package/dist/cjs/utils/misc.cjs +30 -46
- package/dist/cjs/utils/misc.cjs.map +1 -1
- package/dist/cjs/utils/run.cjs +50 -66
- package/dist/cjs/utils/run.cjs.map +1 -1
- package/dist/cjs/utils/schema.cjs +11 -19
- package/dist/cjs/utils/schema.cjs.map +1 -1
- package/dist/cjs/utils/title.cjs +71 -106
- package/dist/cjs/utils/title.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +186 -283
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/cjs/utils/truncation.cjs +95 -114
- package/dist/cjs/utils/truncation.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +844 -1044
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/constants.mjs +13 -11
- package/dist/esm/common/constants.mjs.map +1 -1
- package/dist/esm/common/enum.mjs +221 -238
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/common/index.mjs +3 -0
- package/dist/esm/events.mjs +121 -167
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +1388 -1804
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +713 -943
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/graphs/index.mjs +3 -0
- package/dist/esm/hitl/askUserQuestion.mjs +60 -60
- package/dist/esm/hitl/askUserQuestion.mjs.map +1 -1
- package/dist/esm/hitl/index.mjs +2 -0
- package/dist/esm/hooks/HookRegistry.mjs +176 -200
- package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
- package/dist/esm/hooks/createToolPolicyHook.mjs +71 -99
- package/dist/esm/hooks/createToolPolicyHook.mjs.map +1 -1
- package/dist/esm/hooks/createWorkspacePolicyHook.mjs +170 -271
- package/dist/esm/hooks/createWorkspacePolicyHook.mjs.map +1 -1
- package/dist/esm/hooks/executeHooks.mjs +227 -280
- package/dist/esm/hooks/executeHooks.mjs.map +1 -1
- package/dist/esm/hooks/index.mjs +7 -0
- package/dist/esm/hooks/matchers.mjs +196 -228
- package/dist/esm/hooks/matchers.mjs.map +1 -1
- package/dist/esm/hooks/types.mjs +24 -22
- package/dist/esm/hooks/types.mjs.map +1 -1
- package/dist/esm/instrumentation.mjs +109 -132
- package/dist/esm/instrumentation.mjs.map +1 -1
- package/dist/esm/langchain/google-common.mjs +1 -2
- package/dist/esm/langchain/index.mjs +5 -5
- package/dist/esm/langchain/language_models/chat_models.mjs +1 -2
- package/dist/esm/langchain/messages/tool.mjs +1 -2
- package/dist/esm/langchain/messages.mjs +2 -2
- package/dist/esm/langchain/openai.mjs +1 -2
- package/dist/esm/langchain/prompts.mjs +2 -2
- package/dist/esm/langchain/runnables.mjs +2 -2
- package/dist/esm/langchain/tools.mjs +2 -2
- package/dist/esm/langchain/utils/env.mjs +2 -2
- package/dist/esm/langfuse.mjs +60 -76
- package/dist/esm/langfuse.mjs.map +1 -1
- package/dist/esm/langfuseToolOutputTracing.mjs +267 -395
- package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
- package/dist/esm/llm/anthropic/index.mjs +432 -559
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/anthropic/types.mjs +23 -45
- package/dist/esm/llm/anthropic/types.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +439 -725
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +171 -253
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/output_parsers.mjs +3 -0
- package/dist/esm/llm/anthropic/utils/tools.mjs +12 -24
- package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +214 -238
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/toolCache.mjs +84 -104
- package/dist/esm/llm/bedrock/toolCache.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/index.mjs +3 -0
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs +357 -618
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_outputs.mjs +140 -147
- package/dist/esm/llm/bedrock/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/fake.mjs +86 -94
- package/dist/esm/llm/fake.mjs.map +1 -1
- package/dist/esm/llm/google/index.mjs +183 -235
- package/dist/esm/llm/google/index.mjs.map +1 -1
- package/dist/esm/llm/google/utils/common.mjs +403 -666
- package/dist/esm/llm/google/utils/common.mjs.map +1 -1
- package/dist/esm/llm/google/utils/zod_to_genai_parameters.mjs +3 -0
- package/dist/esm/llm/init.mjs +44 -51
- package/dist/esm/llm/init.mjs.map +1 -1
- package/dist/esm/llm/invoke.mjs +142 -180
- package/dist/esm/llm/invoke.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +1035 -1268
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +188 -312
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs +102 -151
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/toolCache.mjs +35 -42
- package/dist/esm/llm/openrouter/toolCache.mjs.map +1 -1
- package/dist/esm/llm/providers.mjs +29 -34
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/llm/request.mjs +20 -31
- package/dist/esm/llm/request.mjs.map +1 -1
- package/dist/esm/llm/vertexai/index.mjs +446 -449
- package/dist/esm/llm/vertexai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +99 -87
- package/dist/esm/messages/anthropicToolCache.mjs +68 -117
- package/dist/esm/messages/anthropicToolCache.mjs.map +1 -1
- package/dist/esm/messages/cache.mjs +305 -416
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/content.mjs +36 -47
- package/dist/esm/messages/content.mjs.map +1 -1
- package/dist/esm/messages/contextPruning.mjs +112 -143
- package/dist/esm/messages/contextPruning.mjs.map +1 -1
- package/dist/esm/messages/contextPruningSettings.mjs +36 -44
- package/dist/esm/messages/contextPruningSettings.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +254 -393
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +902 -1383
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/ids.mjs +16 -18
- package/dist/esm/messages/ids.mjs.map +1 -1
- package/dist/esm/messages/index.mjs +13 -0
- package/dist/esm/messages/langchain.mjs +18 -16
- package/dist/esm/messages/langchain.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs +1053 -1514
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/messages/recency.mjs +77 -93
- package/dist/esm/messages/recency.mjs.map +1 -1
- package/dist/esm/messages/reducer.mjs +63 -76
- package/dist/esm/messages/reducer.mjs.map +1 -1
- package/dist/esm/messages/tools.mjs +49 -75
- package/dist/esm/messages/tools.mjs.map +1 -1
- package/dist/esm/openai/index.mjs +170 -215
- package/dist/esm/openai/index.mjs.map +1 -1
- package/dist/esm/responses/index.mjs +301 -389
- package/dist/esm/responses/index.mjs.map +1 -1
- package/dist/esm/run.mjs +903 -1111
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/AgentSession.mjs +806 -985
- package/dist/esm/session/AgentSession.mjs.map +1 -1
- package/dist/esm/session/JsonlSessionStore.mjs +326 -407
- package/dist/esm/session/JsonlSessionStore.mjs.map +1 -1
- package/dist/esm/session/handlers.mjs +192 -206
- package/dist/esm/session/handlers.mjs.map +1 -1
- package/dist/esm/session/ids.mjs +9 -8
- package/dist/esm/session/ids.mjs.map +1 -1
- package/dist/esm/session/index.mjs +5 -0
- package/dist/esm/session/messageSerialization.mjs +94 -154
- package/dist/esm/session/messageSerialization.mjs.map +1 -1
- package/dist/esm/splitStream.mjs +147 -204
- package/dist/esm/splitStream.mjs.map +1 -1
- package/dist/esm/stream.mjs +872 -1341
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/index.mjs +57 -99
- package/dist/esm/summarization/index.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +640 -790
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/BashExecutor.mjs +103 -129
- package/dist/esm/tools/BashExecutor.mjs.map +1 -1
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs +162 -239
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/Calculator.mjs +34 -36
- package/dist/esm/tools/Calculator.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +123 -164
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/CodeSessionFileSummary.mjs +36 -44
- package/dist/esm/tools/CodeSessionFileSummary.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +454 -644
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ReadFile.mjs +17 -18
- package/dist/esm/tools/ReadFile.mjs.map +1 -1
- package/dist/esm/tools/SkillTool.mjs +26 -25
- package/dist/esm/tools/SkillTool.mjs.map +1 -1
- package/dist/esm/tools/SubagentTool.mjs +59 -59
- package/dist/esm/tools/SubagentTool.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +2144 -2684
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/ToolSearch.mjs +659 -804
- package/dist/esm/tools/ToolSearch.mjs.map +1 -1
- package/dist/esm/tools/cloudflare/CloudflareBridgeRuntime.mjs +248 -338
- package/dist/esm/tools/cloudflare/CloudflareBridgeRuntime.mjs.map +1 -1
- package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs +170 -195
- package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs +424 -517
- package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs.map +1 -1
- package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs +91 -122
- package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs.map +1 -1
- package/dist/esm/tools/cloudflare/index.mjs +5 -0
- package/dist/esm/tools/eagerEventExecution.mjs +75 -96
- package/dist/esm/tools/eagerEventExecution.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +200 -260
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/local/CompileCheckTool.mjs +150 -210
- package/dist/esm/tools/local/CompileCheckTool.mjs.map +1 -1
- package/dist/esm/tools/local/FileCheckpointer.mjs +77 -83
- package/dist/esm/tools/local/FileCheckpointer.mjs.map +1 -1
- package/dist/esm/tools/local/LocalCodingTools.mjs +760 -1017
- package/dist/esm/tools/local/LocalCodingTools.mjs.map +1 -1
- package/dist/esm/tools/local/LocalExecutionEngine.mjs +663 -936
- package/dist/esm/tools/local/LocalExecutionEngine.mjs.map +1 -1
- package/dist/esm/tools/local/LocalExecutionTools.mjs +49 -90
- package/dist/esm/tools/local/LocalExecutionTools.mjs.map +1 -1
- package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +283 -349
- package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/local/attachments.mjs +108 -163
- package/dist/esm/tools/local/attachments.mjs.map +1 -1
- package/dist/esm/tools/local/bashAst.mjs +99 -111
- package/dist/esm/tools/local/bashAst.mjs.map +1 -1
- package/dist/esm/tools/local/editStrategies.mjs +126 -167
- package/dist/esm/tools/local/editStrategies.mjs.map +1 -1
- package/dist/esm/tools/local/index.mjs +13 -0
- package/dist/esm/tools/local/resolveLocalExecutionTools.mjs +136 -216
- package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -1
- package/dist/esm/tools/local/syntaxCheck.mjs +138 -155
- package/dist/esm/tools/local/syntaxCheck.mjs.map +1 -1
- package/dist/esm/tools/local/textEncoding.mjs +25 -21
- package/dist/esm/tools/local/textEncoding.mjs.map +1 -1
- package/dist/esm/tools/local/workspaceFS.mjs +38 -44
- package/dist/esm/tools/local/workspaceFS.mjs.map +1 -1
- package/dist/esm/tools/ptcTimeout.mjs +27 -42
- package/dist/esm/tools/ptcTimeout.mjs.map +1 -1
- package/dist/esm/tools/schema.mjs +24 -21
- package/dist/esm/tools/schema.mjs.map +1 -1
- package/dist/esm/tools/search/anthropic.mjs +24 -31
- package/dist/esm/tools/search/anthropic.mjs.map +1 -1
- package/dist/esm/tools/search/content.mjs +93 -116
- package/dist/esm/tools/search/content.mjs.map +1 -1
- package/dist/esm/tools/search/firecrawl.mjs +139 -169
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/format.mjs +128 -194
- package/dist/esm/tools/search/format.mjs.map +1 -1
- package/dist/esm/tools/search/highlights.mjs +165 -230
- package/dist/esm/tools/search/highlights.mjs.map +1 -1
- package/dist/esm/tools/search/index.mjs +3 -0
- package/dist/esm/tools/search/rerankers.mjs +149 -168
- package/dist/esm/tools/search/rerankers.mjs.map +1 -1
- package/dist/esm/tools/search/schema.mjs +39 -37
- package/dist/esm/tools/search/schema.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +426 -528
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/serper-scraper.mjs +104 -124
- package/dist/esm/tools/search/serper-scraper.mjs.map +1 -1
- package/dist/esm/tools/search/tavily-scraper.mjs +127 -178
- package/dist/esm/tools/search/tavily-scraper.mjs.map +1 -1
- package/dist/esm/tools/search/tavily-search.mjs +293 -357
- package/dist/esm/tools/search/tavily-search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +259 -297
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +74 -115
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/esm/tools/skillCatalog.mjs +54 -70
- package/dist/esm/tools/skillCatalog.mjs.map +1 -1
- package/dist/esm/tools/streamedToolCallSeals.mjs +42 -31
- package/dist/esm/tools/streamedToolCallSeals.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +612 -768
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/tools/subagent/index.mjs +2 -0
- package/dist/esm/tools/toolOutputReferences.mjs +523 -624
- package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
- package/dist/esm/utils/callbacks.mjs +11 -19
- package/dist/esm/utils/callbacks.mjs.map +1 -1
- package/dist/esm/utils/errors.mjs +70 -93
- package/dist/esm/utils/errors.mjs.map +1 -1
- package/dist/esm/utils/events.mjs +32 -40
- package/dist/esm/utils/events.mjs.map +1 -1
- package/dist/esm/utils/graph.mjs +8 -10
- package/dist/esm/utils/graph.mjs.map +1 -1
- package/dist/esm/utils/handlers.mjs +60 -80
- package/dist/esm/utils/handlers.mjs.map +1 -1
- package/dist/esm/utils/index.mjs +10 -0
- package/dist/esm/utils/llm.mjs +19 -25
- package/dist/esm/utils/llm.mjs.map +1 -1
- package/dist/esm/utils/misc.mjs +30 -44
- package/dist/esm/utils/misc.mjs.map +1 -1
- package/dist/esm/utils/run.mjs +50 -64
- package/dist/esm/utils/run.mjs.map +1 -1
- package/dist/esm/utils/schema.mjs +11 -17
- package/dist/esm/utils/schema.mjs.map +1 -1
- package/dist/esm/utils/title.mjs +71 -104
- package/dist/esm/utils/title.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +186 -281
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/esm/utils/truncation.mjs +95 -112
- package/dist/esm/utils/truncation.mjs.map +1 -1
- package/dist/types/llm/bedrock/utils/index.d.ts +1 -1
- package/dist/types/llm/bedrock/utils/message_outputs.d.ts +9 -0
- package/dist/types/llm/vertexai/index.d.ts +10 -0
- package/dist/types/tools/ToolNode.d.ts +8 -0
- package/dist/types/tools/search/tool.d.ts +17 -0
- package/dist/types/tools/search/types.d.ts +4 -0
- package/dist/types/tools/streamedToolCallSeals.d.ts +5 -1
- package/dist/types/types/tools.d.ts +10 -0
- package/package.json +4 -10
- package/src/__tests__/stream.eagerEventExecution.test.ts +703 -0
- package/src/llm/bedrock/index.ts +40 -0
- package/src/llm/bedrock/streamSealDispatch.test.ts +158 -0
- package/src/llm/bedrock/utils/index.ts +1 -0
- package/src/llm/bedrock/utils/message_outputs.test.ts +85 -0
- package/src/llm/bedrock/utils/message_outputs.ts +43 -0
- package/src/llm/google/utils/common.test.ts +64 -0
- package/src/llm/google/utils/common.ts +18 -0
- package/src/llm/openai/index.ts +95 -1
- package/src/llm/openai/sequentialToolCallSeals.test.ts +199 -0
- package/src/llm/vertexai/index.ts +31 -0
- package/src/llm/vertexai/sealStreamedToolCalls.test.ts +88 -0
- package/src/llm/vertexai/streamSealDispatch.test.ts +148 -0
- package/src/stream.ts +40 -6
- package/src/tools/ToolNode.ts +85 -3
- package/src/tools/__tests__/ToolNode.onResultCompletion.test.ts +368 -0
- package/src/tools/search/highlights.ts +9 -1
- package/src/tools/search/search.ts +41 -3
- package/src/tools/search/source-processing.test.ts +373 -0
- package/src/tools/search/tool.ts +22 -2
- package/src/tools/search/types.ts +4 -0
- package/src/tools/streamedToolCallSeals.ts +37 -9
- package/src/types/tools.ts +10 -0
- package/dist/cjs/langchain/google-common.cjs.map +0 -1
- package/dist/cjs/langchain/index.cjs.map +0 -1
- package/dist/cjs/langchain/language_models/chat_models.cjs.map +0 -1
- package/dist/cjs/langchain/messages/tool.cjs.map +0 -1
- package/dist/cjs/langchain/messages.cjs.map +0 -1
- package/dist/cjs/langchain/openai.cjs.map +0 -1
- package/dist/cjs/langchain/prompts.cjs.map +0 -1
- package/dist/cjs/langchain/runnables.cjs.map +0 -1
- package/dist/cjs/langchain/tools.cjs.map +0 -1
- package/dist/cjs/langchain/utils/env.cjs.map +0 -1
- package/dist/cjs/main.cjs.map +0 -1
- package/dist/esm/langchain/google-common.mjs.map +0 -1
- package/dist/esm/langchain/index.mjs.map +0 -1
- package/dist/esm/langchain/language_models/chat_models.mjs.map +0 -1
- package/dist/esm/langchain/messages/tool.mjs.map +0 -1
- package/dist/esm/langchain/messages.mjs.map +0 -1
- package/dist/esm/langchain/openai.mjs.map +0 -1
- package/dist/esm/langchain/prompts.mjs.map +0 -1
- package/dist/esm/langchain/runnables.mjs.map +0 -1
- package/dist/esm/langchain/tools.mjs.map +0 -1
- package/dist/esm/langchain/utils/env.mjs.map +0 -1
- package/dist/esm/main.mjs.map +0 -1
|
@@ -1,97 +1,81 @@
|
|
|
1
|
+
//#region src/messages/recency.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
3
|
+
* Splits `messages` into a head (older, to summarize) and a tail (recent,
|
|
4
|
+
* to preserve verbatim) at user-message boundaries. The most recent
|
|
5
|
+
* user-led turn is always included in the tail; additional older turns
|
|
6
|
+
* are added subject to `turns` and `tokens` caps.
|
|
7
|
+
*
|
|
8
|
+
* Cutting strictly at HumanMessage boundaries ensures that:
|
|
9
|
+
* - tool_use ↔ tool_result pairs are never split (they always live within
|
|
10
|
+
* the same turn);
|
|
11
|
+
* - the first user message is never replaced by a summary, addressing
|
|
12
|
+
* the "first turn destruction" failure mode where a single large
|
|
13
|
+
* user-pasted payload would otherwise be replaced by a generic summary.
|
|
14
|
+
*
|
|
15
|
+
* When `messages` contains no HumanMessage (degenerate state — e.g. system
|
|
16
|
+
* + assistant messages from a programmatic preamble), everything is
|
|
17
|
+
* placed in the head and the tail is empty. The summarize node treats
|
|
18
|
+
* an empty tail as "nothing recent to preserve" and falls through to its
|
|
19
|
+
* existing logic.
|
|
20
|
+
*/
|
|
20
21
|
function splitAtRecencyBoundary(messages, options = {}) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
let turnTokens = 0;
|
|
77
|
-
for (let i = turnStart; i < turnEnd; i++) {
|
|
78
|
-
turnTokens += tokenCounter(messages[i]);
|
|
79
|
-
}
|
|
80
|
-
if (tailTokens + turnTokens > tokensCap) {
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
tailTokens += turnTokens;
|
|
84
|
-
}
|
|
85
|
-
tailStartIndex = turnStart;
|
|
86
|
-
tailTurnCount += 1;
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
head: messages.slice(0, tailStartIndex),
|
|
90
|
-
tail: messages.slice(tailStartIndex),
|
|
91
|
-
tailTurnCount,
|
|
92
|
-
tailStartIndex,
|
|
93
|
-
};
|
|
22
|
+
const turnsCap = options.turns ?? 2;
|
|
23
|
+
if (messages.length === 0 || turnsCap <= 0) return {
|
|
24
|
+
head: messages,
|
|
25
|
+
tail: [],
|
|
26
|
+
tailTurnCount: 0,
|
|
27
|
+
tailStartIndex: messages.length
|
|
28
|
+
};
|
|
29
|
+
const turnStarts = [];
|
|
30
|
+
for (let i = 0; i < messages.length; i++) if (messages[i].getType() === "human") turnStarts.push(i);
|
|
31
|
+
if (turnStarts.length === 0) return {
|
|
32
|
+
head: messages,
|
|
33
|
+
tail: [],
|
|
34
|
+
tailTurnCount: 0,
|
|
35
|
+
tailStartIndex: messages.length
|
|
36
|
+
};
|
|
37
|
+
const lastTurnStart = turnStarts[turnStarts.length - 1];
|
|
38
|
+
let tailStartIndex = lastTurnStart;
|
|
39
|
+
let tailTurnCount = 1;
|
|
40
|
+
const tokensCap = options.tokens;
|
|
41
|
+
const tokenCounter = options.tokenCounter;
|
|
42
|
+
const trackTokens = tokensCap != null && Number.isFinite(tokensCap) && tokenCounter != null;
|
|
43
|
+
/**
|
|
44
|
+
* Token-counting strategy: each candidate turn `t` spans the half-open
|
|
45
|
+
* range `[turnStarts[t], turnStarts[t + 1])` (or `[turnStarts[t], messages.length)`
|
|
46
|
+
* for the most recent turn). Successive iterations of the outer loop
|
|
47
|
+
* walk older turns one at a time and never revisit messages from a
|
|
48
|
+
* later turn — so each message contributes to `tokenCounter` at most
|
|
49
|
+
* once across the entire selection, making the boundary search
|
|
50
|
+
* `O(messages_in_visited_turns)` and bounded by `O(messages.length)`
|
|
51
|
+
* even before the `turnsCap` short-circuit applies. The inner upper
|
|
52
|
+
* bound uses `turnStarts[t + 1]` (a value derived from immutable
|
|
53
|
+
* `turnStarts`) rather than the mutated `tailStartIndex` to make the
|
|
54
|
+
* disjoint-range invariant self-evident.
|
|
55
|
+
*/
|
|
56
|
+
let tailTokens = 0;
|
|
57
|
+
if (trackTokens) for (let i = lastTurnStart; i < messages.length; i++) tailTokens += tokenCounter(messages[i]);
|
|
58
|
+
for (let t = turnStarts.length - 2; t >= 0; t--) {
|
|
59
|
+
if (tailTurnCount >= turnsCap) break;
|
|
60
|
+
const turnStart = turnStarts[t];
|
|
61
|
+
const turnEnd = turnStarts[t + 1];
|
|
62
|
+
if (trackTokens) {
|
|
63
|
+
let turnTokens = 0;
|
|
64
|
+
for (let i = turnStart; i < turnEnd; i++) turnTokens += tokenCounter(messages[i]);
|
|
65
|
+
if (tailTokens + turnTokens > tokensCap) break;
|
|
66
|
+
tailTokens += turnTokens;
|
|
67
|
+
}
|
|
68
|
+
tailStartIndex = turnStart;
|
|
69
|
+
tailTurnCount += 1;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
head: messages.slice(0, tailStartIndex),
|
|
73
|
+
tail: messages.slice(tailStartIndex),
|
|
74
|
+
tailTurnCount,
|
|
75
|
+
tailStartIndex
|
|
76
|
+
};
|
|
94
77
|
}
|
|
95
|
-
|
|
78
|
+
//#endregion
|
|
96
79
|
export { splitAtRecencyBoundary };
|
|
97
|
-
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=recency.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recency.mjs","sources":["../../../src/messages/recency.ts"],"sourcesContent":["import type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Configuration for splitting a message list into a head (to be summarized)\n * and a tail (to be preserved verbatim).\n */\nexport interface RecencyWindowOptions {\n /**\n * Maximum number of recent user-led turns to keep in the tail. A \"turn\"\n * begins at a HumanMessage and includes every following AIMessage and\n * ToolMessage up to (but not including) the next HumanMessage. Cutting\n * at turn boundaries guarantees that tool_use / tool_result pairs are\n * never split across the head/tail divide.\n *\n * The most recent turn is always preserved regardless of this value or\n * the token cap, so that a single oversized first message is never\n * destroyed by summarization.\n *\n * Defaults to `2`. A value of `0` disables the recency window (head =\n * everything, tail = empty), restoring the pre-recency-window behavior.\n */\n turns?: number;\n /**\n * Optional cap on tail size in tokens. When set, additional turns\n * beyond the most recent one are added to the tail only while the\n * cumulative token count stays at or below this cap. Turns are added\n * whole — never partially — so a turn that would exceed the cap is\n * left in the head.\n *\n * The most recent turn is always preserved even if it exceeds the cap.\n */\n tokens?: number;\n /** Token-counter used to evaluate the optional `tokens` cap. */\n tokenCounter?: (m: BaseMessage) => number;\n}\n\nexport interface RecencySplit {\n /** Older messages eligible for summarization. Empty when nothing to summarize. */\n head: BaseMessage[];\n /** Recent messages preserved verbatim. Always contains the most recent turn when any HumanMessage exists. */\n tail: BaseMessage[];\n /** Number of user-led turns retained in the tail (0 if no HumanMessage exists). */\n tailTurnCount: number;\n /** Index in the original `messages` array where the tail begins. */\n tailStartIndex: number;\n}\n\n/**\n * Splits `messages` into a head (older, to summarize) and a tail (recent,\n * to preserve verbatim) at user-message boundaries. The most recent\n * user-led turn is always included in the tail; additional older turns\n * are added subject to `turns` and `tokens` caps.\n *\n * Cutting strictly at HumanMessage boundaries ensures that:\n * - tool_use ↔ tool_result pairs are never split (they always live within\n * the same turn);\n * - the first user message is never replaced by a summary, addressing\n * the \"first turn destruction\" failure mode where a single large\n * user-pasted payload would otherwise be replaced by a generic summary.\n *\n * When `messages` contains no HumanMessage (degenerate state — e.g. system\n * + assistant messages from a programmatic preamble), everything is\n * placed in the head and the tail is empty. The summarize node treats\n * an empty tail as \"nothing recent to preserve\" and falls through to its\n * existing logic.\n */\nexport function splitAtRecencyBoundary(\n messages: BaseMessage[],\n options: RecencyWindowOptions = {}\n): RecencySplit {\n const turnsCap = options.turns ?? 2;\n\n if (messages.length === 0 || turnsCap <= 0) {\n return {\n head: messages,\n tail: [],\n tailTurnCount: 0,\n tailStartIndex: messages.length,\n };\n }\n\n const turnStarts: number[] = [];\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].getType() === 'human') {\n turnStarts.push(i);\n }\n }\n\n if (turnStarts.length === 0) {\n return {\n head: messages,\n tail: [],\n tailTurnCount: 0,\n tailStartIndex: messages.length,\n };\n }\n\n const lastTurnStart = turnStarts[turnStarts.length - 1] as number;\n let tailStartIndex = lastTurnStart;\n let tailTurnCount = 1;\n\n const tokensCap = options.tokens;\n const tokenCounter = options.tokenCounter;\n const trackTokens =\n tokensCap != null && Number.isFinite(tokensCap) && tokenCounter != null;\n\n /**\n * Token-counting strategy: each candidate turn `t` spans the half-open\n * range `[turnStarts[t], turnStarts[t + 1])` (or `[turnStarts[t], messages.length)`\n * for the most recent turn). Successive iterations of the outer loop\n * walk older turns one at a time and never revisit messages from a\n * later turn — so each message contributes to `tokenCounter` at most\n * once across the entire selection, making the boundary search\n * `O(messages_in_visited_turns)` and bounded by `O(messages.length)`\n * even before the `turnsCap` short-circuit applies. The inner upper\n * bound uses `turnStarts[t + 1]` (a value derived from immutable\n * `turnStarts`) rather than the mutated `tailStartIndex` to make the\n * disjoint-range invariant self-evident.\n */\n let tailTokens = 0;\n if (trackTokens) {\n for (let i = lastTurnStart; i < messages.length; i++) {\n tailTokens += tokenCounter(messages[i] as BaseMessage);\n }\n }\n\n for (let t = turnStarts.length - 2; t >= 0; t--) {\n if (tailTurnCount >= turnsCap) {\n break;\n }\n const turnStart = turnStarts[t] as number;\n const turnEnd = turnStarts[t + 1] as number;\n\n if (trackTokens) {\n let turnTokens = 0;\n for (let i = turnStart; i < turnEnd; i++) {\n turnTokens += tokenCounter(messages[i] as BaseMessage);\n }\n if (tailTokens + turnTokens > (tokensCap as number)) {\n break;\n }\n tailTokens += turnTokens;\n }\n\n tailStartIndex = turnStart;\n tailTurnCount += 1;\n }\n\n return {\n head: messages.slice(0, tailStartIndex),\n tail: messages.slice(tailStartIndex),\n tailTurnCount,\n tailStartIndex,\n };\n}\n"],"
|
|
1
|
+
{"version":3,"file":"recency.mjs","names":[],"sources":["../../../src/messages/recency.ts"],"sourcesContent":["import type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Configuration for splitting a message list into a head (to be summarized)\n * and a tail (to be preserved verbatim).\n */\nexport interface RecencyWindowOptions {\n /**\n * Maximum number of recent user-led turns to keep in the tail. A \"turn\"\n * begins at a HumanMessage and includes every following AIMessage and\n * ToolMessage up to (but not including) the next HumanMessage. Cutting\n * at turn boundaries guarantees that tool_use / tool_result pairs are\n * never split across the head/tail divide.\n *\n * The most recent turn is always preserved regardless of this value or\n * the token cap, so that a single oversized first message is never\n * destroyed by summarization.\n *\n * Defaults to `2`. A value of `0` disables the recency window (head =\n * everything, tail = empty), restoring the pre-recency-window behavior.\n */\n turns?: number;\n /**\n * Optional cap on tail size in tokens. When set, additional turns\n * beyond the most recent one are added to the tail only while the\n * cumulative token count stays at or below this cap. Turns are added\n * whole — never partially — so a turn that would exceed the cap is\n * left in the head.\n *\n * The most recent turn is always preserved even if it exceeds the cap.\n */\n tokens?: number;\n /** Token-counter used to evaluate the optional `tokens` cap. */\n tokenCounter?: (m: BaseMessage) => number;\n}\n\nexport interface RecencySplit {\n /** Older messages eligible for summarization. Empty when nothing to summarize. */\n head: BaseMessage[];\n /** Recent messages preserved verbatim. Always contains the most recent turn when any HumanMessage exists. */\n tail: BaseMessage[];\n /** Number of user-led turns retained in the tail (0 if no HumanMessage exists). */\n tailTurnCount: number;\n /** Index in the original `messages` array where the tail begins. */\n tailStartIndex: number;\n}\n\n/**\n * Splits `messages` into a head (older, to summarize) and a tail (recent,\n * to preserve verbatim) at user-message boundaries. The most recent\n * user-led turn is always included in the tail; additional older turns\n * are added subject to `turns` and `tokens` caps.\n *\n * Cutting strictly at HumanMessage boundaries ensures that:\n * - tool_use ↔ tool_result pairs are never split (they always live within\n * the same turn);\n * - the first user message is never replaced by a summary, addressing\n * the \"first turn destruction\" failure mode where a single large\n * user-pasted payload would otherwise be replaced by a generic summary.\n *\n * When `messages` contains no HumanMessage (degenerate state — e.g. system\n * + assistant messages from a programmatic preamble), everything is\n * placed in the head and the tail is empty. The summarize node treats\n * an empty tail as \"nothing recent to preserve\" and falls through to its\n * existing logic.\n */\nexport function splitAtRecencyBoundary(\n messages: BaseMessage[],\n options: RecencyWindowOptions = {}\n): RecencySplit {\n const turnsCap = options.turns ?? 2;\n\n if (messages.length === 0 || turnsCap <= 0) {\n return {\n head: messages,\n tail: [],\n tailTurnCount: 0,\n tailStartIndex: messages.length,\n };\n }\n\n const turnStarts: number[] = [];\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].getType() === 'human') {\n turnStarts.push(i);\n }\n }\n\n if (turnStarts.length === 0) {\n return {\n head: messages,\n tail: [],\n tailTurnCount: 0,\n tailStartIndex: messages.length,\n };\n }\n\n const lastTurnStart = turnStarts[turnStarts.length - 1] as number;\n let tailStartIndex = lastTurnStart;\n let tailTurnCount = 1;\n\n const tokensCap = options.tokens;\n const tokenCounter = options.tokenCounter;\n const trackTokens =\n tokensCap != null && Number.isFinite(tokensCap) && tokenCounter != null;\n\n /**\n * Token-counting strategy: each candidate turn `t` spans the half-open\n * range `[turnStarts[t], turnStarts[t + 1])` (or `[turnStarts[t], messages.length)`\n * for the most recent turn). Successive iterations of the outer loop\n * walk older turns one at a time and never revisit messages from a\n * later turn — so each message contributes to `tokenCounter` at most\n * once across the entire selection, making the boundary search\n * `O(messages_in_visited_turns)` and bounded by `O(messages.length)`\n * even before the `turnsCap` short-circuit applies. The inner upper\n * bound uses `turnStarts[t + 1]` (a value derived from immutable\n * `turnStarts`) rather than the mutated `tailStartIndex` to make the\n * disjoint-range invariant self-evident.\n */\n let tailTokens = 0;\n if (trackTokens) {\n for (let i = lastTurnStart; i < messages.length; i++) {\n tailTokens += tokenCounter(messages[i] as BaseMessage);\n }\n }\n\n for (let t = turnStarts.length - 2; t >= 0; t--) {\n if (tailTurnCount >= turnsCap) {\n break;\n }\n const turnStart = turnStarts[t] as number;\n const turnEnd = turnStarts[t + 1] as number;\n\n if (trackTokens) {\n let turnTokens = 0;\n for (let i = turnStart; i < turnEnd; i++) {\n turnTokens += tokenCounter(messages[i] as BaseMessage);\n }\n if (tailTokens + turnTokens > (tokensCap as number)) {\n break;\n }\n tailTokens += turnTokens;\n }\n\n tailStartIndex = turnStart;\n tailTurnCount += 1;\n }\n\n return {\n head: messages.slice(0, tailStartIndex),\n tail: messages.slice(tailStartIndex),\n tailTurnCount,\n tailStartIndex,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAkEA,SAAgB,uBACd,UACA,UAAgC,CAAC,GACnB;CACd,MAAM,WAAW,QAAQ,SAAS;CAElC,IAAI,SAAS,WAAW,KAAK,YAAY,GACvC,OAAO;EACL,MAAM;EACN,MAAM,CAAC;EACP,eAAe;EACf,gBAAgB,SAAS;CAC3B;CAGF,MAAM,aAAuB,CAAC;CAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KACnC,IAAI,SAAS,EAAE,CAAC,QAAQ,MAAM,SAC5B,WAAW,KAAK,CAAC;CAIrB,IAAI,WAAW,WAAW,GACxB,OAAO;EACL,MAAM;EACN,MAAM,CAAC;EACP,eAAe;EACf,gBAAgB,SAAS;CAC3B;CAGF,MAAM,gBAAgB,WAAW,WAAW,SAAS;CACrD,IAAI,iBAAiB;CACrB,IAAI,gBAAgB;CAEpB,MAAM,YAAY,QAAQ;CAC1B,MAAM,eAAe,QAAQ;CAC7B,MAAM,cACJ,aAAa,QAAQ,OAAO,SAAS,SAAS,KAAK,gBAAgB;;;;;;;;;;;;;;CAerE,IAAI,aAAa;CACjB,IAAI,aACF,KAAK,IAAI,IAAI,eAAe,IAAI,SAAS,QAAQ,KAC/C,cAAc,aAAa,SAAS,EAAiB;CAIzD,KAAK,IAAI,IAAI,WAAW,SAAS,GAAG,KAAK,GAAG,KAAK;EAC/C,IAAI,iBAAiB,UACnB;EAEF,MAAM,YAAY,WAAW;EAC7B,MAAM,UAAU,WAAW,IAAI;EAE/B,IAAI,aAAa;GACf,IAAI,aAAa;GACjB,KAAK,IAAI,IAAI,WAAW,IAAI,SAAS,KACnC,cAAc,aAAa,SAAS,EAAiB;GAEvD,IAAI,aAAa,aAAc,WAC7B;GAEF,cAAc;EAChB;EAEA,iBAAiB;EACjB,iBAAiB;CACnB;CAEA,OAAO;EACL,MAAM,SAAS,MAAM,GAAG,cAAc;EACtC,MAAM,SAAS,MAAM,cAAc;EACnC;EACA;CACF;AACF"}
|
|
@@ -1,83 +1,70 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
const REMOVE_ALL_MESSAGES =
|
|
1
|
+
import { RemoveMessage, coerceMessageLikeToMessage } from "@langchain/core/messages";
|
|
2
|
+
import { v4 } from "uuid";
|
|
3
|
+
//#region src/messages/reducer.ts
|
|
4
|
+
const REMOVE_ALL_MESSAGES = "__remove_all__";
|
|
5
5
|
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
6
|
+
* Creates a message that instructs messagesStateReducer to remove ALL
|
|
7
|
+
* existing messages from state. Messages appearing after this one in
|
|
8
|
+
* the array become the new state.
|
|
9
|
+
*
|
|
10
|
+
* Usage (in a node return value):
|
|
11
|
+
* ```ts
|
|
12
|
+
* return { messages: [createRemoveAllMessage(), ...survivingMessages] };
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* This works because the reducer checks for `getType() === 'remove'`
|
|
16
|
+
* with `id === REMOVE_ALL_MESSAGES` and discards everything before it.
|
|
17
|
+
*
|
|
18
|
+
* NOTE: Uses RemoveMessage from @langchain/core with a sentinel id so
|
|
19
|
+
* the reducer can distinguish a "remove-all" marker from a single-message
|
|
20
|
+
* removal.
|
|
21
|
+
*/
|
|
22
22
|
function createRemoveAllMessage() {
|
|
23
|
-
|
|
23
|
+
return new RemoveMessage({ id: REMOVE_ALL_MESSAGES });
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
* Prebuilt reducer that combines returned messages.
|
|
27
|
+
* Can handle standard messages and special modifiers like {@link RemoveMessage}
|
|
28
|
+
* instances.
|
|
29
|
+
*/
|
|
30
30
|
function messagesStateReducer(left, right) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
else {
|
|
67
|
-
idsToRemove.delete(m.id);
|
|
68
|
-
merged[existingIdx] = m;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
if (m.getType() === 'remove') {
|
|
73
|
-
throw new Error(`Attempting to delete a message with an ID that doesn't exist ('${m.id}')`);
|
|
74
|
-
}
|
|
75
|
-
mergedById.set(m.id, merged.length);
|
|
76
|
-
merged.push(m);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return merged.filter((m) => !idsToRemove.has(m.id));
|
|
31
|
+
const leftArray = Array.isArray(left) ? left : [left];
|
|
32
|
+
const rightArray = Array.isArray(right) ? right : [right];
|
|
33
|
+
const leftMessages = leftArray.map(coerceMessageLikeToMessage);
|
|
34
|
+
const rightMessages = rightArray.map(coerceMessageLikeToMessage);
|
|
35
|
+
for (const m of leftMessages) if (m.id === null || m.id === void 0) {
|
|
36
|
+
m.id = v4();
|
|
37
|
+
m.lc_kwargs.id = m.id;
|
|
38
|
+
}
|
|
39
|
+
let removeAllIdx;
|
|
40
|
+
for (let i = 0; i < rightMessages.length; i += 1) {
|
|
41
|
+
const m = rightMessages[i];
|
|
42
|
+
if (m.id === null || m.id === void 0) {
|
|
43
|
+
m.id = v4();
|
|
44
|
+
m.lc_kwargs.id = m.id;
|
|
45
|
+
}
|
|
46
|
+
if (m.getType() === "remove" && m.id === "__remove_all__") removeAllIdx = i;
|
|
47
|
+
}
|
|
48
|
+
if (removeAllIdx != null) return rightMessages.slice(removeAllIdx + 1);
|
|
49
|
+
const merged = [...leftMessages];
|
|
50
|
+
const mergedById = new Map(merged.map((m, i) => [m.id, i]));
|
|
51
|
+
const idsToRemove = /* @__PURE__ */ new Set();
|
|
52
|
+
for (const m of rightMessages) {
|
|
53
|
+
const existingIdx = mergedById.get(m.id);
|
|
54
|
+
if (existingIdx !== void 0) if (m.getType() === "remove") idsToRemove.add(m.id);
|
|
55
|
+
else {
|
|
56
|
+
idsToRemove.delete(m.id);
|
|
57
|
+
merged[existingIdx] = m;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
if (m.getType() === "remove") throw new Error(`Attempting to delete a message with an ID that doesn't exist ('${m.id}')`);
|
|
61
|
+
mergedById.set(m.id, merged.length);
|
|
62
|
+
merged.push(m);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return merged.filter((m) => !idsToRemove.has(m.id));
|
|
80
66
|
}
|
|
81
|
-
|
|
67
|
+
//#endregion
|
|
82
68
|
export { REMOVE_ALL_MESSAGES, createRemoveAllMessage, messagesStateReducer };
|
|
83
|
-
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=reducer.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reducer.mjs","sources":["../../../src/messages/reducer.ts"],"sourcesContent":["import { v4 } from 'uuid';\nimport {\n BaseMessage,\n RemoveMessage,\n BaseMessageLike,\n coerceMessageLikeToMessage,\n} from '@langchain/core/messages';\n\nexport const REMOVE_ALL_MESSAGES = '__remove_all__';\n\n/**\n * Creates a message that instructs messagesStateReducer to remove ALL\n * existing messages from state. Messages appearing after this one in\n * the array become the new state.\n *\n * Usage (in a node return value):\n * ```ts\n * return { messages: [createRemoveAllMessage(), ...survivingMessages] };\n * ```\n *\n * This works because the reducer checks for `getType() === 'remove'`\n * with `id === REMOVE_ALL_MESSAGES` and discards everything before it.\n *\n * NOTE: Uses RemoveMessage from @langchain/core with a sentinel id so\n * the reducer can distinguish a \"remove-all\" marker from a single-message\n * removal.\n */\nexport function createRemoveAllMessage(): BaseMessage {\n return new RemoveMessage({ id: REMOVE_ALL_MESSAGES });\n}\n\nexport type Messages =\n | Array<BaseMessage | BaseMessageLike>\n | BaseMessage\n | BaseMessageLike;\n\n/**\n * Prebuilt reducer that combines returned messages.\n * Can handle standard messages and special modifiers like {@link RemoveMessage}\n * instances.\n */\nexport function messagesStateReducer(\n left: Messages,\n right: Messages\n): BaseMessage[] {\n const leftArray = Array.isArray(left) ? left : [left];\n const rightArray = Array.isArray(right) ? right : [right];\n // coerce to message\n const leftMessages = (leftArray as BaseMessageLike[]).map(\n coerceMessageLikeToMessage\n );\n const rightMessages = (rightArray as BaseMessageLike[]).map(\n coerceMessageLikeToMessage\n );\n // assign missing ids\n for (const m of leftMessages) {\n if (m.id === null || m.id === undefined) {\n m.id = v4();\n m.lc_kwargs.id = m.id;\n }\n }\n\n let removeAllIdx: number | undefined;\n for (let i = 0; i < rightMessages.length; i += 1) {\n const m = rightMessages[i];\n if (m.id === null || m.id === undefined) {\n m.id = v4();\n m.lc_kwargs.id = m.id;\n }\n\n if (m.getType() === 'remove' && m.id === REMOVE_ALL_MESSAGES) {\n removeAllIdx = i;\n }\n }\n\n if (removeAllIdx != null) return rightMessages.slice(removeAllIdx + 1);\n\n // merge\n const merged = [...leftMessages];\n const mergedById = new Map(merged.map((m, i) => [m.id, i]));\n const idsToRemove = new Set();\n for (const m of rightMessages) {\n const existingIdx = mergedById.get(m.id);\n if (existingIdx !== undefined) {\n if (m.getType() === 'remove') {\n idsToRemove.add(m.id);\n } else {\n idsToRemove.delete(m.id);\n merged[existingIdx] = m;\n }\n } else {\n if (m.getType() === 'remove') {\n throw new Error(\n `Attempting to delete a message with an ID that doesn't exist ('${m.id}')`\n );\n }\n mergedById.set(m.id, merged.length);\n merged.push(m);\n }\n }\n return merged.filter((m) => !idsToRemove.has(m.id));\n}\n"],"
|
|
1
|
+
{"version":3,"file":"reducer.mjs","names":[],"sources":["../../../src/messages/reducer.ts"],"sourcesContent":["import { v4 } from 'uuid';\nimport {\n BaseMessage,\n RemoveMessage,\n BaseMessageLike,\n coerceMessageLikeToMessage,\n} from '@langchain/core/messages';\n\nexport const REMOVE_ALL_MESSAGES = '__remove_all__';\n\n/**\n * Creates a message that instructs messagesStateReducer to remove ALL\n * existing messages from state. Messages appearing after this one in\n * the array become the new state.\n *\n * Usage (in a node return value):\n * ```ts\n * return { messages: [createRemoveAllMessage(), ...survivingMessages] };\n * ```\n *\n * This works because the reducer checks for `getType() === 'remove'`\n * with `id === REMOVE_ALL_MESSAGES` and discards everything before it.\n *\n * NOTE: Uses RemoveMessage from @langchain/core with a sentinel id so\n * the reducer can distinguish a \"remove-all\" marker from a single-message\n * removal.\n */\nexport function createRemoveAllMessage(): BaseMessage {\n return new RemoveMessage({ id: REMOVE_ALL_MESSAGES });\n}\n\nexport type Messages =\n | Array<BaseMessage | BaseMessageLike>\n | BaseMessage\n | BaseMessageLike;\n\n/**\n * Prebuilt reducer that combines returned messages.\n * Can handle standard messages and special modifiers like {@link RemoveMessage}\n * instances.\n */\nexport function messagesStateReducer(\n left: Messages,\n right: Messages\n): BaseMessage[] {\n const leftArray = Array.isArray(left) ? left : [left];\n const rightArray = Array.isArray(right) ? right : [right];\n // coerce to message\n const leftMessages = (leftArray as BaseMessageLike[]).map(\n coerceMessageLikeToMessage\n );\n const rightMessages = (rightArray as BaseMessageLike[]).map(\n coerceMessageLikeToMessage\n );\n // assign missing ids\n for (const m of leftMessages) {\n if (m.id === null || m.id === undefined) {\n m.id = v4();\n m.lc_kwargs.id = m.id;\n }\n }\n\n let removeAllIdx: number | undefined;\n for (let i = 0; i < rightMessages.length; i += 1) {\n const m = rightMessages[i];\n if (m.id === null || m.id === undefined) {\n m.id = v4();\n m.lc_kwargs.id = m.id;\n }\n\n if (m.getType() === 'remove' && m.id === REMOVE_ALL_MESSAGES) {\n removeAllIdx = i;\n }\n }\n\n if (removeAllIdx != null) return rightMessages.slice(removeAllIdx + 1);\n\n // merge\n const merged = [...leftMessages];\n const mergedById = new Map(merged.map((m, i) => [m.id, i]));\n const idsToRemove = new Set();\n for (const m of rightMessages) {\n const existingIdx = mergedById.get(m.id);\n if (existingIdx !== undefined) {\n if (m.getType() === 'remove') {\n idsToRemove.add(m.id);\n } else {\n idsToRemove.delete(m.id);\n merged[existingIdx] = m;\n }\n } else {\n if (m.getType() === 'remove') {\n throw new Error(\n `Attempting to delete a message with an ID that doesn't exist ('${m.id}')`\n );\n }\n mergedById.set(m.id, merged.length);\n merged.push(m);\n }\n }\n return merged.filter((m) => !idsToRemove.has(m.id));\n}\n"],"mappings":";;;AAQA,MAAa,sBAAsB;;;;;;;;;;;;;;;;;;AAmBnC,SAAgB,yBAAsC;CACpD,OAAO,IAAI,cAAc,EAAE,IAAI,oBAAoB,CAAC;AACtD;;;;;;AAYA,SAAgB,qBACd,MACA,OACe;CACf,MAAM,YAAY,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;CACpD,MAAM,aAAa,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;CAExD,MAAM,eAAgB,UAAgC,IACpD,0BACF;CACA,MAAM,gBAAiB,WAAiC,IACtD,0BACF;CAEA,KAAK,MAAM,KAAK,cACd,IAAI,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAA,GAAW;EACvC,EAAE,KAAK,GAAG;EACV,EAAE,UAAU,KAAK,EAAE;CACrB;CAGF,IAAI;CACJ,KAAK,IAAI,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK,GAAG;EAChD,MAAM,IAAI,cAAc;EACxB,IAAI,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAA,GAAW;GACvC,EAAE,KAAK,GAAG;GACV,EAAE,UAAU,KAAK,EAAE;EACrB;EAEA,IAAI,EAAE,QAAQ,MAAM,YAAY,EAAE,OAAA,kBAChC,eAAe;CAEnB;CAEA,IAAI,gBAAgB,MAAM,OAAO,cAAc,MAAM,eAAe,CAAC;CAGrE,MAAM,SAAS,CAAC,GAAG,YAAY;CAC/B,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;CAC1D,MAAM,8BAAc,IAAI,IAAI;CAC5B,KAAK,MAAM,KAAK,eAAe;EAC7B,MAAM,cAAc,WAAW,IAAI,EAAE,EAAE;EACvC,IAAI,gBAAgB,KAAA,GAClB,IAAI,EAAE,QAAQ,MAAM,UAClB,YAAY,IAAI,EAAE,EAAE;OACf;GACL,YAAY,OAAO,EAAE,EAAE;GACvB,OAAO,eAAe;EACxB;OACK;GACL,IAAI,EAAE,QAAQ,MAAM,UAClB,MAAM,IAAI,MACR,kEAAkE,EAAE,GAAG,GACzE;GAEF,WAAW,IAAI,EAAE,IAAI,OAAO,MAAM;GAClC,OAAO,KAAK,CAAC;EACf;CACF;CACA,OAAO,OAAO,QAAQ,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;AACpD"}
|
|
@@ -1,82 +1,56 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import "../common/enum.mjs";
|
|
2
|
+
import "../common/index.mjs";
|
|
3
|
+
import { findLastIndex } from "./core.mjs";
|
|
4
|
+
import { AIMessageChunk, ToolMessage } from "@langchain/core/messages";
|
|
5
|
+
//#region src/messages/tools.ts
|
|
6
6
|
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
* Extracts discovered tool names from tool search results in the current turn.
|
|
8
|
+
* Only processes tool search messages after the latest AI message with tool calls.
|
|
9
|
+
*
|
|
10
|
+
* Similar pattern to formatArtifactPayload - finds relevant messages efficiently
|
|
11
|
+
* by identifying the latest AI parent and only processing subsequent tool messages.
|
|
12
|
+
*
|
|
13
|
+
* @param messages - All messages in the conversation
|
|
14
|
+
* @returns Array of discovered tool names (empty if no new discoveries)
|
|
15
|
+
*/
|
|
16
16
|
function extractToolDiscoveries(messages) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
continue;
|
|
36
|
-
if (msg.name !== Constants.TOOL_SEARCH)
|
|
37
|
-
continue;
|
|
38
|
-
if (!toolCallIds.has(msg.tool_call_id))
|
|
39
|
-
continue;
|
|
40
|
-
// This is a tool search result from the current turn
|
|
41
|
-
if (typeof msg.artifact === 'object' && msg.artifact != null) {
|
|
42
|
-
const artifact = msg.artifact;
|
|
43
|
-
if (artifact.tool_references && artifact.tool_references.length > 0) {
|
|
44
|
-
for (const ref of artifact.tool_references) {
|
|
45
|
-
discoveredNames.push(ref.tool_name);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return discoveredNames;
|
|
17
|
+
const lastMessage = messages[messages.length - 1];
|
|
18
|
+
if (!(lastMessage instanceof ToolMessage)) return [];
|
|
19
|
+
const latestAIParentIndex = findLastIndex(messages, (msg) => (msg instanceof AIMessageChunk && (msg.tool_calls?.length ?? 0) > 0 && msg.tool_calls?.some((tc) => tc.id === lastMessage.tool_call_id)) ?? false);
|
|
20
|
+
if (latestAIParentIndex === -1) return [];
|
|
21
|
+
const aiMessage = messages[latestAIParentIndex];
|
|
22
|
+
const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);
|
|
23
|
+
const discoveredNames = [];
|
|
24
|
+
for (let i = latestAIParentIndex + 1; i < messages.length; i++) {
|
|
25
|
+
const msg = messages[i];
|
|
26
|
+
if (!(msg instanceof ToolMessage)) continue;
|
|
27
|
+
if (msg.name !== "tool_search") continue;
|
|
28
|
+
if (!toolCallIds.has(msg.tool_call_id)) continue;
|
|
29
|
+
if (typeof msg.artifact === "object" && msg.artifact != null) {
|
|
30
|
+
const artifact = msg.artifact;
|
|
31
|
+
if (artifact.tool_references && artifact.tool_references.length > 0) for (const ref of artifact.tool_references) discoveredNames.push(ref.tool_name);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return discoveredNames;
|
|
51
35
|
}
|
|
52
36
|
/**
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
37
|
+
* Checks if the current turn has any tool search results.
|
|
38
|
+
* Quick check to avoid full extraction when not needed.
|
|
39
|
+
*/
|
|
56
40
|
function hasToolSearchInCurrentTurn(messages) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);
|
|
69
|
-
// Check if any tool search results exist after the AI message
|
|
70
|
-
for (let i = latestAIParentIndex + 1; i < messages.length; i++) {
|
|
71
|
-
const msg = messages[i];
|
|
72
|
-
if (msg instanceof ToolMessage &&
|
|
73
|
-
msg.name === Constants.TOOL_SEARCH &&
|
|
74
|
-
toolCallIds.has(msg.tool_call_id)) {
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return false;
|
|
41
|
+
const lastMessage = messages[messages.length - 1];
|
|
42
|
+
if (!(lastMessage instanceof ToolMessage)) return false;
|
|
43
|
+
const latestAIParentIndex = findLastIndex(messages, (msg) => (msg instanceof AIMessageChunk && (msg.tool_calls?.length ?? 0) > 0 && msg.tool_calls?.some((tc) => tc.id === lastMessage.tool_call_id)) ?? false);
|
|
44
|
+
if (latestAIParentIndex === -1) return false;
|
|
45
|
+
const aiMessage = messages[latestAIParentIndex];
|
|
46
|
+
const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);
|
|
47
|
+
for (let i = latestAIParentIndex + 1; i < messages.length; i++) {
|
|
48
|
+
const msg = messages[i];
|
|
49
|
+
if (msg instanceof ToolMessage && msg.name === "tool_search" && toolCallIds.has(msg.tool_call_id)) return true;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
79
52
|
}
|
|
80
|
-
|
|
53
|
+
//#endregion
|
|
81
54
|
export { extractToolDiscoveries, hasToolSearchInCurrentTurn };
|
|
82
|
-
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=tools.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.mjs","sources":["../../../src/messages/tools.ts"],"sourcesContent":["// src/messages/toolDiscovery.ts\nimport { AIMessageChunk, ToolMessage } from '@langchain/core/messages';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { findLastIndex } from './core';\nimport { Constants } from '@/common';\n\ntype ToolSearchArtifact = {\n tool_references?: Array<{ tool_name: string }>;\n};\n\n/**\n * Extracts discovered tool names from tool search results in the current turn.\n * Only processes tool search messages after the latest AI message with tool calls.\n *\n * Similar pattern to formatArtifactPayload - finds relevant messages efficiently\n * by identifying the latest AI parent and only processing subsequent tool messages.\n *\n * @param messages - All messages in the conversation\n * @returns Array of discovered tool names (empty if no new discoveries)\n */\nexport function extractToolDiscoveries(messages: BaseMessage[]): string[] {\n const lastMessage = messages[messages.length - 1];\n if (!(lastMessage instanceof ToolMessage)) return [];\n\n // Find the latest AIMessage with tool_calls that this tool message belongs to\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n (msg instanceof AIMessageChunk &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastMessage.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return [];\n\n // Collect tool_call_ids from the AI message\n const aiMessage = messages[latestAIParentIndex] as AIMessageChunk;\n const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);\n\n // Only process tool search results after the AI message that belong to this turn\n const discoveredNames: string[] = [];\n for (let i = latestAIParentIndex + 1; i < messages.length; i++) {\n const msg = messages[i];\n if (!(msg instanceof ToolMessage)) continue;\n if (msg.name !== Constants.TOOL_SEARCH) continue;\n if (!toolCallIds.has(msg.tool_call_id)) continue;\n\n // This is a tool search result from the current turn\n if (typeof msg.artifact === 'object' && msg.artifact != null) {\n const artifact = msg.artifact as ToolSearchArtifact;\n if (artifact.tool_references && artifact.tool_references.length > 0) {\n for (const ref of artifact.tool_references) {\n discoveredNames.push(ref.tool_name);\n }\n }\n }\n }\n\n return discoveredNames;\n}\n\n/**\n * Checks if the current turn has any tool search results.\n * Quick check to avoid full extraction when not needed.\n */\nexport function hasToolSearchInCurrentTurn(messages: BaseMessage[]): boolean {\n const lastMessage = messages[messages.length - 1];\n if (!(lastMessage instanceof ToolMessage)) return false;\n\n // Find the latest AIMessage with tool_calls\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n (msg instanceof AIMessageChunk &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastMessage.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return false;\n\n const aiMessage = messages[latestAIParentIndex] as AIMessageChunk;\n const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);\n\n // Check if any tool search results exist after the AI message\n for (let i = latestAIParentIndex + 1; i < messages.length; i++) {\n const msg = messages[i];\n if (\n msg instanceof ToolMessage &&\n msg.name === Constants.TOOL_SEARCH &&\n toolCallIds.has(msg.tool_call_id)\n ) {\n return true;\n }\n }\n\n return false;\n}\n"],"
|
|
1
|
+
{"version":3,"file":"tools.mjs","names":[],"sources":["../../../src/messages/tools.ts"],"sourcesContent":["// src/messages/toolDiscovery.ts\nimport { AIMessageChunk, ToolMessage } from '@langchain/core/messages';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { findLastIndex } from './core';\nimport { Constants } from '@/common';\n\ntype ToolSearchArtifact = {\n tool_references?: Array<{ tool_name: string }>;\n};\n\n/**\n * Extracts discovered tool names from tool search results in the current turn.\n * Only processes tool search messages after the latest AI message with tool calls.\n *\n * Similar pattern to formatArtifactPayload - finds relevant messages efficiently\n * by identifying the latest AI parent and only processing subsequent tool messages.\n *\n * @param messages - All messages in the conversation\n * @returns Array of discovered tool names (empty if no new discoveries)\n */\nexport function extractToolDiscoveries(messages: BaseMessage[]): string[] {\n const lastMessage = messages[messages.length - 1];\n if (!(lastMessage instanceof ToolMessage)) return [];\n\n // Find the latest AIMessage with tool_calls that this tool message belongs to\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n (msg instanceof AIMessageChunk &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastMessage.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return [];\n\n // Collect tool_call_ids from the AI message\n const aiMessage = messages[latestAIParentIndex] as AIMessageChunk;\n const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);\n\n // Only process tool search results after the AI message that belong to this turn\n const discoveredNames: string[] = [];\n for (let i = latestAIParentIndex + 1; i < messages.length; i++) {\n const msg = messages[i];\n if (!(msg instanceof ToolMessage)) continue;\n if (msg.name !== Constants.TOOL_SEARCH) continue;\n if (!toolCallIds.has(msg.tool_call_id)) continue;\n\n // This is a tool search result from the current turn\n if (typeof msg.artifact === 'object' && msg.artifact != null) {\n const artifact = msg.artifact as ToolSearchArtifact;\n if (artifact.tool_references && artifact.tool_references.length > 0) {\n for (const ref of artifact.tool_references) {\n discoveredNames.push(ref.tool_name);\n }\n }\n }\n }\n\n return discoveredNames;\n}\n\n/**\n * Checks if the current turn has any tool search results.\n * Quick check to avoid full extraction when not needed.\n */\nexport function hasToolSearchInCurrentTurn(messages: BaseMessage[]): boolean {\n const lastMessage = messages[messages.length - 1];\n if (!(lastMessage instanceof ToolMessage)) return false;\n\n // Find the latest AIMessage with tool_calls\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n (msg instanceof AIMessageChunk &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastMessage.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return false;\n\n const aiMessage = messages[latestAIParentIndex] as AIMessageChunk;\n const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);\n\n // Check if any tool search results exist after the AI message\n for (let i = latestAIParentIndex + 1; i < messages.length; i++) {\n const msg = messages[i];\n if (\n msg instanceof ToolMessage &&\n msg.name === Constants.TOOL_SEARCH &&\n toolCallIds.has(msg.tool_call_id)\n ) {\n return true;\n }\n }\n\n return false;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAoBA,SAAgB,uBAAuB,UAAmC;CACxE,MAAM,cAAc,SAAS,SAAS,SAAS;CAC/C,IAAI,EAAE,uBAAuB,cAAc,OAAO,CAAC;CAGnD,MAAM,sBAAsB,cAC1B,WACC,SACE,eAAe,mBACb,IAAI,YAAY,UAAU,KAAK,KAChC,IAAI,YAAY,MAAM,OAAO,GAAG,OAAO,YAAY,YAAY,MACjE,KACJ;CAEA,IAAI,wBAAwB,IAAI,OAAO,CAAC;CAGxC,MAAM,YAAY,SAAS;CAC3B,MAAM,cAAc,IAAI,IAAI,UAAU,YAAY,KAAK,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC;CAG1E,MAAM,kBAA4B,CAAC;CACnC,KAAK,IAAI,IAAI,sBAAsB,GAAG,IAAI,SAAS,QAAQ,KAAK;EAC9D,MAAM,MAAM,SAAS;EACrB,IAAI,EAAE,eAAe,cAAc;EACnC,IAAI,IAAI,SAAA,eAAgC;EACxC,IAAI,CAAC,YAAY,IAAI,IAAI,YAAY,GAAG;EAGxC,IAAI,OAAO,IAAI,aAAa,YAAY,IAAI,YAAY,MAAM;GAC5D,MAAM,WAAW,IAAI;GACrB,IAAI,SAAS,mBAAmB,SAAS,gBAAgB,SAAS,GAChE,KAAK,MAAM,OAAO,SAAS,iBACzB,gBAAgB,KAAK,IAAI,SAAS;EAGxC;CACF;CAEA,OAAO;AACT;;;;;AAMA,SAAgB,2BAA2B,UAAkC;CAC3E,MAAM,cAAc,SAAS,SAAS,SAAS;CAC/C,IAAI,EAAE,uBAAuB,cAAc,OAAO;CAGlD,MAAM,sBAAsB,cAC1B,WACC,SACE,eAAe,mBACb,IAAI,YAAY,UAAU,KAAK,KAChC,IAAI,YAAY,MAAM,OAAO,GAAG,OAAO,YAAY,YAAY,MACjE,KACJ;CAEA,IAAI,wBAAwB,IAAI,OAAO;CAEvC,MAAM,YAAY,SAAS;CAC3B,MAAM,cAAc,IAAI,IAAI,UAAU,YAAY,KAAK,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC;CAG1E,KAAK,IAAI,IAAI,sBAAsB,GAAG,IAAI,SAAS,QAAQ,KAAK;EAC9D,MAAM,MAAM,SAAS;EACrB,IACE,eAAe,eACf,IAAI,SAAA,iBACJ,YAAY,IAAI,IAAI,YAAY,GAEhC,OAAO;CAEX;CAEA,OAAO;AACT"}
|