@librechat/agents 3.1.21 → 3.1.23
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 +33 -8
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +3 -2
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/main.cjs +6 -6
- package/dist/cjs/tools/ToolNode.cjs +45 -12
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/{createSchemaOnlyTool.cjs → schema.cjs} +1 -1
- package/dist/cjs/tools/schema.cjs.map +1 -0
- package/dist/esm/agents/AgentContext.mjs +33 -8
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +2 -1
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -1
- package/dist/esm/tools/ToolNode.mjs +45 -12
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/{createSchemaOnlyTool.mjs → schema.mjs} +1 -1
- package/dist/esm/tools/schema.mjs.map +1 -0
- package/dist/types/agents/AgentContext.d.ts +6 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/tools/ToolNode.d.ts +3 -1
- package/dist/types/types/tools.d.ts +6 -0
- package/package.json +1 -1
- package/src/agents/AgentContext.ts +40 -9
- package/src/graphs/Graph.ts +2 -1
- package/src/index.ts +1 -1
- package/src/tools/ToolNode.ts +55 -13
- package/src/types/tools.ts +6 -0
- package/dist/cjs/tools/createSchemaOnlyTool.cjs.map +0 -1
- package/dist/esm/tools/createSchemaOnlyTool.mjs.map +0 -1
- /package/dist/types/tools/{createSchemaOnlyTool.d.ts → schema.d.ts} +0 -0
- /package/src/tools/{createSchemaOnlyTool.ts → schema.ts} +0 -0
package/dist/types/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export * from './tools/CodeExecutor';
|
|
|
9
9
|
export * from './tools/ProgrammaticToolCalling';
|
|
10
10
|
export * from './tools/ToolSearch';
|
|
11
11
|
export * from './tools/ToolNode';
|
|
12
|
-
export * from './tools/
|
|
12
|
+
export * from './tools/schema';
|
|
13
13
|
export * from './tools/handlers';
|
|
14
14
|
export * from './tools/search';
|
|
15
15
|
export * from './common';
|
|
@@ -22,7 +22,9 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
22
22
|
private eventDrivenMode;
|
|
23
23
|
/** Tool definitions for event-driven mode */
|
|
24
24
|
private toolDefinitions?;
|
|
25
|
-
|
|
25
|
+
/** Agent ID for event-driven mode */
|
|
26
|
+
private agentId?;
|
|
27
|
+
constructor({ tools, toolMap, name, tags, errorHandler, toolCallStepIds, handleToolErrors, loadRuntimeTools, toolRegistry, sessions, eventDrivenMode, toolDefinitions, agentId, }: t.ToolNodeConstructorParams);
|
|
26
28
|
/**
|
|
27
29
|
* Returns cached programmatic tools, computing once on first access.
|
|
28
30
|
* Single iteration builds both toolMap and toolDefs simultaneously.
|
|
@@ -35,6 +35,8 @@ export type ToolNodeOptions = {
|
|
|
35
35
|
eventDrivenMode?: boolean;
|
|
36
36
|
/** Tool definitions for event-driven mode (used for context, not invocation) */
|
|
37
37
|
toolDefinitions?: Map<string, LCTool>;
|
|
38
|
+
/** Agent ID for event-driven mode (used to identify which agent's context to use) */
|
|
39
|
+
agentId?: string;
|
|
38
40
|
};
|
|
39
41
|
export type ToolNodeConstructorParams = ToolRefs & ToolNodeOptions;
|
|
40
42
|
export type ToolEndEvent = {
|
|
@@ -128,6 +130,10 @@ export type ToolExecuteBatchRequest = {
|
|
|
128
130
|
userId?: string;
|
|
129
131
|
/** Agent ID for context */
|
|
130
132
|
agentId?: string;
|
|
133
|
+
/** Runtime configurable from RunnableConfig (includes user, userMCPAuthMap, etc.) */
|
|
134
|
+
configurable?: Record<string, unknown>;
|
|
135
|
+
/** Runtime metadata from RunnableConfig (includes thread_id, run_id, provider, etc.) */
|
|
136
|
+
metadata?: Record<string, unknown>;
|
|
131
137
|
/** Promise resolver - handler calls this with ALL results */
|
|
132
138
|
resolve: (results: ToolExecuteResult[]) => void;
|
|
133
139
|
/** Promise rejector - handler calls this on fatal error */
|
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
import type { RunnableConfig, Runnable } from '@langchain/core/runnables';
|
|
11
11
|
import type * as t from '@/types';
|
|
12
12
|
import type { createPruneMessages } from '@/messages';
|
|
13
|
+
import { createSchemaOnlyTools } from '@/tools/schema';
|
|
13
14
|
import { ContentTypes, Providers } from '@/common';
|
|
14
15
|
import { toJsonSchema } from '@/utils/schema';
|
|
15
16
|
|
|
@@ -571,40 +572,70 @@ export class AgentContext {
|
|
|
571
572
|
|
|
572
573
|
/**
|
|
573
574
|
* Gets tools that should be bound to the LLM.
|
|
574
|
-
*
|
|
575
|
+
* In event-driven mode (toolDefinitions present, tools empty), creates schema-only tools.
|
|
576
|
+
* Otherwise filters tool instances based on:
|
|
575
577
|
* 1. Non-deferred tools with allowed_callers: ['direct']
|
|
576
578
|
* 2. Discovered tools (from tool search)
|
|
577
579
|
* @returns Array of tools to bind to model
|
|
578
580
|
*/
|
|
579
581
|
getToolsForBinding(): t.GraphTools | undefined {
|
|
582
|
+
/** Event-driven mode: create schema-only tools from definitions */
|
|
583
|
+
if (this.toolDefinitions && this.toolDefinitions.length > 0) {
|
|
584
|
+
return this.getEventDrivenToolsForBinding();
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/** Traditional mode: filter actual tool instances */
|
|
580
588
|
if (!this.tools || !this.toolRegistry) {
|
|
581
589
|
return this.tools;
|
|
582
590
|
}
|
|
583
591
|
|
|
584
|
-
|
|
592
|
+
return this.filterToolsForBinding(this.tools);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/** Creates schema-only tools from toolDefinitions for event-driven mode */
|
|
596
|
+
private getEventDrivenToolsForBinding(): t.GraphTools {
|
|
597
|
+
if (!this.toolDefinitions) {
|
|
598
|
+
return [];
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const defsToInclude = this.toolDefinitions.filter((def) => {
|
|
602
|
+
const allowedCallers = def.allowed_callers ?? ['direct'];
|
|
603
|
+
if (!allowedCallers.includes('direct')) {
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
if (
|
|
607
|
+
def.defer_loading === true &&
|
|
608
|
+
!this.discoveredToolNames.has(def.name)
|
|
609
|
+
) {
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
return true;
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
return createSchemaOnlyTools(defsToInclude) as t.GraphTools;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/** Filters tool instances for binding based on registry config */
|
|
619
|
+
private filterToolsForBinding(tools: t.GraphTools): t.GraphTools {
|
|
620
|
+
return tools.filter((tool) => {
|
|
585
621
|
if (!('name' in tool)) {
|
|
586
|
-
return true;
|
|
622
|
+
return true;
|
|
587
623
|
}
|
|
588
624
|
|
|
589
625
|
const toolDef = this.toolRegistry?.get(tool.name);
|
|
590
626
|
if (!toolDef) {
|
|
591
|
-
return true;
|
|
627
|
+
return true;
|
|
592
628
|
}
|
|
593
629
|
|
|
594
|
-
// Check if discovered (overrides defer_loading)
|
|
595
630
|
if (this.discoveredToolNames.has(tool.name)) {
|
|
596
|
-
// Discovered tools must still have allowed_callers: ['direct']
|
|
597
631
|
const allowedCallers = toolDef.allowed_callers ?? ['direct'];
|
|
598
632
|
return allowedCallers.includes('direct');
|
|
599
633
|
}
|
|
600
634
|
|
|
601
|
-
// Not discovered: must be direct-callable AND not deferred
|
|
602
635
|
const allowedCallers = toolDef.allowed_callers ?? ['direct'];
|
|
603
636
|
return (
|
|
604
637
|
allowedCallers.includes('direct') && toolDef.defer_loading !== true
|
|
605
638
|
);
|
|
606
639
|
});
|
|
607
|
-
|
|
608
|
-
return toolsToInclude;
|
|
609
640
|
}
|
|
610
641
|
}
|
package/src/graphs/Graph.ts
CHANGED
|
@@ -58,9 +58,9 @@ import {
|
|
|
58
58
|
} from '@/utils';
|
|
59
59
|
import { getChatModelClass, manualToolStreamProviders } from '@/llm/providers';
|
|
60
60
|
import { ToolNode as CustomToolNode, toolsCondition } from '@/tools/ToolNode';
|
|
61
|
-
import { createSchemaOnlyTools } from '@/tools/createSchemaOnlyTool';
|
|
62
61
|
import { ChatOpenAI, AzureChatOpenAI } from '@/llm/openai';
|
|
63
62
|
import { safeDispatchCustomEvent } from '@/utils/events';
|
|
63
|
+
import { createSchemaOnlyTools } from '@/tools/schema';
|
|
64
64
|
import { AgentContext } from '@/agents/AgentContext';
|
|
65
65
|
import { createFakeStreamingLLM } from '@/llm/fake';
|
|
66
66
|
import { HandlerRegistry } from '@/events';
|
|
@@ -472,6 +472,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
472
472
|
sessions: this.sessions,
|
|
473
473
|
eventDrivenMode: true,
|
|
474
474
|
toolDefinitions: toolDefMap,
|
|
475
|
+
agentId: agentContext?.agentId,
|
|
475
476
|
});
|
|
476
477
|
}
|
|
477
478
|
|
package/src/index.ts
CHANGED
|
@@ -14,7 +14,7 @@ export * from './tools/CodeExecutor';
|
|
|
14
14
|
export * from './tools/ProgrammaticToolCalling';
|
|
15
15
|
export * from './tools/ToolSearch';
|
|
16
16
|
export * from './tools/ToolNode';
|
|
17
|
-
export * from './tools/
|
|
17
|
+
export * from './tools/schema';
|
|
18
18
|
export * from './tools/handlers';
|
|
19
19
|
export * from './tools/search';
|
|
20
20
|
|
package/src/tools/ToolNode.ts
CHANGED
|
@@ -49,6 +49,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
49
49
|
private eventDrivenMode: boolean = false;
|
|
50
50
|
/** Tool definitions for event-driven mode */
|
|
51
51
|
private toolDefinitions?: Map<string, t.LCTool>;
|
|
52
|
+
/** Agent ID for event-driven mode */
|
|
53
|
+
private agentId?: string;
|
|
52
54
|
|
|
53
55
|
constructor({
|
|
54
56
|
tools,
|
|
@@ -63,6 +65,7 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
63
65
|
sessions,
|
|
64
66
|
eventDrivenMode,
|
|
65
67
|
toolDefinitions,
|
|
68
|
+
agentId,
|
|
66
69
|
}: t.ToolNodeConstructorParams) {
|
|
67
70
|
super({ name, tags, func: (input, config) => this.run(input, config) });
|
|
68
71
|
this.toolMap = toolMap ?? new Map(tools.map((tool) => [tool.name, tool]));
|
|
@@ -75,6 +78,7 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
75
78
|
this.sessions = sessions;
|
|
76
79
|
this.eventDrivenMode = eventDrivenMode ?? false;
|
|
77
80
|
this.toolDefinitions = toolDefinitions;
|
|
81
|
+
this.agentId = agentId;
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
/**
|
|
@@ -279,7 +283,11 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
279
283
|
const request: t.ToolExecuteBatchRequest = {
|
|
280
284
|
toolCalls: requests,
|
|
281
285
|
userId: config.configurable?.user_id as string | undefined,
|
|
282
|
-
agentId:
|
|
286
|
+
agentId: this.agentId,
|
|
287
|
+
configurable: config.configurable as
|
|
288
|
+
| Record<string, unknown>
|
|
289
|
+
| undefined,
|
|
290
|
+
metadata: config.metadata as Record<string, unknown> | undefined,
|
|
283
291
|
resolve,
|
|
284
292
|
reject,
|
|
285
293
|
};
|
|
@@ -289,27 +297,61 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
289
297
|
);
|
|
290
298
|
|
|
291
299
|
const outputs: ToolMessage[] = results.map((result) => {
|
|
292
|
-
const
|
|
293
|
-
|
|
300
|
+
const request = requests.find((r) => r.id === result.toolCallId);
|
|
301
|
+
const toolName = request?.name ?? 'unknown';
|
|
302
|
+
const stepId = this.toolCallStepIds?.get(result.toolCallId) ?? '';
|
|
303
|
+
|
|
304
|
+
let toolMessage: ToolMessage;
|
|
305
|
+
let contentString: string;
|
|
294
306
|
|
|
295
307
|
if (result.status === 'error') {
|
|
296
|
-
|
|
308
|
+
contentString = `Error: ${result.errorMessage ?? 'Unknown error'}\n Please fix your mistakes.`;
|
|
309
|
+
toolMessage = new ToolMessage({
|
|
297
310
|
status: 'error',
|
|
298
|
-
content:
|
|
311
|
+
content: contentString,
|
|
299
312
|
name: toolName,
|
|
300
313
|
tool_call_id: result.toolCallId,
|
|
301
314
|
});
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return new ToolMessage({
|
|
305
|
-
status: 'success',
|
|
306
|
-
content:
|
|
315
|
+
} else {
|
|
316
|
+
contentString =
|
|
307
317
|
typeof result.content === 'string'
|
|
308
318
|
? result.content
|
|
309
|
-
: JSON.stringify(result.content)
|
|
319
|
+
: JSON.stringify(result.content);
|
|
320
|
+
toolMessage = new ToolMessage({
|
|
321
|
+
status: 'success',
|
|
322
|
+
content: contentString,
|
|
323
|
+
name: toolName,
|
|
324
|
+
tool_call_id: result.toolCallId,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const tool_call: t.ProcessedToolCall = {
|
|
329
|
+
args:
|
|
330
|
+
typeof request?.args === 'string'
|
|
331
|
+
? request.args
|
|
332
|
+
: JSON.stringify(request?.args ?? {}),
|
|
310
333
|
name: toolName,
|
|
311
|
-
|
|
312
|
-
|
|
334
|
+
id: result.toolCallId,
|
|
335
|
+
output: contentString,
|
|
336
|
+
progress: 1,
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const runStepCompletedData = {
|
|
340
|
+
result: {
|
|
341
|
+
id: stepId,
|
|
342
|
+
index: request?.turn ?? 0,
|
|
343
|
+
type: 'tool_call' as const,
|
|
344
|
+
tool_call,
|
|
345
|
+
},
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
safeDispatchCustomEvent(
|
|
349
|
+
GraphEvents.ON_RUN_STEP_COMPLETED,
|
|
350
|
+
runStepCompletedData,
|
|
351
|
+
config
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
return toolMessage;
|
|
313
355
|
});
|
|
314
356
|
|
|
315
357
|
return (Array.isArray(input) ? outputs : { messages: outputs }) as T;
|
package/src/types/tools.ts
CHANGED
|
@@ -45,6 +45,8 @@ export type ToolNodeOptions = {
|
|
|
45
45
|
eventDrivenMode?: boolean;
|
|
46
46
|
/** Tool definitions for event-driven mode (used for context, not invocation) */
|
|
47
47
|
toolDefinitions?: Map<string, LCTool>;
|
|
48
|
+
/** Agent ID for event-driven mode (used to identify which agent's context to use) */
|
|
49
|
+
agentId?: string;
|
|
48
50
|
};
|
|
49
51
|
|
|
50
52
|
export type ToolNodeConstructorParams = ToolRefs & ToolNodeOptions;
|
|
@@ -159,6 +161,10 @@ export type ToolExecuteBatchRequest = {
|
|
|
159
161
|
userId?: string;
|
|
160
162
|
/** Agent ID for context */
|
|
161
163
|
agentId?: string;
|
|
164
|
+
/** Runtime configurable from RunnableConfig (includes user, userMCPAuthMap, etc.) */
|
|
165
|
+
configurable?: Record<string, unknown>;
|
|
166
|
+
/** Runtime metadata from RunnableConfig (includes thread_id, run_id, provider, etc.) */
|
|
167
|
+
metadata?: Record<string, unknown>;
|
|
162
168
|
/** Promise resolver - handler calls this with ALL results */
|
|
163
169
|
resolve: (results: ToolExecuteResult[]) => void;
|
|
164
170
|
/** Promise rejector - handler calls this on fatal error */
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createSchemaOnlyTool.cjs","sources":["../../../src/tools/createSchemaOnlyTool.ts"],"sourcesContent":["import { tool, type StructuredToolInterface } from '@langchain/core/tools';\nimport type { LCTool } from '@/types';\n\n/**\n * Creates a schema-only tool for LLM binding in event-driven mode.\n * These tools have valid schemas for the LLM to understand but should\n * never be invoked directly - ToolNode handles execution via events.\n */\nexport function createSchemaOnlyTool(\n definition: LCTool\n): StructuredToolInterface {\n const { name, description, parameters, responseFormat } = definition;\n\n return tool(\n async () => {\n throw new Error(\n `Tool \"${name}\" should not be invoked directly in event-driven mode. ` +\n 'ToolNode should dispatch ON_TOOL_EXECUTE events instead.'\n );\n },\n {\n name,\n description: description ?? '',\n schema: parameters ?? { type: 'object', properties: {} },\n responseFormat: responseFormat ?? 'content_and_artifact',\n }\n );\n}\n\n/**\n * Creates schema-only tools for all definitions in an array.\n */\nexport function createSchemaOnlyTools(\n definitions: LCTool[]\n): StructuredToolInterface[] {\n return definitions.map((def) => createSchemaOnlyTool(def));\n}\n"],"names":["tool"],"mappings":";;;;AAGA;;;;AAIG;AACG,SAAU,oBAAoB,CAClC,UAAkB,EAAA;IAElB,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,UAAU;AAEpE,IAAA,OAAOA,UAAI,CACT,YAAW;AACT,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,MAAA,EAAS,IAAI,CAAyD,uDAAA,CAAA;AACpE,YAAA,0DAA0D,CAC7D;AACH,KAAC,EACD;QACE,IAAI;QACJ,WAAW,EAAE,WAAW,IAAI,EAAE;QAC9B,MAAM,EAAE,UAAU,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;QACxD,cAAc,EAAE,cAAc,IAAI,sBAAsB;AACzD,KAAA,CACF;AACH;AAEA;;AAEG;AACG,SAAU,qBAAqB,CACnC,WAAqB,EAAA;AAErB,IAAA,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,oBAAoB,CAAC,GAAG,CAAC,CAAC;AAC5D;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createSchemaOnlyTool.mjs","sources":["../../../src/tools/createSchemaOnlyTool.ts"],"sourcesContent":["import { tool, type StructuredToolInterface } from '@langchain/core/tools';\nimport type { LCTool } from '@/types';\n\n/**\n * Creates a schema-only tool for LLM binding in event-driven mode.\n * These tools have valid schemas for the LLM to understand but should\n * never be invoked directly - ToolNode handles execution via events.\n */\nexport function createSchemaOnlyTool(\n definition: LCTool\n): StructuredToolInterface {\n const { name, description, parameters, responseFormat } = definition;\n\n return tool(\n async () => {\n throw new Error(\n `Tool \"${name}\" should not be invoked directly in event-driven mode. ` +\n 'ToolNode should dispatch ON_TOOL_EXECUTE events instead.'\n );\n },\n {\n name,\n description: description ?? '',\n schema: parameters ?? { type: 'object', properties: {} },\n responseFormat: responseFormat ?? 'content_and_artifact',\n }\n );\n}\n\n/**\n * Creates schema-only tools for all definitions in an array.\n */\nexport function createSchemaOnlyTools(\n definitions: LCTool[]\n): StructuredToolInterface[] {\n return definitions.map((def) => createSchemaOnlyTool(def));\n}\n"],"names":[],"mappings":";;AAGA;;;;AAIG;AACG,SAAU,oBAAoB,CAClC,UAAkB,EAAA;IAElB,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,UAAU;AAEpE,IAAA,OAAO,IAAI,CACT,YAAW;AACT,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,MAAA,EAAS,IAAI,CAAyD,uDAAA,CAAA;AACpE,YAAA,0DAA0D,CAC7D;AACH,KAAC,EACD;QACE,IAAI;QACJ,WAAW,EAAE,WAAW,IAAI,EAAE;QAC9B,MAAM,EAAE,UAAU,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;QACxD,cAAc,EAAE,cAAc,IAAI,sBAAsB;AACzD,KAAA,CACF;AACH;AAEA;;AAEG;AACG,SAAU,qBAAqB,CACnC,WAAqB,EAAA;AAErB,IAAA,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,oBAAoB,CAAC,GAAG,CAAC,CAAC;AAC5D;;;;"}
|
|
File without changes
|
|
File without changes
|