@librechat/agents 3.2.2 → 3.2.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/agents/AgentContext.cjs +3 -2
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +200 -54
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +13 -7
- package/dist/cjs/hooks/createWorkspacePolicyHook.cjs.map +1 -1
- package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
- package/dist/cjs/hooks/types.cjs.map +1 -1
- package/dist/cjs/instrumentation.cjs +33 -0
- package/dist/cjs/instrumentation.cjs.map +1 -1
- package/dist/cjs/langfuse.cjs +17 -1
- package/dist/cjs/langfuse.cjs.map +1 -1
- package/dist/cjs/langfuseToolOutputTracing.cjs +2 -2
- package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/index.cjs +1 -1
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +2 -2
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/toolCache.cjs +8 -5
- package/dist/cjs/llm/bedrock/toolCache.cjs.map +1 -1
- package/dist/cjs/llm/fake.cjs +16 -14
- package/dist/cjs/llm/fake.cjs.map +1 -1
- package/dist/cjs/llm/google/index.cjs +22 -0
- package/dist/cjs/llm/google/index.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/common.cjs +88 -27
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
- package/dist/cjs/llm/init.cjs +2 -2
- package/dist/cjs/llm/invoke.cjs +108 -11
- package/dist/cjs/llm/invoke.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +1 -1
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +1 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +8 -7
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/content.cjs.map +1 -1
- package/dist/cjs/messages/contextPruning.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +124 -17
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/messages/reducer.cjs +1 -1
- package/dist/cjs/messages/reducer.cjs.map +1 -1
- package/dist/cjs/messages/tools.cjs +1 -1
- package/dist/cjs/messages/tools.cjs.map +1 -1
- package/dist/cjs/openai/index.cjs.map +1 -1
- package/dist/cjs/responses/index.cjs.map +1 -1
- package/dist/cjs/run.cjs +47 -21
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/AgentSession.cjs +4 -4
- package/dist/cjs/session/AgentSession.cjs.map +1 -1
- package/dist/cjs/session/JsonlSessionStore.cjs +2 -2
- package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -1
- package/dist/cjs/session/handlers.cjs +2 -2
- package/dist/cjs/session/handlers.cjs.map +1 -1
- package/dist/cjs/stream.cjs +248 -25
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +1 -1
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/Calculator.cjs +1 -1
- package/dist/cjs/tools/Calculator.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +37 -18
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/ToolSearch.cjs +1 -1
- package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
- package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs +7 -4
- package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs.map +1 -1
- package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs +4 -4
- package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +2 -1
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/local/CompileCheckTool.cjs.map +1 -1
- package/dist/cjs/tools/local/FileCheckpointer.cjs +2 -1
- package/dist/cjs/tools/local/FileCheckpointer.cjs.map +1 -1
- package/dist/cjs/tools/local/LocalCodingTools.cjs +45 -19
- package/dist/cjs/tools/local/LocalCodingTools.cjs.map +1 -1
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs +3 -3
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs.map +1 -1
- package/dist/cjs/tools/local/LocalExecutionTools.cjs +2 -2
- package/dist/cjs/tools/local/LocalExecutionTools.cjs.map +1 -1
- package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +4 -3
- package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/local/attachments.cjs +0 -5
- package/dist/cjs/tools/local/attachments.cjs.map +1 -1
- package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs +4 -4
- package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -1
- package/dist/cjs/tools/search/firecrawl.cjs +1 -1
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/rerankers.cjs +7 -3
- package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
- package/dist/cjs/tools/search/tavily-search.cjs +1 -1
- package/dist/cjs/tools/search/tavily-search.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +76 -8
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/utils/handlers.cjs +1 -1
- package/dist/cjs/utils/handlers.cjs.map +1 -1
- package/dist/cjs/utils/run.cjs +1 -1
- package/dist/cjs/utils/run.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +3 -2
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +200 -54
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/hooks/createWorkspacePolicyHook.mjs +13 -7
- package/dist/esm/hooks/createWorkspacePolicyHook.mjs.map +1 -1
- package/dist/esm/hooks/executeHooks.mjs.map +1 -1
- package/dist/esm/hooks/types.mjs.map +1 -1
- package/dist/esm/instrumentation.mjs +33 -1
- package/dist/esm/instrumentation.mjs.map +1 -1
- package/dist/esm/langfuse.mjs +17 -2
- package/dist/esm/langfuse.mjs.map +1 -1
- package/dist/esm/langfuseToolOutputTracing.mjs +2 -2
- package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
- package/dist/esm/llm/anthropic/index.mjs +1 -1
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +2 -2
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/toolCache.mjs +8 -5
- package/dist/esm/llm/bedrock/toolCache.mjs.map +1 -1
- package/dist/esm/llm/fake.mjs +16 -14
- package/dist/esm/llm/fake.mjs.map +1 -1
- package/dist/esm/llm/google/index.mjs +23 -1
- package/dist/esm/llm/google/index.mjs.map +1 -1
- package/dist/esm/llm/google/utils/common.mjs +88 -27
- package/dist/esm/llm/google/utils/common.mjs.map +1 -1
- package/dist/esm/llm/init.mjs +2 -2
- package/dist/esm/llm/invoke.mjs +104 -7
- package/dist/esm/llm/invoke.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +1 -1
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +1 -1
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/llm/vertexai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -1
- package/dist/esm/messages/cache.mjs +8 -7
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/content.mjs.map +1 -1
- package/dist/esm/messages/contextPruning.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +124 -18
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/messages/reducer.mjs +1 -1
- package/dist/esm/messages/reducer.mjs.map +1 -1
- package/dist/esm/messages/tools.mjs +1 -1
- package/dist/esm/messages/tools.mjs.map +1 -1
- package/dist/esm/openai/index.mjs.map +1 -1
- package/dist/esm/responses/index.mjs.map +1 -1
- package/dist/esm/run.mjs +47 -21
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/AgentSession.mjs +4 -4
- package/dist/esm/session/AgentSession.mjs.map +1 -1
- package/dist/esm/session/JsonlSessionStore.mjs +2 -2
- package/dist/esm/session/JsonlSessionStore.mjs.map +1 -1
- package/dist/esm/session/handlers.mjs +2 -2
- package/dist/esm/session/handlers.mjs.map +1 -1
- package/dist/esm/stream.mjs +248 -25
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs +1 -1
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/Calculator.mjs +1 -1
- package/dist/esm/tools/Calculator.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +1 -1
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/SubagentTool.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +37 -18
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/ToolSearch.mjs +1 -1
- package/dist/esm/tools/ToolSearch.mjs.map +1 -1
- package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs +7 -4
- package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs.map +1 -1
- package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs +4 -4
- package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +2 -1
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/local/CompileCheckTool.mjs.map +1 -1
- package/dist/esm/tools/local/FileCheckpointer.mjs +2 -1
- package/dist/esm/tools/local/FileCheckpointer.mjs.map +1 -1
- package/dist/esm/tools/local/LocalCodingTools.mjs +45 -19
- package/dist/esm/tools/local/LocalCodingTools.mjs.map +1 -1
- package/dist/esm/tools/local/LocalExecutionEngine.mjs +3 -3
- package/dist/esm/tools/local/LocalExecutionEngine.mjs.map +1 -1
- package/dist/esm/tools/local/LocalExecutionTools.mjs +2 -2
- package/dist/esm/tools/local/LocalExecutionTools.mjs.map +1 -1
- package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +4 -3
- package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/local/attachments.mjs +0 -5
- package/dist/esm/tools/local/attachments.mjs.map +1 -1
- package/dist/esm/tools/local/resolveLocalExecutionTools.mjs +4 -4
- package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -1
- package/dist/esm/tools/search/firecrawl.mjs +1 -1
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/rerankers.mjs +8 -4
- package/dist/esm/tools/search/rerankers.mjs.map +1 -1
- package/dist/esm/tools/search/tavily-search.mjs +1 -1
- package/dist/esm/tools/search/tavily-search.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +76 -9
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/utils/handlers.mjs +1 -1
- package/dist/esm/utils/handlers.mjs.map +1 -1
- package/dist/esm/utils/run.mjs +1 -1
- package/dist/esm/utils/run.mjs.map +1 -1
- package/dist/types/agents/__tests__/promptCacheLiveHelpers.d.ts +1 -1
- package/dist/types/events.d.ts +1 -1
- package/dist/types/graphs/Graph.d.ts +7 -1
- package/dist/types/hooks/executeHooks.d.ts +1 -1
- package/dist/types/hooks/types.d.ts +5 -0
- package/dist/types/instrumentation.d.ts +1 -0
- package/dist/types/langfuse.d.ts +4 -0
- package/dist/types/llm/anthropic/utils/message_inputs.d.ts +1 -1
- package/dist/types/llm/anthropic/utils/message_outputs.d.ts +1 -1
- package/dist/types/llm/anthropic/utils/output_parsers.d.ts +2 -2
- package/dist/types/llm/bedrock/index.d.ts +2 -2
- package/dist/types/llm/fake.d.ts +3 -3
- package/dist/types/llm/google/index.d.ts +1 -0
- package/dist/types/llm/google/types.d.ts +1 -1
- package/dist/types/llm/google/utils/common.d.ts +2 -2
- package/dist/types/llm/google/utils/tools.d.ts +1 -1
- package/dist/types/llm/google/utils/zod_to_genai_parameters.d.ts +1 -1
- package/dist/types/llm/openai/index.d.ts +2 -2
- package/dist/types/llm/openai/utils/index.d.ts +1 -1
- package/dist/types/llm/openrouter/index.d.ts +4 -4
- package/dist/types/messages/contextPruning.d.ts +1 -1
- package/dist/types/messages/format.d.ts +9 -4
- package/dist/types/messages/prune.d.ts +1 -1
- package/dist/types/session/JsonlSessionStore.d.ts +1 -1
- package/dist/types/session/handlers.d.ts +1 -1
- package/dist/types/session/types.d.ts +1 -1
- package/dist/types/summarization/node.d.ts +1 -1
- package/dist/types/tools/SubagentTool.d.ts +2 -2
- package/dist/types/tools/ToolNode.d.ts +9 -2
- package/dist/types/tools/cloudflare/CloudflareSandboxExecutionEngine.d.ts +1 -1
- package/dist/types/tools/search/types.d.ts +1 -1
- package/dist/types/tools/search/utils.d.ts +11 -0
- package/dist/types/types/graph.d.ts +12 -4
- package/dist/types/types/llm.d.ts +4 -3
- package/dist/types/types/messages.d.ts +1 -1
- package/dist/types/types/run.d.ts +6 -6
- package/dist/types/types/stream.d.ts +2 -2
- package/dist/types/types/tools.d.ts +5 -1
- package/dist/types/utils/handlers.d.ts +2 -2
- package/dist/types/utils/run.d.ts +1 -1
- package/package.json +6 -3
- package/src/__tests__/stream.eagerEventExecution.test.ts +543 -6
- package/src/agents/AgentContext.ts +2 -2
- package/src/agents/__tests__/AgentContext.test.ts +3 -3
- package/src/agents/__tests__/promptCacheLiveHelpers.ts +1 -1
- package/src/events.ts +1 -1
- package/src/graphs/Graph.ts +329 -72
- package/src/graphs/MultiAgentGraph.ts +1 -1
- package/src/graphs/__tests__/Graph.reasoning.test.ts +919 -6
- package/src/graphs/__tests__/MultiAgentGraph.test.ts +1 -1
- package/src/graphs/__tests__/composition.smoke.test.ts +1 -1
- package/src/hooks/__tests__/HookRegistry.test.ts +1 -1
- package/src/hooks/__tests__/compactHooks.test.ts +8 -8
- package/src/hooks/__tests__/createWorkspacePolicyHook.test.ts +34 -22
- package/src/hooks/__tests__/executeHooks.test.ts +3 -3
- package/src/hooks/__tests__/integration.test.ts +3 -3
- package/src/hooks/__tests__/toolHooks.test.ts +10 -10
- package/src/hooks/createWorkspacePolicyHook.ts +17 -14
- package/src/hooks/executeHooks.ts +1 -1
- package/src/hooks/types.ts +5 -0
- package/src/instrumentation.ts +49 -8
- package/src/langfuse.ts +35 -1
- package/src/langfuseToolOutputTracing.ts +2 -2
- package/src/llm/anthropic/index.ts +1 -1
- package/src/llm/anthropic/utils/message_inputs.ts +1 -1
- package/src/llm/anthropic/utils/message_outputs.ts +3 -5
- package/src/llm/anthropic/utils/output_parsers.ts +5 -5
- package/src/llm/bedrock/index.ts +4 -4
- package/src/llm/bedrock/toolCache.test.ts +48 -9
- package/src/llm/bedrock/toolCache.ts +11 -6
- package/src/llm/custom-chat-models.smoke.test.ts +114 -0
- package/src/llm/fake.ts +30 -25
- package/src/llm/google/index.ts +43 -1
- package/src/llm/google/llm.spec.ts +173 -1
- package/src/llm/google/types.ts +1 -1
- package/src/llm/google/utils/common.ts +154 -45
- package/src/llm/google/utils/tools.ts +8 -8
- package/src/llm/google/utils/zod_to_genai_parameters.ts +4 -4
- package/src/llm/invoke.test.ts +3 -3
- package/src/llm/invoke.ts +170 -10
- package/src/llm/openai/index.ts +4 -4
- package/src/llm/openai/utils/index.ts +14 -14
- package/src/llm/openrouter/index.ts +4 -4
- package/src/llm/openrouter/reasoning.test.ts +2 -2
- package/src/llm/vertexai/fixThoughtSignatures.test.ts +1 -1
- package/src/llm/vertexai/index.ts +1 -1
- package/src/messages/cache.test.ts +22 -0
- package/src/messages/cache.ts +25 -12
- package/src/messages/content.ts +1 -1
- package/src/messages/contextPruning.ts +1 -1
- package/src/messages/format.ts +227 -43
- package/src/messages/formatAgentMessages.skills.test.ts +105 -26
- package/src/messages/formatAgentMessages.test.ts +841 -10
- package/src/messages/labelContentByAgent.test.ts +2 -2
- package/src/messages/prune.ts +1 -1
- package/src/messages/reducer.ts +1 -1
- package/src/messages/tools.ts +1 -1
- package/src/openai/__tests__/openai.test.ts +2 -2
- package/src/openai/index.ts +1 -1
- package/src/responses/__tests__/responses.test.ts +2 -2
- package/src/responses/index.ts +1 -1
- package/src/run.ts +82 -47
- package/src/session/AgentSession.ts +6 -6
- package/src/session/JsonlSessionStore.ts +3 -3
- package/src/session/__tests__/JsonlSessionStore.test.ts +5 -5
- package/src/session/__tests__/handlers.test.ts +2 -2
- package/src/session/handlers.ts +5 -5
- package/src/session/types.ts +1 -1
- package/src/specs/agent-handoffs.test.ts +1 -1
- package/src/specs/deterministic-trace-id.test.ts +50 -0
- package/src/specs/langfuse-callbacks.test.ts +2 -2
- package/src/specs/langfuse-metadata.test.ts +39 -0
- package/src/specs/langfuse-tool-output-tracing.test.ts +1 -1
- package/src/specs/multi-agent-summarization.test.ts +4 -4
- package/src/specs/subagent.test.ts +3 -3
- package/src/specs/summarization-unit.test.ts +1 -1
- package/src/specs/thinking-handoff.test.ts +1 -1
- package/src/splitStream.test.ts +48 -0
- package/src/stream.test.ts +53 -3
- package/src/stream.ts +450 -39
- package/src/summarization/__tests__/aggregator.test.ts +2 -2
- package/src/summarization/__tests__/node.test.ts +2 -2
- package/src/summarization/node.ts +1 -1
- package/src/tools/BashProgrammaticToolCalling.ts +5 -5
- package/src/tools/Calculator.ts +1 -1
- package/src/tools/CodeExecutor.ts +2 -4
- package/src/tools/SubagentTool.ts +2 -2
- package/src/tools/ToolNode.ts +37 -16
- package/src/tools/ToolSearch.ts +1 -1
- package/src/tools/__tests__/CloudflareSandboxExecution.test.ts +4 -4
- package/src/tools/__tests__/CodeApiAuthHeaders.test.ts +12 -12
- package/src/tools/__tests__/LocalExecutionTools.test.ts +125 -93
- package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +29 -5
- package/src/tools/__tests__/ReadFile.test.ts +1 -1
- package/src/tools/__tests__/SkillTool.test.ts +4 -4
- package/src/tools/__tests__/SubagentExecutor.test.ts +17 -13
- package/src/tools/__tests__/SubagentTool.test.ts +2 -2
- package/src/tools/__tests__/ToolNode.eagerEventExecution.test.ts +1 -1
- package/src/tools/__tests__/ToolNode.outputReferences.test.ts +2 -5
- package/src/tools/__tests__/ToolNode.session.test.ts +1 -1
- package/src/tools/__tests__/ToolSearch.test.ts +1 -1
- package/src/tools/__tests__/annotateMessagesForLLM.test.ts +1 -1
- package/src/tools/__tests__/directToolHITLResumeScope.test.ts +35 -32
- package/src/tools/__tests__/directToolHooks.test.ts +41 -0
- package/src/tools/__tests__/handlers.test.ts +2 -2
- package/src/tools/__tests__/hitl.test.ts +11 -11
- package/src/tools/__tests__/localToolNames.test.ts +8 -6
- package/src/tools/__tests__/skillCatalog.test.ts +1 -1
- package/src/tools/__tests__/subagentHooks.test.ts +20 -10
- package/src/tools/__tests__/workspaceSeam.test.ts +20 -7
- package/src/tools/cloudflare/CloudflareSandboxExecutionEngine.ts +9 -6
- package/src/tools/cloudflare/CloudflareSandboxTools.ts +19 -19
- package/src/tools/handlers.ts +5 -5
- package/src/tools/local/CompileCheckTool.ts +4 -7
- package/src/tools/local/FileCheckpointer.ts +6 -5
- package/src/tools/local/LocalCodingTools.ts +100 -45
- package/src/tools/local/LocalExecutionEngine.ts +5 -5
- package/src/tools/local/LocalExecutionTools.ts +9 -9
- package/src/tools/local/LocalProgrammaticToolCalling.ts +5 -4
- package/src/tools/local/attachments.ts +0 -6
- package/src/tools/local/resolveLocalExecutionTools.ts +15 -15
- package/src/tools/search/firecrawl.ts +1 -1
- package/src/tools/search/jina-reranker.test.ts +148 -37
- package/src/tools/search/rerankers.ts +14 -4
- package/src/tools/search/tavily-search.ts +2 -2
- package/src/tools/search/types.ts +1 -1
- package/src/tools/search/utils.ts +99 -9
- package/src/tools/subagent/SubagentExecutor.ts +12 -6
- package/src/types/graph.ts +20 -12
- package/src/types/llm.ts +7 -6
- package/src/types/messages.ts +1 -1
- package/src/types/run.ts +7 -7
- package/src/types/stream.ts +2 -2
- package/src/types/tools.ts +5 -1
- package/src/utils/handlers.ts +2 -2
- package/src/utils/llmConfig.ts +1 -1
- package/src/utils/logging.ts +20 -10
- package/src/utils/run.ts +2 -2
|
@@ -2,18 +2,18 @@ import { z } from 'zod';
|
|
|
2
2
|
import { tool } from '@langchain/core/tools';
|
|
3
3
|
import { describe, it, expect } from '@jest/globals';
|
|
4
4
|
import { AIMessage, HumanMessage } from '@langchain/core/messages';
|
|
5
|
-
import type { BaseMessage } from '@langchain/core/messages';
|
|
6
5
|
import type { StructuredToolInterface } from '@langchain/core/tools';
|
|
6
|
+
import type { BaseMessage } from '@langchain/core/messages';
|
|
7
7
|
import type * as t from '@/types';
|
|
8
|
-
import * as events from '@/utils/events';
|
|
9
|
-
import { ToolNode } from '../ToolNode';
|
|
10
|
-
import { Constants } from '@/common';
|
|
11
8
|
import {
|
|
12
9
|
SkillToolDescription,
|
|
13
10
|
SkillToolDefinition,
|
|
14
11
|
SkillToolSchema,
|
|
15
12
|
SkillToolName,
|
|
16
13
|
} from '../SkillTool';
|
|
14
|
+
import * as events from '@/utils/events';
|
|
15
|
+
import { ToolNode } from '../ToolNode';
|
|
16
|
+
import { Constants } from '@/common';
|
|
17
17
|
|
|
18
18
|
describe('SkillTool', () => {
|
|
19
19
|
describe('schema structure', () => {
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach } from '@jest/globals';
|
|
2
2
|
import { AIMessage, HumanMessage, ToolMessage } from '@langchain/core/messages';
|
|
3
3
|
import type { BaseMessage } from '@langchain/core/messages';
|
|
4
|
-
import { HookRegistry } from '@/hooks/HookRegistry';
|
|
5
|
-
import { Providers, GraphEvents, StepTypes } from '@/common';
|
|
6
|
-
import { HandlerRegistry } from '@/events';
|
|
7
|
-
import { AgentContext } from '@/agents/AgentContext';
|
|
8
4
|
import type {
|
|
9
5
|
AgentInputs,
|
|
10
6
|
ResolvedSubagentConfig,
|
|
@@ -12,6 +8,7 @@ import type {
|
|
|
12
8
|
ToolExecuteBatchRequest,
|
|
13
9
|
ToolExecuteResult,
|
|
14
10
|
} from '@/types';
|
|
11
|
+
import type { StandardGraph } from '@/graphs/Graph';
|
|
15
12
|
import {
|
|
16
13
|
SubagentExecutor,
|
|
17
14
|
filterSubagentResult,
|
|
@@ -20,7 +17,10 @@ import {
|
|
|
20
17
|
summarizeEvent,
|
|
21
18
|
} from '../subagent';
|
|
22
19
|
import { sanitizeForwardedSubagentUpdateData } from '../subagent/SubagentExecutor';
|
|
23
|
-
import
|
|
20
|
+
import { Providers, GraphEvents, StepTypes } from '@/common';
|
|
21
|
+
import { AgentContext } from '@/agents/AgentContext';
|
|
22
|
+
import { HookRegistry } from '@/hooks/HookRegistry';
|
|
23
|
+
import { HandlerRegistry } from '@/events';
|
|
24
24
|
|
|
25
25
|
jest.setTimeout(15000);
|
|
26
26
|
|
|
@@ -635,7 +635,10 @@ describe('SubagentExecutor', () => {
|
|
|
635
635
|
|
|
636
636
|
const invokeConfig = getInvokeConfig();
|
|
637
637
|
expect(invokeConfig).toBeDefined();
|
|
638
|
-
const configurable = invokeConfig!.configurable as Record<
|
|
638
|
+
const configurable = invokeConfig!.configurable as Record<
|
|
639
|
+
string,
|
|
640
|
+
unknown
|
|
641
|
+
>;
|
|
639
642
|
expect(configurable.requestBody).toEqual({
|
|
640
643
|
messageId: 'msg-123',
|
|
641
644
|
conversationId: 'conv-456',
|
|
@@ -1183,11 +1186,13 @@ describe('SubagentExecutor', () => {
|
|
|
1183
1186
|
handle: (_event, rawData): void => {
|
|
1184
1187
|
const request = rawData as ToolExecuteBatchRequest;
|
|
1185
1188
|
toolRequests.push(request);
|
|
1186
|
-
const results: ToolExecuteResult[] = request.toolCalls.map(
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1189
|
+
const results: ToolExecuteResult[] = request.toolCalls.map(
|
|
1190
|
+
(call) => ({
|
|
1191
|
+
toolCallId: call.id,
|
|
1192
|
+
status: 'success',
|
|
1193
|
+
content: `ran ${call.name}`,
|
|
1194
|
+
})
|
|
1195
|
+
);
|
|
1191
1196
|
request.resolve(results);
|
|
1192
1197
|
},
|
|
1193
1198
|
});
|
|
@@ -1268,8 +1273,7 @@ describe('SubagentExecutor', () => {
|
|
|
1268
1273
|
|
|
1269
1274
|
const toolUpdate = subagentUpdates.find(
|
|
1270
1275
|
(update) =>
|
|
1271
|
-
update.phase === 'run_step' &&
|
|
1272
|
-
update.label === 'Calling calculator'
|
|
1276
|
+
update.phase === 'run_step' && update.label === 'Calling calculator'
|
|
1273
1277
|
);
|
|
1274
1278
|
expect(toolUpdate?.data).toEqual({
|
|
1275
1279
|
agentId: 'researcher',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from '@jest/globals';
|
|
2
|
-
import {
|
|
2
|
+
import type { SubagentConfig } from '@/types';
|
|
3
3
|
import {
|
|
4
4
|
SubagentToolName,
|
|
5
5
|
SubagentToolDescription,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
createSubagentToolDefinition,
|
|
9
9
|
buildSubagentToolParams,
|
|
10
10
|
} from '../SubagentTool';
|
|
11
|
-
import
|
|
11
|
+
import { Constants } from '@/common';
|
|
12
12
|
|
|
13
13
|
describe('SubagentTool', () => {
|
|
14
14
|
describe('schema structure', () => {
|
|
@@ -5,9 +5,9 @@ import { describe, it, expect, jest, afterEach } from '@jest/globals';
|
|
|
5
5
|
import type { StructuredToolInterface } from '@langchain/core/tools';
|
|
6
6
|
import type { PreToolUseHookInput, PreToolUseHookOutput } from '@/hooks';
|
|
7
7
|
import type * as t from '@/types';
|
|
8
|
+
import * as events from '@/utils/events';
|
|
8
9
|
import { GraphEvents } from '@/common';
|
|
9
10
|
import { HookRegistry } from '@/hooks';
|
|
10
|
-
import * as events from '@/utils/events';
|
|
11
11
|
import { ToolNode } from '../ToolNode';
|
|
12
12
|
|
|
13
13
|
function createDummyTool(name: string): StructuredToolInterface {
|
|
@@ -3,15 +3,12 @@ import { tool } from '@langchain/core/tools';
|
|
|
3
3
|
import { AIMessage, ToolMessage } from '@langchain/core/messages';
|
|
4
4
|
import { describe, it, expect, jest, afterEach } from '@jest/globals';
|
|
5
5
|
import type { StructuredToolInterface } from '@langchain/core/tools';
|
|
6
|
+
import type { PostToolUseHookOutput, PreToolUseHookOutput } from '@/hooks';
|
|
6
7
|
import type * as t from '@/types';
|
|
8
|
+
import { ToolOutputReferenceRegistry } from '../toolOutputReferences';
|
|
7
9
|
import * as events from '@/utils/events';
|
|
8
|
-
import type {
|
|
9
|
-
PostToolUseHookOutput,
|
|
10
|
-
PreToolUseHookOutput,
|
|
11
|
-
} from '@/hooks';
|
|
12
10
|
import { HookRegistry } from '@/hooks';
|
|
13
11
|
import { ToolNode } from '../ToolNode';
|
|
14
|
-
import { ToolOutputReferenceRegistry } from '../toolOutputReferences';
|
|
15
12
|
|
|
16
13
|
/**
|
|
17
14
|
* Reads the lazy ref-metadata stamped onto a `ToolMessage` by ToolNode.
|
|
@@ -4,9 +4,9 @@ import { AIMessage } from '@langchain/core/messages';
|
|
|
4
4
|
import { describe, it, expect, jest, afterEach } from '@jest/globals';
|
|
5
5
|
import type { StructuredToolInterface } from '@langchain/core/tools';
|
|
6
6
|
import type * as t from '@/types';
|
|
7
|
+
import * as events from '@/utils/events';
|
|
7
8
|
import { ToolNode } from '../ToolNode';
|
|
8
9
|
import { Constants } from '@/common';
|
|
9
|
-
import * as events from '@/utils/events';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Creates a mock execute_code tool that captures the toolCall config it receives.
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Tests helper functions and sanitization logic without hitting the API.
|
|
5
5
|
*/
|
|
6
6
|
import { describe, it, expect } from '@jest/globals';
|
|
7
|
+
import type { ToolMetadata, LCToolRegistry } from '@/types';
|
|
7
8
|
import {
|
|
8
9
|
sanitizeRegex,
|
|
9
10
|
escapeRegexSpecialChars,
|
|
@@ -20,7 +21,6 @@ import {
|
|
|
20
21
|
getBaseToolName,
|
|
21
22
|
formatServerListing,
|
|
22
23
|
} from '../ToolSearch';
|
|
23
|
-
import type { ToolMetadata, LCToolRegistry } from '@/types';
|
|
24
24
|
|
|
25
25
|
describe('ToolSearch', () => {
|
|
26
26
|
describe('escapeRegexSpecialChars', () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AIMessage, HumanMessage, ToolMessage } from '@langchain/core/messages';
|
|
2
1
|
import { describe, it, expect } from '@jest/globals';
|
|
2
|
+
import { AIMessage, HumanMessage, ToolMessage } from '@langchain/core/messages';
|
|
3
3
|
import {
|
|
4
4
|
annotateMessagesForLLM,
|
|
5
5
|
ToolOutputReferenceRegistry,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { tool } from '@langchain/core/tools';
|
|
3
|
+
import { AIMessage, ToolMessage } from '@langchain/core/messages';
|
|
4
|
+
import { describe, it, expect, jest, afterEach } from '@jest/globals';
|
|
3
5
|
import {
|
|
4
6
|
END,
|
|
5
7
|
START,
|
|
@@ -9,11 +11,9 @@ import {
|
|
|
9
11
|
MessagesAnnotation,
|
|
10
12
|
Command,
|
|
11
13
|
} from '@langchain/langgraph';
|
|
12
|
-
import {
|
|
13
|
-
import { describe, it, expect, jest, afterEach } from '@jest/globals';
|
|
14
|
+
import type { Runnable, RunnableConfig } from '@langchain/core/runnables';
|
|
14
15
|
import type { StructuredToolInterface } from '@langchain/core/tools';
|
|
15
16
|
import type { BaseMessage } from '@langchain/core/messages';
|
|
16
|
-
import type { Runnable, RunnableConfig } from '@langchain/core/runnables';
|
|
17
17
|
import type { PreToolUseHookOutput } from '@/hooks';
|
|
18
18
|
import type * as t from '@/types';
|
|
19
19
|
import { HookRegistry } from '@/hooks';
|
|
@@ -60,7 +60,11 @@ function buildGraph(
|
|
|
60
60
|
.addNode('agent', (): MessagesUpdate => {
|
|
61
61
|
agentInvocations += 1;
|
|
62
62
|
if (agentInvocations === 1) {
|
|
63
|
-
return {
|
|
63
|
+
return {
|
|
64
|
+
messages: [
|
|
65
|
+
aiCall(toolCalls[0].id, toolCalls[0].name, toolCalls[0].args),
|
|
66
|
+
],
|
|
67
|
+
};
|
|
64
68
|
}
|
|
65
69
|
return { messages: [] };
|
|
66
70
|
})
|
|
@@ -80,14 +84,11 @@ describe('direct-path HITL: resume scope', () => {
|
|
|
80
84
|
|
|
81
85
|
it('re-executes the direct tool body on resume when interrupt() fires from the direct path', async () => {
|
|
82
86
|
const sideEffect = jest.fn(() => 'EXECUTED');
|
|
83
|
-
const directTool = tool(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
schema: z.object({ command: z.string().optional() }).passthrough(),
|
|
89
|
-
}
|
|
90
|
-
) as unknown as StructuredToolInterface;
|
|
87
|
+
const directTool = tool(async () => sideEffect(), {
|
|
88
|
+
name: 'echo',
|
|
89
|
+
description: 'direct tool that records every body invocation',
|
|
90
|
+
schema: z.object({ command: z.string().optional() }).passthrough(),
|
|
91
|
+
}) as unknown as StructuredToolInterface;
|
|
91
92
|
|
|
92
93
|
const registry = new HookRegistry();
|
|
93
94
|
let hookInvocations = 0;
|
|
@@ -149,7 +150,9 @@ describe('direct-path HITL: resume scope', () => {
|
|
|
149
150
|
|
|
150
151
|
// Result should carry the executed output.
|
|
151
152
|
const messages = (second as { messages: ToolMessage[] }).messages;
|
|
152
|
-
const toolMsg = messages.find(
|
|
153
|
+
const toolMsg = messages.find(
|
|
154
|
+
(m) => m instanceof ToolMessage
|
|
155
|
+
) as ToolMessage;
|
|
153
156
|
expect(String(toolMsg.content)).toBe('EXECUTED');
|
|
154
157
|
});
|
|
155
158
|
|
|
@@ -199,17 +202,20 @@ describe('direct-path HITL: resume scope', () => {
|
|
|
199
202
|
});
|
|
200
203
|
|
|
201
204
|
const builder = new StateGraph(MessagesAnnotation)
|
|
202
|
-
.addNode(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
205
|
+
.addNode(
|
|
206
|
+
'agent',
|
|
207
|
+
(): MessagesUpdate => ({
|
|
208
|
+
messages: [
|
|
209
|
+
new AIMessage({
|
|
210
|
+
content: '',
|
|
211
|
+
tool_calls: [
|
|
212
|
+
{ id: 'a1', name: 'tool_a', args: {} },
|
|
213
|
+
{ id: 'b1', name: 'tool_b', args: {} },
|
|
214
|
+
],
|
|
215
|
+
}),
|
|
216
|
+
],
|
|
217
|
+
})
|
|
218
|
+
)
|
|
213
219
|
.addNode('tools', node)
|
|
214
220
|
.addEdge(START, 'agent')
|
|
215
221
|
.addEdge('agent', 'tools')
|
|
@@ -311,14 +317,11 @@ describe('direct-path HITL: resume scope', () => {
|
|
|
311
317
|
});
|
|
312
318
|
|
|
313
319
|
it('fails closed when updatedInput is missing or wrong-shaped', async () => {
|
|
314
|
-
const directTool = tool(
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
schema: z.object({ command: z.string().optional() }).passthrough(),
|
|
320
|
-
}
|
|
321
|
-
) as unknown as StructuredToolInterface;
|
|
320
|
+
const directTool = tool(async () => 'should-not-execute', {
|
|
321
|
+
name: 'echo',
|
|
322
|
+
description: 'must not execute on malformed edit',
|
|
323
|
+
schema: z.object({ command: z.string().optional() }).passthrough(),
|
|
324
|
+
}) as unknown as StructuredToolInterface;
|
|
322
325
|
|
|
323
326
|
const registry = new HookRegistry();
|
|
324
327
|
registry.register('PreToolUse', {
|
|
@@ -147,6 +147,47 @@ describe('Direct-path lifecycle hooks (in-process tools)', () => {
|
|
|
147
147
|
expect(String(message.content)).toBe('ran:ls');
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
+
it('executingAgentId defaults to agentId for direct callers, and an explicit value wins', async () => {
|
|
151
|
+
const echo = createDirectTool('echo', (args) => `ran:${args.command}`);
|
|
152
|
+
const captured: Array<string | undefined> = [];
|
|
153
|
+
const registry = new HookRegistry();
|
|
154
|
+
registry.register('PreToolUse', {
|
|
155
|
+
hooks: [
|
|
156
|
+
async (input): Promise<PreToolUseHookOutput> => {
|
|
157
|
+
captured.push(input.executingAgentId);
|
|
158
|
+
return { decision: 'allow' };
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Only the existing `agentId` option is passed → executingAgentId defaults to it.
|
|
164
|
+
const defaulted = new ToolNode({
|
|
165
|
+
tools: [echo],
|
|
166
|
+
eventDrivenMode: true,
|
|
167
|
+
hookRegistry: registry,
|
|
168
|
+
directToolNames: new Set(['echo']),
|
|
169
|
+
agentId: 'solo-agent',
|
|
170
|
+
});
|
|
171
|
+
await defaulted.invoke({
|
|
172
|
+
messages: [aiCall('call_def', 'echo', { command: 'a' })],
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// An explicit executingAgentId overrides the agentId default.
|
|
176
|
+
const explicit = new ToolNode({
|
|
177
|
+
tools: [echo],
|
|
178
|
+
eventDrivenMode: true,
|
|
179
|
+
hookRegistry: registry,
|
|
180
|
+
directToolNames: new Set(['echo']),
|
|
181
|
+
agentId: 'solo-agent',
|
|
182
|
+
executingAgentId: 'owner-agent',
|
|
183
|
+
});
|
|
184
|
+
await explicit.invoke({
|
|
185
|
+
messages: [aiCall('call_exp', 'echo', { command: 'b' })],
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
expect(captured).toEqual(['solo-agent', 'owner-agent']);
|
|
189
|
+
});
|
|
190
|
+
|
|
150
191
|
it('PreToolUse updatedInput rewrites the args before runTool sees them', async () => {
|
|
151
192
|
const seen: Record<string, unknown>[] = [];
|
|
152
193
|
const echo = createDirectTool('echo', (args) => {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
|
|
2
2
|
import type { ToolCall, ToolCallChunk } from '@langchain/core/messages/tool';
|
|
3
|
-
import type { StandardGraph } from '@/graphs';
|
|
4
3
|
import type { AgentContext } from '@/agents/AgentContext';
|
|
4
|
+
import type { StandardGraph } from '@/graphs';
|
|
5
5
|
import type * as t from '@/types';
|
|
6
|
-
import { StepTypes, ToolCallTypes, Providers, GraphEvents } from '@/common';
|
|
7
6
|
import {
|
|
8
7
|
handleToolCallChunks,
|
|
9
8
|
handleToolCalls,
|
|
10
9
|
handleServerToolResult,
|
|
11
10
|
} from '../handlers';
|
|
11
|
+
import { StepTypes, ToolCallTypes, Providers, GraphEvents } from '@/common';
|
|
12
12
|
|
|
13
13
|
type MockGraph = {
|
|
14
14
|
getStepKey: jest.Mock;
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { tool } from '@langchain/core/tools';
|
|
3
|
-
import {
|
|
4
|
-
END,
|
|
5
|
-
START,
|
|
6
|
-
Command,
|
|
7
|
-
StateGraph,
|
|
8
|
-
MemorySaver,
|
|
9
|
-
isInterrupted,
|
|
10
|
-
MessagesAnnotation,
|
|
11
|
-
} from '@langchain/langgraph';
|
|
12
3
|
import { AIMessage, ToolMessage } from '@langchain/core/messages';
|
|
13
4
|
import {
|
|
14
5
|
describe,
|
|
@@ -18,9 +9,18 @@ import {
|
|
|
18
9
|
afterEach,
|
|
19
10
|
beforeEach,
|
|
20
11
|
} from '@jest/globals';
|
|
12
|
+
import {
|
|
13
|
+
END,
|
|
14
|
+
START,
|
|
15
|
+
Command,
|
|
16
|
+
StateGraph,
|
|
17
|
+
MemorySaver,
|
|
18
|
+
isInterrupted,
|
|
19
|
+
MessagesAnnotation,
|
|
20
|
+
} from '@langchain/langgraph';
|
|
21
|
+
import type { Runnable, RunnableConfig } from '@langchain/core/runnables';
|
|
21
22
|
import type { StructuredToolInterface } from '@langchain/core/tools';
|
|
22
23
|
import type { BaseMessage } from '@langchain/core/messages';
|
|
23
|
-
import type { Runnable, RunnableConfig } from '@langchain/core/runnables';
|
|
24
24
|
import type {
|
|
25
25
|
PreToolUseHookOutput,
|
|
26
26
|
PostToolUseHookOutput,
|
|
@@ -32,9 +32,9 @@ import type {
|
|
|
32
32
|
UserPromptSubmitHookOutput,
|
|
33
33
|
} from '@/hooks';
|
|
34
34
|
import type * as t from '@/types';
|
|
35
|
+
import { Providers as providers, GraphEvents } from '@/common';
|
|
35
36
|
import * as events from '@/utils/events';
|
|
36
37
|
import { HookRegistry } from '@/hooks';
|
|
37
|
-
import { Providers as providers, GraphEvents } from '@/common';
|
|
38
38
|
import { ToolNode } from '../ToolNode';
|
|
39
39
|
|
|
40
40
|
async function flushAsyncWork(): Promise<void> {
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { describe, it, expect } from '@jest/globals';
|
|
2
|
-
import {
|
|
3
|
-
Constants,
|
|
4
|
-
LOCAL_CODING_BUNDLE_NAMES,
|
|
5
|
-
LOCAL_CODING_TOOL_NAMES,
|
|
6
|
-
} from '@/common';
|
|
7
2
|
import {
|
|
8
3
|
createLocalCodingTools,
|
|
9
4
|
createLocalCodingToolDefinitions,
|
|
@@ -13,6 +8,11 @@ import {
|
|
|
13
8
|
LocalListDirectoryToolName,
|
|
14
9
|
LocalWriteFileToolName,
|
|
15
10
|
} from '../local/LocalCodingTools';
|
|
11
|
+
import {
|
|
12
|
+
Constants,
|
|
13
|
+
LOCAL_CODING_BUNDLE_NAMES,
|
|
14
|
+
LOCAL_CODING_TOOL_NAMES,
|
|
15
|
+
} from '@/common';
|
|
16
16
|
import { CompileCheckToolName } from '../local/CompileCheckTool';
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -45,7 +45,9 @@ describe('local coding tool names', () => {
|
|
|
45
45
|
expect(Constants.BASH_TOOL).toBe('bash_tool');
|
|
46
46
|
expect(Constants.EXECUTE_CODE).toBe('execute_code');
|
|
47
47
|
expect(Constants.PROGRAMMATIC_TOOL_CALLING).toBe('run_tools_with_code');
|
|
48
|
-
expect(Constants.BASH_PROGRAMMATIC_TOOL_CALLING).toBe(
|
|
48
|
+
expect(Constants.BASH_PROGRAMMATIC_TOOL_CALLING).toBe(
|
|
49
|
+
'run_tools_with_bash'
|
|
50
|
+
);
|
|
49
51
|
});
|
|
50
52
|
|
|
51
53
|
it('LOCAL_CODING_BUNDLE_NAMES matches every name the bundle ships', () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from '@jest/globals';
|
|
2
|
-
import { formatSkillCatalog } from '../skillCatalog';
|
|
3
2
|
import type { SkillCatalogEntry } from '@/types';
|
|
3
|
+
import { formatSkillCatalog } from '../skillCatalog';
|
|
4
4
|
|
|
5
5
|
describe('formatSkillCatalog', () => {
|
|
6
6
|
it('returns empty string for empty array', () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { HumanMessage } from '@langchain/core/messages';
|
|
2
2
|
import { FakeListChatModel } from '@langchain/core/utils/testing';
|
|
3
3
|
import type { ToolCall } from '@langchain/core/messages/tool';
|
|
4
|
-
import type * as t from '@/types';
|
|
5
4
|
import type {
|
|
6
5
|
HookCallback,
|
|
7
6
|
PermissionDeniedHookOutput,
|
|
@@ -12,9 +11,7 @@ import type {
|
|
|
12
11
|
SubagentStopHookInput,
|
|
13
12
|
SubagentStopHookOutput,
|
|
14
13
|
} from '@/hooks/types';
|
|
15
|
-
import
|
|
16
|
-
import { Run } from '@/run';
|
|
17
|
-
import { FakeChatModel } from '@/llm/fake';
|
|
14
|
+
import type * as t from '@/types';
|
|
18
15
|
import {
|
|
19
16
|
Constants,
|
|
20
17
|
GraphEvents,
|
|
@@ -22,7 +19,10 @@ import {
|
|
|
22
19
|
ToolEndHandler,
|
|
23
20
|
ModelEndHandler,
|
|
24
21
|
} from '@/index';
|
|
22
|
+
import { HookRegistry } from '@/hooks/HookRegistry';
|
|
25
23
|
import * as providers from '@/llm/providers';
|
|
24
|
+
import { FakeChatModel } from '@/llm/fake';
|
|
25
|
+
import { Run } from '@/run';
|
|
26
26
|
|
|
27
27
|
const CHILD_RESPONSE = 'Hook test child response.';
|
|
28
28
|
|
|
@@ -275,9 +275,7 @@ describe('Subagent hook integration (end-to-end via Run)', () => {
|
|
|
275
275
|
toolCalls: [createCalculatorToolCall()],
|
|
276
276
|
});
|
|
277
277
|
}
|
|
278
|
-
bindTools(
|
|
279
|
-
tools: unknown
|
|
280
|
-
): ReturnType<FakeChatModel['withConfig']> {
|
|
278
|
+
bindTools(tools: unknown): ReturnType<FakeChatModel['withConfig']> {
|
|
281
279
|
const config = {
|
|
282
280
|
tools,
|
|
283
281
|
} as Parameters<FakeChatModel['withConfig']>[0];
|
|
@@ -292,11 +290,16 @@ describe('Subagent hook integration (end-to-end via Run)', () => {
|
|
|
292
290
|
const registry = new HookRegistry();
|
|
293
291
|
const preToolEvents: string[] = [];
|
|
294
292
|
const postToolEvents: string[] = [];
|
|
293
|
+
// `executingAgentId` is always the owning agent (incl. top-level), unlike
|
|
294
|
+
// `agentId` which stays undefined outside a subagent scope.
|
|
295
|
+
const preExecEvents: string[] = [];
|
|
296
|
+
const postExecEvents: string[] = [];
|
|
295
297
|
|
|
296
298
|
const preHook: HookCallback<'PreToolUse'> = async (
|
|
297
299
|
input
|
|
298
300
|
): Promise<PreToolUseHookOutput> => {
|
|
299
301
|
preToolEvents.push(`${input.agentId ?? '-'}:${input.toolName}`);
|
|
302
|
+
preExecEvents.push(`${input.executingAgentId ?? '-'}:${input.toolName}`);
|
|
300
303
|
return { decision: 'allow' };
|
|
301
304
|
};
|
|
302
305
|
registry.register('PreToolUse', { hooks: [preHook] });
|
|
@@ -305,6 +308,7 @@ describe('Subagent hook integration (end-to-end via Run)', () => {
|
|
|
305
308
|
input
|
|
306
309
|
): Promise<PostToolUseHookOutput> => {
|
|
307
310
|
postToolEvents.push(`${input.agentId ?? '-'}:${input.toolName}`);
|
|
311
|
+
postExecEvents.push(`${input.executingAgentId ?? '-'}:${input.toolName}`);
|
|
308
312
|
return {};
|
|
309
313
|
};
|
|
310
314
|
registry.register('PostToolUse', { hooks: [postHook] });
|
|
@@ -351,6 +355,14 @@ describe('Subagent hook integration (end-to-end via Run)', () => {
|
|
|
351
355
|
expect(preToolEvents).toContain('researcher-child:calculator');
|
|
352
356
|
expect(postToolEvents).toContain('-:subagent');
|
|
353
357
|
expect(postToolEvents).toContain('researcher-child:calculator');
|
|
358
|
+
|
|
359
|
+
// `agentId` stays the subagent-scope marker (undefined at the top level),
|
|
360
|
+
// but `executingAgentId` attributes every batch to its owning agent — incl.
|
|
361
|
+
// the top-level parent, which a multi-agent host needs and `agentId` can't give.
|
|
362
|
+
expect(preExecEvents).toContain('hook-parent:subagent');
|
|
363
|
+
expect(preExecEvents).toContain('researcher-child:calculator');
|
|
364
|
+
expect(postExecEvents).toContain('hook-parent:subagent');
|
|
365
|
+
expect(postExecEvents).toContain('researcher-child:calculator');
|
|
354
366
|
});
|
|
355
367
|
|
|
356
368
|
it('child subagent tool ask hooks fail closed instead of starting unsupported nested HITL', async () => {
|
|
@@ -365,9 +377,7 @@ describe('Subagent hook integration (end-to-end via Run)', () => {
|
|
|
365
377
|
toolCalls: [createCalculatorToolCall()],
|
|
366
378
|
});
|
|
367
379
|
}
|
|
368
|
-
bindTools(
|
|
369
|
-
tools: unknown
|
|
370
|
-
): ReturnType<FakeChatModel['withConfig']> {
|
|
380
|
+
bindTools(tools: unknown): ReturnType<FakeChatModel['withConfig']> {
|
|
371
381
|
const config = {
|
|
372
382
|
tools,
|
|
373
383
|
} as Parameters<FakeChatModel['withConfig']>[0];
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { tmpdir } from 'os';
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { mkdtemp, rm, writeFile } from 'fs/promises';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import {
|
|
5
|
+
describe,
|
|
6
|
+
it,
|
|
7
|
+
expect,
|
|
8
|
+
beforeEach,
|
|
9
|
+
afterEach,
|
|
10
|
+
jest,
|
|
11
|
+
} from '@jest/globals';
|
|
12
|
+
import type { WorkspaceFS } from '../local/workspaceFS';
|
|
7
13
|
import {
|
|
8
14
|
resolveWorkspacePathSafe,
|
|
9
15
|
getWorkspaceFS,
|
|
10
16
|
} from '../local/LocalExecutionEngine';
|
|
17
|
+
import { createLocalCodingToolBundle } from '../local/LocalCodingTools';
|
|
11
18
|
import { nodeWorkspaceFS } from '../local/workspaceFS';
|
|
12
|
-
import
|
|
19
|
+
import { Constants } from '@/common';
|
|
13
20
|
|
|
14
21
|
describe('workspace seam', () => {
|
|
15
22
|
let workspace: string;
|
|
@@ -97,10 +104,14 @@ describe('workspace seam', () => {
|
|
|
97
104
|
// the real Node impl so the tool actually completes; the spy just
|
|
98
105
|
// proves the seam.
|
|
99
106
|
const tracked: WorkspaceFS = {
|
|
100
|
-
readFile: jest.fn(
|
|
107
|
+
readFile: jest.fn(
|
|
108
|
+
nodeWorkspaceFS.readFile
|
|
109
|
+
) as unknown as WorkspaceFS['readFile'],
|
|
101
110
|
writeFile: jest.fn(nodeWorkspaceFS.writeFile),
|
|
102
111
|
stat: jest.fn(nodeWorkspaceFS.stat),
|
|
103
|
-
readdir: jest.fn(
|
|
112
|
+
readdir: jest.fn(
|
|
113
|
+
nodeWorkspaceFS.readdir
|
|
114
|
+
) as unknown as WorkspaceFS['readdir'],
|
|
104
115
|
mkdir: jest.fn(nodeWorkspaceFS.mkdir),
|
|
105
116
|
realpath: jest.fn(nodeWorkspaceFS.realpath),
|
|
106
117
|
unlink: jest.fn(nodeWorkspaceFS.unlink),
|
|
@@ -120,7 +131,9 @@ describe('workspace seam', () => {
|
|
|
120
131
|
expect(tracked.writeFile).toHaveBeenCalled();
|
|
121
132
|
expect(tracked.mkdir).toHaveBeenCalled();
|
|
122
133
|
|
|
123
|
-
const readTool = bundle.tools.find(
|
|
134
|
+
const readTool = bundle.tools.find(
|
|
135
|
+
(t) => t.name === Constants.READ_FILE
|
|
136
|
+
)!;
|
|
124
137
|
await readTool.invoke({
|
|
125
138
|
id: 'c2',
|
|
126
139
|
name: Constants.READ_FILE,
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
2
1
|
import { PassThrough } from 'stream';
|
|
3
2
|
import { posix as path } from 'path';
|
|
4
|
-
import
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
5
4
|
import type { WriteFileOptions, MakeDirectoryOptions, Stats } from 'fs';
|
|
5
|
+
import type { ChildProcessWithoutNullStreams } from 'child_process';
|
|
6
6
|
import type { FileHandle } from 'fs/promises';
|
|
7
|
+
import type { WorkspaceFS, ReaddirEntry } from '@/tools/local/workspaceFS';
|
|
7
8
|
import type * as t from '@/types';
|
|
8
9
|
import {
|
|
9
10
|
LOCAL_SPAWN_TIMEOUT_MS,
|
|
10
11
|
validateBashCommand,
|
|
11
12
|
} from '@/tools/local/LocalExecutionEngine';
|
|
12
|
-
import type { WorkspaceFS, ReaddirEntry } from '@/tools/local/workspaceFS';
|
|
13
13
|
|
|
14
14
|
const DEFAULT_WORKSPACE_ROOT = '/workspace';
|
|
15
15
|
const DEFAULT_TIMEOUT_MS = 60000;
|
|
@@ -403,6 +403,9 @@ function createCloudflareSpawn(
|
|
|
403
403
|
const child = new EventEmitter() as ChildProcessWithoutNullStreams;
|
|
404
404
|
const abortController = new AbortController();
|
|
405
405
|
const state = { closed: false };
|
|
406
|
+
/** Read through a function so concurrent `closeOnce` mutation (via
|
|
407
|
+
* `kill()`/abort during an `await`) isn't statically narrowed away. */
|
|
408
|
+
const isClosed = (): boolean => state.closed;
|
|
406
409
|
const closeOnce = (
|
|
407
410
|
exitCode: number | null,
|
|
408
411
|
signal: NodeJS.Signals | null
|
|
@@ -451,7 +454,7 @@ function createCloudflareSpawn(
|
|
|
451
454
|
const timedCommand = withInSandboxTimeout(rendered, timeoutMs);
|
|
452
455
|
const cwd =
|
|
453
456
|
options.cwd == null ? ctx.workspaceRoot : options.cwd.toString();
|
|
454
|
-
if (
|
|
457
|
+
if (isClosed()) {
|
|
455
458
|
return;
|
|
456
459
|
}
|
|
457
460
|
const execOptions: t.CloudflareSandboxExecOptions = {
|
|
@@ -464,14 +467,14 @@ function createCloudflareSpawn(
|
|
|
464
467
|
}
|
|
465
468
|
try {
|
|
466
469
|
const result = await ctx.sandbox.exec(timedCommand, execOptions);
|
|
467
|
-
if (
|
|
470
|
+
if (isClosed()) {
|
|
468
471
|
return;
|
|
469
472
|
}
|
|
470
473
|
if (result.stdout) stdout.write(result.stdout);
|
|
471
474
|
if (result.stderr) stderr.write(result.stderr);
|
|
472
475
|
closeOnce(result.exitCode, null);
|
|
473
476
|
} catch (error) {
|
|
474
|
-
if (
|
|
477
|
+
if (isClosed()) {
|
|
475
478
|
return;
|
|
476
479
|
}
|
|
477
480
|
stderr.write((error as Error).message);
|