@librechat/agents 3.7.3 → 3.7.4
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/stream.cjs +3 -1
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +10 -3
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/eagerEventExecution.cjs +32 -2
- package/dist/cjs/tools/eagerEventExecution.cjs.map +1 -1
- package/dist/esm/stream.mjs +3 -1
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +11 -4
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/eagerEventExecution.mjs +32 -3
- package/dist/esm/tools/eagerEventExecution.mjs.map +1 -1
- package/dist/types/tools/ToolNode.d.ts +2 -0
- package/dist/types/tools/eagerEventExecution.d.ts +6 -0
- package/package.json +1 -1
- package/src/stream.ts +7 -0
- package/src/tools/ToolNode.ts +29 -3
- package/src/tools/eagerEventExecution.ts +90 -2
package/src/tools/ToolNode.ts
CHANGED
|
@@ -71,6 +71,8 @@ import {
|
|
|
71
71
|
} from '@/tools/intentArg';
|
|
72
72
|
import {
|
|
73
73
|
buildToolExecutionRequestPlan,
|
|
74
|
+
coerceArgsForSchema,
|
|
75
|
+
coerceRecordArgs,
|
|
74
76
|
resolveRuntimeSessionHint,
|
|
75
77
|
recordArgsEqual,
|
|
76
78
|
} from '@/tools/eagerEventExecution';
|
|
@@ -1129,6 +1131,26 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
1129
1131
|
);
|
|
1130
1132
|
}
|
|
1131
1133
|
|
|
1134
|
+
private getToolParameterSchema(
|
|
1135
|
+
toolName: string
|
|
1136
|
+
): t.JsonSchemaType | undefined {
|
|
1137
|
+
return (
|
|
1138
|
+
this.toolDefinitions?.get(toolName)?.parameters ??
|
|
1139
|
+
this.toolRegistry?.get(toolName)?.parameters
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
private coerceEventToolArgs(
|
|
1144
|
+
toolName: string,
|
|
1145
|
+
args: unknown
|
|
1146
|
+
): Record<string, unknown> {
|
|
1147
|
+
const recordArgs = coerceRecordArgs(args);
|
|
1148
|
+
return coerceArgsForSchema(
|
|
1149
|
+
recordArgs ?? (args as Record<string, unknown>),
|
|
1150
|
+
this.getToolParameterSchema(toolName)
|
|
1151
|
+
);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1132
1154
|
/** Serializes the live caller projection for event-driven hosts. */
|
|
1133
1155
|
private getCallerCapabilityProjectionSnapshot(): t.CallerCapabilityProjectionSnapshot {
|
|
1134
1156
|
return createCallerCapabilityProjectionSnapshot(
|
|
@@ -2758,7 +2780,7 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
2758
2780
|
return {
|
|
2759
2781
|
call,
|
|
2760
2782
|
stepId: this.toolCallStepIds?.get(call.id!) ?? '',
|
|
2761
|
-
args: resolvedArgs,
|
|
2783
|
+
args: this.coerceEventToolArgs(call.name, resolvedArgs),
|
|
2762
2784
|
batchIndex: batchIndices?.[i],
|
|
2763
2785
|
};
|
|
2764
2786
|
});
|
|
@@ -3002,7 +3024,10 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
3002
3024
|
entry.call.name
|
|
3003
3025
|
),
|
|
3004
3026
|
});
|
|
3005
|
-
entry.args =
|
|
3027
|
+
entry.args = this.coerceEventToolArgs(
|
|
3028
|
+
entry.call.name,
|
|
3029
|
+
resolved as Record<string, unknown>
|
|
3030
|
+
);
|
|
3006
3031
|
if (entry.call.id != null) {
|
|
3007
3032
|
if (unresolved.length > 0) {
|
|
3008
3033
|
unresolvedByCallId.set(entry.call.id, unresolved);
|
|
@@ -3012,7 +3037,7 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
3012
3037
|
}
|
|
3013
3038
|
return;
|
|
3014
3039
|
}
|
|
3015
|
-
entry.args = nextArgs;
|
|
3040
|
+
entry.args = this.coerceEventToolArgs(entry.call.name, nextArgs);
|
|
3016
3041
|
};
|
|
3017
3042
|
|
|
3018
3043
|
const askEntries: Array<{
|
|
@@ -3369,6 +3394,7 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
3369
3394
|
}),
|
|
3370
3395
|
usageCount: this.toolUsageCount,
|
|
3371
3396
|
invalidArgsBehavior: 'error-result',
|
|
3397
|
+
getToolSchema: (toolName) => this.getToolParameterSchema(toolName),
|
|
3372
3398
|
recordTurn: (toolName, reservedTurn, callId) => {
|
|
3373
3399
|
this.recordEventToolPlanningTurn(
|
|
3374
3400
|
toolName,
|
|
@@ -19,6 +19,89 @@ export function coerceRecordArgs(
|
|
|
19
19
|
return args as Record<string, unknown>;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
const INTEGER_STRING = /^-?(?:0|[1-9]\d*)$/;
|
|
23
|
+
const NUMBER_STRING = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
|
|
24
|
+
|
|
25
|
+
function coerceValueForSchema(
|
|
26
|
+
value: unknown,
|
|
27
|
+
schema: t.JsonSchemaType | undefined
|
|
28
|
+
): unknown {
|
|
29
|
+
if (schema == null) {
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (schema.type === 'integer' && typeof value === 'string') {
|
|
34
|
+
if (!INTEGER_STRING.test(value)) {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
const parsed = Number(value);
|
|
38
|
+
return Number.isSafeInteger(parsed) ? parsed : value;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
(schema.type === 'number' || schema.type === 'float') &&
|
|
43
|
+
typeof value === 'string'
|
|
44
|
+
) {
|
|
45
|
+
if (!NUMBER_STRING.test(value)) {
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
const parsed = Number(value);
|
|
49
|
+
return Number.isFinite(parsed) && String(parsed) === value
|
|
50
|
+
? parsed
|
|
51
|
+
: value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (schema.type === 'boolean' && typeof value === 'string') {
|
|
55
|
+
if (value === 'true') {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (value === 'false') {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (schema.type === 'array' && Array.isArray(value)) {
|
|
65
|
+
return value.map((item) => coerceValueForSchema(item, schema.items));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (
|
|
69
|
+
schema.type !== 'object' ||
|
|
70
|
+
value == null ||
|
|
71
|
+
typeof value !== 'object' ||
|
|
72
|
+
Array.isArray(value)
|
|
73
|
+
) {
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const record = value as Record<string, unknown>;
|
|
78
|
+
const additionalProperties =
|
|
79
|
+
typeof schema.additionalProperties === 'object'
|
|
80
|
+
? schema.additionalProperties
|
|
81
|
+
: undefined;
|
|
82
|
+
|
|
83
|
+
return Object.fromEntries(
|
|
84
|
+
Object.entries(record).map(([key, entry]) => [
|
|
85
|
+
key,
|
|
86
|
+
coerceValueForSchema(
|
|
87
|
+
entry,
|
|
88
|
+
schema.properties?.[key] ?? additionalProperties
|
|
89
|
+
),
|
|
90
|
+
])
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Applies only lossless, schema-directed repairs to model-generated arguments.
|
|
96
|
+
* The host remains responsible for full schema validation and all business rules.
|
|
97
|
+
*/
|
|
98
|
+
export function coerceArgsForSchema(
|
|
99
|
+
args: Record<string, unknown>,
|
|
100
|
+
schema: t.JsonSchemaType | undefined
|
|
101
|
+
): Record<string, unknown> {
|
|
102
|
+
return coerceValueForSchema(args, schema) as Record<string, unknown>;
|
|
103
|
+
}
|
|
104
|
+
|
|
22
105
|
export function stableStringify(value: unknown): string {
|
|
23
106
|
if (Array.isArray(value)) {
|
|
24
107
|
return `[${value.map((item) => stableStringify(item)).join(',')}]`;
|
|
@@ -87,6 +170,7 @@ export function buildToolExecutionRequestPlan(args: {
|
|
|
87
170
|
usageCount: Map<string, number>;
|
|
88
171
|
invalidArgsBehavior?: 'abort' | 'error-result';
|
|
89
172
|
recordTurn?: (toolName: string, turn: number, callId: string) => void;
|
|
173
|
+
getToolSchema?: (toolName: string) => t.JsonSchemaType | undefined;
|
|
90
174
|
}): ToolExecutionRequestPlan | undefined {
|
|
91
175
|
const invalidArgsBehavior = args.invalidArgsBehavior ?? 'abort';
|
|
92
176
|
const prepared: Array<{
|
|
@@ -103,8 +187,8 @@ export function buildToolExecutionRequestPlan(args: {
|
|
|
103
187
|
if (toolCall.id == null || toolCall.id === '' || toolCall.name === '') {
|
|
104
188
|
return undefined;
|
|
105
189
|
}
|
|
106
|
-
const
|
|
107
|
-
if (
|
|
190
|
+
const recordArgs = coerceRecordArgs(toolCall.args);
|
|
191
|
+
if (recordArgs == null) {
|
|
108
192
|
if (invalidArgsBehavior === 'abort') {
|
|
109
193
|
return undefined;
|
|
110
194
|
}
|
|
@@ -120,6 +204,10 @@ export function buildToolExecutionRequestPlan(args: {
|
|
|
120
204
|
});
|
|
121
205
|
continue;
|
|
122
206
|
}
|
|
207
|
+
const coercedArgs = coerceArgsForSchema(
|
|
208
|
+
recordArgs,
|
|
209
|
+
args.getToolSchema?.(toolCall.name)
|
|
210
|
+
);
|
|
123
211
|
prepared.push({
|
|
124
212
|
id: toolCall.id,
|
|
125
213
|
name: toolCall.name,
|