@librechat/agents 3.6.9 → 3.6.10

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.
Files changed (141) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +46 -39
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/agents/projection.cjs +2 -2
  4. package/dist/cjs/agents/projection.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +28 -18
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/graphs/MultiAgentGraph.cjs +87 -16
  8. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  9. package/dist/cjs/llm/openai/index.cjs +10 -0
  10. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  11. package/dist/cjs/main.cjs +14 -0
  12. package/dist/cjs/messages/alternation.cjs +125 -20
  13. package/dist/cjs/messages/alternation.cjs.map +1 -1
  14. package/dist/cjs/messages/core.cjs +195 -18
  15. package/dist/cjs/messages/core.cjs.map +1 -1
  16. package/dist/cjs/messages/format.cjs +488 -118
  17. package/dist/cjs/messages/format.cjs.map +1 -1
  18. package/dist/cjs/messages/handoffCue.cjs +3 -2
  19. package/dist/cjs/messages/handoffCue.cjs.map +1 -1
  20. package/dist/cjs/messages/index.cjs +1 -0
  21. package/dist/cjs/messages/injected.cjs +5 -2
  22. package/dist/cjs/messages/injected.cjs.map +1 -1
  23. package/dist/cjs/messages/provenance.cjs +411 -0
  24. package/dist/cjs/messages/provenance.cjs.map +1 -0
  25. package/dist/cjs/messages/prune.cjs +18 -13
  26. package/dist/cjs/messages/prune.cjs.map +1 -1
  27. package/dist/cjs/messages/toolResultTypes.cjs +663 -0
  28. package/dist/cjs/messages/toolResultTypes.cjs.map +1 -0
  29. package/dist/cjs/run.cjs +7 -4
  30. package/dist/cjs/run.cjs.map +1 -1
  31. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +21 -4
  32. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  33. package/dist/cjs/tools/CallerCapabilities.cjs +48 -0
  34. package/dist/cjs/tools/CallerCapabilities.cjs.map +1 -0
  35. package/dist/cjs/tools/ProgrammaticCallerPolicy.cjs +34 -0
  36. package/dist/cjs/tools/ProgrammaticCallerPolicy.cjs.map +1 -0
  37. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +21 -4
  38. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  39. package/dist/cjs/tools/ToolNode.cjs +25 -24
  40. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  41. package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs +12 -4
  42. package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs.map +1 -1
  43. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +13 -4
  44. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -1
  45. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs +47 -11
  46. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -1
  47. package/dist/cjs/tools/ptcTimeout.cjs.map +1 -1
  48. package/dist/cjs/utils/toolContent.cjs +2 -2
  49. package/dist/cjs/utils/toolContent.cjs.map +1 -1
  50. package/dist/esm/agents/AgentContext.mjs +46 -39
  51. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  52. package/dist/esm/agents/projection.mjs +2 -2
  53. package/dist/esm/agents/projection.mjs.map +1 -1
  54. package/dist/esm/graphs/Graph.mjs +30 -20
  55. package/dist/esm/graphs/Graph.mjs.map +1 -1
  56. package/dist/esm/graphs/MultiAgentGraph.mjs +87 -16
  57. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  58. package/dist/esm/llm/openai/index.mjs +10 -0
  59. package/dist/esm/llm/openai/index.mjs.map +1 -1
  60. package/dist/esm/main.mjs +4 -3
  61. package/dist/esm/messages/alternation.mjs +125 -20
  62. package/dist/esm/messages/alternation.mjs.map +1 -1
  63. package/dist/esm/messages/core.mjs +196 -19
  64. package/dist/esm/messages/core.mjs.map +1 -1
  65. package/dist/esm/messages/format.mjs +488 -119
  66. package/dist/esm/messages/format.mjs.map +1 -1
  67. package/dist/esm/messages/handoffCue.mjs +3 -2
  68. package/dist/esm/messages/handoffCue.mjs.map +1 -1
  69. package/dist/esm/messages/index.mjs +1 -0
  70. package/dist/esm/messages/injected.mjs +5 -2
  71. package/dist/esm/messages/injected.mjs.map +1 -1
  72. package/dist/esm/messages/provenance.mjs +401 -0
  73. package/dist/esm/messages/provenance.mjs.map +1 -0
  74. package/dist/esm/messages/prune.mjs +18 -13
  75. package/dist/esm/messages/prune.mjs.map +1 -1
  76. package/dist/esm/messages/toolResultTypes.mjs +657 -0
  77. package/dist/esm/messages/toolResultTypes.mjs.map +1 -0
  78. package/dist/esm/run.mjs +7 -4
  79. package/dist/esm/run.mjs.map +1 -1
  80. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +21 -4
  81. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  82. package/dist/esm/tools/CallerCapabilities.mjs +45 -0
  83. package/dist/esm/tools/CallerCapabilities.mjs.map +1 -0
  84. package/dist/esm/tools/ProgrammaticCallerPolicy.mjs +32 -0
  85. package/dist/esm/tools/ProgrammaticCallerPolicy.mjs.map +1 -0
  86. package/dist/esm/tools/ProgrammaticToolCalling.mjs +21 -4
  87. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  88. package/dist/esm/tools/ToolNode.mjs +25 -24
  89. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  90. package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs +14 -6
  91. package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs.map +1 -1
  92. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +15 -6
  93. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -1
  94. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs +47 -12
  95. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -1
  96. package/dist/esm/tools/ptcTimeout.mjs.map +1 -1
  97. package/dist/esm/utils/toolContent.mjs +2 -2
  98. package/dist/esm/utils/toolContent.mjs.map +1 -1
  99. package/dist/types/agents/AgentContext.d.ts +8 -13
  100. package/dist/types/agents/projection.d.ts +3 -1
  101. package/dist/types/graphs/Graph.d.ts +1 -1
  102. package/dist/types/llm/openai/index.d.ts +20 -0
  103. package/dist/types/messages/format.d.ts +5 -0
  104. package/dist/types/messages/index.d.ts +1 -0
  105. package/dist/types/messages/provenance.d.ts +85 -0
  106. package/dist/types/messages/toolResultTypes.d.ts +33 -0
  107. package/dist/types/tools/CallerCapabilities.d.ts +12 -0
  108. package/dist/types/tools/ProgrammaticCallerPolicy.d.ts +20 -0
  109. package/dist/types/tools/ToolNode.d.ts +4 -7
  110. package/dist/types/tools/local/resolveLocalExecutionTools.d.ts +4 -0
  111. package/dist/types/tools/ptcTimeout.d.ts +8 -0
  112. package/dist/types/types/graph.d.ts +3 -1
  113. package/dist/types/types/tools.d.ts +13 -2
  114. package/package.json +1 -1
  115. package/src/agents/AgentContext.ts +109 -67
  116. package/src/agents/projection.ts +9 -1
  117. package/src/graphs/Graph.ts +56 -23
  118. package/src/graphs/MultiAgentGraph.ts +175 -33
  119. package/src/llm/openai/index.ts +43 -0
  120. package/src/messages/alternation.ts +217 -34
  121. package/src/messages/core.ts +358 -38
  122. package/src/messages/format.ts +958 -137
  123. package/src/messages/handoffCue.ts +7 -4
  124. package/src/messages/index.ts +1 -0
  125. package/src/messages/injected.ts +9 -6
  126. package/src/messages/provenance.ts +897 -0
  127. package/src/messages/prune.ts +28 -10
  128. package/src/messages/toolResultTypes.ts +1174 -0
  129. package/src/run.ts +9 -4
  130. package/src/tools/BashProgrammaticToolCalling.ts +46 -12
  131. package/src/tools/CallerCapabilities.ts +78 -0
  132. package/src/tools/ProgrammaticCallerPolicy.ts +97 -0
  133. package/src/tools/ProgrammaticToolCalling.ts +41 -7
  134. package/src/tools/ToolNode.ts +70 -52
  135. package/src/tools/cloudflare/CloudflareProgrammaticToolCalling.ts +24 -26
  136. package/src/tools/local/LocalProgrammaticToolCalling.ts +28 -23
  137. package/src/tools/local/resolveLocalExecutionTools.ts +132 -13
  138. package/src/tools/ptcTimeout.ts +6 -0
  139. package/src/types/graph.ts +3 -0
  140. package/src/types/tools.ts +14 -3
  141. package/src/utils/toolContent.ts +2 -2
@@ -9,14 +9,17 @@ import {
9
9
  ProgrammaticToolCallingDescription,
10
10
  ProgrammaticToolCallingName,
11
11
  ProgrammaticToolCallingSchema,
12
- filterToolsByUsage,
13
12
  } from '@/tools/ProgrammaticToolCalling';
14
13
  import {
15
14
  BashProgrammaticToolCallingDescription,
16
15
  BashProgrammaticToolCallingSchema,
17
- filterBashToolsByUsage,
18
16
  normalizeToBashIdentifier,
19
17
  } from '@/tools/BashProgrammaticToolCalling';
18
+ import {
19
+ resolveProgrammaticToolDefinitions,
20
+ selectProgrammaticTools,
21
+ type ProgrammaticInvocationParams,
22
+ } from '@/tools/ProgrammaticCallerPolicy';
20
23
  import { Constants } from '@/common';
21
24
  import {
22
25
  clientExecTimeoutMs,
@@ -27,13 +30,7 @@ import {
27
30
  validateCloudflareBashCommand,
28
31
  } from './CloudflareSandboxExecutionEngine';
29
32
 
30
- type ProgrammaticParams = {
31
- code: string;
32
- timeout?: number;
33
- lang?: string;
34
- runtime?: string;
35
- language?: string;
36
- };
33
+ type ProgrammaticParams = ProgrammaticInvocationParams;
37
34
 
38
35
  const DEFAULT_TIMEOUT = 60000;
39
36
  const MIN_TIMEOUT = 1000;
@@ -224,15 +221,8 @@ function resolveRuntime(params: ProgrammaticParams): 'python' | 'bash' {
224
221
  return raw === 'py' || raw === 'python' ? 'python' : 'bash';
225
222
  }
226
223
 
227
- function filterNativeTools(
228
- toolDefs: t.LCTool[],
229
- code: string,
230
- runtime: 'python' | 'bash'
231
- ): t.LCTool[] {
232
- const nativeDefs = toolDefs.filter((def) => NATIVE_TOOL_NAMES.has(def.name));
233
- const filter =
234
- runtime === 'bash' ? filterBashToolsByUsage : filterToolsByUsage;
235
- return filter(nativeDefs, code);
224
+ function filterNativeTools(toolDefs: t.LCTool[]): t.LCTool[] {
225
+ return toolDefs.filter((def) => NATIVE_TOOL_NAMES.has(def.name));
236
226
  }
237
227
 
238
228
  function indent(code: string, spaces = 4): string {
@@ -1060,14 +1050,22 @@ async function runProgrammatic(args: {
1060
1050
  cloudflareConfig: t.CloudflareSandboxExecutionConfig;
1061
1051
  runtime: 'python' | 'bash';
1062
1052
  }): Promise<[string, t.ProgrammaticExecutionArtifact]> {
1063
- const toolCall = (args.config?.toolCall ??
1064
- {}) as Partial<t.ProgrammaticCache>;
1065
- const toolDefs = toolCall.toolDefs ?? [];
1066
- const effectiveTools = filterNativeTools(
1067
- toolDefs,
1068
- args.params.code,
1069
- args.runtime
1070
- );
1053
+ const toolCall = (args.config?.toolCall ?? {}) as Partial<
1054
+ t.ProgrammaticCache
1055
+ > & { tools?: t.LCTool[] };
1056
+ const toolDefs = resolveProgrammaticToolDefinitions(toolCall);
1057
+ const programmaticToolName =
1058
+ toolCall.programmaticToolName ??
1059
+ (args.runtime === 'bash'
1060
+ ? Constants.BASH_PROGRAMMATIC_TOOL_CALLING
1061
+ : Constants.PROGRAMMATIC_TOOL_CALLING);
1062
+ const selectedTools = selectProgrammaticTools({
1063
+ requestedToolNames: args.params.tool_manifest,
1064
+ allowedToolDefs: toolDefs,
1065
+ disallowedToolDefs: toolCall.disallowedToolDefs,
1066
+ programmaticToolName,
1067
+ });
1068
+ const effectiveTools = filterNativeTools(selectedTools);
1071
1069
  const timeoutMs = clampExecutionTimeout(
1072
1070
  args.params.timeout,
1073
1071
  args.cloudflareConfig.timeoutMs
@@ -7,7 +7,6 @@ import type { AddressInfo } from 'net';
7
7
  import type * as t from '@/types';
8
8
  import {
9
9
  executeTools,
10
- filterToolsByUsage,
11
10
  formatCompletedResponse,
12
11
  normalizeToPythonIdentifier,
13
12
  ProgrammaticToolCallingName,
@@ -17,9 +16,13 @@ import {
17
16
  import {
18
17
  BashProgrammaticToolCallingSchema,
19
18
  BashProgrammaticToolCallingDescription,
20
- filterBashToolsByUsage,
21
19
  normalizeToBashIdentifier,
22
20
  } from '@/tools/BashProgrammaticToolCalling';
21
+ import {
22
+ resolveProgrammaticToolDefinitions,
23
+ selectProgrammaticTools,
24
+ type ProgrammaticInvocationParams,
25
+ } from '@/tools/ProgrammaticCallerPolicy';
23
26
  import {
24
27
  executeLocalBash,
25
28
  executeLocalCode,
@@ -150,15 +153,7 @@ function constantTimeEquals(a: string, b: string): boolean {
150
153
 
151
154
  type LocalProgrammaticRuntime = 'python' | 'bash';
152
155
 
153
- type LocalProgrammaticParams = {
154
- code: string;
155
- timeout?: number;
156
- lang?: string;
157
- runtime?: string;
158
- language?: string;
159
- };
160
-
161
- type ToolFilter = (toolDefs: t.LCTool[], code: string) => t.LCTool[];
156
+ type LocalProgrammaticParams = ProgrammaticInvocationParams;
162
157
 
163
158
  function resolveRuntime(
164
159
  params: LocalProgrammaticParams
@@ -547,17 +542,16 @@ ${code}
547
542
 
548
543
  function getProgrammaticContext(config?: {
549
544
  toolCall?: unknown;
550
- }): Partial<t.ProgrammaticCache> {
551
- return (config?.toolCall ?? {}) as Partial<t.ProgrammaticCache>;
545
+ }): Partial<t.ProgrammaticCache> & { tools?: t.LCTool[] } {
546
+ return (config?.toolCall ?? {}) as Partial<t.ProgrammaticCache> & {
547
+ tools?: t.LCTool[];
548
+ };
552
549
  }
553
550
 
554
551
  function createEffectiveToolMap(
555
552
  toolMap: t.ToolMap,
556
- toolDefs: t.LCTool[],
557
- code: string,
558
- filterTools: ToolFilter
553
+ effectiveTools: t.LCTool[]
559
554
  ): { effectiveTools: t.LCTool[]; effectiveMap: t.ToolMap } {
560
- const effectiveTools = filterTools(toolDefs, code);
561
555
  const effectiveMap = new Map<string, t.GenericTool>(
562
556
  effectiveTools
563
557
  .map((def) => {
@@ -578,9 +572,22 @@ async function runLocalProgrammaticTool(args: {
578
572
  localConfig: t.LocalExecutionConfig;
579
573
  runtime: LocalProgrammaticRuntime;
580
574
  }): Promise<[string, t.ProgrammaticExecutionArtifact]> {
581
- const { toolMap, toolDefs, hookContext } = getProgrammaticContext(
582
- args.config
583
- );
575
+ const context = getProgrammaticContext(args.config);
576
+ const { toolMap, disallowedToolDefs, programmaticToolName, hookContext } =
577
+ context;
578
+ const toolDefs = resolveProgrammaticToolDefinitions(context);
579
+
580
+ const runnerName =
581
+ programmaticToolName ??
582
+ (args.runtime === 'bash'
583
+ ? Constants.BASH_PROGRAMMATIC_TOOL_CALLING
584
+ : Constants.PROGRAMMATIC_TOOL_CALLING);
585
+ const selectedTools = selectProgrammaticTools({
586
+ requestedToolNames: args.params.tool_manifest,
587
+ allowedToolDefs: toolDefs,
588
+ disallowedToolDefs,
589
+ programmaticToolName: runnerName,
590
+ });
584
591
 
585
592
  if (toolMap == null || toolMap.size === 0) {
586
593
  throw new Error('No toolMap provided for local programmatic execution.');
@@ -593,9 +600,7 @@ async function runLocalProgrammaticTool(args: {
593
600
 
594
601
  const { effectiveTools, effectiveMap } = createEffectiveToolMap(
595
602
  toolMap,
596
- toolDefs,
597
- args.params.code,
598
- args.runtime === 'bash' ? filterBashToolsByUsage : filterToolsByUsage
603
+ selectedTools
599
604
  );
600
605
  const bridge = await createToolBridge(effectiveMap, hookContext);
601
606
 
@@ -17,6 +17,10 @@ import {
17
17
  createLocalBashExecutionTool,
18
18
  createLocalCodeExecutionTool,
19
19
  } from './LocalExecutionTools';
20
+ import {
21
+ allowsToolCaller,
22
+ isToolDefinitionActive,
23
+ } from '@/tools/CallerCapabilities';
20
24
  import {
21
25
  Constants,
22
26
  CODE_EXECUTION_TOOLS,
@@ -58,6 +62,25 @@ function shouldIncludeCodingTools(config?: t.ToolExecutionConfig): boolean {
58
62
  );
59
63
  }
60
64
 
65
+ export function isProgrammaticRunnerAutoBound(
66
+ name: string,
67
+ config?: t.ToolExecutionConfig
68
+ ): boolean {
69
+ if (
70
+ !shouldIncludeCodingTools(config) ||
71
+ (name !== Constants.PROGRAMMATIC_TOOL_CALLING &&
72
+ name !== Constants.BASH_PROGRAMMATIC_TOOL_CALLING)
73
+ ) {
74
+ return false;
75
+ }
76
+ if (shouldUseCloudflareSandboxExecution(config)) {
77
+ return getSelectedCloudflareCodingToolNames(
78
+ getCloudflareConfig(config)
79
+ ).has(name);
80
+ }
81
+ return shouldUseLocalExecution(config);
82
+ }
83
+
61
84
  function getCloudflareConfig(
62
85
  config?: t.ToolExecutionConfig
63
86
  ): t.CloudflareSandboxExecutionConfig {
@@ -150,9 +173,43 @@ function mergeToolsByName(
150
173
  return orderedTools;
151
174
  }
152
175
 
176
+ function filterToolsForDirectCaller(
177
+ tools: t.GraphTools | undefined,
178
+ toolRegistry?: t.LCToolRegistry,
179
+ discoveredToolNames: ReadonlySet<string> = new Set()
180
+ ): t.GraphTools | undefined {
181
+ if (tools == null || toolRegistry == null) {
182
+ return tools;
183
+ }
184
+ return tools.filter((tool) => {
185
+ if (!('name' in tool) || typeof tool.name !== 'string') {
186
+ return true;
187
+ }
188
+ const toolDef = toolRegistry.get(tool.name);
189
+ return (
190
+ toolDef == null ||
191
+ (allowsToolCaller(toolDef, 'direct') &&
192
+ isToolDefinitionActive(toolDef, discoveredToolNames))
193
+ );
194
+ });
195
+ }
196
+
197
+ function addDirectToolName(
198
+ directToolNames: Set<string>,
199
+ name: string,
200
+ toolRegistry?: t.LCToolRegistry
201
+ ): void {
202
+ const toolDef = toolRegistry?.get(name);
203
+ if (toolDef == null || allowsToolCaller(toolDef, 'direct')) {
204
+ directToolNames.add(name);
205
+ }
206
+ }
207
+
153
208
  export function resolveLocalToolsForBinding(args: {
154
209
  tools?: t.GraphTools;
155
210
  toolExecution?: t.ToolExecutionConfig;
211
+ toolRegistry?: t.LCToolRegistry;
212
+ discoveredToolNames?: ReadonlySet<string>;
156
213
  }): t.GraphTools | undefined {
157
214
  if (
158
215
  !shouldUseLocalExecution(args.toolExecution) &&
@@ -166,9 +223,13 @@ export function resolveLocalToolsForBinding(args: {
166
223
  if (shouldIncludeCodingTools(args.toolExecution)) {
167
224
  const selectedNames =
168
225
  getSelectedCloudflareCodingToolNames(cloudflareConfig);
169
- return mergeToolsByName(
170
- filterCloudflareCodingToolAllowlist(args.tools, selectedNames),
171
- createCloudflareCodingTools(cloudflareConfig)
226
+ return filterToolsForDirectCaller(
227
+ mergeToolsByName(
228
+ filterCloudflareCodingToolAllowlist(args.tools, selectedNames),
229
+ createCloudflareCodingTools(cloudflareConfig)
230
+ ),
231
+ args.toolRegistry,
232
+ args.discoveredToolNames
172
233
  );
173
234
  }
174
235
 
@@ -187,14 +248,23 @@ export function resolveLocalToolsForBinding(args: {
187
248
  cloudflareTool != null
188
249
  );
189
250
 
190
- return replacements.length === 0
251
+ const resolvedTools = replacements.length === 0
191
252
  ? args.tools
192
253
  : mergeToolsByName(args.tools, replacements);
254
+ return filterToolsForDirectCaller(
255
+ resolvedTools,
256
+ args.toolRegistry,
257
+ args.discoveredToolNames
258
+ );
193
259
  }
194
260
 
195
261
  const localConfig = args.toolExecution?.local ?? {};
196
262
  if (shouldIncludeCodingTools(args.toolExecution)) {
197
- return mergeToolsByName(args.tools, createLocalCodingTools(localConfig));
263
+ return filterToolsForDirectCaller(
264
+ mergeToolsByName(args.tools, createLocalCodingTools(localConfig)),
265
+ args.toolRegistry,
266
+ args.discoveredToolNames
267
+ );
198
268
  }
199
269
 
200
270
  const replacements = ((args.tools as t.GenericTool[] | undefined) ?? [])
@@ -209,9 +279,14 @@ export function resolveLocalToolsForBinding(args: {
209
279
  )
210
280
  .filter((localTool): localTool is t.GenericTool => localTool != null);
211
281
 
212
- return replacements.length === 0
282
+ const resolvedTools = replacements.length === 0
213
283
  ? args.tools
214
284
  : mergeToolsByName(args.tools, replacements);
285
+ return filterToolsForDirectCaller(
286
+ resolvedTools,
287
+ args.toolRegistry,
288
+ args.discoveredToolNames
289
+ );
215
290
  }
216
291
 
217
292
  export function resolveLocalToolRegistry(args: {
@@ -228,12 +303,39 @@ export function resolveLocalToolRegistry(args: {
228
303
  getCloudflareConfig(args.toolExecution)
229
304
  )
230
305
  : undefined;
306
+
307
+ if (selectedNames != null) {
308
+ const callableInsideCloudflare = new Set(selectedNames);
309
+ callableInsideCloudflare.delete(Constants.PROGRAMMATIC_TOOL_CALLING);
310
+ callableInsideCloudflare.delete(Constants.BASH_PROGRAMMATIC_TOOL_CALLING);
311
+ for (const [name, definition] of registry) {
312
+ if (callableInsideCloudflare.has(name)) {
313
+ continue;
314
+ }
315
+ const allowedCallers = definition.allowed_callers ?? ['direct'];
316
+ if (allowedCallers.includes('code_execution')) {
317
+ registry.set(name, {
318
+ ...definition,
319
+ allowed_callers: allowedCallers.filter(
320
+ (caller) => caller !== 'code_execution'
321
+ ),
322
+ });
323
+ }
324
+ }
325
+ }
326
+
231
327
  for (const definition of createLocalCodingToolDefinitions()) {
232
328
  if (selectedNames != null && !selectedNames.has(definition.name)) {
233
329
  registry.delete(definition.name);
234
330
  continue;
235
331
  }
236
- registry.set(definition.name, definition);
332
+ const existingDefinition = registry.get(definition.name);
333
+ registry.set(
334
+ definition.name,
335
+ existingDefinition == null
336
+ ? definition
337
+ : { ...definition, ...existingDefinition }
338
+ );
237
339
  }
238
340
  return registry;
239
341
  }
@@ -241,6 +343,7 @@ export function resolveLocalToolRegistry(args: {
241
343
  export function resolveLocalExecutionTools(args: {
242
344
  toolMap: t.ToolMap;
243
345
  toolExecution?: t.ToolExecutionConfig;
346
+ toolRegistry?: t.LCToolRegistry;
244
347
  /**
245
348
  * Caller-provided checkpointer that overrides the bundle's
246
349
  * auto-created one. The Graph layer threads a single per-Run
@@ -281,14 +384,22 @@ export function resolveLocalExecutionTools(args: {
281
384
  fileCheckpointer = bundle.checkpointer;
282
385
  for (const cloudflareTool of bundle.tools) {
283
386
  toolMap.set(cloudflareTool.name, cloudflareTool);
284
- directToolNames.add(cloudflareTool.name);
387
+ addDirectToolName(
388
+ directToolNames,
389
+ cloudflareTool.name,
390
+ args.toolRegistry
391
+ );
285
392
  }
286
393
  } else {
287
394
  for (const cloudflareTool of createCloudflareCodingTools(
288
395
  cloudflareConfig
289
396
  )) {
290
397
  toolMap.set(cloudflareTool.name, cloudflareTool);
291
- directToolNames.add(cloudflareTool.name);
398
+ addDirectToolName(
399
+ directToolNames,
400
+ cloudflareTool.name,
401
+ args.toolRegistry
402
+ );
292
403
  }
293
404
  }
294
405
  }
@@ -307,7 +418,7 @@ export function resolveLocalExecutionTools(args: {
307
418
  }
308
419
 
309
420
  toolMap.set(name, cloudflareTool);
310
- directToolNames.add(name);
421
+ addDirectToolName(directToolNames, name, args.toolRegistry);
311
422
  }
312
423
 
313
424
  return { toolMap, directToolNames, fileCheckpointer };
@@ -332,12 +443,20 @@ export function resolveLocalExecutionTools(args: {
332
443
  fileCheckpointer = bundle.checkpointer;
333
444
  for (const localTool of bundle.tools) {
334
445
  toolMap.set(localTool.name, localTool);
335
- directToolNames.add(localTool.name);
446
+ addDirectToolName(
447
+ directToolNames,
448
+ localTool.name,
449
+ args.toolRegistry
450
+ );
336
451
  }
337
452
  } else {
338
453
  for (const localTool of createLocalCodingTools(localConfig)) {
339
454
  toolMap.set(localTool.name, localTool);
340
- directToolNames.add(localTool.name);
455
+ addDirectToolName(
456
+ directToolNames,
457
+ localTool.name,
458
+ args.toolRegistry
459
+ );
341
460
  }
342
461
  }
343
462
  }
@@ -363,7 +482,7 @@ export function resolveLocalExecutionTools(args: {
363
482
  }
364
483
 
365
484
  toolMap.set(name, localTool);
366
- directToolNames.add(name);
485
+ addDirectToolName(directToolNames, name, args.toolRegistry);
367
486
  }
368
487
 
369
488
  return { toolMap, directToolNames, fileCheckpointer };
@@ -22,6 +22,12 @@ export type ProgrammaticToolCallingJsonSchema = {
22
22
  minLength: number;
23
23
  description: string;
24
24
  };
25
+ tool_manifest: {
26
+ type: 'array';
27
+ items: { type: 'string' };
28
+ uniqueItems: true;
29
+ description: string;
30
+ };
25
31
  timeout: TimeoutSchema;
26
32
  };
27
33
  required: readonly ['code'];
@@ -31,6 +31,7 @@ import type {
31
31
  ToolEndEvent,
32
32
  GenericTool,
33
33
  LCTool,
34
+ ToolExecutionConfig,
34
35
  ToolExecuteBatchRequest,
35
36
  } from '@/types/tools';
36
37
  import type {
@@ -338,6 +339,8 @@ export type StandardGraphInput = {
338
339
  runId?: string;
339
340
  signal?: AbortSignal;
340
341
  agents: AgentInputs[];
342
+ /** Execution backend used to resolve the effective tool registry. */
343
+ toolExecution?: ToolExecutionConfig;
341
344
  langfuse?: LangfuseConfig;
342
345
  tokenCounter?: TokenCounter;
343
346
  indexTokenCountMap?: Record<string, number>;
@@ -1,17 +1,17 @@
1
1
  // src/types/tools.ts
2
- import type { StructuredToolInterface } from '@langchain/core/tools';
3
2
  import type {
4
3
  RunnableConfig,
5
4
  RunnableToolLike,
6
5
  } from '@langchain/core/runnables';
6
+ import type { StructuredToolInterface } from '@langchain/core/tools';
7
7
  import type { ToolCall } from '@langchain/core/messages/tool';
8
- import type { ToolOutputReferenceRegistry } from '@/tools/toolOutputReferences';
9
- import type { RunBreakerScope } from '@/llm/streamLimits';
10
8
  import type {
11
9
  MessageContentComplex,
12
10
  RunStepResumeState,
13
11
  ToolErrorData,
14
12
  } from './stream';
13
+ import type { ToolOutputReferenceRegistry } from '@/tools/toolOutputReferences';
14
+ import type { RunBreakerScope } from '@/llm/streamLimits';
15
15
  import type { HumanInTheLoopConfig } from './hitl';
16
16
  import type { LangfuseConfig } from './graph';
17
17
  import type { HookRegistry } from '@/hooks';
@@ -133,6 +133,8 @@ export type ToolNodeOptions = {
133
133
  ) => Promise<boolean | void>;
134
134
  /** Tool registry for lazy computation of programmatic tools and tool search */
135
135
  toolRegistry?: LCToolRegistry;
136
+ /** Returns the owning agent's currently discovered deferred tool names. */
137
+ getDiscoveredToolNames?: () => readonly string[];
136
138
  /** Reference to Graph's sessions map for automatic session injection */
137
139
  sessions?: ToolSessionMap;
138
140
  /** Partition within `sessions` used by this agent's code tools. */
@@ -1171,6 +1173,15 @@ export type ToolExecutionConfig = {
1171
1173
  export type ProgrammaticCache = {
1172
1174
  toolMap: ToolMap;
1173
1175
  toolDefs: LCTool[];
1176
+ /** Actual outer runner name used for caller-policy diagnostics. */
1177
+ programmaticToolName?: string;
1178
+ /**
1179
+ * Known tools that cannot be invoked from programmatic execution. Kept
1180
+ * separate from `toolDefs` so the Programmatic Tool Manifest can be
1181
+ * validated before the execution runtime starts without exposing their
1182
+ * schemas to that runtime.
1183
+ */
1184
+ disallowedToolDefs?: LCTool[];
1174
1185
  /**
1175
1186
  * Hook context plumbed through by ToolNode for the local
1176
1187
  * programmatic-tool path so the in-process bridge can run
@@ -1818,7 +1818,7 @@ function classifyToolContentBlock(
1818
1818
  }
1819
1819
  }
1820
1820
  const remaining = { value: MAX_ATOMIC_VALIDATION_WORK };
1821
- let kind = TOOL_BLOCK_OPAQUE;
1821
+ let kind: number;
1822
1822
  try {
1823
1823
  if (
1824
1824
  hasUnsafeCallableToJSON(
@@ -2701,7 +2701,7 @@ export function cloneToolMessageWithContent(
2701
2701
  status: message.status,
2702
2702
  artifact,
2703
2703
  metadata: message.metadata,
2704
- additional_kwargs: message.additional_kwargs,
2704
+ additional_kwargs: { ...message.additional_kwargs },
2705
2705
  response_metadata: message.response_metadata,
2706
2706
  });
2707
2707
  }