@illuma-ai/agents 1.5.0 → 2.1.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 +0 -62
- package/dist/cjs/agents/AgentContext.cjs +159 -258
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +25 -8
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +1 -5
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +33 -61
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +10 -27
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +3 -84
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +0 -89
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +10 -68
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/tools/BashExecutor.cjs +11 -21
- package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +10 -37
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +11 -16
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +73 -8
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +3 -11
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +4 -28
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +3 -10
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +48 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/types/graph.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +159 -258
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +25 -8
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +1 -5
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +34 -61
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +10 -27
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -5
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/messages/cache.mjs +0 -89
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +10 -68
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/tools/BashExecutor.mjs +12 -22
- package/dist/esm/tools/BashExecutor.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +11 -37
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +12 -17
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +73 -8
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +3 -11
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +4 -28
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +3 -10
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +48 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/types/graph.mjs.map +1 -1
- package/dist/types/agents/AgentContext.d.ts +25 -95
- package/dist/types/index.d.ts +0 -1
- package/dist/types/llm/bedrock/index.d.ts +1 -54
- package/dist/types/messages/format.d.ts +1 -4
- package/dist/types/tools/CodeExecutor.d.ts +0 -6
- package/dist/types/tools/search/types.d.ts +5 -99
- package/dist/types/tools/search/utils.d.ts +2 -2
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +29 -0
- package/dist/types/types/graph.d.ts +24 -27
- package/dist/types/types/index.d.ts +0 -1
- package/dist/types/types/run.d.ts +0 -2
- package/dist/types/types/tools.d.ts +0 -9
- package/package.json +1 -61
- package/src/agents/AgentContext.test.ts +176 -0
- package/src/agents/AgentContext.ts +178 -304
- package/src/agents/__tests__/AgentContext.test.ts +0 -632
- package/src/graphs/Graph.ts +27 -8
- package/src/index.ts +0 -6
- package/src/llm/anthropic/utils/message_inputs.ts +1 -10
- package/src/llm/bedrock/__tests__/bedrock-caching.test.ts +18 -166
- package/src/llm/bedrock/index.ts +41 -116
- package/src/llm/openai/utils/index.ts +14 -31
- package/src/messages/cache.test.ts +24 -62
- package/src/messages/cache.ts +0 -112
- package/src/messages/format.ts +10 -89
- package/src/scripts/subagent-configurable-inheritance.ts +263 -0
- package/src/specs/anthropic.simple.test.ts +0 -61
- package/src/tools/BashExecutor.ts +13 -37
- package/src/tools/CodeExecutor.ts +11 -55
- package/src/tools/ProgrammaticToolCalling.ts +14 -29
- package/src/tools/ToolNode.ts +69 -8
- package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +0 -60
- package/src/tools/__tests__/SubagentExecutor.test.ts +157 -0
- package/src/tools/search/search.ts +2 -12
- package/src/tools/search/tool.ts +2 -36
- package/src/tools/search/types.ts +8 -133
- package/src/tools/search/utils.ts +5 -13
- package/src/tools/subagent/SubagentExecutor.ts +78 -0
- package/src/types/graph.ts +21 -27
- package/src/types/index.ts +0 -1
- package/src/types/run.ts +0 -2
- package/src/types/tools.ts +0 -9
- package/dist/cjs/langchain/google-common.cjs +0 -3
- package/dist/cjs/langchain/google-common.cjs.map +0 -1
- package/dist/cjs/langchain/index.cjs +0 -86
- package/dist/cjs/langchain/index.cjs.map +0 -1
- package/dist/cjs/langchain/language_models/chat_models.cjs +0 -3
- package/dist/cjs/langchain/language_models/chat_models.cjs.map +0 -1
- package/dist/cjs/langchain/messages/tool.cjs +0 -3
- package/dist/cjs/langchain/messages/tool.cjs.map +0 -1
- package/dist/cjs/langchain/messages.cjs +0 -51
- package/dist/cjs/langchain/messages.cjs.map +0 -1
- package/dist/cjs/langchain/openai.cjs +0 -3
- package/dist/cjs/langchain/openai.cjs.map +0 -1
- package/dist/cjs/langchain/prompts.cjs +0 -11
- package/dist/cjs/langchain/prompts.cjs.map +0 -1
- package/dist/cjs/langchain/runnables.cjs +0 -19
- package/dist/cjs/langchain/runnables.cjs.map +0 -1
- package/dist/cjs/langchain/tools.cjs +0 -23
- package/dist/cjs/langchain/tools.cjs.map +0 -1
- package/dist/cjs/langchain/utils/env.cjs +0 -11
- package/dist/cjs/langchain/utils/env.cjs.map +0 -1
- package/dist/cjs/llm/bedrock/cacheSupport.cjs +0 -55
- package/dist/cjs/llm/bedrock/cacheSupport.cjs.map +0 -1
- package/dist/cjs/tools/search/tavily-scraper.cjs +0 -189
- package/dist/cjs/tools/search/tavily-scraper.cjs.map +0 -1
- package/dist/cjs/tools/search/tavily-search.cjs +0 -372
- package/dist/cjs/tools/search/tavily-search.cjs.map +0 -1
- package/dist/cjs/types/agent-cache.cjs +0 -53
- package/dist/cjs/types/agent-cache.cjs.map +0 -1
- package/dist/esm/langchain/google-common.mjs +0 -2
- package/dist/esm/langchain/google-common.mjs.map +0 -1
- package/dist/esm/langchain/index.mjs +0 -5
- package/dist/esm/langchain/index.mjs.map +0 -1
- package/dist/esm/langchain/language_models/chat_models.mjs +0 -2
- package/dist/esm/langchain/language_models/chat_models.mjs.map +0 -1
- package/dist/esm/langchain/messages/tool.mjs +0 -2
- package/dist/esm/langchain/messages/tool.mjs.map +0 -1
- package/dist/esm/langchain/messages.mjs +0 -2
- package/dist/esm/langchain/messages.mjs.map +0 -1
- package/dist/esm/langchain/openai.mjs +0 -2
- package/dist/esm/langchain/openai.mjs.map +0 -1
- package/dist/esm/langchain/prompts.mjs +0 -2
- package/dist/esm/langchain/prompts.mjs.map +0 -1
- package/dist/esm/langchain/runnables.mjs +0 -2
- package/dist/esm/langchain/runnables.mjs.map +0 -1
- package/dist/esm/langchain/tools.mjs +0 -2
- package/dist/esm/langchain/tools.mjs.map +0 -1
- package/dist/esm/langchain/utils/env.mjs +0 -2
- package/dist/esm/langchain/utils/env.mjs.map +0 -1
- package/dist/esm/llm/bedrock/cacheSupport.mjs +0 -52
- package/dist/esm/llm/bedrock/cacheSupport.mjs.map +0 -1
- package/dist/esm/tools/search/tavily-scraper.mjs +0 -186
- package/dist/esm/tools/search/tavily-scraper.mjs.map +0 -1
- package/dist/esm/tools/search/tavily-search.mjs +0 -370
- package/dist/esm/tools/search/tavily-search.mjs.map +0 -1
- package/dist/esm/types/agent-cache.mjs +0 -51
- package/dist/esm/types/agent-cache.mjs.map +0 -1
- package/dist/types/langchain/google-common.d.ts +0 -1
- package/dist/types/langchain/index.d.ts +0 -8
- package/dist/types/langchain/language_models/chat_models.d.ts +0 -1
- package/dist/types/langchain/messages/tool.d.ts +0 -1
- package/dist/types/langchain/messages.d.ts +0 -2
- package/dist/types/langchain/openai.d.ts +0 -1
- package/dist/types/langchain/prompts.d.ts +0 -1
- package/dist/types/langchain/runnables.d.ts +0 -2
- package/dist/types/langchain/tools.d.ts +0 -2
- package/dist/types/langchain/utils/env.d.ts +0 -1
- package/dist/types/llm/bedrock/cacheSupport.d.ts +0 -35
- package/dist/types/tools/search/tavily-scraper.d.ts +0 -19
- package/dist/types/tools/search/tavily-search.d.ts +0 -4
- package/dist/types/tools/subagent/types.d.ts +0 -84
- package/dist/types/types/agent-cache.d.ts +0 -70
- package/src/agents/AgentContext.js.map +0 -1
- package/src/agents/AgentContext.test.js.map +0 -1
- package/src/agents/__tests__/AgentContext.cacheTtl.live.test.ts +0 -259
- package/src/agents/__tests__/AgentContext.crossAgentTier1.live.test.ts +0 -264
- package/src/agents/__tests__/AgentContext.crossUserCache.live.test.ts +0 -342
- package/src/agents/__tests__/AgentContext.test.js.map +0 -1
- package/src/agents/__tests__/resolveStructuredOutputMode.test.js.map +0 -1
- package/src/common/enum.js.map +0 -1
- package/src/common/index.js.map +0 -1
- package/src/events.js.map +0 -1
- package/src/graphs/Graph.js.map +0 -1
- package/src/graphs/MultiAgentGraph.js.map +0 -1
- package/src/graphs/__tests__/structured-output.integration.test.js.map +0 -1
- package/src/graphs/__tests__/structured-output.test.js.map +0 -1
- package/src/graphs/contextManagement.e2e.test.js.map +0 -1
- package/src/graphs/contextManagement.test.js.map +0 -1
- package/src/graphs/handoffValidation.test.js.map +0 -1
- package/src/graphs/index.js.map +0 -1
- package/src/index.js.map +0 -1
- package/src/instrumentation.js.map +0 -1
- package/src/langchain/google-common.ts +0 -1
- package/src/langchain/index.ts +0 -8
- package/src/langchain/language_models/chat_models.ts +0 -1
- package/src/langchain/messages/tool.ts +0 -5
- package/src/langchain/messages.ts +0 -21
- package/src/langchain/openai.ts +0 -1
- package/src/langchain/prompts.ts +0 -1
- package/src/langchain/runnables.ts +0 -7
- package/src/langchain/tools.ts +0 -8
- package/src/langchain/utils/env.ts +0 -1
- package/src/llm/anthropic/index.js.map +0 -1
- package/src/llm/anthropic/types.js.map +0 -1
- package/src/llm/anthropic/utils/message_inputs.js.map +0 -1
- package/src/llm/anthropic/utils/message_outputs.js.map +0 -1
- package/src/llm/anthropic/utils/output_parsers.js.map +0 -1
- package/src/llm/anthropic/utils/server-tool-inputs.test.ts +0 -436
- package/src/llm/anthropic/utils/tools.js.map +0 -1
- package/src/llm/bedrock/__tests__/bedrock-caching.test.js.map +0 -1
- package/src/llm/bedrock/cacheSupport.test.ts +0 -99
- package/src/llm/bedrock/cacheSupport.ts +0 -53
- package/src/llm/bedrock/index.js.map +0 -1
- package/src/llm/bedrock/types.js.map +0 -1
- package/src/llm/bedrock/utils/index.js.map +0 -1
- package/src/llm/bedrock/utils/message_inputs.js.map +0 -1
- package/src/llm/bedrock/utils/message_outputs.js.map +0 -1
- package/src/llm/fake.js.map +0 -1
- package/src/llm/google/index.js.map +0 -1
- package/src/llm/google/types.js.map +0 -1
- package/src/llm/google/utils/common.js.map +0 -1
- package/src/llm/google/utils/tools.js.map +0 -1
- package/src/llm/google/utils/zod_to_genai_parameters.js.map +0 -1
- package/src/llm/openai/index.js.map +0 -1
- package/src/llm/openai/types.js.map +0 -1
- package/src/llm/openai/utils/index.js.map +0 -1
- package/src/llm/openai/utils/isReasoningModel.test.js.map +0 -1
- package/src/llm/openrouter/index.js.map +0 -1
- package/src/llm/openrouter/reasoning.test.js.map +0 -1
- package/src/llm/providers.js.map +0 -1
- package/src/llm/text.js.map +0 -1
- package/src/llm/vertexai/index.js.map +0 -1
- package/src/messages/__tests__/tools.test.js.map +0 -1
- package/src/messages/cache.js.map +0 -1
- package/src/messages/cache.test.js.map +0 -1
- package/src/messages/content.js.map +0 -1
- package/src/messages/content.test.js.map +0 -1
- package/src/messages/core.js.map +0 -1
- package/src/messages/ensureThinkingBlock.test.js.map +0 -1
- package/src/messages/format.js.map +0 -1
- package/src/messages/formatAgentMessages.test.js.map +0 -1
- package/src/messages/formatAgentMessages.tools.test.js.map +0 -1
- package/src/messages/formatMessage.test.js.map +0 -1
- package/src/messages/ids.js.map +0 -1
- package/src/messages/index.js.map +0 -1
- package/src/messages/labelContentByAgent.test.js.map +0 -1
- package/src/messages/prune.js.map +0 -1
- package/src/messages/reducer.js.map +0 -1
- package/src/messages/shiftIndexTokenCountMap.test.js.map +0 -1
- package/src/messages/summarize.js.map +0 -1
- package/src/messages/summarize.test.js.map +0 -1
- package/src/messages/tools.js.map +0 -1
- package/src/mockStream.js.map +0 -1
- package/src/prompts/collab.js.map +0 -1
- package/src/prompts/index.js.map +0 -1
- package/src/prompts/taskmanager.js.map +0 -1
- package/src/run.js.map +0 -1
- package/src/schemas/index.js.map +0 -1
- package/src/schemas/schema-preparation.test.js.map +0 -1
- package/src/schemas/validate.js.map +0 -1
- package/src/schemas/validate.test.js.map +0 -1
- package/src/scripts/abort.js.map +0 -1
- package/src/scripts/ant_web_search.js.map +0 -1
- package/src/scripts/ant_web_search_edge_case.js.map +0 -1
- package/src/scripts/ant_web_search_error_edge_case.js.map +0 -1
- package/src/scripts/args.js.map +0 -1
- package/src/scripts/bedrock-cache-debug.js.map +0 -1
- package/src/scripts/bedrock-content-aggregation-test.js.map +0 -1
- package/src/scripts/bedrock-merge-test.js.map +0 -1
- package/src/scripts/bedrock-parallel-tools-test.js.map +0 -1
- package/src/scripts/caching.js.map +0 -1
- package/src/scripts/cli.js.map +0 -1
- package/src/scripts/cli2.js.map +0 -1
- package/src/scripts/cli3.js.map +0 -1
- package/src/scripts/cli4.js.map +0 -1
- package/src/scripts/cli5.js.map +0 -1
- package/src/scripts/code_exec.js.map +0 -1
- package/src/scripts/code_exec_files.js.map +0 -1
- package/src/scripts/code_exec_multi_session.js.map +0 -1
- package/src/scripts/code_exec_ptc.js.map +0 -1
- package/src/scripts/code_exec_session.js.map +0 -1
- package/src/scripts/code_exec_simple.js.map +0 -1
- package/src/scripts/content.js.map +0 -1
- package/src/scripts/empty_input.js.map +0 -1
- package/src/scripts/handoff-test.js.map +0 -1
- package/src/scripts/image.js.map +0 -1
- package/src/scripts/memory.js.map +0 -1
- package/src/scripts/multi-agent-chain.js.map +0 -1
- package/src/scripts/multi-agent-conditional.js.map +0 -1
- package/src/scripts/multi-agent-document-review-chain.js.map +0 -1
- package/src/scripts/multi-agent-hybrid-flow.js.map +0 -1
- package/src/scripts/multi-agent-parallel-start.js.map +0 -1
- package/src/scripts/multi-agent-parallel.js.map +0 -1
- package/src/scripts/multi-agent-sequence.js.map +0 -1
- package/src/scripts/multi-agent-supervisor.js.map +0 -1
- package/src/scripts/multi-agent-test.js.map +0 -1
- package/src/scripts/parallel-asymmetric-tools-test.js.map +0 -1
- package/src/scripts/parallel-full-metadata-test.js.map +0 -1
- package/src/scripts/parallel-tools-test.js.map +0 -1
- package/src/scripts/programmatic_exec.js.map +0 -1
- package/src/scripts/programmatic_exec_agent.js.map +0 -1
- package/src/scripts/search.js.map +0 -1
- package/src/scripts/sequential-full-metadata-test.js.map +0 -1
- package/src/scripts/simple.js.map +0 -1
- package/src/scripts/single-agent-metadata-test.js.map +0 -1
- package/src/scripts/stream.js.map +0 -1
- package/src/scripts/test-custom-prompt-key.js.map +0 -1
- package/src/scripts/test-handoff-input.js.map +0 -1
- package/src/scripts/test-handoff-preamble.js.map +0 -1
- package/src/scripts/test-handoff-steering.js.map +0 -1
- package/src/scripts/test-multi-agent-list-handoff.js.map +0 -1
- package/src/scripts/test-parallel-agent-labeling.js.map +0 -1
- package/src/scripts/test-parallel-handoffs.js.map +0 -1
- package/src/scripts/test-thinking-handoff-bedrock.js.map +0 -1
- package/src/scripts/test-thinking-handoff.js.map +0 -1
- package/src/scripts/test-thinking-to-thinking-handoff-bedrock.js.map +0 -1
- package/src/scripts/test-tool-before-handoff-role-order.js.map +0 -1
- package/src/scripts/test-tools-before-handoff.js.map +0 -1
- package/src/scripts/test_code_api.js.map +0 -1
- package/src/scripts/thinking-bedrock.js.map +0 -1
- package/src/scripts/thinking-vertexai.js.map +0 -1
- package/src/scripts/thinking.js.map +0 -1
- package/src/scripts/tool_search.js.map +0 -1
- package/src/scripts/tools.js.map +0 -1
- package/src/specs/agent-handoffs-bedrock.integration.test.js.map +0 -1
- package/src/specs/agent-handoffs.test.js.map +0 -1
- package/src/specs/anthropic.simple.test.js.map +0 -1
- package/src/specs/azure.simple.test.js.map +0 -1
- package/src/specs/cache.simple.test.js.map +0 -1
- package/src/specs/custom-event-await.test.js.map +0 -1
- package/src/specs/deepseek.simple.test.js.map +0 -1
- package/src/specs/emergency-prune.test.js.map +0 -1
- package/src/specs/moonshot.simple.test.js.map +0 -1
- package/src/specs/observability.integration.test.js.map +0 -1
- package/src/specs/openai.simple.test.js.map +0 -1
- package/src/specs/openrouter.simple.test.js.map +0 -1
- package/src/specs/prune.test.js.map +0 -1
- package/src/specs/reasoning.test.js.map +0 -1
- package/src/specs/spec.utils.js.map +0 -1
- package/src/specs/thinking-handoff.test.js.map +0 -1
- package/src/specs/thinking-prune.test.js.map +0 -1
- package/src/specs/token-distribution-edge-case.test.js.map +0 -1
- package/src/specs/token-memoization.test.js.map +0 -1
- package/src/specs/tokens.test.js.map +0 -1
- package/src/specs/tool-error.test.js.map +0 -1
- package/src/splitStream.js.map +0 -1
- package/src/splitStream.test.js.map +0 -1
- package/src/stream.js.map +0 -1
- package/src/stream.test.js.map +0 -1
- package/src/test/mockTools.js.map +0 -1
- package/src/tools/BrowserTools.js.map +0 -1
- package/src/tools/Calculator.js.map +0 -1
- package/src/tools/Calculator.test.js.map +0 -1
- package/src/tools/CodeExecutor.js.map +0 -1
- package/src/tools/ProgrammaticToolCalling.js.map +0 -1
- package/src/tools/StreamingToolCallBuffer.js.map +0 -1
- package/src/tools/ToolNode.js.map +0 -1
- package/src/tools/ToolSearch.js.map +0 -1
- package/src/tools/__tests__/BrowserTools.test.js.map +0 -1
- package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.js.map +0 -1
- package/src/tools/__tests__/ProgrammaticToolCalling.test.js.map +0 -1
- package/src/tools/__tests__/StreamingToolCallBuffer.test.js.map +0 -1
- package/src/tools/__tests__/ToolApproval.test.js.map +0 -1
- package/src/tools/__tests__/ToolNode.recovery.test.js.map +0 -1
- package/src/tools/__tests__/ToolNode.session.test.js.map +0 -1
- package/src/tools/__tests__/ToolSearch.integration.test.js.map +0 -1
- package/src/tools/__tests__/ToolSearch.test.js.map +0 -1
- package/src/tools/__tests__/handlers.test.js.map +0 -1
- package/src/tools/__tests__/truncation-recovery.integration.test.js.map +0 -1
- package/src/tools/handlers.js.map +0 -1
- package/src/tools/schema.js.map +0 -1
- package/src/tools/search/anthropic.js.map +0 -1
- package/src/tools/search/content.js.map +0 -1
- package/src/tools/search/content.test.js.map +0 -1
- package/src/tools/search/firecrawl.js.map +0 -1
- package/src/tools/search/format.js.map +0 -1
- package/src/tools/search/highlights.js.map +0 -1
- package/src/tools/search/index.js.map +0 -1
- package/src/tools/search/jina-reranker.test.js.map +0 -1
- package/src/tools/search/rerankers.js.map +0 -1
- package/src/tools/search/schema.js.map +0 -1
- package/src/tools/search/search.js.map +0 -1
- package/src/tools/search/serper-scraper.js.map +0 -1
- package/src/tools/search/tavily-scraper.ts +0 -235
- package/src/tools/search/tavily-search.ts +0 -424
- package/src/tools/search/tavily.test.ts +0 -965
- package/src/tools/search/test.js.map +0 -1
- package/src/tools/search/tool.js.map +0 -1
- package/src/tools/search/types.js.map +0 -1
- package/src/tools/search/utils.js.map +0 -1
- package/src/tools/subagent/types.test.ts +0 -70
- package/src/tools/subagent/types.ts +0 -115
- package/src/types/agent-cache.ts +0 -73
- package/src/types/graph.js.map +0 -1
- package/src/types/graph.test.js.map +0 -1
- package/src/types/index.js.map +0 -1
- package/src/types/llm.js.map +0 -1
- package/src/types/messages.js.map +0 -1
- package/src/types/run.js.map +0 -1
- package/src/types/stream.js.map +0 -1
- package/src/types/tools.js.map +0 -1
- package/src/utils/contextAnalytics.js.map +0 -1
- package/src/utils/contextAnalytics.test.js.map +0 -1
- package/src/utils/events.js.map +0 -1
- package/src/utils/graph.js.map +0 -1
- package/src/utils/handlers.js.map +0 -1
- package/src/utils/index.js.map +0 -1
- package/src/utils/llm.js.map +0 -1
- package/src/utils/llmConfig.js.map +0 -1
- package/src/utils/logging.js.map +0 -1
- package/src/utils/misc.js.map +0 -1
- package/src/utils/run.js.map +0 -1
- package/src/utils/schema.js.map +0 -1
- package/src/utils/title.js.map +0 -1
- package/src/utils/tokens.js.map +0 -1
- package/src/utils/toonFormat.js.map +0 -1
|
@@ -376,67 +376,6 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
|
|
|
376
376
|
);
|
|
377
377
|
});
|
|
378
378
|
|
|
379
|
-
test(`${capitalizeFirstLetter(provider)}: follow-up after assistant message with only whitespace text content`, async () => {
|
|
380
|
-
/**
|
|
381
|
-
* Regression for upstream discussion #12806.
|
|
382
|
-
*
|
|
383
|
-
* The Anthropic API has two distinct rejection rules (verified against
|
|
384
|
-
* the live API):
|
|
385
|
-
* 1. Strict empty `text: ''` → rejected anywhere
|
|
386
|
-
* "messages: text content blocks must be non-empty"
|
|
387
|
-
* 2. Whitespace-only `text: ' '` / '\n' / '\t' → rejected when the
|
|
388
|
-
* assistant message has no other accepted blocks (no tool blocks,
|
|
389
|
-
* no non-whitespace text)
|
|
390
|
-
* "messages: text content blocks must contain non-whitespace text"
|
|
391
|
-
*
|
|
392
|
-
* Anthropic responses for some prompts include a whitespace-only text
|
|
393
|
-
* block as the sole text content. Re-sending that history on a
|
|
394
|
-
* follow-up turn triggers rule 2.
|
|
395
|
-
*
|
|
396
|
-
* The wire-send filter in `_formatContent` must drop any text block
|
|
397
|
-
* whose trimmed content is empty. The previous filter used strict
|
|
398
|
-
* `text === ''` only, which caught rule 1 but not rule 2.
|
|
399
|
-
*/
|
|
400
|
-
const llmConfig = getLLMConfig(provider);
|
|
401
|
-
const customHandlers1 = setupCustomHandlers();
|
|
402
|
-
|
|
403
|
-
const followUpRun = await Run.create<t.IState>({
|
|
404
|
-
runId: 'repro-12806-followup',
|
|
405
|
-
graphConfig: {
|
|
406
|
-
type: 'standard',
|
|
407
|
-
llmConfig,
|
|
408
|
-
instructions: 'You are a friendly AI assistant.',
|
|
409
|
-
},
|
|
410
|
-
returnContent: true,
|
|
411
|
-
skipCleanup: true,
|
|
412
|
-
customHandlers: customHandlers1,
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
// Build history with an assistant message whose entire content array
|
|
416
|
-
// is a single whitespace-only text block. This is the precise shape
|
|
417
|
-
// the API rejects under rule 2 above.
|
|
418
|
-
conversationHistory = [
|
|
419
|
-
new HumanMessage('hi'),
|
|
420
|
-
new (require('@langchain/core/messages').AIMessage)({
|
|
421
|
-
content: [{ type: 'text', text: ' ' }],
|
|
422
|
-
}),
|
|
423
|
-
new HumanMessage('please respond with a short greeting'),
|
|
424
|
-
];
|
|
425
|
-
|
|
426
|
-
// With the fix: `_formatContent` drops the whitespace text block,
|
|
427
|
-
// the assistant content becomes an empty array, and the API accepts.
|
|
428
|
-
// Without the fix: the whitespace block is forwarded and the API
|
|
429
|
-
// rejects with "messages: text content blocks must contain non-whitespace text".
|
|
430
|
-
const finalContentParts = await followUpRun.processStream(
|
|
431
|
-
{ messages: conversationHistory },
|
|
432
|
-
config
|
|
433
|
-
);
|
|
434
|
-
expect(finalContentParts).toBeDefined();
|
|
435
|
-
const finalMessages = followUpRun.getRunMessages();
|
|
436
|
-
expect(finalMessages).toBeDefined();
|
|
437
|
-
expect(finalMessages?.length).toBeGreaterThan(0);
|
|
438
|
-
});
|
|
439
|
-
|
|
440
379
|
test('should handle errors appropriately', async () => {
|
|
441
380
|
// Test error scenarios
|
|
442
381
|
await expect(async () => {
|
|
@@ -4,23 +4,17 @@ import { HttpsProxyAgent } from 'https-proxy-agent';
|
|
|
4
4
|
import { getEnvironmentVariable } from '@langchain/core/utils/env';
|
|
5
5
|
import { tool, DynamicStructuredTool } from '@langchain/core/tools';
|
|
6
6
|
import type * as t from '@/types';
|
|
7
|
-
import {
|
|
7
|
+
import { imageExtRegex, getCodeBaseURL } from './CodeExecutor';
|
|
8
8
|
import { Constants, EnvVar } from '@/common';
|
|
9
9
|
|
|
10
10
|
config();
|
|
11
11
|
|
|
12
|
+
const imageMessage = 'Image is already displayed to the user';
|
|
12
13
|
const otherMessage = 'File is already downloaded by the user';
|
|
13
|
-
const inheritedFileMessage =
|
|
14
|
-
'Available as an input — already known to the user';
|
|
15
14
|
const accessMessage =
|
|
16
15
|
'Note: Files from previous executions are automatically available and can be modified.';
|
|
17
16
|
const emptyOutputMessage =
|
|
18
17
|
"stdout: Empty. Ensure you're writing output explicitly.\n";
|
|
19
|
-
const inheritedFilesHeader =
|
|
20
|
-
'Available files (inputs, not generated by this execution):';
|
|
21
|
-
const generatedFilesHeader = 'Generated files:';
|
|
22
|
-
const inheritedNote =
|
|
23
|
-
'Note: Files in "Available files" are inputs the user (or a skill) already provided to the sandbox. They were not produced by this execution and you should not present them as new outputs in your response.';
|
|
24
18
|
|
|
25
19
|
export const BashExecutionToolSchema = {
|
|
26
20
|
type: 'object',
|
|
@@ -221,38 +215,20 @@ function createBashExecutionTool(
|
|
|
221
215
|
}
|
|
222
216
|
if (result.stderr) formattedOutput += `stderr:\n${result.stderr}\n`;
|
|
223
217
|
if (result.files && result.files.length > 0) {
|
|
224
|
-
|
|
225
|
-
* codeapi) from genuine generated outputs. The LLM was previously
|
|
226
|
-
* shown skill files under "Generated files:" with the message
|
|
227
|
-
* "File is already downloaded by the user", which led it to
|
|
228
|
-
* (a) believe it had just produced files it merely referenced
|
|
229
|
-
* and (b) sometimes invent paths like /mnt/user-data/uploads/
|
|
230
|
-
* trying to find the "originals". Labeling them as inputs makes
|
|
231
|
-
* the mental model accurate. */
|
|
232
|
-
const inheritedFiles = result.files.filter(
|
|
233
|
-
(f) => f.inherited === true
|
|
234
|
-
);
|
|
235
|
-
const generatedFiles = result.files.filter(
|
|
236
|
-
(f) => f.inherited !== true
|
|
237
|
-
);
|
|
218
|
+
formattedOutput += 'Generated files:\n';
|
|
238
219
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
formattedOutput += renderFileSection(
|
|
245
|
-
inheritedFilesHeader,
|
|
246
|
-
inheritedFiles,
|
|
247
|
-
inheritedFileMessage
|
|
248
|
-
);
|
|
220
|
+
const fileCount = result.files.length;
|
|
221
|
+
for (let i = 0; i < fileCount; i++) {
|
|
222
|
+
const file = result.files[i];
|
|
223
|
+
const isImage = imageExtRegex.test(file.name);
|
|
224
|
+
formattedOutput += `- /mnt/data/${file.name} | ${isImage ? imageMessage : otherMessage}`;
|
|
249
225
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if (inheritedFiles.length > 0) {
|
|
254
|
-
formattedOutput += `\n\n${inheritedNote}`;
|
|
226
|
+
if (i < fileCount - 1) {
|
|
227
|
+
formattedOutput += fileCount <= 3 ? ', ' : ',\n';
|
|
228
|
+
}
|
|
255
229
|
}
|
|
230
|
+
|
|
231
|
+
formattedOutput += `\n\n${accessMessage}`;
|
|
256
232
|
return [
|
|
257
233
|
formattedOutput.trim(),
|
|
258
234
|
{
|
|
@@ -15,41 +15,10 @@ export const getCodeBaseURL = (): string =>
|
|
|
15
15
|
|
|
16
16
|
const imageMessage = 'Image is already displayed to the user';
|
|
17
17
|
const otherMessage = 'File is already downloaded by the user';
|
|
18
|
-
const inheritedFileMessage =
|
|
19
|
-
'Available as an input — already known to the user';
|
|
20
18
|
const accessMessage =
|
|
21
19
|
'Note: Files from previous executions are automatically available and can be modified.';
|
|
22
20
|
const emptyOutputMessage =
|
|
23
21
|
"stdout: Empty. Ensure you're writing output explicitly.\n";
|
|
24
|
-
const inheritedFilesHeader =
|
|
25
|
-
'Available files (inputs, not generated by this execution):';
|
|
26
|
-
const generatedFilesHeader = 'Generated files:';
|
|
27
|
-
const inheritedNote =
|
|
28
|
-
'Note: Files in "Available files" are inputs the user (or a skill) already provided to the sandbox. They were not produced by this execution and you should not present them as new outputs in your response.';
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Renders one section of the post-execution file listing. Used by the
|
|
32
|
-
* code/bash tool formatters to keep generated outputs and inherited
|
|
33
|
-
* inputs visually separated. See BashExecutor for full docs.
|
|
34
|
-
*/
|
|
35
|
-
export function renderFileSection(
|
|
36
|
-
header: string,
|
|
37
|
-
files: t.FileRefs,
|
|
38
|
-
defaultMessage: string
|
|
39
|
-
): string {
|
|
40
|
-
if (files.length === 0) return '';
|
|
41
|
-
let out = `${header}\n`;
|
|
42
|
-
for (let i = 0; i < files.length; i++) {
|
|
43
|
-
const file = files[i];
|
|
44
|
-
const isImage = imageExtRegex.test(file.name);
|
|
45
|
-
out += `- /mnt/data/${file.name} | ${isImage ? imageMessage : defaultMessage}`;
|
|
46
|
-
if (i < files.length - 1) {
|
|
47
|
-
out += files.length <= 3 ? ', ' : ',\n';
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
out += '\n';
|
|
51
|
-
return out;
|
|
52
|
-
}
|
|
53
22
|
|
|
54
23
|
const SUPPORTED_LANGUAGES = [
|
|
55
24
|
'py',
|
|
@@ -333,33 +302,20 @@ function createCodeExecutionTool(
|
|
|
333
302
|
}
|
|
334
303
|
|
|
335
304
|
if (result.files && result.files.length > 0) {
|
|
336
|
-
|
|
337
|
-
* generated outputs so the LLM doesn't conflate skill files
|
|
338
|
-
* with newly-produced artifacts. */
|
|
339
|
-
const inheritedFiles = result.files.filter(
|
|
340
|
-
(f) => f.inherited === true
|
|
341
|
-
);
|
|
342
|
-
const generatedFiles = result.files.filter(
|
|
343
|
-
(f) => f.inherited !== true
|
|
344
|
-
);
|
|
305
|
+
formattedOutput += 'Generated files:\n';
|
|
345
306
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
formattedOutput += renderFileSection(
|
|
352
|
-
inheritedFilesHeader,
|
|
353
|
-
inheritedFiles,
|
|
354
|
-
inheritedFileMessage
|
|
355
|
-
);
|
|
307
|
+
const fileCount = result.files.length;
|
|
308
|
+
for (let i = 0; i < fileCount; i++) {
|
|
309
|
+
const file = result.files[i];
|
|
310
|
+
const isImage = imageExtRegex.test(file.name);
|
|
311
|
+
formattedOutput += `- /mnt/data/${file.name} | ${isImage ? imageMessage : otherMessage}`;
|
|
356
312
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
if (inheritedFiles.length > 0) {
|
|
361
|
-
formattedOutput += `\n\n${inheritedNote}`;
|
|
313
|
+
if (i < fileCount - 1) {
|
|
314
|
+
formattedOutput += fileCount <= 3 ? ', ' : ',\n';
|
|
315
|
+
}
|
|
362
316
|
}
|
|
317
|
+
|
|
318
|
+
formattedOutput += `\n\n${accessMessage}`;
|
|
363
319
|
return [
|
|
364
320
|
formattedOutput.trim(),
|
|
365
321
|
{
|
|
@@ -6,7 +6,7 @@ import { getEnvironmentVariable } from '@langchain/core/utils/env';
|
|
|
6
6
|
import { tool, DynamicStructuredTool } from '@langchain/core/tools';
|
|
7
7
|
import type { ToolCall } from '@langchain/core/messages/tool';
|
|
8
8
|
import type * as t from '@/types';
|
|
9
|
-
import {
|
|
9
|
+
import { imageExtRegex, getCodeBaseURL } from './CodeExecutor';
|
|
10
10
|
import { EnvVar, Constants } from '@/common';
|
|
11
11
|
|
|
12
12
|
config();
|
|
@@ -15,14 +15,8 @@ config();
|
|
|
15
15
|
// Constants
|
|
16
16
|
// ============================================================================
|
|
17
17
|
|
|
18
|
+
const imageMessage = 'Image is already displayed to the user';
|
|
18
19
|
const otherMessage = 'File is already downloaded by the user';
|
|
19
|
-
const inheritedFileMessage =
|
|
20
|
-
'Available as an input — already known to the user';
|
|
21
|
-
const inheritedFilesHeader =
|
|
22
|
-
'Available files (inputs, not generated by this execution):';
|
|
23
|
-
const generatedFilesHeader = 'Generated files:';
|
|
24
|
-
const inheritedNote =
|
|
25
|
-
'Note: Files in "Available files" are inputs the user (or a skill) already provided to the sandbox. They were not produced by this execution and you should not present them as new outputs in your response.';
|
|
26
20
|
const accessMessage =
|
|
27
21
|
'Note: Files from previous executions are automatically available and can be modified.';
|
|
28
22
|
const emptyOutputMessage =
|
|
@@ -569,29 +563,20 @@ export function formatCompletedResponse(
|
|
|
569
563
|
}
|
|
570
564
|
|
|
571
565
|
if (response.files && response.files.length > 0) {
|
|
572
|
-
|
|
573
|
-
* passthrough) inputs from real generated outputs so the LLM doesn't
|
|
574
|
-
* conflate skill files with newly-produced artifacts. */
|
|
575
|
-
const inheritedFiles = response.files.filter((f) => f.inherited === true);
|
|
576
|
-
const generatedFiles = response.files.filter((f) => f.inherited !== true);
|
|
577
|
-
|
|
578
|
-
formatted += renderFileSection(
|
|
579
|
-
generatedFilesHeader,
|
|
580
|
-
generatedFiles,
|
|
581
|
-
otherMessage
|
|
582
|
-
);
|
|
583
|
-
formatted += renderFileSection(
|
|
584
|
-
inheritedFilesHeader,
|
|
585
|
-
inheritedFiles,
|
|
586
|
-
inheritedFileMessage
|
|
587
|
-
);
|
|
566
|
+
formatted += 'Generated files:\n';
|
|
588
567
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
formatted +=
|
|
568
|
+
const fileCount = response.files.length;
|
|
569
|
+
for (let i = 0; i < fileCount; i++) {
|
|
570
|
+
const file = response.files[i];
|
|
571
|
+
const isImage = imageExtRegex.test(file.name);
|
|
572
|
+
formatted += `- /mnt/data/${file.name} | ${isImage ? imageMessage : otherMessage}`;
|
|
573
|
+
|
|
574
|
+
if (i < fileCount - 1) {
|
|
575
|
+
formatted += fileCount <= 3 ? ', ' : ',\n';
|
|
576
|
+
}
|
|
594
577
|
}
|
|
578
|
+
|
|
579
|
+
formatted += `\n\n${accessMessage}`;
|
|
595
580
|
}
|
|
596
581
|
|
|
597
582
|
return [
|
package/src/tools/ToolNode.ts
CHANGED
|
@@ -754,19 +754,74 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
754
754
|
}
|
|
755
755
|
}
|
|
756
756
|
|
|
757
|
-
// Field-level recovery: extract missing fields from the raw buffer
|
|
757
|
+
// Field-level recovery: extract missing fields from the raw buffer.
|
|
758
|
+
//
|
|
759
|
+
// Only attempt this when `parsedArgs` is missing top-level keys that
|
|
760
|
+
// appear at depth 0 in the raw JSON. The previous implementation walked
|
|
761
|
+
// EVERY `"key":` match the regex found — including keys nested inside
|
|
762
|
+
// arrays/objects like `steps[].options[].label` — and tried to "recover"
|
|
763
|
+
// them as top-level fields. That produced confusing log spam (false
|
|
764
|
+
// positives like `recoveredFields=[question,label,value]` for a clean
|
|
765
|
+
// multi-step `ask_user` call) and could inject stray top-level fields
|
|
766
|
+
// into `args` for downstream tool execution.
|
|
758
767
|
const parsedArgs = typeof args === 'object' ? { ...args } : {};
|
|
759
768
|
const recoveredFields: string[] = [];
|
|
760
769
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
770
|
+
/**
|
|
771
|
+
* Extract only TOP-LEVEL keys from the raw JSON. Walks the buffer
|
|
772
|
+
* tracking brace/bracket depth so nested keys are skipped.
|
|
773
|
+
*/
|
|
774
|
+
const topLevelKeys: string[] = [];
|
|
775
|
+
let depth = 0;
|
|
776
|
+
let inString = false;
|
|
777
|
+
let escaped = false;
|
|
778
|
+
let i = 0;
|
|
779
|
+
while (i < rawArgs.length) {
|
|
780
|
+
const ch = rawArgs[i];
|
|
781
|
+
if (escaped) {
|
|
782
|
+
escaped = false;
|
|
783
|
+
i++;
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
if (inString) {
|
|
787
|
+
if (ch === '\\') escaped = true;
|
|
788
|
+
else if (ch === '"') inString = false;
|
|
789
|
+
i++;
|
|
790
|
+
continue;
|
|
791
|
+
}
|
|
792
|
+
if (ch === '"') {
|
|
793
|
+
// Possible key — only count if at depth 1 (inside the outer object)
|
|
794
|
+
const start = i + 1;
|
|
795
|
+
let j = start;
|
|
796
|
+
while (j < rawArgs.length) {
|
|
797
|
+
const c = rawArgs[j];
|
|
798
|
+
if (c === '\\') {
|
|
799
|
+
j += 2;
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
if (c === '"') break;
|
|
803
|
+
j++;
|
|
804
|
+
}
|
|
805
|
+
if (j < rawArgs.length) {
|
|
806
|
+
// Skip whitespace after closing quote and check for ':'
|
|
807
|
+
let k = j + 1;
|
|
808
|
+
while (k < rawArgs.length && /\s/.test(rawArgs[k])) k++;
|
|
809
|
+
if (depth === 1 && rawArgs[k] === ':') {
|
|
810
|
+
topLevelKeys.push(rawArgs.slice(start, j));
|
|
811
|
+
}
|
|
812
|
+
i = j + 1;
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
inString = true;
|
|
816
|
+
i++;
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
if (ch === '{' || ch === '[') depth++;
|
|
820
|
+
else if (ch === '}' || ch === ']') depth--;
|
|
821
|
+
i++;
|
|
767
822
|
}
|
|
768
823
|
|
|
769
|
-
for (const fieldName of
|
|
824
|
+
for (const fieldName of topLevelKeys) {
|
|
770
825
|
if (
|
|
771
826
|
parsedArgs[fieldName] == null ||
|
|
772
827
|
parsedArgs[fieldName] === '' ||
|
|
@@ -991,6 +1046,12 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
991
1046
|
// Dispatch ON_RUN_STEP_COMPLETED via custom event (same path as dispatchToolEvents)
|
|
992
1047
|
const stepId = this.toolCallStepIds?.get(toolCallId) ?? '';
|
|
993
1048
|
if (!stepId) {
|
|
1049
|
+
// eslint-disable-next-line no-console
|
|
1050
|
+
console.warn(
|
|
1051
|
+
`[ToolNode.handleRunToolCompletions] missing stepId for toolCallId=${toolCallId} ` +
|
|
1052
|
+
`name=${call.name} — ON_RUN_STEP_COMPLETED skipped, output will not be persisted. ` +
|
|
1053
|
+
`If this is a resumed HITL tool call, verify Graph.resetValues preserves toolCallStepIds when keepContent=true.`
|
|
1054
|
+
);
|
|
994
1055
|
continue;
|
|
995
1056
|
}
|
|
996
1057
|
|
|
@@ -664,66 +664,6 @@ for member in team:
|
|
|
664
664
|
expect(output).toContain('chart.png');
|
|
665
665
|
expect(output).toContain('Image is already displayed to the user');
|
|
666
666
|
});
|
|
667
|
-
|
|
668
|
-
it('splits inherited inputs from generated outputs into distinct sections', () => {
|
|
669
|
-
const response: t.ProgrammaticExecutionResponse = {
|
|
670
|
-
status: 'completed',
|
|
671
|
-
stdout: 'analysis done\n',
|
|
672
|
-
stderr: '',
|
|
673
|
-
files: [
|
|
674
|
-
{ id: 'g1', name: 'report.pdf' },
|
|
675
|
-
{ id: 'i1', name: 'pptx/SKILL.md', inherited: true },
|
|
676
|
-
{ id: 'i2', name: 'pptx/scripts/clean.py', inherited: true },
|
|
677
|
-
{ id: 'g2', name: 'chart.png' },
|
|
678
|
-
],
|
|
679
|
-
session_id: 'sess_abc123',
|
|
680
|
-
};
|
|
681
|
-
|
|
682
|
-
const [output, artifact] = formatCompletedResponse(response);
|
|
683
|
-
|
|
684
|
-
/* Generated section lists only outputs the run produced. */
|
|
685
|
-
const generatedIdx = output.indexOf('Generated files:');
|
|
686
|
-
const inheritedIdx = output.indexOf('Available files (inputs');
|
|
687
|
-
expect(generatedIdx).toBeGreaterThan(-1);
|
|
688
|
-
expect(inheritedIdx).toBeGreaterThan(generatedIdx);
|
|
689
|
-
|
|
690
|
-
/* Slice each section so we can assert membership without
|
|
691
|
-
* cross-talk between the two listings. */
|
|
692
|
-
const generatedSection = output.slice(generatedIdx, inheritedIdx);
|
|
693
|
-
const inheritedSection = output.slice(inheritedIdx);
|
|
694
|
-
|
|
695
|
-
expect(generatedSection).toContain('report.pdf');
|
|
696
|
-
expect(generatedSection).toContain('chart.png');
|
|
697
|
-
expect(generatedSection).not.toContain('SKILL.md');
|
|
698
|
-
|
|
699
|
-
expect(inheritedSection).toContain('pptx/SKILL.md');
|
|
700
|
-
expect(inheritedSection).toContain('pptx/scripts/clean.py');
|
|
701
|
-
expect(inheritedSection).toContain('Available as an input');
|
|
702
|
-
|
|
703
|
-
/* The artifact still carries every file so the host can still
|
|
704
|
-
* thread per-file ids through to subsequent calls. */
|
|
705
|
-
expect(artifact.files).toHaveLength(4);
|
|
706
|
-
});
|
|
707
|
-
|
|
708
|
-
it('omits the Generated files header when every entry is inherited', () => {
|
|
709
|
-
const response: t.ProgrammaticExecutionResponse = {
|
|
710
|
-
status: 'completed',
|
|
711
|
-
stdout: 'cat: ok\n',
|
|
712
|
-
stderr: '',
|
|
713
|
-
files: [
|
|
714
|
-
{ id: 'i1', name: 'pptx/SKILL.md', inherited: true },
|
|
715
|
-
{ id: 'i2', name: 'pptx/editing.md', inherited: true },
|
|
716
|
-
],
|
|
717
|
-
session_id: 'sess_abc123',
|
|
718
|
-
};
|
|
719
|
-
|
|
720
|
-
const [output] = formatCompletedResponse(response);
|
|
721
|
-
|
|
722
|
-
expect(output).not.toContain('Generated files:');
|
|
723
|
-
expect(output).toContain('Available files (inputs');
|
|
724
|
-
expect(output).toContain('pptx/SKILL.md');
|
|
725
|
-
expect(output).toContain('pptx/editing.md');
|
|
726
|
-
});
|
|
727
667
|
});
|
|
728
668
|
|
|
729
669
|
describe('createProgrammaticToolCallingTool - Manual Invocation', () => {
|
|
@@ -546,6 +546,163 @@ describe('SubagentExecutor', () => {
|
|
|
546
546
|
expect(observedChildInputs!.maxSubagentDepth).toBeUndefined();
|
|
547
547
|
});
|
|
548
548
|
|
|
549
|
+
describe('parentConfigurable inheritance', () => {
|
|
550
|
+
/**
|
|
551
|
+
* Build a stub factory that captures the second argument to
|
|
552
|
+
* `workflow.invoke()` (the runnable config) so tests can assert on
|
|
553
|
+
* the `configurable` we forwarded to the child graph.
|
|
554
|
+
*/
|
|
555
|
+
function makeCapturingGraphFactory(): {
|
|
556
|
+
factory: () => StandardGraph;
|
|
557
|
+
getInvokeConfig: () => Record<string, unknown> | undefined;
|
|
558
|
+
} {
|
|
559
|
+
let capturedConfig: Record<string, unknown> | undefined;
|
|
560
|
+
const factory = (): StandardGraph =>
|
|
561
|
+
({
|
|
562
|
+
createWorkflow: (): { invoke: jest.Mock } => ({
|
|
563
|
+
invoke: jest
|
|
564
|
+
.fn()
|
|
565
|
+
.mockImplementation(
|
|
566
|
+
async (
|
|
567
|
+
_input: unknown,
|
|
568
|
+
config: Record<string, unknown>
|
|
569
|
+
): Promise<{ messages: BaseMessage[] }> => {
|
|
570
|
+
capturedConfig = config;
|
|
571
|
+
return { messages: [new AIMessage('done')] };
|
|
572
|
+
}
|
|
573
|
+
),
|
|
574
|
+
}),
|
|
575
|
+
clearHeavyState: jest.fn(),
|
|
576
|
+
}) as unknown as StandardGraph;
|
|
577
|
+
return { factory, getInvokeConfig: () => capturedConfig };
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
it('forwards parentConfigurable into the child workflow.invoke configurable', async () => {
|
|
581
|
+
const { factory, getInvokeConfig } = makeCapturingGraphFactory();
|
|
582
|
+
const executor = createExecutor({ createChildGraph: factory });
|
|
583
|
+
|
|
584
|
+
await executor.execute({
|
|
585
|
+
description: 'task',
|
|
586
|
+
subagentType: 'researcher',
|
|
587
|
+
parentConfigurable: {
|
|
588
|
+
requestBody: { messageId: 'msg-123', conversationId: 'conv-456' },
|
|
589
|
+
user: { id: 'user_abc' },
|
|
590
|
+
user_id: 'user_abc',
|
|
591
|
+
userMCPAuthMap: { 'mcp-github': { token: 'abc' } },
|
|
592
|
+
},
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
const invokeConfig = getInvokeConfig();
|
|
596
|
+
expect(invokeConfig).toBeDefined();
|
|
597
|
+
const configurable = invokeConfig!.configurable as Record<
|
|
598
|
+
string,
|
|
599
|
+
unknown
|
|
600
|
+
>;
|
|
601
|
+
expect(configurable.requestBody).toEqual({
|
|
602
|
+
messageId: 'msg-123',
|
|
603
|
+
conversationId: 'conv-456',
|
|
604
|
+
});
|
|
605
|
+
expect(configurable.user).toEqual({ id: 'user_abc' });
|
|
606
|
+
expect(configurable.user_id).toBe('user_abc');
|
|
607
|
+
expect(configurable.userMCPAuthMap).toEqual({
|
|
608
|
+
'mcp-github': { token: 'abc' },
|
|
609
|
+
});
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
it('inherits parent thread_id when supplied (subagent is part of same conversation)', async () => {
|
|
613
|
+
const { factory, getInvokeConfig } = makeCapturingGraphFactory();
|
|
614
|
+
const executor = createExecutor({
|
|
615
|
+
createChildGraph: factory,
|
|
616
|
+
parentRunId: 'parent-run-xyz',
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
await executor.execute({
|
|
620
|
+
description: 'task',
|
|
621
|
+
subagentType: 'researcher',
|
|
622
|
+
parentConfigurable: { thread_id: 'parent-thread-conv-abc' },
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
const configurable = getInvokeConfig()!.configurable as Record<
|
|
626
|
+
string,
|
|
627
|
+
unknown
|
|
628
|
+
>;
|
|
629
|
+
expect(configurable.thread_id).toBe('parent-thread-conv-abc');
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
it('falls back to childRunId for thread_id when parent did not supply one', async () => {
|
|
633
|
+
const { factory, getInvokeConfig } = makeCapturingGraphFactory();
|
|
634
|
+
const executor = createExecutor({
|
|
635
|
+
createChildGraph: factory,
|
|
636
|
+
parentRunId: 'parent-run-xyz',
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
await executor.execute({
|
|
640
|
+
description: 'task',
|
|
641
|
+
subagentType: 'researcher',
|
|
642
|
+
parentConfigurable: { user_id: 'user_abc' },
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
const configurable = getInvokeConfig()!.configurable as Record<
|
|
646
|
+
string,
|
|
647
|
+
unknown
|
|
648
|
+
>;
|
|
649
|
+
expect(configurable.thread_id as string).toMatch(/^parent-run-xyz_sub_/);
|
|
650
|
+
expect(configurable.user_id).toBe('user_abc');
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
it('forwards run-identity fields verbatim into the child invoke configurable', async () => {
|
|
654
|
+
const { factory, getInvokeConfig } = makeCapturingGraphFactory();
|
|
655
|
+
const executor = createExecutor({ createChildGraph: factory });
|
|
656
|
+
|
|
657
|
+
await executor.execute({
|
|
658
|
+
description: 'task',
|
|
659
|
+
subagentType: 'researcher',
|
|
660
|
+
parentConfigurable: {
|
|
661
|
+
run_id: 'parent-run-id',
|
|
662
|
+
parent_run_id: 'grandparent-run-id',
|
|
663
|
+
requestBody: { messageId: 'msg-1' },
|
|
664
|
+
},
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
const configurable = getInvokeConfig()!.configurable as Record<
|
|
668
|
+
string,
|
|
669
|
+
unknown
|
|
670
|
+
>;
|
|
671
|
+
// The SDK forwards these fields as part of its inheritance contract.
|
|
672
|
+
// NOTE: the LangGraph runtime overwrites `configurable.run_id` at
|
|
673
|
+
// actual child-invoke time (verified empirically); this unit test
|
|
674
|
+
// only asserts what the SDK forwards into `workflow.invoke` — not
|
|
675
|
+
// what tools downstream observe. `parent_run_id` and other
|
|
676
|
+
// host-set keys do survive the runtime pass-through.
|
|
677
|
+
expect(configurable.run_id).toBe('parent-run-id');
|
|
678
|
+
expect(configurable.parent_run_id).toBe('grandparent-run-id');
|
|
679
|
+
expect(configurable.requestBody).toEqual({ messageId: 'msg-1' });
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
it('does not require parentConfigurable (back-compat with hosts that omit it)', async () => {
|
|
683
|
+
const { factory, getInvokeConfig } = makeCapturingGraphFactory();
|
|
684
|
+
const executor = createExecutor({ createChildGraph: factory });
|
|
685
|
+
|
|
686
|
+
await executor.execute({
|
|
687
|
+
description: 'task',
|
|
688
|
+
subagentType: 'researcher',
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
const configurable = getInvokeConfig()!.configurable as Record<
|
|
692
|
+
string,
|
|
693
|
+
unknown
|
|
694
|
+
>;
|
|
695
|
+
// Only thread_id (childRunId fallback) and the host-attached
|
|
696
|
+
// parentToolCallId (used by ranger for attachment routing) are set
|
|
697
|
+
// when no parent context is supplied. parentToolCallId is undefined
|
|
698
|
+
// here because no tool_call_id was passed in the metadata.
|
|
699
|
+
expect(Object.keys(configurable).sort()).toEqual(
|
|
700
|
+
['parentToolCallId', 'thread_id'].sort()
|
|
701
|
+
);
|
|
702
|
+
expect(configurable.parentToolCallId).toBeUndefined();
|
|
703
|
+
});
|
|
704
|
+
});
|
|
705
|
+
|
|
549
706
|
describe('hooks', () => {
|
|
550
707
|
let capturedStart: unknown;
|
|
551
708
|
let capturedStop: unknown;
|
|
@@ -2,7 +2,6 @@ import axios from 'axios';
|
|
|
2
2
|
import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';
|
|
3
3
|
import type * as t from './types';
|
|
4
4
|
import { getAttribution, createDefaultLogger } from './utils';
|
|
5
|
-
import { createTavilyAPI } from './tavily-search';
|
|
6
5
|
import { BaseReranker } from './rerankers';
|
|
7
6
|
|
|
8
7
|
const chunker = {
|
|
@@ -439,9 +438,6 @@ export const createSearchAPI = (
|
|
|
439
438
|
serperApiKey,
|
|
440
439
|
searxngInstanceUrl,
|
|
441
440
|
searxngApiKey,
|
|
442
|
-
tavilyApiKey,
|
|
443
|
-
tavilySearchUrl,
|
|
444
|
-
tavilySearchOptions,
|
|
445
441
|
domainBlocklist,
|
|
446
442
|
countryBlocklist,
|
|
447
443
|
} = config;
|
|
@@ -450,11 +446,9 @@ export const createSearchAPI = (
|
|
|
450
446
|
return createSerperAPI(serperApiKey, domainBlocklist, countryBlocklist);
|
|
451
447
|
} else if (searchProvider.toLowerCase() === 'searxng') {
|
|
452
448
|
return createSearXNGAPI(searxngInstanceUrl, searxngApiKey);
|
|
453
|
-
} else if (searchProvider.toLowerCase() === 'tavily') {
|
|
454
|
-
return createTavilyAPI(tavilyApiKey, tavilySearchUrl, tavilySearchOptions);
|
|
455
449
|
} else {
|
|
456
450
|
throw new Error(
|
|
457
|
-
`Invalid search provider: ${searchProvider}. Must be 'serper'
|
|
451
|
+
`Invalid search provider: ${searchProvider}. Must be 'serper' or 'searxng'`
|
|
458
452
|
);
|
|
459
453
|
}
|
|
460
454
|
};
|
|
@@ -500,13 +494,9 @@ export const createSourceProcessor = (
|
|
|
500
494
|
const promise: Promise<t.ScrapeResult> = scraper
|
|
501
495
|
.scrapeUrl(currentLink, {})
|
|
502
496
|
.then(([url, response]) => {
|
|
503
|
-
/* metadata exists on Firecrawl/Serper responses but not on
|
|
504
|
-
* Tavily's. Read it via the scraper's extractMetadata abstraction
|
|
505
|
-
* to stay polymorphic across all scraper providers. */
|
|
506
|
-
const rawMeta = scraper.extractMetadata(response);
|
|
507
497
|
const attribution = getAttribution(
|
|
508
498
|
url,
|
|
509
|
-
|
|
499
|
+
response.data?.metadata,
|
|
510
500
|
logger_
|
|
511
501
|
);
|
|
512
502
|
if (response.success && response.data) {
|