@illuma-ai/agents 1.5.1 → 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 +160 -259
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/enum.cjs +12 -12
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +30 -13
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/graphs/phases/memoryFlushPhase.cjs +1 -1
- package/dist/cjs/graphs/phases/memoryFlushPhase.cjs.map +1 -1
- package/dist/cjs/hooks/HookRegistry.cjs +1 -1
- package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
- package/dist/cjs/hooks/matchers.cjs +2 -2
- package/dist/cjs/hooks/matchers.cjs.map +1 -1
- package/dist/cjs/hooks/types.cjs +1 -1
- package/dist/cjs/hooks/types.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/index.cjs +1 -1
- package/dist/cjs/llm/openai/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/memory/citations.cjs +4 -4
- package/dist/cjs/memory/citations.cjs.map +1 -1
- package/dist/cjs/memory/constants.cjs +17 -17
- package/dist/cjs/memory/constants.cjs.map +1 -1
- package/dist/cjs/memory/mmr.cjs +1 -1
- package/dist/cjs/memory/mmr.cjs.map +1 -1
- package/dist/cjs/memory/paths.cjs +1 -1
- package/dist/cjs/memory/paths.cjs.map +1 -1
- package/dist/cjs/memory/recallTracking.cjs +3 -3
- package/dist/cjs/memory/recallTracking.cjs.map +1 -1
- package/dist/cjs/memory/temporalDecay.cjs +2 -2
- package/dist/cjs/memory/temporalDecay.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +0 -89
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +13 -71
- 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 +13 -41
- 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 +78 -13
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/memory/memoryAppendTool.cjs +1 -1
- package/dist/cjs/tools/memory/memoryAppendTool.cjs.map +1 -1
- package/dist/cjs/tools/memory/memoryGetTool.cjs +2 -2
- package/dist/cjs/tools/memory/memoryGetTool.cjs.map +1 -1
- package/dist/cjs/tools/memory/memorySearchTool.cjs +3 -3
- package/dist/cjs/tools/memory/memorySearchTool.cjs.map +1 -1
- package/dist/cjs/tools/memory/shared.cjs +1 -1
- package/dist/cjs/tools/memory/shared.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +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 +160 -259
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/enum.mjs +12 -12
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +30 -13
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/graphs/phases/memoryFlushPhase.mjs +1 -1
- package/dist/esm/graphs/phases/memoryFlushPhase.mjs.map +1 -1
- package/dist/esm/hooks/HookRegistry.mjs +1 -1
- package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
- package/dist/esm/hooks/matchers.mjs +2 -2
- package/dist/esm/hooks/matchers.mjs.map +1 -1
- package/dist/esm/hooks/types.mjs +1 -1
- package/dist/esm/hooks/types.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/index.mjs +1 -1
- package/dist/esm/llm/openai/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/memory/citations.mjs +4 -4
- package/dist/esm/memory/citations.mjs.map +1 -1
- package/dist/esm/memory/constants.mjs +17 -17
- package/dist/esm/memory/constants.mjs.map +1 -1
- package/dist/esm/memory/mmr.mjs +1 -1
- package/dist/esm/memory/mmr.mjs.map +1 -1
- package/dist/esm/memory/paths.mjs +1 -1
- package/dist/esm/memory/paths.mjs.map +1 -1
- package/dist/esm/memory/recallTracking.mjs +3 -3
- package/dist/esm/memory/recallTracking.mjs.map +1 -1
- package/dist/esm/memory/temporalDecay.mjs +2 -2
- package/dist/esm/memory/temporalDecay.mjs.map +1 -1
- package/dist/esm/messages/cache.mjs +0 -89
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +13 -71
- 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 +14 -41
- 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 +78 -13
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/memory/memoryAppendTool.mjs +1 -1
- package/dist/esm/tools/memory/memoryAppendTool.mjs.map +1 -1
- package/dist/esm/tools/memory/memoryGetTool.mjs +2 -2
- package/dist/esm/tools/memory/memoryGetTool.mjs.map +1 -1
- package/dist/esm/tools/memory/memorySearchTool.mjs +3 -3
- package/dist/esm/tools/memory/memorySearchTool.mjs.map +1 -1
- package/dist/esm/tools/memory/shared.mjs +1 -1
- package/dist/esm/tools/memory/shared.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +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/common/enum.d.ts +12 -12
- package/dist/types/graphs/Graph.d.ts +2 -2
- package/dist/types/graphs/phases/memoryFlushPhase.d.ts +2 -2
- package/dist/types/hooks/HookRegistry.d.ts +1 -1
- package/dist/types/hooks/matchers.d.ts +2 -2
- package/dist/types/hooks/types.d.ts +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/llm/bedrock/index.d.ts +1 -54
- package/dist/types/llm/openai/index.d.ts +1 -1
- package/dist/types/memory/citations.d.ts +4 -4
- package/dist/types/memory/constants.d.ts +17 -17
- package/dist/types/memory/mmr.d.ts +3 -3
- package/dist/types/memory/paths.d.ts +1 -1
- package/dist/types/memory/temporalDecay.d.ts +2 -2
- package/dist/types/memory/types.d.ts +3 -3
- package/dist/types/messages/format.d.ts +2 -5
- package/dist/types/tools/CodeExecutor.d.ts +0 -6
- package/dist/types/tools/ToolNode.d.ts +3 -3
- package/dist/types/tools/memory/shared.d.ts +1 -1
- package/dist/types/tools/search/test.d.ts +1 -0
- 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 +30 -34
- package/dist/types/types/index.d.ts +0 -1
- package/dist/types/types/messages.d.ts +1 -1
- package/dist/types/types/run.d.ts +1 -3
- package/dist/types/types/tools.d.ts +5 -14
- package/package.json +1 -61
- package/src/agents/AgentContext.test.ts +176 -0
- package/src/agents/AgentContext.ts +179 -305
- package/src/agents/__tests__/AgentContext.test.ts +0 -632
- package/src/common/__tests__/enum.test.ts +1 -1
- package/src/common/enum.ts +12 -12
- package/src/graphs/Graph.ts +32 -13
- package/src/graphs/MultiAgentGraph.ts +1 -1
- package/src/graphs/gapFeatures.test.ts +1 -1
- package/src/graphs/phases/__tests__/memoryFlushPhase.test.ts +1 -1
- package/src/graphs/phases/memoryFlushPhase.ts +2 -2
- package/src/hooks/HookRegistry.ts +1 -1
- package/src/hooks/index.ts +1 -1
- package/src/hooks/matchers.ts +2 -2
- package/src/hooks/types.ts +1 -1
- 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/index.ts +2 -2
- package/src/llm/openai/utils/index.ts +14 -31
- package/src/memory/citations.ts +4 -4
- package/src/memory/constants.ts +17 -17
- package/src/memory/mmr.ts +3 -3
- package/src/memory/paths.ts +1 -1
- package/src/memory/recallTracking.ts +3 -3
- package/src/memory/temporalDecay.ts +2 -2
- package/src/memory/types.ts +3 -3
- package/src/messages/cache.test.ts +24 -62
- package/src/messages/cache.ts +0 -112
- package/src/messages/ensureThinkingBlock.test.ts +1 -1
- package/src/messages/format.ts +13 -92
- package/src/messages/formatAgentMessages.test.ts +1 -1
- package/src/scripts/subagent-configurable-inheritance.ts +263 -0
- package/src/scripts/subagent-event-driven-debug.ts +2 -2
- package/src/specs/anthropic.simple.test.ts +0 -61
- package/src/specs/prune.orphans.test.ts +1 -1
- package/src/tools/BashExecutor.ts +13 -37
- package/src/tools/CodeExecutor.ts +14 -59
- package/src/tools/ProgrammaticToolCalling.ts +14 -29
- package/src/tools/ToolNode.ts +75 -14
- package/src/tools/__tests__/CodeExecutor.test.ts +3 -3
- package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +0 -60
- package/src/tools/__tests__/SubagentExecutor.test.ts +157 -0
- package/src/tools/memory/memoryAppendTool.ts +1 -1
- package/src/tools/memory/memoryGetTool.ts +2 -2
- package/src/tools/memory/memorySearchTool.ts +3 -3
- package/src/tools/memory/shared.ts +1 -1
- package/src/tools/search/output.md +2775 -0
- package/src/tools/search/search.ts +2 -12
- package/src/tools/search/test.html +884 -0
- package/src/tools/search/test.md +643 -0
- package/src/tools/search/test.ts +159 -0
- 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 +27 -34
- package/src/types/index.ts +0 -1
- package/src/types/messages.ts +1 -1
- package/src/types/run.ts +1 -3
- package/src/types/tools.ts +5 -14
- 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 -54
- 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 -52
- 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 -71
- package/src/agents/__tests__/AgentContext.cacheTtl.live.test.ts +0 -259
- package/src/agents/__tests__/AgentContext.crossAgentTier1.live.test.ts +0 -266
- package/src/agents/__tests__/AgentContext.crossUserCache.live.test.ts +0 -342
- 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/utils/server-tool-inputs.test.ts +0 -436
- package/src/llm/bedrock/cacheSupport.test.ts +0 -99
- package/src/llm/bedrock/cacheSupport.ts +0 -53
- 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/subagent/types.test.ts +0 -70
- package/src/tools/subagent/types.ts +0 -115
- package/src/types/agent-cache.ts +0 -74
package/src/messages/cache.ts
CHANGED
|
@@ -14,61 +14,6 @@ type MessageWithContent = {
|
|
|
14
14
|
content?: string | MessageContentComplex[];
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
type MessageContentWithCacheControl = MessageContentComplex & {
|
|
18
|
-
cache_control?: unknown;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Strips Anthropic-style `cache_control` markers from every block in the
|
|
23
|
-
* given content array. Returns the (possibly cloned) content and a flag
|
|
24
|
-
* indicating whether anything was actually modified — so callers can avoid
|
|
25
|
-
* unnecessary message clones.
|
|
26
|
-
*
|
|
27
|
-
* Used to sanitize a system message's content array before adding Bedrock
|
|
28
|
-
* cache points, so stray Anthropic markers (e.g. left over from a previous
|
|
29
|
-
* Anthropic-provider turn) don't prevent the Bedrock provider from caching
|
|
30
|
-
* the system prefix.
|
|
31
|
-
*/
|
|
32
|
-
function stripAnthropicCacheControlFromBlocks(
|
|
33
|
-
content: MessageContentComplex[]
|
|
34
|
-
): { content: MessageContentComplex[]; modified: boolean } {
|
|
35
|
-
let modified = false;
|
|
36
|
-
const strippedContent = content.map((block) => {
|
|
37
|
-
if (!('cache_control' in block)) {
|
|
38
|
-
return block;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const cloned: MessageContentWithCacheControl = { ...block };
|
|
42
|
-
delete cloned.cache_control;
|
|
43
|
-
modified = true;
|
|
44
|
-
return cloned;
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return { content: strippedContent, modified };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* For the Bedrock cache pass, system messages must NOT carry Anthropic
|
|
52
|
-
* cache_control markers (those are an Anthropic-specific encoding and
|
|
53
|
-
* Bedrock uses cachePoint blocks instead). Strip them before the cache
|
|
54
|
-
* point insertion logic walks the message.
|
|
55
|
-
*/
|
|
56
|
-
function sanitizeBedrockSystemMessage<T extends MessageWithContent>(
|
|
57
|
-
message: T
|
|
58
|
-
): T {
|
|
59
|
-
const content = message.content;
|
|
60
|
-
if (!Array.isArray(content)) {
|
|
61
|
-
return message;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const stripped = stripAnthropicCacheControlFromBlocks(content);
|
|
65
|
-
if (!stripped.modified) {
|
|
66
|
-
return message;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return cloneMessage(message, stripped.content);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
17
|
/** Debug logger for cache operations - set ILLUMA_DEBUG_CACHE=true to enable */
|
|
73
18
|
const debugCache = (message: string, data?: unknown): void => {
|
|
74
19
|
if (process.env.ILLUMA_DEBUG_CACHE === 'true') {
|
|
@@ -416,36 +361,8 @@ export function addBedrockCacheControl<
|
|
|
416
361
|
|
|
417
362
|
// Clone messages to avoid mutating originals
|
|
418
363
|
const updatedMessages: T[] = messages.map((msg) => {
|
|
419
|
-
/* PRESERVE cachePoint on system messages — they're added inline by
|
|
420
|
-
* AgentContext.buildSystemRunnable to mark the cacheable system prefix
|
|
421
|
-
* for account-level caching. Only strip stray Anthropic cache_control
|
|
422
|
-
* (which Bedrock ignores). For non-system messages keep the existing
|
|
423
|
-
* behaviour: full strip + repopulate based on last-2 strategy. */
|
|
424
|
-
const msgType =
|
|
425
|
-
'getType' in msg && typeof msg.getType === 'function'
|
|
426
|
-
? msg.getType()
|
|
427
|
-
: undefined;
|
|
428
|
-
const msgRole = (msg as Record<string, unknown>).role as string | undefined;
|
|
429
|
-
const isSystem = msgType === 'system' || msgRole === 'system';
|
|
430
|
-
|
|
431
364
|
const content = msg.content;
|
|
432
365
|
if (Array.isArray(content)) {
|
|
433
|
-
if (isSystem) {
|
|
434
|
-
/* System: keep cachePoint, only strip Anthropic cache_control. */
|
|
435
|
-
if (hasAnthropicCacheControl(content)) {
|
|
436
|
-
const stripped = content.map((block) => {
|
|
437
|
-
const rec = block as Record<string, unknown>;
|
|
438
|
-
if ('cache_control' in rec) {
|
|
439
|
-
const { cache_control: _, ...rest } = rec;
|
|
440
|
-
return rest as MessageContentComplex;
|
|
441
|
-
}
|
|
442
|
-
return block;
|
|
443
|
-
});
|
|
444
|
-
return cloneMessage(msg, stripped) as T;
|
|
445
|
-
}
|
|
446
|
-
return cloneMessage(msg, content) as T;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
366
|
// Strip existing cachePoint blocks and Anthropic-style cache_control
|
|
450
367
|
const stripped = content
|
|
451
368
|
.filter((block) => !isCachePoint(block))
|
|
@@ -539,35 +456,6 @@ export function addBedrockCacheControl<
|
|
|
539
456
|
const message = updatedMessages[i];
|
|
540
457
|
const msgContent = message.content;
|
|
541
458
|
|
|
542
|
-
/* System messages are handled by AgentContext.buildSystemRunnable —
|
|
543
|
-
* the cachePoint is emitted INLINE in the system message content array
|
|
544
|
-
* so the cacheable system prefix gets a marker every turn (not just
|
|
545
|
-
* when the system message happens to be in the last 2 eligible). The
|
|
546
|
-
* Bedrock converter (src/llm/bedrock/utils/message_inputs.ts:261-294)
|
|
547
|
-
* passes through cachePoint blocks in system content arrays.
|
|
548
|
-
*
|
|
549
|
-
* If we ALSO marked system here, we'd: (a) waste one of the two
|
|
550
|
-
* cachePoint budget slots that Bedrock honours per-request, starving
|
|
551
|
-
* the conversation tail, and (b) potentially double-mark a stable
|
|
552
|
-
* prefix that already has its own cachePoint.
|
|
553
|
-
*
|
|
554
|
-
* As a defensive cleanup, strip stray Anthropic-style cache_control
|
|
555
|
-
* markers from the system message — Bedrock ignores them and they
|
|
556
|
-
* can confuse provider validation. */
|
|
557
|
-
const _msgType =
|
|
558
|
-
'getType' in message && typeof message.getType === 'function'
|
|
559
|
-
? message.getType()
|
|
560
|
-
: undefined;
|
|
561
|
-
const _msgRole = (message as Record<string, unknown>).role as
|
|
562
|
-
| string
|
|
563
|
-
| undefined;
|
|
564
|
-
if (_msgType === 'system' || _msgRole === 'system') {
|
|
565
|
-
updatedMessages[i] = sanitizeBedrockSystemMessage(
|
|
566
|
-
message as MessageWithContent
|
|
567
|
-
) as T;
|
|
568
|
-
continue;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
459
|
// Skip empty/whitespace-only content
|
|
572
460
|
if (msgContent == null) continue;
|
|
573
461
|
if (typeof msgContent === 'string' && msgContent.trim() === '') continue;
|
|
@@ -148,7 +148,7 @@ describe('ensureThinkingBlockInMessages', () => {
|
|
|
148
148
|
// Bedrock reasoning models produce reasoning on the first AI response,
|
|
149
149
|
// then subsequent tool calls in the same chain have content: "" with no
|
|
150
150
|
// reasoning block. These should NOT be converted because the chain
|
|
151
|
-
// already has a thinking block
|
|
151
|
+
// already has a thinking block upstream.
|
|
152
152
|
const messages = [
|
|
153
153
|
new HumanMessage({ content: 'show me something cool' }),
|
|
154
154
|
new AIMessage({
|
package/src/messages/format.ts
CHANGED
|
@@ -274,90 +274,18 @@ export const formatFromLangChain = (
|
|
|
274
274
|
};
|
|
275
275
|
};
|
|
276
276
|
|
|
277
|
-
/* DeepSeek reasoning roundtrip: when active, accumulate reasoning text
|
|
278
|
-
* from THINK/THINKING/REASONING blocks and attach to the next AI message
|
|
279
|
-
* as `additional_kwargs.reasoning_content` so it survives multi-turn
|
|
280
|
-
* replays through the OpenAI-compatible DeepSeek API. PR #136. */
|
|
281
|
-
interface FormatAssistantMessageOptions {
|
|
282
|
-
preserveReasoningContent?: boolean;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
interface FormatAgentMessagesOptions {
|
|
286
|
-
provider?: Providers;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function extractReasoningContent(
|
|
290
|
-
part: MessageContentComplex | undefined | null
|
|
291
|
-
): string {
|
|
292
|
-
if (part == null || typeof part !== 'object') return '';
|
|
293
|
-
if (part.type === ContentTypes.THINK) {
|
|
294
|
-
const think = (part as ReasoningContentText).think;
|
|
295
|
-
return typeof think === 'string' ? think : '';
|
|
296
|
-
}
|
|
297
|
-
if (part.type === ContentTypes.THINKING) {
|
|
298
|
-
const thinking = (part as { thinking?: string }).thinking;
|
|
299
|
-
return typeof thinking === 'string' ? thinking : '';
|
|
300
|
-
}
|
|
301
|
-
if (part.type === ContentTypes.REASONING) {
|
|
302
|
-
const reasoning = (part as { reasoning?: string }).reasoning;
|
|
303
|
-
return typeof reasoning === 'string' ? reasoning : '';
|
|
304
|
-
}
|
|
305
|
-
if (part.type === ContentTypes.REASONING_CONTENT) {
|
|
306
|
-
/* Bedrock/Google nested shape: { reasoningContent: { text: ... } } */
|
|
307
|
-
const nested = (part as { reasoningContent?: { text?: string } })
|
|
308
|
-
.reasoningContent;
|
|
309
|
-
if (nested && typeof nested.text === 'string') return nested.text;
|
|
310
|
-
}
|
|
311
|
-
return '';
|
|
312
|
-
}
|
|
313
|
-
|
|
314
277
|
/**
|
|
315
278
|
* Helper function to format an assistant message
|
|
316
279
|
* @param message The message to format
|
|
317
|
-
* @param options Optional formatting options (e.g. DeepSeek reasoning roundtrip)
|
|
318
280
|
* @returns Array of formatted messages
|
|
319
281
|
*/
|
|
320
282
|
function formatAssistantMessage(
|
|
321
|
-
message: Partial<TMessage
|
|
322
|
-
options?: FormatAssistantMessageOptions
|
|
283
|
+
message: Partial<TMessage>
|
|
323
284
|
): Array<AIMessage | ToolMessage> {
|
|
324
285
|
const formattedMessages: Array<AIMessage | ToolMessage> = [];
|
|
325
286
|
let currentContent: MessageContentComplex[] = [];
|
|
326
287
|
let lastAIMessage: AIMessage | null = null;
|
|
327
288
|
let hasReasoning = false;
|
|
328
|
-
let pendingReasoningContent = '';
|
|
329
|
-
const shouldPreserveReasoningContent =
|
|
330
|
-
options?.preserveReasoningContent === true;
|
|
331
|
-
|
|
332
|
-
const takePendingReasoningContent = (): string | undefined => {
|
|
333
|
-
if (!shouldPreserveReasoningContent || !pendingReasoningContent) {
|
|
334
|
-
return undefined;
|
|
335
|
-
}
|
|
336
|
-
const reasoningContent = pendingReasoningContent;
|
|
337
|
-
pendingReasoningContent = '';
|
|
338
|
-
return reasoningContent;
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
const createAIMessage = (
|
|
342
|
-
content: string | MessageContentComplex[]
|
|
343
|
-
): AIMessage => {
|
|
344
|
-
const reasoningContent = takePendingReasoningContent();
|
|
345
|
-
return new AIMessage({
|
|
346
|
-
content,
|
|
347
|
-
...(reasoningContent != null && {
|
|
348
|
-
additional_kwargs: { reasoning_content: reasoningContent },
|
|
349
|
-
}),
|
|
350
|
-
});
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
const attachPendingReasoningContent = (aiMessage: AIMessage): void => {
|
|
354
|
-
const reasoningContent = takePendingReasoningContent();
|
|
355
|
-
if (reasoningContent == null) return;
|
|
356
|
-
aiMessage.additional_kwargs.reasoning_content =
|
|
357
|
-
typeof aiMessage.additional_kwargs.reasoning_content === 'string'
|
|
358
|
-
? `${aiMessage.additional_kwargs.reasoning_content}${reasoningContent}`
|
|
359
|
-
: reasoningContent;
|
|
360
|
-
};
|
|
361
289
|
|
|
362
290
|
if (Array.isArray(message.content)) {
|
|
363
291
|
for (const part of message.content as Array<
|
|
@@ -380,15 +308,15 @@ function formatAssistantMessage(
|
|
|
380
308
|
}, '');
|
|
381
309
|
content =
|
|
382
310
|
`${content}\n${part[ContentTypes.TEXT] ?? part.text ?? ''}`.trim();
|
|
383
|
-
lastAIMessage =
|
|
311
|
+
lastAIMessage = new AIMessage({ content });
|
|
384
312
|
formattedMessages.push(lastAIMessage);
|
|
385
313
|
currentContent = [];
|
|
386
314
|
continue;
|
|
387
315
|
}
|
|
388
316
|
// Create a new AIMessage with this text and prepare for tool calls
|
|
389
|
-
lastAIMessage =
|
|
390
|
-
part.text != null ? part.text : ''
|
|
391
|
-
);
|
|
317
|
+
lastAIMessage = new AIMessage({
|
|
318
|
+
content: part.text != null ? part.text : '',
|
|
319
|
+
});
|
|
392
320
|
formattedMessages.push(lastAIMessage);
|
|
393
321
|
} else if (part.type === ContentTypes.TOOL_CALL) {
|
|
394
322
|
// Skip malformed tool call entries without tool_call property
|
|
@@ -413,10 +341,8 @@ function formatAssistantMessage(
|
|
|
413
341
|
|
|
414
342
|
if (!lastAIMessage) {
|
|
415
343
|
// "Heal" the payload by creating an AIMessage to precede the tool call
|
|
416
|
-
lastAIMessage =
|
|
344
|
+
lastAIMessage = new AIMessage({ content: '' });
|
|
417
345
|
formattedMessages.push(lastAIMessage);
|
|
418
|
-
} else {
|
|
419
|
-
attachPendingReasoningContent(lastAIMessage);
|
|
420
346
|
}
|
|
421
347
|
|
|
422
348
|
const tool_call: ToolCallPart = _tool_call;
|
|
@@ -459,12 +385,10 @@ function formatAssistantMessage(
|
|
|
459
385
|
} else if (
|
|
460
386
|
part.type === ContentTypes.THINK ||
|
|
461
387
|
part.type === ContentTypes.THINKING ||
|
|
462
|
-
part.type === ContentTypes.REASONING ||
|
|
463
388
|
part.type === ContentTypes.REASONING_CONTENT ||
|
|
464
389
|
part.type === 'redacted_thinking'
|
|
465
390
|
) {
|
|
466
391
|
hasReasoning = true;
|
|
467
|
-
pendingReasoningContent += extractReasoningContent(part);
|
|
468
392
|
continue;
|
|
469
393
|
} else if (
|
|
470
394
|
part.type === ContentTypes.ERROR ||
|
|
@@ -494,10 +418,10 @@ function formatAssistantMessage(
|
|
|
494
418
|
.trim();
|
|
495
419
|
|
|
496
420
|
if (content) {
|
|
497
|
-
formattedMessages.push(
|
|
421
|
+
formattedMessages.push(new AIMessage({ content }));
|
|
498
422
|
}
|
|
499
423
|
} else if (currentContent.length > 0) {
|
|
500
|
-
formattedMessages.push(
|
|
424
|
+
formattedMessages.push(new AIMessage({ content: currentContent }));
|
|
501
425
|
}
|
|
502
426
|
|
|
503
427
|
return formattedMessages;
|
|
@@ -791,15 +715,14 @@ function extractSkillName(args: unknown): string | undefined {
|
|
|
791
715
|
* When SkillTool is invoked, the body is injected as a HumanMessage into LangGraph state
|
|
792
716
|
* but NOT persisted to conversation history. On follow-up runs the skill body is lost.
|
|
793
717
|
* Pass `skills` to reconstruct the HumanMessage at the right position after each skill
|
|
794
|
-
* ToolMessage. PRs #96 / #97.
|
|
718
|
+
* ToolMessage. Upstream PRs #96 / #97.
|
|
795
719
|
* @returns - Object containing formatted messages and updated indexTokenCountMap if provided.
|
|
796
720
|
*/
|
|
797
721
|
export const formatAgentMessages = (
|
|
798
722
|
payload: TPayload,
|
|
799
723
|
indexTokenCountMap?: Record<number, number | undefined>,
|
|
800
724
|
tools?: Set<string>,
|
|
801
|
-
skills?: Map<string, string
|
|
802
|
-
options?: FormatAgentMessagesOptions
|
|
725
|
+
skills?: Map<string, string>
|
|
803
726
|
): {
|
|
804
727
|
messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;
|
|
805
728
|
indexTokenCountMap?: Record<number, number>;
|
|
@@ -903,7 +826,7 @@ export const formatAgentMessages = (
|
|
|
903
826
|
if (discoveredTools.has(toolName)) {
|
|
904
827
|
/** Valid tool - keep it */
|
|
905
828
|
filteredContent.push(part);
|
|
906
|
-
// Skill body reconstruction (PRs #96/#97): when a
|
|
829
|
+
// Skill body reconstruction (upstream PRs #96/#97): when a
|
|
907
830
|
// SkillTool tool_call is present in this assistant turn, mark
|
|
908
831
|
// the skill name so we can reconstruct the body HumanMessage
|
|
909
832
|
// after the assistant turn has been pushed.
|
|
@@ -1008,14 +931,12 @@ export const formatAgentMessages = (
|
|
|
1008
931
|
}
|
|
1009
932
|
|
|
1010
933
|
// Process the assistant message using the helper function
|
|
1011
|
-
const formattedMessages = formatAssistantMessage(processedMessage
|
|
1012
|
-
preserveReasoningContent: options?.provider === Providers.DEEPSEEK,
|
|
1013
|
-
});
|
|
934
|
+
const formattedMessages = formatAssistantMessage(processedMessage);
|
|
1014
935
|
messages.push(...formattedMessages);
|
|
1015
936
|
|
|
1016
937
|
// Capture index range BEFORE skill body injection so injected
|
|
1017
938
|
// HumanMessages are excluded from the assistant's token distribution
|
|
1018
|
-
// (PR #97 fix).
|
|
939
|
+
// (upstream PR #97 fix).
|
|
1019
940
|
const endMessageIndex = messages.length;
|
|
1020
941
|
|
|
1021
942
|
if (pendingSkillNames?.size) {
|
|
@@ -643,7 +643,7 @@ describe('formatAgentMessages', () => {
|
|
|
643
643
|
tool_call: {
|
|
644
644
|
id: 'commits_1',
|
|
645
645
|
name: 'list_commits_mcp_github',
|
|
646
|
-
args: '{"owner":"
|
|
646
|
+
args: '{"owner":"librechat","repo":"librechat"}',
|
|
647
647
|
output:
|
|
648
648
|
'[{"sha":"abc123","message":"feat: add deferred tools"},{"sha":"def456","message":"fix: tool loading"}]',
|
|
649
649
|
},
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { config } from 'dotenv';
|
|
2
|
+
config();
|
|
3
|
+
|
|
4
|
+
import { HumanMessage } from '@langchain/core/messages';
|
|
5
|
+
import type * as t from '@/types';
|
|
6
|
+
import { ChatModelStreamHandler } from '@/stream';
|
|
7
|
+
import { ToolEndHandler, ModelEndHandler } from '@/events';
|
|
8
|
+
import { Providers, GraphEvents } from '@/common';
|
|
9
|
+
import { Run } from '@/run';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Live verification that host-set fields on the parent's outer
|
|
13
|
+
* `configurable` (e.g. `requestBody`, `user`, `userMCPAuthMap`)
|
|
14
|
+
* propagate into the subagent's `ON_TOOL_EXECUTE` dispatches.
|
|
15
|
+
*
|
|
16
|
+
* Pass criteria: when the SUBAGENT calls the calculator tool, the
|
|
17
|
+
* `data.configurable` arriving at the parent's ON_TOOL_EXECUTE
|
|
18
|
+
* handler contains every key the parent put on its outer
|
|
19
|
+
* configurable (with `thread_id` overridden to a child run id).
|
|
20
|
+
*/
|
|
21
|
+
const apiKey = process.env.OPENAI_API_KEY!;
|
|
22
|
+
if (!apiKey) {
|
|
23
|
+
console.error('Missing OPENAI_API_KEY');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const calculatorDef: t.LCTool = {
|
|
28
|
+
name: 'calculator',
|
|
29
|
+
description: 'Evaluate a math expression. Use for any arithmetic.',
|
|
30
|
+
parameters: {
|
|
31
|
+
type: 'object',
|
|
32
|
+
properties: {
|
|
33
|
+
expression: {
|
|
34
|
+
type: 'string',
|
|
35
|
+
description: "A JS math expression, e.g. '42 * 58'",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
required: ['expression'],
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
type ConfigurableSnapshot = {
|
|
43
|
+
agentId: string | undefined;
|
|
44
|
+
configurable: Record<string, unknown> | undefined;
|
|
45
|
+
metadata: Record<string, unknown> | undefined;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
async function main() {
|
|
49
|
+
console.log('=== Subagent parentConfigurable inheritance — live ===\n');
|
|
50
|
+
|
|
51
|
+
// Parent has NO tools — it can only delegate via the math subagent.
|
|
52
|
+
// The math subagent has the calculator. This forces the spawn-subagent
|
|
53
|
+
// path so we can observe the subagent's `ON_TOOL_EXECUTE` dispatch.
|
|
54
|
+
const mathSubagentInputs: t.AgentInputs = {
|
|
55
|
+
agentId: 'math-worker',
|
|
56
|
+
provider: Providers.OPENAI,
|
|
57
|
+
clientOptions: { modelName: 'gpt-4o', apiKey },
|
|
58
|
+
instructions:
|
|
59
|
+
'You compute arithmetic. Always use the calculator tool — never estimate. Return the final numeric result as plain text.',
|
|
60
|
+
maxContextTokens: 8000,
|
|
61
|
+
toolDefinitions: [calculatorDef],
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const parentAgent: t.AgentInputs = {
|
|
65
|
+
agentId: 'supervisor',
|
|
66
|
+
provider: Providers.OPENAI,
|
|
67
|
+
clientOptions: { modelName: 'gpt-4o', apiKey },
|
|
68
|
+
instructions: `You delegate arithmetic to the "math" subagent. You have NO calculator yourself. For any math task, spawn the "math" subagent with the full task as its description, then echo the subagent's text result back to the user.`,
|
|
69
|
+
maxContextTokens: 8000,
|
|
70
|
+
// No toolDefinitions on the parent — only the subagent gets the calculator.
|
|
71
|
+
subagentConfigs: [
|
|
72
|
+
{
|
|
73
|
+
type: 'math',
|
|
74
|
+
name: 'math',
|
|
75
|
+
description:
|
|
76
|
+
'A focused arithmetic worker that uses the calculator tool to compute numerical results.',
|
|
77
|
+
agentInputs: mathSubagentInputs,
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const parentSnapshots: ConfigurableSnapshot[] = [];
|
|
83
|
+
const subagentSnapshots: ConfigurableSnapshot[] = [];
|
|
84
|
+
|
|
85
|
+
const customHandlers: Record<string, t.EventHandler> = {
|
|
86
|
+
[GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
|
|
87
|
+
[GraphEvents.TOOL_END]: new ToolEndHandler(),
|
|
88
|
+
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
|
|
89
|
+
[GraphEvents.ON_TOOL_EXECUTE]: {
|
|
90
|
+
handle: (_event, rawData): void => {
|
|
91
|
+
const data = rawData as t.ToolExecuteBatchRequest;
|
|
92
|
+
const snapshot: ConfigurableSnapshot = {
|
|
93
|
+
agentId: data.agentId,
|
|
94
|
+
configurable: data.configurable as
|
|
95
|
+
| Record<string, unknown>
|
|
96
|
+
| undefined,
|
|
97
|
+
metadata: data.metadata as Record<string, unknown> | undefined,
|
|
98
|
+
};
|
|
99
|
+
const callsLabel = data.toolCalls.map((c) => c.name).join(',');
|
|
100
|
+
// Parent and subagent have different agent IDs in this script
|
|
101
|
+
// (parent: 'supervisor', subagent: 'math-worker'). With a self-spawn
|
|
102
|
+
// subagent both would be the same; this script uses a non-self
|
|
103
|
+
// subagent precisely so we can distinguish reliably.
|
|
104
|
+
const isSubagent = data.agentId !== 'supervisor';
|
|
105
|
+
const metadataRunId = (data.metadata as { run_id?: string } | undefined)
|
|
106
|
+
?.run_id;
|
|
107
|
+
if (isSubagent) {
|
|
108
|
+
subagentSnapshots.push(snapshot);
|
|
109
|
+
} else {
|
|
110
|
+
parentSnapshots.push(snapshot);
|
|
111
|
+
}
|
|
112
|
+
console.log(
|
|
113
|
+
`[ON_TOOL_EXECUTE] origin=${isSubagent ? 'SUBAGENT' : 'PARENT'} agentId=${data.agentId} calls=${callsLabel}`
|
|
114
|
+
);
|
|
115
|
+
console.log(
|
|
116
|
+
` metadata keys: ${Object.keys(data.metadata ?? {}).join(',') || '<none>'}`
|
|
117
|
+
);
|
|
118
|
+
console.log(
|
|
119
|
+
` metadata.run_id="${metadataRunId ?? '<none>'}" configurable.run_id="${(data.configurable as { run_id?: string } | undefined)?.run_id ?? '<none>'}" configurable.thread_id="${(data.configurable as { thread_id?: string } | undefined)?.thread_id ?? '<none>'}"`
|
|
120
|
+
);
|
|
121
|
+
const results: t.ToolExecuteResult[] = data.toolCalls.map((call) => {
|
|
122
|
+
const args = call.args as { expression?: string };
|
|
123
|
+
const expression = args.expression ?? '';
|
|
124
|
+
let content: string;
|
|
125
|
+
try {
|
|
126
|
+
// eslint-disable-next-line no-eval
|
|
127
|
+
const result = eval(expression);
|
|
128
|
+
content = `${expression} = ${result}`;
|
|
129
|
+
} catch (err) {
|
|
130
|
+
content = `Error: ${String(err)}`;
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
toolCallId: call.id!,
|
|
134
|
+
status: 'success',
|
|
135
|
+
content,
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
data.resolve(results);
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const run = await Run.create<t.IState>({
|
|
144
|
+
runId: `sub-cfg-inherit-${Date.now()}`,
|
|
145
|
+
graphConfig: { type: 'standard', agents: [parentAgent] },
|
|
146
|
+
customHandlers,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const question = new HumanMessage(
|
|
150
|
+
'Compute (42 * 58) + (13 ** 3). Use the self subagent, and have it use the calculator.'
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
// Parent's outer configurable carries host-set fields AND explicit
|
|
154
|
+
// run-identity fields so we can verify whether LangGraph respects or
|
|
155
|
+
// overwrites parent's `run_id` / `parent_run_id` when we forward them
|
|
156
|
+
// into the child's `workflow.invoke`.
|
|
157
|
+
const outerConfigurable = {
|
|
158
|
+
thread_id: 'parent-thread-conv-xyz',
|
|
159
|
+
run_id: 'parent-run-id-001',
|
|
160
|
+
parent_run_id: 'grandparent-run-id-000',
|
|
161
|
+
user_id: 'user_abc',
|
|
162
|
+
user: { id: 'user_abc', email: 'a@b.c', role: 'USER' },
|
|
163
|
+
requestBody: {
|
|
164
|
+
messageId: 'msg-response-id-001',
|
|
165
|
+
conversationId: 'parent-thread-conv-xyz',
|
|
166
|
+
parentMessageId: 'user-message-id-000',
|
|
167
|
+
},
|
|
168
|
+
userMCPAuthMap: { 'mcp-github': { token: 'abc' } },
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
console.log('User:', question.content);
|
|
172
|
+
console.log(
|
|
173
|
+
'Parent outer configurable keys:',
|
|
174
|
+
Object.keys(outerConfigurable)
|
|
175
|
+
);
|
|
176
|
+
console.log();
|
|
177
|
+
|
|
178
|
+
await run.processStream(
|
|
179
|
+
{ messages: [question] },
|
|
180
|
+
{
|
|
181
|
+
configurable: outerConfigurable,
|
|
182
|
+
version: 'v2' as const,
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
console.log('\n=== Verification ===');
|
|
187
|
+
console.log(
|
|
188
|
+
`Parent ON_TOOL_EXECUTE dispatches captured: ${parentSnapshots.length}`
|
|
189
|
+
);
|
|
190
|
+
console.log(
|
|
191
|
+
`Subagent ON_TOOL_EXECUTE dispatches captured: ${subagentSnapshots.length}`
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
if (subagentSnapshots.length === 0) {
|
|
195
|
+
console.error(
|
|
196
|
+
'\n❌ FAIL: subagent never invoked a tool — model may not have spawned the subagent.'
|
|
197
|
+
);
|
|
198
|
+
process.exit(2);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const expectedHostKeys = ['user_id', 'user', 'requestBody', 'userMCPAuthMap'];
|
|
202
|
+
let allPassed = true;
|
|
203
|
+
subagentSnapshots.forEach((snap, idx) => {
|
|
204
|
+
const cfg = snap.configurable ?? {};
|
|
205
|
+
const meta = snap.metadata ?? {};
|
|
206
|
+
console.log(
|
|
207
|
+
`\nSubagent dispatch #${idx + 1} (agentId=${snap.agentId}, metadata.run_id=${(meta as { run_id?: string }).run_id ?? '-'}):`
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
// Host-set fields must propagate.
|
|
211
|
+
for (const key of expectedHostKeys) {
|
|
212
|
+
const present = key in cfg;
|
|
213
|
+
const value = cfg[key];
|
|
214
|
+
console.log(
|
|
215
|
+
` ${present ? '✅' : '❌'} ${key} = ${JSON.stringify(value)}`
|
|
216
|
+
);
|
|
217
|
+
if (!present) allPassed = false;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Run-identity fields: with full inheritance we expect parent's
|
|
221
|
+
// values to flow through. LangGraph runtime MAY overwrite them at
|
|
222
|
+
// child-invoke time — the script logs what actually arrived so we
|
|
223
|
+
// can see empirically what propagates.
|
|
224
|
+
console.log(
|
|
225
|
+
` ⓘ thread_id observed: "${cfg.thread_id as string}" (parent's: "${outerConfigurable.thread_id}")`
|
|
226
|
+
);
|
|
227
|
+
console.log(
|
|
228
|
+
` ⓘ run_id observed: "${cfg.run_id as string}" (parent's: "${outerConfigurable.run_id}")`
|
|
229
|
+
);
|
|
230
|
+
console.log(
|
|
231
|
+
` ⓘ parent_run_id observed: "${cfg.parent_run_id as string}" (parent's: "${outerConfigurable.parent_run_id}")`
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
const threadInherited = cfg.thread_id === outerConfigurable.thread_id;
|
|
235
|
+
const runInherited = cfg.run_id === outerConfigurable.run_id;
|
|
236
|
+
const parentRunInherited =
|
|
237
|
+
cfg.parent_run_id === outerConfigurable.parent_run_id;
|
|
238
|
+
console.log(
|
|
239
|
+
` ${threadInherited ? '✅' : '⚠️ '} thread_id inherited from parent: ${threadInherited}`
|
|
240
|
+
);
|
|
241
|
+
console.log(
|
|
242
|
+
` ${runInherited ? '✅' : '⚠️ '} run_id inherited from parent: ${runInherited}`
|
|
243
|
+
);
|
|
244
|
+
console.log(
|
|
245
|
+
` ${parentRunInherited ? '✅' : '⚠️ '} parent_run_id inherited from parent: ${parentRunInherited}`
|
|
246
|
+
);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
if (allPassed) {
|
|
250
|
+
console.log(
|
|
251
|
+
'\n✅ Host-set fields propagate. (Run-identity inheritance is informational — see ⚠️ markers above for any LangGraph-runtime overwrites.)'
|
|
252
|
+
);
|
|
253
|
+
process.exit(0);
|
|
254
|
+
} else {
|
|
255
|
+
console.log('\n❌ FAIL: at least one expected host-set key was missing.');
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
main().catch((err) => {
|
|
261
|
+
console.error('Script error:', err);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
});
|
|
@@ -10,7 +10,7 @@ import { Providers, GraphEvents, Constants } from '@/common';
|
|
|
10
10
|
import { Run } from '@/run';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Repro for
|
|
13
|
+
* Repro for LibreChat's actual setup: event-driven tools via `toolDefinitions`
|
|
14
14
|
* + an ON_TOOL_EXECUTE handler that runs the tool. Self-spawn subagent must
|
|
15
15
|
* be able to drive the SAME tool pipeline.
|
|
16
16
|
*/
|
|
@@ -20,7 +20,7 @@ if (!apiKey) {
|
|
|
20
20
|
process.exit(1);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
// Simulate
|
|
23
|
+
// Simulate LibreChat: tool definitions only, execution routed via event.
|
|
24
24
|
const calculatorDef: t.LCTool = {
|
|
25
25
|
name: 'calculator',
|
|
26
26
|
description: 'Evaluate a math expression. Use for any arithmetic.',
|