@illuma-ai/agents 1.4.0-alpha.6 → 1.5.1
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/README.md +62 -0
- package/dist/cjs/agents/AgentContext.cjs +274 -67
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/enum.cjs +44 -13
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +182 -5
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +152 -1167
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/graphs/phases/memoryFlushPhase.cjs +1 -1
- package/dist/cjs/graphs/phases/memoryFlushPhase.cjs.map +1 -1
- package/dist/cjs/hooks/HookRegistry.cjs +162 -0
- package/dist/cjs/hooks/HookRegistry.cjs.map +1 -0
- package/dist/cjs/hooks/executeHooks.cjs +276 -0
- package/dist/cjs/hooks/executeHooks.cjs.map +1 -0
- package/dist/cjs/hooks/matchers.cjs +256 -0
- package/dist/cjs/hooks/matchers.cjs.map +1 -0
- package/dist/cjs/hooks/types.cjs +27 -0
- package/dist/cjs/hooks/types.cjs.map +1 -0
- package/dist/cjs/langchain/google-common.cjs +3 -0
- package/dist/cjs/langchain/google-common.cjs.map +1 -0
- package/dist/cjs/langchain/index.cjs +86 -0
- package/dist/cjs/langchain/index.cjs.map +1 -0
- package/dist/cjs/langchain/language_models/chat_models.cjs +3 -0
- package/dist/cjs/langchain/language_models/chat_models.cjs.map +1 -0
- package/dist/cjs/langchain/messages/tool.cjs +3 -0
- package/dist/cjs/langchain/messages/tool.cjs.map +1 -0
- package/dist/cjs/langchain/messages.cjs +51 -0
- package/dist/cjs/langchain/messages.cjs.map +1 -0
- package/dist/cjs/langchain/openai.cjs +3 -0
- package/dist/cjs/langchain/openai.cjs.map +1 -0
- package/dist/cjs/langchain/prompts.cjs +11 -0
- package/dist/cjs/langchain/prompts.cjs.map +1 -0
- package/dist/cjs/langchain/runnables.cjs +19 -0
- package/dist/cjs/langchain/runnables.cjs.map +1 -0
- package/dist/cjs/langchain/tools.cjs +23 -0
- package/dist/cjs/langchain/tools.cjs.map +1 -0
- package/dist/cjs/langchain/utils/env.cjs +11 -0
- package/dist/cjs/langchain/utils/env.cjs.map +1 -0
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +5 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/cacheSupport.cjs +55 -0
- package/dist/cjs/llm/bedrock/cacheSupport.cjs.map +1 -0
- package/dist/cjs/llm/bedrock/index.cjs +61 -33
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +1 -4
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +27 -10
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +178 -127
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/memory/citations.cjs +4 -4
- package/dist/cjs/memory/citations.cjs.map +1 -1
- package/dist/cjs/memory/constants.cjs +17 -17
- package/dist/cjs/memory/constants.cjs.map +1 -1
- package/dist/cjs/memory/mmr.cjs +1 -1
- package/dist/cjs/memory/mmr.cjs.map +1 -1
- package/dist/cjs/memory/paths.cjs +1 -1
- package/dist/cjs/memory/paths.cjs.map +1 -1
- package/dist/cjs/memory/recallTracking.cjs +3 -3
- package/dist/cjs/memory/recallTracking.cjs.map +1 -1
- package/dist/cjs/memory/temporalDecay.cjs +2 -2
- package/dist/cjs/memory/temporalDecay.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +89 -0
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/contextPruning.cjs +156 -0
- package/dist/cjs/messages/contextPruning.cjs.map +1 -0
- package/dist/cjs/messages/contextPruningSettings.cjs +53 -0
- package/dist/cjs/messages/contextPruningSettings.cjs.map +1 -0
- package/dist/cjs/messages/format.cjs +144 -20
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs +505 -4
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/run.cjs +141 -1
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/tools/BashExecutor.cjs +235 -0
- package/dist/cjs/tools/BashExecutor.cjs.map +1 -0
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +297 -0
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -0
- package/dist/cjs/tools/CodeExecutor.cjs +45 -47
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +16 -11
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ReadFile.cjs +44 -0
- package/dist/cjs/tools/ReadFile.cjs.map +1 -0
- package/dist/cjs/tools/SkillTool.cjs +51 -0
- package/dist/cjs/tools/SkillTool.cjs.map +1 -0
- package/dist/cjs/tools/SubagentTool.cjs +93 -0
- package/dist/cjs/tools/SubagentTool.cjs.map +1 -0
- package/dist/cjs/tools/ToolNode.cjs +450 -24
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/memory/memoryAppendTool.cjs +1 -1
- package/dist/cjs/tools/memory/memoryAppendTool.cjs.map +1 -1
- package/dist/cjs/tools/memory/memoryGetTool.cjs +2 -2
- package/dist/cjs/tools/memory/memoryGetTool.cjs.map +1 -1
- package/dist/cjs/tools/memory/memorySearchTool.cjs +3 -3
- package/dist/cjs/tools/memory/memorySearchTool.cjs.map +1 -1
- package/dist/cjs/tools/memory/shared.cjs +1 -1
- package/dist/cjs/tools/memory/shared.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +11 -3
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tavily-scraper.cjs +189 -0
- package/dist/cjs/tools/search/tavily-scraper.cjs.map +1 -0
- package/dist/cjs/tools/search/tavily-search.cjs +372 -0
- package/dist/cjs/tools/search/tavily-search.cjs.map +1 -0
- package/dist/cjs/tools/search/tool.cjs +28 -4
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +10 -3
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/cjs/tools/skillCatalog.cjs +84 -0
- package/dist/cjs/tools/skillCatalog.cjs.map +1 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +512 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -0
- package/dist/cjs/tools/toolOutputReferences.cjs +670 -0
- package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -0
- package/dist/cjs/types/agent-cache.cjs +54 -0
- package/dist/cjs/types/agent-cache.cjs.map +1 -0
- package/dist/cjs/types/graph.cjs.map +1 -1
- package/dist/cjs/utils/truncation.cjs +135 -0
- package/dist/cjs/utils/truncation.cjs.map +1 -0
- package/dist/esm/agents/AgentContext.mjs +274 -67
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/enum.mjs +44 -12
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +182 -5
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +155 -1170
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/graphs/phases/memoryFlushPhase.mjs +1 -1
- package/dist/esm/graphs/phases/memoryFlushPhase.mjs.map +1 -1
- package/dist/esm/hooks/HookRegistry.mjs +160 -0
- package/dist/esm/hooks/HookRegistry.mjs.map +1 -0
- package/dist/esm/hooks/executeHooks.mjs +273 -0
- package/dist/esm/hooks/executeHooks.mjs.map +1 -0
- package/dist/esm/hooks/matchers.mjs +251 -0
- package/dist/esm/hooks/matchers.mjs.map +1 -0
- package/dist/esm/hooks/types.mjs +25 -0
- package/dist/esm/hooks/types.mjs.map +1 -0
- package/dist/esm/langchain/google-common.mjs +2 -0
- package/dist/esm/langchain/google-common.mjs.map +1 -0
- package/dist/esm/langchain/index.mjs +5 -0
- package/dist/esm/langchain/language_models/chat_models.mjs +2 -0
- package/dist/esm/langchain/language_models/chat_models.mjs.map +1 -0
- package/dist/esm/langchain/messages/tool.mjs +2 -0
- package/dist/esm/langchain/messages/tool.mjs.map +1 -0
- package/dist/esm/langchain/messages.mjs +2 -0
- package/dist/esm/langchain/messages.mjs.map +1 -0
- package/dist/esm/langchain/openai.mjs +2 -0
- package/dist/esm/langchain/openai.mjs.map +1 -0
- package/dist/esm/langchain/prompts.mjs +2 -0
- package/dist/esm/langchain/prompts.mjs.map +1 -0
- package/dist/esm/langchain/runnables.mjs +2 -0
- package/dist/esm/langchain/runnables.mjs.map +1 -0
- package/dist/esm/langchain/tools.mjs +2 -0
- package/dist/esm/langchain/tools.mjs.map +1 -0
- package/dist/esm/langchain/utils/env.mjs +2 -0
- package/dist/esm/langchain/utils/env.mjs.map +1 -0
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +5 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/cacheSupport.mjs +52 -0
- package/dist/esm/llm/bedrock/cacheSupport.mjs.map +1 -0
- package/dist/esm/llm/bedrock/index.mjs +61 -34
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +1 -4
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +27 -10
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/main.mjs +21 -27
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/memory/citations.mjs +4 -4
- package/dist/esm/memory/citations.mjs.map +1 -1
- package/dist/esm/memory/constants.mjs +17 -17
- package/dist/esm/memory/constants.mjs.map +1 -1
- package/dist/esm/memory/mmr.mjs +1 -1
- package/dist/esm/memory/mmr.mjs.map +1 -1
- package/dist/esm/memory/paths.mjs +1 -1
- package/dist/esm/memory/paths.mjs.map +1 -1
- package/dist/esm/memory/recallTracking.mjs +3 -3
- package/dist/esm/memory/recallTracking.mjs.map +1 -1
- package/dist/esm/memory/temporalDecay.mjs +2 -2
- package/dist/esm/memory/temporalDecay.mjs.map +1 -1
- package/dist/esm/messages/cache.mjs +89 -0
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/contextPruning.mjs +154 -0
- package/dist/esm/messages/contextPruning.mjs.map +1 -0
- package/dist/esm/messages/contextPruningSettings.mjs +50 -0
- package/dist/esm/messages/contextPruningSettings.mjs.map +1 -0
- package/dist/esm/messages/format.mjs +136 -12
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs +504 -7
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/run.mjs +141 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/tools/BashExecutor.mjs +227 -0
- package/dist/esm/tools/BashExecutor.mjs.map +1 -0
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs +288 -0
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -0
- package/dist/esm/tools/CodeExecutor.mjs +45 -48
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +17 -12
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ReadFile.mjs +39 -0
- package/dist/esm/tools/ReadFile.mjs.map +1 -0
- package/dist/esm/tools/SkillTool.mjs +46 -0
- package/dist/esm/tools/SkillTool.mjs.map +1 -0
- package/dist/esm/tools/SubagentTool.mjs +86 -0
- package/dist/esm/tools/SubagentTool.mjs.map +1 -0
- package/dist/esm/tools/ToolNode.mjs +452 -26
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/memory/memoryAppendTool.mjs +1 -1
- package/dist/esm/tools/memory/memoryAppendTool.mjs.map +1 -1
- package/dist/esm/tools/memory/memoryGetTool.mjs +2 -2
- package/dist/esm/tools/memory/memoryGetTool.mjs.map +1 -1
- package/dist/esm/tools/memory/memorySearchTool.mjs +3 -3
- package/dist/esm/tools/memory/memorySearchTool.mjs.map +1 -1
- package/dist/esm/tools/memory/shared.mjs +1 -1
- package/dist/esm/tools/memory/shared.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +11 -3
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tavily-scraper.mjs +186 -0
- package/dist/esm/tools/search/tavily-scraper.mjs.map +1 -0
- package/dist/esm/tools/search/tavily-search.mjs +370 -0
- package/dist/esm/tools/search/tavily-search.mjs.map +1 -0
- package/dist/esm/tools/search/tool.mjs +28 -4
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +10 -3
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/esm/tools/skillCatalog.mjs +82 -0
- package/dist/esm/tools/skillCatalog.mjs.map +1 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +506 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -0
- package/dist/esm/tools/toolOutputReferences.mjs +662 -0
- package/dist/esm/tools/toolOutputReferences.mjs.map +1 -0
- package/dist/esm/types/agent-cache.mjs +52 -0
- package/dist/esm/types/agent-cache.mjs.map +1 -0
- package/dist/esm/types/graph.mjs.map +1 -1
- package/dist/esm/utils/truncation.mjs +128 -0
- package/dist/esm/utils/truncation.mjs.map +1 -0
- package/dist/types/agents/AgentContext.d.ts +101 -8
- package/dist/types/common/enum.d.ts +39 -12
- package/dist/types/common/index.d.ts +0 -1
- package/dist/types/graphs/Graph.d.ts +43 -0
- package/dist/types/graphs/MultiAgentGraph.d.ts +26 -150
- package/dist/types/graphs/index.d.ts +0 -1
- package/dist/types/graphs/phases/memoryFlushPhase.d.ts +2 -2
- package/dist/types/hooks/HookRegistry.d.ts +56 -0
- package/dist/types/hooks/executeHooks.d.ts +79 -0
- package/dist/types/hooks/index.d.ts +6 -0
- package/dist/types/hooks/matchers.d.ts +95 -0
- package/dist/types/hooks/types.d.ts +320 -0
- package/dist/types/index.d.ts +9 -9
- package/dist/types/langchain/google-common.d.ts +1 -0
- package/dist/types/langchain/index.d.ts +8 -0
- package/dist/types/langchain/language_models/chat_models.d.ts +1 -0
- package/dist/types/langchain/messages/tool.d.ts +1 -0
- package/dist/types/langchain/messages.d.ts +2 -0
- package/dist/types/langchain/openai.d.ts +1 -0
- package/dist/types/langchain/prompts.d.ts +1 -0
- package/dist/types/langchain/runnables.d.ts +2 -0
- package/dist/types/langchain/tools.d.ts +2 -0
- package/dist/types/langchain/utils/env.d.ts +1 -0
- package/dist/types/llm/bedrock/cacheSupport.d.ts +35 -0
- package/dist/types/llm/bedrock/index.d.ts +54 -1
- package/dist/types/llm/openai/index.d.ts +1 -1
- package/dist/types/memory/citations.d.ts +4 -4
- package/dist/types/memory/constants.d.ts +17 -17
- package/dist/types/memory/mmr.d.ts +3 -3
- package/dist/types/memory/paths.d.ts +1 -1
- package/dist/types/memory/temporalDecay.d.ts +2 -2
- package/dist/types/memory/types.d.ts +3 -3
- package/dist/types/messages/contextPruning.d.ts +42 -0
- package/dist/types/messages/contextPruningSettings.d.ts +44 -0
- package/dist/types/messages/format.d.ts +9 -1
- package/dist/types/messages/index.d.ts +2 -0
- package/dist/types/messages/prune.d.ts +91 -1
- package/dist/types/run.d.ts +2 -0
- package/dist/types/tools/BashExecutor.d.ts +76 -0
- package/dist/types/tools/BashProgrammaticToolCalling.d.ts +72 -0
- package/dist/types/tools/CodeExecutor.d.ts +8 -26
- package/dist/types/tools/ReadFile.d.ts +28 -0
- package/dist/types/tools/SkillTool.d.ts +40 -0
- package/dist/types/tools/SubagentTool.d.ts +36 -0
- package/dist/types/tools/ToolNode.d.ts +77 -5
- package/dist/types/tools/memory/shared.d.ts +1 -1
- package/dist/types/tools/search/tavily-scraper.d.ts +19 -0
- package/dist/types/tools/search/tavily-search.d.ts +4 -0
- package/dist/types/tools/search/types.d.ts +99 -5
- package/dist/types/tools/search/utils.d.ts +2 -2
- package/dist/types/tools/skillCatalog.d.ts +19 -0
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +137 -0
- package/dist/types/tools/subagent/index.d.ts +2 -0
- package/dist/types/tools/subagent/types.d.ts +84 -0
- package/dist/types/tools/toolOutputReferences.d.ts +236 -0
- package/dist/types/types/agent-cache.d.ts +71 -0
- package/dist/types/types/graph.d.ts +163 -22
- package/dist/types/types/index.d.ts +3 -0
- package/dist/types/types/messages.d.ts +26 -0
- package/dist/types/types/run.d.ts +22 -0
- package/dist/types/types/skill.d.ts +9 -0
- package/dist/types/types/tools.d.ts +111 -0
- package/dist/types/utils/index.d.ts +1 -3
- package/dist/types/utils/truncation.d.ts +70 -0
- package/package.json +57 -17
- package/src/agents/AgentContext.ts +321 -78
- package/src/agents/__tests__/AgentContext.cacheTtl.live.test.ts +259 -0
- package/src/agents/__tests__/AgentContext.crossAgentTier1.live.test.ts +266 -0
- package/src/agents/__tests__/AgentContext.crossUserCache.live.test.ts +342 -0
- package/src/agents/__tests__/AgentContext.test.ts +632 -0
- package/src/common/__tests__/enum.test.ts +7 -17
- package/src/common/enum.ts +43 -12
- package/src/common/index.ts +0 -1
- package/src/graphs/Graph.ts +222 -2
- package/src/graphs/MultiAgentGraph.ts +154 -1466
- package/src/graphs/__tests__/MultiAgentGraph.test.ts +91 -0
- package/src/graphs/gapFeatures.test.ts +1 -1
- package/src/graphs/index.ts +0 -1
- package/src/graphs/phases/__tests__/memoryFlushPhase.test.ts +1 -1
- package/src/graphs/phases/memoryFlushPhase.ts +2 -2
- package/src/hooks/HookRegistry.ts +208 -0
- package/src/hooks/__tests__/HookRegistry.test.ts +190 -0
- package/src/hooks/__tests__/compactHooks.test.ts +214 -0
- package/src/hooks/__tests__/executeHooks.test.ts +1013 -0
- package/src/hooks/__tests__/integration.test.ts +337 -0
- package/src/hooks/__tests__/matchers.test.ts +238 -0
- package/src/hooks/__tests__/toolHooks.test.ts +665 -0
- package/src/hooks/executeHooks.ts +375 -0
- package/src/hooks/index.ts +57 -0
- package/src/hooks/matchers.ts +280 -0
- package/src/hooks/types.ts +404 -0
- package/src/index.ts +15 -24
- package/src/langchain/google-common.ts +1 -0
- package/src/langchain/index.ts +8 -0
- package/src/langchain/language_models/chat_models.ts +1 -0
- package/src/langchain/messages/tool.ts +5 -0
- package/src/langchain/messages.ts +21 -0
- package/src/langchain/openai.ts +1 -0
- package/src/langchain/prompts.ts +1 -0
- package/src/langchain/runnables.ts +7 -0
- package/src/langchain/tools.ts +8 -0
- package/src/langchain/utils/env.ts +1 -0
- package/src/llm/anthropic/utils/message_inputs.ts +10 -1
- package/src/llm/anthropic/utils/server-tool-inputs.test.ts +436 -0
- package/src/llm/bedrock/__tests__/bedrock-caching.test.ts +166 -18
- package/src/llm/bedrock/cacheSupport.test.ts +99 -0
- package/src/llm/bedrock/cacheSupport.ts +53 -0
- package/src/llm/bedrock/index.ts +116 -41
- package/src/llm/openai/index.ts +2 -2
- package/src/llm/openai/utils/index.ts +31 -14
- package/src/memory/citations.ts +4 -4
- package/src/memory/constants.ts +17 -17
- package/src/memory/mmr.ts +3 -3
- package/src/memory/paths.ts +1 -1
- package/src/memory/recallTracking.ts +3 -3
- package/src/memory/temporalDecay.ts +2 -2
- package/src/memory/types.ts +3 -3
- package/src/messages/__tests__/contextPruning.test.ts +228 -0
- package/src/messages/cache.test.ts +62 -24
- package/src/messages/cache.ts +112 -0
- package/src/messages/contextPruning.ts +191 -0
- package/src/messages/contextPruningSettings.ts +90 -0
- package/src/messages/ensureThinkingBlock.test.ts +1 -1
- package/src/messages/format.ts +164 -12
- package/src/messages/formatAgentMessages.skills.test.ts +413 -0
- package/src/messages/formatAgentMessages.test.ts +1 -1
- package/src/messages/index.ts +2 -0
- package/src/messages/prune.ts +661 -4
- package/src/run.ts +155 -1
- package/src/scripts/multi-agent-chain.ts +2 -2
- package/src/scripts/multi-agent-document-review-chain.ts +2 -2
- package/src/scripts/multi-agent-hybrid-flow.ts +4 -4
- package/src/scripts/multi-agent-parallel.ts +3 -3
- package/src/scripts/multi-agent-sequence.ts +3 -3
- package/src/scripts/multi-agent-subagent.ts +246 -0
- package/src/scripts/multi-agent-supervisor.ts +5 -5
- package/src/scripts/poc-multi-agent-comprehensive.ts +8 -8
- package/src/scripts/sequential-full-metadata-test.ts +2 -2
- package/src/scripts/subagent-event-driven-debug.ts +190 -0
- package/src/scripts/subagent-tools-debug.ts +160 -0
- package/src/scripts/test-custom-prompt-key.ts +3 -3
- package/src/scripts/test-handoff-input.ts +1 -1
- package/src/scripts/test-handoff-steering.ts +3 -3
- package/src/scripts/test-multi-agent-list-handoff.ts +1 -1
- package/src/scripts/test-parallel-agent-labeling.ts +3 -3
- package/src/scripts/test-parallel-handoffs.ts +2 -2
- package/src/scripts/test-thinking-handoff-bedrock.ts +1 -1
- package/src/scripts/test-thinking-handoff.ts +1 -1
- package/src/scripts/test-thinking-to-thinking-handoff-bedrock.ts +1 -1
- package/src/scripts/test-tool-before-handoff-role-order.ts +1 -1
- package/src/scripts/test-tools-before-handoff.ts +1 -1
- package/src/specs/agent-handoffs.test.ts +26 -483
- package/src/specs/anthropic.simple.test.ts +61 -0
- package/src/specs/multi-agent-summarization.test.ts +396 -0
- package/src/specs/prune.orphans.test.ts +248 -0
- package/src/specs/prune.test.ts +104 -16
- package/src/specs/thinking-handoff.test.ts +19 -19
- package/src/tools/BashExecutor.ts +281 -0
- package/src/tools/BashProgrammaticToolCalling.ts +397 -0
- package/src/tools/CodeExecutor.ts +63 -54
- package/src/tools/ProgrammaticToolCalling.ts +29 -14
- package/src/tools/ReadFile.ts +39 -0
- package/src/tools/SkillTool.ts +46 -0
- package/src/tools/SubagentTool.ts +100 -0
- package/src/tools/ToolNode.ts +548 -26
- package/src/tools/__tests__/BashExecutor.test.ts +49 -0
- package/src/tools/__tests__/CodeExecutor.test.ts +37 -36
- package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +60 -0
- package/src/tools/__tests__/ReadFile.test.ts +44 -0
- package/src/tools/__tests__/SkillTool.test.ts +442 -0
- package/src/tools/__tests__/SubagentExecutor.test.ts +1148 -0
- package/src/tools/__tests__/SubagentTool.test.ts +149 -0
- package/src/tools/__tests__/ToolNode.outputReferences.test.ts +1438 -0
- package/src/tools/__tests__/annotateMessagesForLLM.test.ts +479 -0
- package/src/tools/__tests__/skillCatalog.test.ts +161 -0
- package/src/tools/__tests__/subagentHooks.test.ts +210 -0
- package/src/tools/__tests__/toolOutputReferences.test.ts +415 -0
- package/src/tools/memory/memoryAppendTool.ts +1 -1
- package/src/tools/memory/memoryGetTool.ts +2 -2
- package/src/tools/memory/memorySearchTool.ts +3 -3
- package/src/tools/memory/shared.ts +1 -1
- package/src/tools/search/search.ts +12 -2
- package/src/tools/search/tavily-scraper.ts +235 -0
- package/src/tools/search/tavily-search.ts +424 -0
- package/src/tools/search/tavily.test.ts +965 -0
- package/src/tools/search/tool.ts +36 -2
- package/src/tools/search/types.ts +133 -8
- package/src/tools/search/utils.ts +13 -5
- package/src/tools/skillCatalog.ts +126 -0
- package/src/tools/subagent/SubagentExecutor.ts +676 -0
- package/src/tools/subagent/index.ts +13 -0
- package/src/tools/subagent/types.test.ts +70 -0
- package/src/tools/subagent/types.ts +115 -0
- package/src/tools/toolOutputReferences.ts +825 -0
- package/src/types/agent-cache.ts +74 -0
- package/src/types/graph.ts +172 -20
- package/src/types/index.ts +3 -0
- package/src/types/messages.ts +27 -0
- package/src/types/run.ts +22 -0
- package/src/types/skill.ts +11 -0
- package/src/types/tools.ts +118 -0
- package/src/utils/__tests__/truncation.test.ts +66 -0
- package/src/utils/index.ts +1 -3
- package/src/utils/truncation.ts +154 -0
- package/dist/cjs/common/spawnPath.cjs +0 -104
- package/dist/cjs/common/spawnPath.cjs.map +0 -1
- package/dist/cjs/content/ArtifactStore.cjs +0 -579
- package/dist/cjs/content/ArtifactStore.cjs.map +0 -1
- package/dist/cjs/content/ContentStore.cjs +0 -638
- package/dist/cjs/content/ContentStore.cjs.map +0 -1
- package/dist/cjs/content/contentAnalyzer.cjs +0 -91
- package/dist/cjs/content/contentAnalyzer.cjs.map +0 -1
- package/dist/cjs/content/index.cjs +0 -20
- package/dist/cjs/content/index.cjs.map +0 -1
- package/dist/cjs/content/mcpAutoCache.cjs +0 -115
- package/dist/cjs/content/mcpAutoCache.cjs.map +0 -1
- package/dist/cjs/graphs/HandoffRegistry.cjs +0 -143
- package/dist/cjs/graphs/HandoffRegistry.cjs.map +0 -1
- package/dist/cjs/providers/a2a/A2ACapabilityProvider.cjs +0 -288
- package/dist/cjs/providers/a2a/A2ACapabilityProvider.cjs.map +0 -1
- package/dist/cjs/providers/a2a/client.cjs +0 -92
- package/dist/cjs/providers/a2a/client.cjs.map +0 -1
- package/dist/cjs/providers/a2a/config.cjs +0 -38
- package/dist/cjs/providers/a2a/config.cjs.map +0 -1
- package/dist/cjs/providers/capabilityNaming.cjs +0 -43
- package/dist/cjs/providers/capabilityNaming.cjs.map +0 -1
- package/dist/cjs/providers/mcp/MCPCapabilityProvider.cjs +0 -244
- package/dist/cjs/providers/mcp/MCPCapabilityProvider.cjs.map +0 -1
- package/dist/cjs/providers/mcp/config.cjs +0 -42
- package/dist/cjs/providers/mcp/config.cjs.map +0 -1
- package/dist/cjs/providers/mcp/transport.cjs +0 -65
- package/dist/cjs/providers/mcp/transport.cjs.map +0 -1
- package/dist/cjs/providers/tools-server/ToolsServerCapabilityProvider.cjs +0 -128
- package/dist/cjs/providers/tools-server/ToolsServerCapabilityProvider.cjs.map +0 -1
- package/dist/cjs/providers/types.cjs +0 -51
- package/dist/cjs/providers/types.cjs.map +0 -1
- package/dist/cjs/tools/artifacts/schema.cjs +0 -86
- package/dist/cjs/tools/artifacts/schema.cjs.map +0 -1
- package/dist/cjs/tools/artifacts/tool.cjs +0 -219
- package/dist/cjs/tools/artifacts/tool.cjs.map +0 -1
- package/dist/cjs/tools/fileSearch/formatter.cjs +0 -93
- package/dist/cjs/tools/fileSearch/formatter.cjs.map +0 -1
- package/dist/cjs/tools/fileSearch/ragClient.cjs +0 -102
- package/dist/cjs/tools/fileSearch/ragClient.cjs.map +0 -1
- package/dist/cjs/tools/fileSearch/schema.cjs +0 -18
- package/dist/cjs/tools/fileSearch/schema.cjs.map +0 -1
- package/dist/cjs/tools/fileSearch/tool.cjs +0 -155
- package/dist/cjs/tools/fileSearch/tool.cjs.map +0 -1
- package/dist/cjs/tools/proxyTool.cjs +0 -102
- package/dist/cjs/tools/proxyTool.cjs.map +0 -1
- package/dist/cjs/utils/childAgentContext.cjs +0 -242
- package/dist/cjs/utils/childAgentContext.cjs.map +0 -1
- package/dist/cjs/utils/credentials.cjs +0 -142
- package/dist/cjs/utils/credentials.cjs.map +0 -1
- package/dist/cjs/utils/httpClient.cjs +0 -74
- package/dist/cjs/utils/httpClient.cjs.map +0 -1
- package/dist/cjs/utils/toolManifest.cjs +0 -100
- package/dist/cjs/utils/toolManifest.cjs.map +0 -1
- package/dist/esm/common/spawnPath.mjs +0 -95
- package/dist/esm/common/spawnPath.mjs.map +0 -1
- package/dist/esm/content/ArtifactStore.mjs +0 -576
- package/dist/esm/content/ArtifactStore.mjs.map +0 -1
- package/dist/esm/content/ContentStore.mjs +0 -635
- package/dist/esm/content/ContentStore.mjs.map +0 -1
- package/dist/esm/content/contentAnalyzer.mjs +0 -87
- package/dist/esm/content/contentAnalyzer.mjs.map +0 -1
- package/dist/esm/content/index.mjs +0 -5
- package/dist/esm/content/mcpAutoCache.mjs +0 -111
- package/dist/esm/content/mcpAutoCache.mjs.map +0 -1
- package/dist/esm/graphs/HandoffRegistry.mjs +0 -141
- package/dist/esm/graphs/HandoffRegistry.mjs.map +0 -1
- package/dist/esm/providers/a2a/A2ACapabilityProvider.mjs +0 -281
- package/dist/esm/providers/a2a/A2ACapabilityProvider.mjs.map +0 -1
- package/dist/esm/providers/a2a/client.mjs +0 -88
- package/dist/esm/providers/a2a/client.mjs.map +0 -1
- package/dist/esm/providers/a2a/config.mjs +0 -35
- package/dist/esm/providers/a2a/config.mjs.map +0 -1
- package/dist/esm/providers/capabilityNaming.mjs +0 -39
- package/dist/esm/providers/capabilityNaming.mjs.map +0 -1
- package/dist/esm/providers/mcp/MCPCapabilityProvider.mjs +0 -240
- package/dist/esm/providers/mcp/MCPCapabilityProvider.mjs.map +0 -1
- package/dist/esm/providers/mcp/config.mjs +0 -39
- package/dist/esm/providers/mcp/config.mjs.map +0 -1
- package/dist/esm/providers/mcp/transport.mjs +0 -63
- package/dist/esm/providers/mcp/transport.mjs.map +0 -1
- package/dist/esm/providers/tools-server/ToolsServerCapabilityProvider.mjs +0 -126
- package/dist/esm/providers/tools-server/ToolsServerCapabilityProvider.mjs.map +0 -1
- package/dist/esm/providers/types.mjs +0 -51
- package/dist/esm/providers/types.mjs.map +0 -1
- package/dist/esm/tools/artifacts/schema.mjs +0 -79
- package/dist/esm/tools/artifacts/schema.mjs.map +0 -1
- package/dist/esm/tools/artifacts/tool.mjs +0 -213
- package/dist/esm/tools/artifacts/tool.mjs.map +0 -1
- package/dist/esm/tools/fileSearch/formatter.mjs +0 -90
- package/dist/esm/tools/fileSearch/formatter.mjs.map +0 -1
- package/dist/esm/tools/fileSearch/ragClient.mjs +0 -98
- package/dist/esm/tools/fileSearch/ragClient.mjs.map +0 -1
- package/dist/esm/tools/fileSearch/schema.mjs +0 -15
- package/dist/esm/tools/fileSearch/schema.mjs.map +0 -1
- package/dist/esm/tools/fileSearch/tool.mjs +0 -152
- package/dist/esm/tools/fileSearch/tool.mjs.map +0 -1
- package/dist/esm/tools/proxyTool.mjs +0 -100
- package/dist/esm/tools/proxyTool.mjs.map +0 -1
- package/dist/esm/utils/childAgentContext.mjs +0 -237
- package/dist/esm/utils/childAgentContext.mjs.map +0 -1
- package/dist/esm/utils/credentials.mjs +0 -135
- package/dist/esm/utils/credentials.mjs.map +0 -1
- package/dist/esm/utils/httpClient.mjs +0 -70
- package/dist/esm/utils/httpClient.mjs.map +0 -1
- package/dist/esm/utils/toolManifest.mjs +0 -96
- package/dist/esm/utils/toolManifest.mjs.map +0 -1
- package/dist/types/common/spawnPath.d.ts +0 -59
- package/dist/types/content/ArtifactStore.d.ts +0 -223
- package/dist/types/content/ContentStore.d.ts +0 -140
- package/dist/types/content/contentAnalyzer.d.ts +0 -38
- package/dist/types/content/index.d.ts +0 -24
- package/dist/types/content/mcpAutoCache.d.ts +0 -89
- package/dist/types/content/types.d.ts +0 -75
- package/dist/types/graphs/HandoffRegistry.d.ts +0 -97
- package/dist/types/providers/a2a/A2ACapabilityProvider.d.ts +0 -89
- package/dist/types/providers/a2a/client.d.ts +0 -47
- package/dist/types/providers/a2a/config.d.ts +0 -18
- package/dist/types/providers/a2a/index.d.ts +0 -6
- package/dist/types/providers/a2a/types.d.ts +0 -173
- package/dist/types/providers/capabilityNaming.d.ts +0 -25
- package/dist/types/providers/index.d.ts +0 -12
- package/dist/types/providers/mcp/MCPCapabilityProvider.d.ts +0 -54
- package/dist/types/providers/mcp/config.d.ts +0 -20
- package/dist/types/providers/mcp/index.d.ts +0 -5
- package/dist/types/providers/mcp/transport.d.ts +0 -18
- package/dist/types/providers/mcp/types.d.ts +0 -112
- package/dist/types/providers/tools-server/ToolsServerCapabilityProvider.d.ts +0 -59
- package/dist/types/providers/tools-server/index.d.ts +0 -1
- package/dist/types/providers/types.d.ts +0 -184
- package/dist/types/tools/artifacts/index.d.ts +0 -3
- package/dist/types/tools/artifacts/schema.d.ts +0 -63
- package/dist/types/tools/artifacts/tool.d.ts +0 -16
- package/dist/types/tools/artifacts/types.d.ts +0 -127
- package/dist/types/tools/fileSearch/formatter.d.ts +0 -25
- package/dist/types/tools/fileSearch/index.d.ts +0 -5
- package/dist/types/tools/fileSearch/ragClient.d.ts +0 -32
- package/dist/types/tools/fileSearch/schema.d.ts +0 -13
- package/dist/types/tools/fileSearch/tool.d.ts +0 -18
- package/dist/types/tools/fileSearch/types.d.ts +0 -139
- package/dist/types/tools/proxyTool.d.ts +0 -62
- package/dist/types/tools/search/test.d.ts +0 -1
- package/dist/types/utils/childAgentContext.d.ts +0 -99
- package/dist/types/utils/credentials.d.ts +0 -77
- package/dist/types/utils/httpClient.d.ts +0 -46
- package/dist/types/utils/toolManifest.d.ts +0 -49
- package/src/common/__tests__/spawnPath.test.ts +0 -110
- package/src/common/spawnPath.ts +0 -101
- package/src/content/ArtifactStore.ts +0 -782
- package/src/content/ContentStore.ts +0 -753
- package/src/content/contentAnalyzer.ts +0 -105
- package/src/content/index.ts +0 -51
- package/src/content/mcpAutoCache.ts +0 -185
- package/src/content/types.ts +0 -82
- package/src/graphs/HandoffRegistry.ts +0 -199
- package/src/graphs/__tests__/HandoffRegistry.test.ts +0 -410
- package/src/graphs/__tests__/multi-agent-delegate.test.ts +0 -458
- package/src/graphs/__tests__/multi-agent-edges.test.ts +0 -276
- package/src/graphs/__tests__/multi-agent-nested-subgraph.test.ts +0 -221
- package/src/graphs/handoffValidation.test.ts +0 -353
- package/src/providers/__tests__/ToolsServerCapabilityProvider.integration.spec.ts +0 -79
- package/src/providers/__tests__/ToolsServerCapabilityProvider.test.ts +0 -271
- package/src/providers/__tests__/types.test.ts +0 -64
- package/src/providers/a2a/A2ACapabilityProvider.ts +0 -384
- package/src/providers/a2a/__tests__/A2ACapabilityProvider.integration.spec.ts +0 -345
- package/src/providers/a2a/__tests__/A2ACapabilityProvider.test.ts +0 -460
- package/src/providers/a2a/client.ts +0 -115
- package/src/providers/a2a/config.ts +0 -40
- package/src/providers/a2a/index.ts +0 -29
- package/src/providers/a2a/types.ts +0 -191
- package/src/providers/capabilityNaming.ts +0 -42
- package/src/providers/index.ts +0 -68
- package/src/providers/mcp/MCPCapabilityProvider.ts +0 -345
- package/src/providers/mcp/__tests__/MCPCapabilityProvider.integration.spec.ts +0 -386
- package/src/providers/mcp/__tests__/MCPCapabilityProvider.test.ts +0 -371
- package/src/providers/mcp/config.ts +0 -45
- package/src/providers/mcp/index.ts +0 -21
- package/src/providers/mcp/transport.ts +0 -76
- package/src/providers/mcp/types.ts +0 -139
- package/src/providers/tools-server/ToolsServerCapabilityProvider.ts +0 -249
- package/src/providers/tools-server/index.ts +0 -1
- package/src/providers/types.ts +0 -204
- package/src/scripts/test-bedrock-handoff-autonomous.ts +0 -267
- package/src/scripts/test-handoff-preamble.ts +0 -278
- package/src/specs/agent-handoffs-bedrock.integration.test.ts +0 -415
- package/src/tools/artifacts/__tests__/tool.test.ts +0 -259
- package/src/tools/artifacts/index.ts +0 -33
- package/src/tools/artifacts/schema.ts +0 -99
- package/src/tools/artifacts/tool.ts +0 -289
- package/src/tools/artifacts/types.ts +0 -162
- package/src/tools/fileSearch/__tests__/tool.test.ts +0 -261
- package/src/tools/fileSearch/formatter.ts +0 -129
- package/src/tools/fileSearch/index.ts +0 -23
- package/src/tools/fileSearch/ragClient.ts +0 -137
- package/src/tools/fileSearch/schema.ts +0 -19
- package/src/tools/fileSearch/tool.ts +0 -207
- package/src/tools/fileSearch/types.ts +0 -149
- package/src/tools/proxyTool.ts +0 -166
- package/src/tools/search/output.md +0 -2775
- package/src/tools/search/test.html +0 -884
- package/src/tools/search/test.md +0 -643
- package/src/tools/search/test.ts +0 -159
- package/src/utils/__tests__/childAgentContext.test.ts +0 -217
- package/src/utils/__tests__/credentials.test.ts +0 -130
- package/src/utils/__tests__/httpClient.test.ts +0 -75
- package/src/utils/__tests__/toolManifest.test.ts +0 -116
- package/src/utils/childAgentContext.ts +0 -259
- package/src/utils/credentials.ts +0 -157
- package/src/utils/httpClient.ts +0 -92
- package/src/utils/toolManifest.ts +0 -109
- /package/dist/esm/{content → langchain}/index.mjs.map +0 -0
package/src/memory/types.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Autonomous memory — core types.
|
|
3
3
|
*
|
|
4
|
-
* Ported from
|
|
4
|
+
* Ported from the reference implementation's memory-core pattern, adapted for Postgres + pgvector
|
|
5
5
|
* and shaped so a future graph-backend layer (Graphiti, Neo4j agent-memory, etc.)
|
|
6
6
|
* can be added alongside the vector store without changing the tool contracts.
|
|
7
7
|
*
|
|
@@ -79,7 +79,7 @@ export interface MemorySearchOptions {
|
|
|
79
79
|
minScore?: number;
|
|
80
80
|
/**
|
|
81
81
|
* Phase 2 toggles — when the backend supports them. Each is independently
|
|
82
|
-
* opt-in; all false =
|
|
82
|
+
* opt-in; all false = Phase 1 behavior.
|
|
83
83
|
*/
|
|
84
84
|
mmr?: { enabled?: boolean; lambda?: number };
|
|
85
85
|
temporalDecay?: { enabled?: boolean; halfLifeDays?: number };
|
|
@@ -156,7 +156,7 @@ export interface MemoryConfig {
|
|
|
156
156
|
search?: {
|
|
157
157
|
maxResults?: number;
|
|
158
158
|
maxInjectedChars?: number;
|
|
159
|
-
/** Phase 2 — enable MMR reranking (
|
|
159
|
+
/** Phase 2 — enable MMR reranking (defaults when true). */
|
|
160
160
|
mmr?: { enabled?: boolean; lambda?: number };
|
|
161
161
|
/** Phase 2 — enable temporal decay on dated memory files. */
|
|
162
162
|
temporalDecay?: { enabled?: boolean; halfLifeDays?: number };
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AIMessage,
|
|
3
|
+
BaseMessage,
|
|
4
|
+
HumanMessage,
|
|
5
|
+
SystemMessage,
|
|
6
|
+
ToolMessage,
|
|
7
|
+
} from '@langchain/core/messages';
|
|
8
|
+
import type { TokenCounter } from '@/types/run';
|
|
9
|
+
import { applyContextPruning } from '../contextPruning';
|
|
10
|
+
|
|
11
|
+
const counter: TokenCounter = (msg: BaseMessage) => {
|
|
12
|
+
if (typeof msg.content === 'string') return Math.max(1, msg.content.length);
|
|
13
|
+
return 1;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe('applyContextPruning', () => {
|
|
17
|
+
it('returns zero counts when disabled', () => {
|
|
18
|
+
const messages: BaseMessage[] = [
|
|
19
|
+
new HumanMessage('hi'),
|
|
20
|
+
new AIMessage('thinking'),
|
|
21
|
+
new ToolMessage({
|
|
22
|
+
content: 'a'.repeat(10000),
|
|
23
|
+
tool_call_id: 't1',
|
|
24
|
+
}),
|
|
25
|
+
];
|
|
26
|
+
const map = { 0: 1, 1: 1, 2: 10000 };
|
|
27
|
+
const out = applyContextPruning({
|
|
28
|
+
messages,
|
|
29
|
+
indexTokenCountMap: map,
|
|
30
|
+
tokenCounter: counter,
|
|
31
|
+
config: { enabled: false },
|
|
32
|
+
});
|
|
33
|
+
expect(out.softTrimmed).toBe(0);
|
|
34
|
+
expect(out.hardCleared).toBe(0);
|
|
35
|
+
// Message untouched
|
|
36
|
+
expect((messages[2] as ToolMessage).content).toHaveLength(10000);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('soft-trims an older tool result with content over the threshold', () => {
|
|
40
|
+
// Build a sequence with an old tool result outside the protected zone.
|
|
41
|
+
const messages: BaseMessage[] = [
|
|
42
|
+
new SystemMessage('sys'),
|
|
43
|
+
new HumanMessage('q1'),
|
|
44
|
+
new AIMessage({
|
|
45
|
+
content: 'thinking',
|
|
46
|
+
tool_calls: [{ name: 't', args: {}, id: 'old' }],
|
|
47
|
+
}),
|
|
48
|
+
new ToolMessage({
|
|
49
|
+
// Long string — should soft-trim.
|
|
50
|
+
content: 'OLD_TOOL_RESULT' + 'a'.repeat(20000),
|
|
51
|
+
tool_call_id: 'old',
|
|
52
|
+
}),
|
|
53
|
+
new HumanMessage('q2'),
|
|
54
|
+
new AIMessage('answer 1'),
|
|
55
|
+
new HumanMessage('q3'),
|
|
56
|
+
new AIMessage('answer 2'),
|
|
57
|
+
new HumanMessage('q4'),
|
|
58
|
+
new AIMessage('answer 3'),
|
|
59
|
+
new HumanMessage('q5'),
|
|
60
|
+
new AIMessage('answer 4'),
|
|
61
|
+
];
|
|
62
|
+
const map: Record<string, number> = {};
|
|
63
|
+
for (let i = 0; i < messages.length; i++) {
|
|
64
|
+
map[i] = counter(messages[i]);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const result = applyContextPruning({
|
|
68
|
+
messages,
|
|
69
|
+
indexTokenCountMap: map,
|
|
70
|
+
tokenCounter: counter,
|
|
71
|
+
config: {
|
|
72
|
+
enabled: true,
|
|
73
|
+
keepLastAssistants: 2,
|
|
74
|
+
softTrimRatio: 0.3,
|
|
75
|
+
hardClearRatio: 0.95,
|
|
76
|
+
minPrunableToolChars: 100,
|
|
77
|
+
softTrim: { maxChars: 200, headChars: 50, tailChars: 50 },
|
|
78
|
+
hardClear: { enabled: true, placeholder: '[evicted]' },
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// The old tool result at index 3 should be soft-trimmed.
|
|
83
|
+
expect(result.softTrimmed).toBeGreaterThan(0);
|
|
84
|
+
const oldToolMsg = messages[3] as ToolMessage;
|
|
85
|
+
expect((oldToolMsg.content as string).length).toBeLessThan(20000);
|
|
86
|
+
expect(oldToolMsg.content).toContain('soft-trimmed');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('hard-clears very old tool results when above hardClearRatio', () => {
|
|
90
|
+
// Position-age = (totalMessages - i) / totalMessages; with totalMessages=12
|
|
91
|
+
// and i=0, ratio=1.0 (oldest). But system at i=0 is in the protected zone.
|
|
92
|
+
// i=2 (the AI/tool pair) gives ratio=10/12 ≈ 0.83.
|
|
93
|
+
const messages: BaseMessage[] = [
|
|
94
|
+
new SystemMessage('sys'),
|
|
95
|
+
new HumanMessage('q1'),
|
|
96
|
+
new AIMessage({
|
|
97
|
+
content: 'thinking',
|
|
98
|
+
tool_calls: [{ name: 't', args: {}, id: 'oldest' }],
|
|
99
|
+
}),
|
|
100
|
+
new ToolMessage({
|
|
101
|
+
content: 'OLDEST' + 'x'.repeat(5000),
|
|
102
|
+
tool_call_id: 'oldest',
|
|
103
|
+
}),
|
|
104
|
+
];
|
|
105
|
+
for (let i = 0; i < 8; i++) {
|
|
106
|
+
messages.push(new HumanMessage(`recent ${i}`));
|
|
107
|
+
messages.push(new AIMessage(`reply ${i}`));
|
|
108
|
+
}
|
|
109
|
+
const map: Record<string, number> = {};
|
|
110
|
+
for (let i = 0; i < messages.length; i++) {
|
|
111
|
+
map[i] = counter(messages[i]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const result = applyContextPruning({
|
|
115
|
+
messages,
|
|
116
|
+
indexTokenCountMap: map,
|
|
117
|
+
tokenCounter: counter,
|
|
118
|
+
config: {
|
|
119
|
+
enabled: true,
|
|
120
|
+
keepLastAssistants: 2,
|
|
121
|
+
softTrimRatio: 0.3,
|
|
122
|
+
hardClearRatio: 0.7,
|
|
123
|
+
minPrunableToolChars: 100,
|
|
124
|
+
softTrim: { maxChars: 200, headChars: 50, tailChars: 50 },
|
|
125
|
+
hardClear: { enabled: true, placeholder: '[evicted]' },
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
expect(result.hardCleared).toBeGreaterThan(0);
|
|
130
|
+
const oldToolMsg = messages[3] as ToolMessage;
|
|
131
|
+
expect(oldToolMsg.content).toBe('[evicted]');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('does not touch tool results inside the protected zone (last N assistant turns)', () => {
|
|
135
|
+
const messages: BaseMessage[] = [
|
|
136
|
+
new SystemMessage('sys'),
|
|
137
|
+
new HumanMessage('q1'),
|
|
138
|
+
new AIMessage({
|
|
139
|
+
content: 'thinking',
|
|
140
|
+
tool_calls: [{ name: 't', args: {}, id: 'recent' }],
|
|
141
|
+
}),
|
|
142
|
+
new ToolMessage({
|
|
143
|
+
content: 'RECENT' + 'y'.repeat(20000),
|
|
144
|
+
tool_call_id: 'recent',
|
|
145
|
+
}),
|
|
146
|
+
];
|
|
147
|
+
const map: Record<string, number> = {};
|
|
148
|
+
for (let i = 0; i < messages.length; i++) {
|
|
149
|
+
map[i] = counter(messages[i]);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const result = applyContextPruning({
|
|
153
|
+
messages,
|
|
154
|
+
indexTokenCountMap: map,
|
|
155
|
+
tokenCounter: counter,
|
|
156
|
+
config: {
|
|
157
|
+
enabled: true,
|
|
158
|
+
keepLastAssistants: 4,
|
|
159
|
+
softTrimRatio: 0.0,
|
|
160
|
+
hardClearRatio: 0.0,
|
|
161
|
+
minPrunableToolChars: 100,
|
|
162
|
+
softTrim: { maxChars: 200, headChars: 50, tailChars: 50 },
|
|
163
|
+
hardClear: { enabled: true, placeholder: '[evicted]' },
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
expect(result.softTrimmed).toBe(0);
|
|
168
|
+
expect(result.hardCleared).toBe(0);
|
|
169
|
+
expect((messages[3] as ToolMessage).content).toContain('y'.repeat(100));
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('skips messages with image content even when out of protected zone', () => {
|
|
173
|
+
const imageBlock = {
|
|
174
|
+
type: 'image_url',
|
|
175
|
+
image_url: { url: 'data:image/png;base64,iVBORw0K...' },
|
|
176
|
+
};
|
|
177
|
+
const messages: BaseMessage[] = [
|
|
178
|
+
new SystemMessage('sys'),
|
|
179
|
+
new HumanMessage('q'),
|
|
180
|
+
new AIMessage({
|
|
181
|
+
content: 'thinking',
|
|
182
|
+
tool_calls: [{ name: 't', args: {}, id: 'img' }],
|
|
183
|
+
}),
|
|
184
|
+
new ToolMessage({
|
|
185
|
+
content: [imageBlock] as never, // structured content not pruned
|
|
186
|
+
tool_call_id: 'img',
|
|
187
|
+
}),
|
|
188
|
+
];
|
|
189
|
+
for (let i = 0; i < 8; i++) {
|
|
190
|
+
messages.push(new HumanMessage(`recent ${i}`));
|
|
191
|
+
messages.push(new AIMessage(`reply ${i}`));
|
|
192
|
+
}
|
|
193
|
+
const map: Record<string, number> = {};
|
|
194
|
+
for (let i = 0; i < messages.length; i++) {
|
|
195
|
+
map[i] = 1;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const result = applyContextPruning({
|
|
199
|
+
messages,
|
|
200
|
+
indexTokenCountMap: map,
|
|
201
|
+
tokenCounter: counter,
|
|
202
|
+
config: {
|
|
203
|
+
enabled: true,
|
|
204
|
+
keepLastAssistants: 2,
|
|
205
|
+
softTrimRatio: 0.0,
|
|
206
|
+
hardClearRatio: 0.0,
|
|
207
|
+
minPrunableToolChars: 0,
|
|
208
|
+
softTrim: { maxChars: 200, headChars: 50, tailChars: 50 },
|
|
209
|
+
hardClear: { enabled: true, placeholder: '[evicted]' },
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Image-containing tool message must not have been touched.
|
|
214
|
+
expect(result.softTrimmed).toBe(0);
|
|
215
|
+
expect(Array.isArray((messages[3] as ToolMessage).content)).toBe(true);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('returns zero counts on empty message array', () => {
|
|
219
|
+
const out = applyContextPruning({
|
|
220
|
+
messages: [],
|
|
221
|
+
indexTokenCountMap: {},
|
|
222
|
+
tokenCounter: counter,
|
|
223
|
+
config: { enabled: true },
|
|
224
|
+
});
|
|
225
|
+
expect(out.softTrimmed).toBe(0);
|
|
226
|
+
expect(out.hardCleared).toBe(0);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
@@ -412,7 +412,14 @@ describe('addBedrockCacheControl (Bedrock cache checkpoints)', () => {
|
|
|
412
412
|
expect(first[1]).toEqual({ cachePoint: { type: 'default' } });
|
|
413
413
|
});
|
|
414
414
|
|
|
415
|
-
it('
|
|
415
|
+
it('skips system messages (cachePoint added inline by AgentContext.buildSystemRunnable)', () => {
|
|
416
|
+
/* Contract change (PR #128 alignment): system message
|
|
417
|
+
* cachePoint is now emitted inline in AgentContext.buildSystemRunnable.
|
|
418
|
+
* addBedrockCacheControl must therefore SKIP system messages so the
|
|
419
|
+
* 2-cachePoint per-request budget stays available for the conversation
|
|
420
|
+
* tail. Caching the system prefix is what unlocks cross-user cost
|
|
421
|
+
* savings — Bedrock's prompt cache is account-scoped, so a stable
|
|
422
|
+
* system prefix shared across users hits the same cache entry. */
|
|
416
423
|
const messages: TestMsg[] = [
|
|
417
424
|
{
|
|
418
425
|
role: 'system',
|
|
@@ -430,15 +437,17 @@ describe('addBedrockCacheControl (Bedrock cache checkpoints)', () => {
|
|
|
430
437
|
|
|
431
438
|
const result = addBedrockCacheControl(messages);
|
|
432
439
|
|
|
433
|
-
|
|
434
|
-
|
|
440
|
+
const system = result[0].content as MessageContentComplex[];
|
|
441
|
+
const user = result[1].content as MessageContentComplex[];
|
|
435
442
|
|
|
436
|
-
//
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
443
|
+
// System message is left untouched — addBedrockCacheControl does NOT
|
|
444
|
+
// add a cachePoint here. The cachePoint is added in AgentContext when
|
|
445
|
+
// the system message is first built.
|
|
446
|
+
expect(system).toEqual([
|
|
447
|
+
{ type: ContentTypes.TEXT, text: 'You\'re an advanced AI assistant.' },
|
|
448
|
+
]);
|
|
449
|
+
|
|
450
|
+
// User message still gets a cachePoint (last eligible).
|
|
442
451
|
expect(user[0]).toEqual({
|
|
443
452
|
type: ContentTypes.TEXT,
|
|
444
453
|
text: 'What is the capital of France?',
|
|
@@ -458,30 +467,59 @@ describe('addBedrockCacheControl (Bedrock cache checkpoints)', () => {
|
|
|
458
467
|
|
|
459
468
|
const result2 = addBedrockCacheControl(result);
|
|
460
469
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
const
|
|
470
|
+
const system2 = result2[0].content as MessageContentComplex[];
|
|
471
|
+
const user2 = result2[1].content as MessageContentComplex[];
|
|
472
|
+
const assistant2 = result2[2].content as MessageContentComplex[];
|
|
464
473
|
|
|
465
|
-
// System message
|
|
466
|
-
expect(
|
|
467
|
-
type: ContentTypes.TEXT,
|
|
468
|
-
|
|
469
|
-
});
|
|
470
|
-
expect(system.length).toBe(1);
|
|
474
|
+
// System message still untouched.
|
|
475
|
+
expect(system2).toEqual([
|
|
476
|
+
{ type: ContentTypes.TEXT, text: 'You\'re an advanced AI assistant.' },
|
|
477
|
+
]);
|
|
471
478
|
|
|
472
|
-
//
|
|
473
|
-
expect(
|
|
479
|
+
// Both conversation messages now get cachePoints (last 2 eligible).
|
|
480
|
+
expect(user2[0]).toEqual({
|
|
474
481
|
type: ContentTypes.TEXT,
|
|
475
482
|
text: 'What is the capital of France?',
|
|
476
483
|
});
|
|
477
|
-
expect(
|
|
484
|
+
expect(user2[1]).toEqual({ cachePoint: { type: 'default' } });
|
|
478
485
|
|
|
479
|
-
|
|
480
|
-
expect(assistant[0]).toEqual({
|
|
486
|
+
expect(assistant2[0]).toEqual({
|
|
481
487
|
type: ContentTypes.TEXT,
|
|
482
488
|
text: 'Sure! The capital of France is Paris.',
|
|
483
489
|
});
|
|
484
|
-
expect(
|
|
490
|
+
expect(assistant2[1]).toEqual({ cachePoint: { type: 'default' } });
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
it('strips stray Anthropic cache_control from system message (cross-provider safety)', () => {
|
|
494
|
+
/* If a system message arrives with an Anthropic-style cache_control
|
|
495
|
+
* marker (e.g. cross-provider switch), addBedrockCacheControl should
|
|
496
|
+
* sanitize it — Bedrock ignores cache_control and stale markers can
|
|
497
|
+
* confuse provider validation. */
|
|
498
|
+
const messages: TestMsg[] = [
|
|
499
|
+
{
|
|
500
|
+
role: 'system',
|
|
501
|
+
content: [
|
|
502
|
+
{
|
|
503
|
+
type: ContentTypes.TEXT,
|
|
504
|
+
text: 'You\'re an advanced AI assistant.',
|
|
505
|
+
cache_control: { type: 'ephemeral' },
|
|
506
|
+
} as MessageContentComplex,
|
|
507
|
+
],
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
role: 'user',
|
|
511
|
+
content: [{ type: ContentTypes.TEXT, text: 'Hi' }],
|
|
512
|
+
},
|
|
513
|
+
];
|
|
514
|
+
|
|
515
|
+
const result = addBedrockCacheControl(messages);
|
|
516
|
+
const system = result[0].content as MessageContentComplex[];
|
|
517
|
+
|
|
518
|
+
expect(system).toHaveLength(1);
|
|
519
|
+
expect('cache_control' in system[0]).toBe(false);
|
|
520
|
+
expect((system[0] as { text?: string }).text).toBe(
|
|
521
|
+
'You\'re an advanced AI assistant.'
|
|
522
|
+
);
|
|
485
523
|
});
|
|
486
524
|
|
|
487
525
|
it('is idempotent - calling multiple times does not add duplicate cache points', () => {
|
package/src/messages/cache.ts
CHANGED
|
@@ -14,6 +14,61 @@ type MessageWithContent = {
|
|
|
14
14
|
content?: string | MessageContentComplex[];
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
type MessageContentWithCacheControl = MessageContentComplex & {
|
|
18
|
+
cache_control?: unknown;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Strips Anthropic-style `cache_control` markers from every block in the
|
|
23
|
+
* given content array. Returns the (possibly cloned) content and a flag
|
|
24
|
+
* indicating whether anything was actually modified — so callers can avoid
|
|
25
|
+
* unnecessary message clones.
|
|
26
|
+
*
|
|
27
|
+
* Used to sanitize a system message's content array before adding Bedrock
|
|
28
|
+
* cache points, so stray Anthropic markers (e.g. left over from a previous
|
|
29
|
+
* Anthropic-provider turn) don't prevent the Bedrock provider from caching
|
|
30
|
+
* the system prefix.
|
|
31
|
+
*/
|
|
32
|
+
function stripAnthropicCacheControlFromBlocks(
|
|
33
|
+
content: MessageContentComplex[]
|
|
34
|
+
): { content: MessageContentComplex[]; modified: boolean } {
|
|
35
|
+
let modified = false;
|
|
36
|
+
const strippedContent = content.map((block) => {
|
|
37
|
+
if (!('cache_control' in block)) {
|
|
38
|
+
return block;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const cloned: MessageContentWithCacheControl = { ...block };
|
|
42
|
+
delete cloned.cache_control;
|
|
43
|
+
modified = true;
|
|
44
|
+
return cloned;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return { content: strippedContent, modified };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* For the Bedrock cache pass, system messages must NOT carry Anthropic
|
|
52
|
+
* cache_control markers (those are an Anthropic-specific encoding and
|
|
53
|
+
* Bedrock uses cachePoint blocks instead). Strip them before the cache
|
|
54
|
+
* point insertion logic walks the message.
|
|
55
|
+
*/
|
|
56
|
+
function sanitizeBedrockSystemMessage<T extends MessageWithContent>(
|
|
57
|
+
message: T
|
|
58
|
+
): T {
|
|
59
|
+
const content = message.content;
|
|
60
|
+
if (!Array.isArray(content)) {
|
|
61
|
+
return message;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const stripped = stripAnthropicCacheControlFromBlocks(content);
|
|
65
|
+
if (!stripped.modified) {
|
|
66
|
+
return message;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return cloneMessage(message, stripped.content);
|
|
70
|
+
}
|
|
71
|
+
|
|
17
72
|
/** Debug logger for cache operations - set ILLUMA_DEBUG_CACHE=true to enable */
|
|
18
73
|
const debugCache = (message: string, data?: unknown): void => {
|
|
19
74
|
if (process.env.ILLUMA_DEBUG_CACHE === 'true') {
|
|
@@ -361,8 +416,36 @@ export function addBedrockCacheControl<
|
|
|
361
416
|
|
|
362
417
|
// Clone messages to avoid mutating originals
|
|
363
418
|
const updatedMessages: T[] = messages.map((msg) => {
|
|
419
|
+
/* PRESERVE cachePoint on system messages — they're added inline by
|
|
420
|
+
* AgentContext.buildSystemRunnable to mark the cacheable system prefix
|
|
421
|
+
* for account-level caching. Only strip stray Anthropic cache_control
|
|
422
|
+
* (which Bedrock ignores). For non-system messages keep the existing
|
|
423
|
+
* behaviour: full strip + repopulate based on last-2 strategy. */
|
|
424
|
+
const msgType =
|
|
425
|
+
'getType' in msg && typeof msg.getType === 'function'
|
|
426
|
+
? msg.getType()
|
|
427
|
+
: undefined;
|
|
428
|
+
const msgRole = (msg as Record<string, unknown>).role as string | undefined;
|
|
429
|
+
const isSystem = msgType === 'system' || msgRole === 'system';
|
|
430
|
+
|
|
364
431
|
const content = msg.content;
|
|
365
432
|
if (Array.isArray(content)) {
|
|
433
|
+
if (isSystem) {
|
|
434
|
+
/* System: keep cachePoint, only strip Anthropic cache_control. */
|
|
435
|
+
if (hasAnthropicCacheControl(content)) {
|
|
436
|
+
const stripped = content.map((block) => {
|
|
437
|
+
const rec = block as Record<string, unknown>;
|
|
438
|
+
if ('cache_control' in rec) {
|
|
439
|
+
const { cache_control: _, ...rest } = rec;
|
|
440
|
+
return rest as MessageContentComplex;
|
|
441
|
+
}
|
|
442
|
+
return block;
|
|
443
|
+
});
|
|
444
|
+
return cloneMessage(msg, stripped) as T;
|
|
445
|
+
}
|
|
446
|
+
return cloneMessage(msg, content) as T;
|
|
447
|
+
}
|
|
448
|
+
|
|
366
449
|
// Strip existing cachePoint blocks and Anthropic-style cache_control
|
|
367
450
|
const stripped = content
|
|
368
451
|
.filter((block) => !isCachePoint(block))
|
|
@@ -456,6 +539,35 @@ export function addBedrockCacheControl<
|
|
|
456
539
|
const message = updatedMessages[i];
|
|
457
540
|
const msgContent = message.content;
|
|
458
541
|
|
|
542
|
+
/* System messages are handled by AgentContext.buildSystemRunnable —
|
|
543
|
+
* the cachePoint is emitted INLINE in the system message content array
|
|
544
|
+
* so the cacheable system prefix gets a marker every turn (not just
|
|
545
|
+
* when the system message happens to be in the last 2 eligible). The
|
|
546
|
+
* Bedrock converter (src/llm/bedrock/utils/message_inputs.ts:261-294)
|
|
547
|
+
* passes through cachePoint blocks in system content arrays.
|
|
548
|
+
*
|
|
549
|
+
* If we ALSO marked system here, we'd: (a) waste one of the two
|
|
550
|
+
* cachePoint budget slots that Bedrock honours per-request, starving
|
|
551
|
+
* the conversation tail, and (b) potentially double-mark a stable
|
|
552
|
+
* prefix that already has its own cachePoint.
|
|
553
|
+
*
|
|
554
|
+
* As a defensive cleanup, strip stray Anthropic-style cache_control
|
|
555
|
+
* markers from the system message — Bedrock ignores them and they
|
|
556
|
+
* can confuse provider validation. */
|
|
557
|
+
const _msgType =
|
|
558
|
+
'getType' in message && typeof message.getType === 'function'
|
|
559
|
+
? message.getType()
|
|
560
|
+
: undefined;
|
|
561
|
+
const _msgRole = (message as Record<string, unknown>).role as
|
|
562
|
+
| string
|
|
563
|
+
| undefined;
|
|
564
|
+
if (_msgType === 'system' || _msgRole === 'system') {
|
|
565
|
+
updatedMessages[i] = sanitizeBedrockSystemMessage(
|
|
566
|
+
message as MessageWithContent
|
|
567
|
+
) as T;
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
570
|
+
|
|
459
571
|
// Skip empty/whitespace-only content
|
|
460
572
|
if (msgContent == null) continue;
|
|
461
573
|
if (typeof msgContent === 'string' && msgContent.trim() === '') continue;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Position-based context pruning for tool results.
|
|
3
|
+
*
|
|
4
|
+
* Uses position-based age: the distance of a message
|
|
5
|
+
* from the conversation end as a fraction of total messages.
|
|
6
|
+
*
|
|
7
|
+
* Two degradation levels:
|
|
8
|
+
* - Soft-trim: Keep head + tail of tool result content, drop middle.
|
|
9
|
+
* - Hard-clear: Replace entire content with a placeholder.
|
|
10
|
+
*
|
|
11
|
+
* Messages in the "protected zone" (recent assistant turns, system/pre-first-human
|
|
12
|
+
* messages, and messages with image content) are never pruned.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { ToolMessage, type BaseMessage } from '@langchain/core/messages';
|
|
16
|
+
import type { ContextPruningConfig } from '@/types/graph';
|
|
17
|
+
import type { TokenCounter } from '@/types/run';
|
|
18
|
+
import type { ContextPruningSettings } from './contextPruningSettings';
|
|
19
|
+
import { resolveContextPruningSettings } from './contextPruningSettings';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Checks if a message contains image content blocks.
|
|
23
|
+
* Messages with images are skipped by position-based content degradation
|
|
24
|
+
* because images cannot be meaningfully soft-trimmed or replaced with placeholders.
|
|
25
|
+
*/
|
|
26
|
+
function hasImageContent(message: BaseMessage): boolean {
|
|
27
|
+
if (!Array.isArray(message.content)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return message.content.some(
|
|
31
|
+
(block) =>
|
|
32
|
+
typeof block === 'object' &&
|
|
33
|
+
'type' in block &&
|
|
34
|
+
(block.type === 'image_url' || block.type === 'image')
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Applies head+tail soft-trim to tool result content.
|
|
40
|
+
*/
|
|
41
|
+
function softTrimContent(
|
|
42
|
+
content: string,
|
|
43
|
+
settings: ContextPruningSettings['softTrim']
|
|
44
|
+
): string {
|
|
45
|
+
const { headChars, tailChars } = settings;
|
|
46
|
+
const indicator = `\n\n… [soft-trimmed: ${content.length} chars → ${headChars + tailChars} chars, middle removed] …\n\n`;
|
|
47
|
+
return content.slice(0, headChars) + indicator + content.slice(-tailChars);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ContextPruningResult {
|
|
51
|
+
/** Number of messages that were soft-trimmed. */
|
|
52
|
+
softTrimmed: number;
|
|
53
|
+
/** Number of messages that were hard-cleared. */
|
|
54
|
+
hardCleared: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Applies position-based context pruning to tool result messages.
|
|
59
|
+
*
|
|
60
|
+
* Modifies messages in-place and updates indexTokenCountMap with recounted
|
|
61
|
+
* token values for modified messages.
|
|
62
|
+
*
|
|
63
|
+
* @param params.messages - The full message array (modified in-place).
|
|
64
|
+
* @param params.indexTokenCountMap - Token count map (updated in-place).
|
|
65
|
+
* @param params.tokenCounter - Function to recount tokens after modification.
|
|
66
|
+
* @param params.config - Partial context pruning config (merged with defaults).
|
|
67
|
+
* @returns Counts of soft-trimmed and hard-cleared messages.
|
|
68
|
+
*/
|
|
69
|
+
export function applyContextPruning(params: {
|
|
70
|
+
messages: BaseMessage[];
|
|
71
|
+
indexTokenCountMap: Record<string, number | undefined>;
|
|
72
|
+
tokenCounter: TokenCounter;
|
|
73
|
+
config?: ContextPruningConfig;
|
|
74
|
+
resolvedSettings?: ContextPruningSettings;
|
|
75
|
+
}): ContextPruningResult {
|
|
76
|
+
const {
|
|
77
|
+
messages,
|
|
78
|
+
indexTokenCountMap,
|
|
79
|
+
tokenCounter,
|
|
80
|
+
config,
|
|
81
|
+
resolvedSettings,
|
|
82
|
+
} = params;
|
|
83
|
+
const settings = resolvedSettings ?? resolveContextPruningSettings(config);
|
|
84
|
+
|
|
85
|
+
if (!settings.enabled || messages.length === 0) {
|
|
86
|
+
return { softTrimmed: 0, hardCleared: 0 };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const totalMessages = messages.length;
|
|
90
|
+
let softTrimmed = 0;
|
|
91
|
+
let hardCleared = 0;
|
|
92
|
+
|
|
93
|
+
// Find the protected zone: last N assistant turns from the end.
|
|
94
|
+
// An "assistant turn" is a contiguous sequence of AI + Tool messages.
|
|
95
|
+
const protectedIndices = new Set<number>();
|
|
96
|
+
|
|
97
|
+
// Always protect the system message (index 0 if present)
|
|
98
|
+
if (messages[0]?.getType() === 'system') {
|
|
99
|
+
protectedIndices.add(0);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Protect messages before the first human message
|
|
103
|
+
for (let i = 0; i < totalMessages; i++) {
|
|
104
|
+
if (messages[i].getType() === 'human') {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
protectedIndices.add(i);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Protect the last N assistant turns (walking backwards)
|
|
111
|
+
let assistantTurnsFound = 0;
|
|
112
|
+
let inAssistantSequence = false;
|
|
113
|
+
for (let i = totalMessages - 1; i >= 0; i--) {
|
|
114
|
+
const type = messages[i].getType();
|
|
115
|
+
if (type === 'ai' || type === 'tool') {
|
|
116
|
+
protectedIndices.add(i);
|
|
117
|
+
if (!inAssistantSequence) {
|
|
118
|
+
inAssistantSequence = true;
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
if (inAssistantSequence) {
|
|
122
|
+
assistantTurnsFound++;
|
|
123
|
+
inAssistantSequence = false;
|
|
124
|
+
if (assistantTurnsFound >= settings.keepLastAssistants) {
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Protect the human message between assistant turns in the protected zone
|
|
129
|
+
if (assistantTurnsFound < settings.keepLastAssistants) {
|
|
130
|
+
protectedIndices.add(i);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Process each tool message outside the protected zone
|
|
136
|
+
for (let i = 0; i < totalMessages; i++) {
|
|
137
|
+
const message = messages[i];
|
|
138
|
+
if (message.getType() !== 'tool') {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (protectedIndices.has(i)) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (hasImageContent(message)) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const content = message.content;
|
|
149
|
+
if (typeof content !== 'string') {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (content.length < settings.minPrunableToolChars) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Compute age ratio: how far back from the end (0 = latest, 1 = oldest)
|
|
157
|
+
const ageRatio = (totalMessages - i) / totalMessages;
|
|
158
|
+
|
|
159
|
+
if (ageRatio >= settings.hardClearRatio && settings.hardClear.enabled) {
|
|
160
|
+
// Hard-clear: replace with placeholder
|
|
161
|
+
const cloned = new ToolMessage({
|
|
162
|
+
content: settings.hardClear.placeholder,
|
|
163
|
+
tool_call_id: (message as ToolMessage).tool_call_id,
|
|
164
|
+
name: message.name,
|
|
165
|
+
id: message.id,
|
|
166
|
+
additional_kwargs: message.additional_kwargs,
|
|
167
|
+
response_metadata: message.response_metadata,
|
|
168
|
+
});
|
|
169
|
+
messages[i] = cloned;
|
|
170
|
+
indexTokenCountMap[i] = tokenCounter(cloned);
|
|
171
|
+
hardCleared++;
|
|
172
|
+
} else if (ageRatio >= settings.softTrimRatio) {
|
|
173
|
+
// Soft-trim: keep head + tail
|
|
174
|
+
if (content.length > settings.softTrim.maxChars) {
|
|
175
|
+
const cloned = new ToolMessage({
|
|
176
|
+
content: softTrimContent(content, settings.softTrim),
|
|
177
|
+
tool_call_id: (message as ToolMessage).tool_call_id,
|
|
178
|
+
name: message.name,
|
|
179
|
+
id: message.id,
|
|
180
|
+
additional_kwargs: message.additional_kwargs,
|
|
181
|
+
response_metadata: message.response_metadata,
|
|
182
|
+
});
|
|
183
|
+
messages[i] = cloned;
|
|
184
|
+
indexTokenCountMap[i] = tokenCounter(cloned);
|
|
185
|
+
softTrimmed++;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return { softTrimmed, hardCleared };
|
|
191
|
+
}
|