10xgraph-client 0.6.0 → 1.0.0-rc.2
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/CHANGELOG.md +207 -0
- package/README.md +11 -5
- package/dist/agent.d.ts +17 -5
- package/dist/agent.d.ts.map +1 -1
- package/dist/cjs/agent.d.ts +33 -0
- package/dist/cjs/client.d.ts +533 -0
- package/dist/cjs/compat.d.ts +27 -0
- package/dist/cjs/endpoints/addThreadMessages.d.ts +25 -0
- package/dist/cjs/endpoints/clearThreadState.d.ts +14 -0
- package/dist/cjs/endpoints/deleteFile.d.ts +13 -0
- package/dist/cjs/endpoints/deleteMemory.d.ts +18 -0
- package/dist/cjs/endpoints/deleteThread.d.ts +18 -0
- package/dist/cjs/endpoints/deleteThreadMessage.d.ts +19 -0
- package/dist/cjs/endpoints/files.d.ts +115 -0
- package/dist/cjs/endpoints/fixGraph.d.ts +33 -0
- package/dist/cjs/endpoints/forgetMemories.d.ts +21 -0
- package/dist/cjs/endpoints/getMemory.d.ts +18 -0
- package/dist/cjs/endpoints/graph.d.ts +50 -0
- package/dist/cjs/endpoints/graphTools.d.ts +31 -0
- package/dist/cjs/endpoints/invoke.d.ts +66 -0
- package/dist/cjs/endpoints/listMemories.d.ts +24 -0
- package/dist/cjs/endpoints/metadata.d.ts +5 -0
- package/dist/cjs/endpoints/observability.d.ts +111 -0
- package/dist/cjs/endpoints/ping.d.ts +9 -0
- package/dist/cjs/endpoints/realtime.d.ts +154 -0
- package/dist/cjs/endpoints/searchMemory.d.ts +56 -0
- package/dist/cjs/endpoints/stateSchema.d.ts +49 -0
- package/dist/cjs/endpoints/stopGraph.d.ts +35 -0
- package/dist/cjs/endpoints/storeMemory.d.ts +32 -0
- package/dist/cjs/endpoints/stream.d.ts +67 -0
- package/dist/cjs/endpoints/threadDetails.d.ts +18 -0
- package/dist/cjs/endpoints/threadMessage.d.ts +16 -0
- package/dist/cjs/endpoints/threadMessages.d.ts +28 -0
- package/dist/cjs/endpoints/threadState.d.ts +13 -0
- package/dist/cjs/endpoints/threads.d.ts +35 -0
- package/dist/cjs/endpoints/updateMemory.d.ts +20 -0
- package/dist/cjs/endpoints/updateThreadMessageFeedback.d.ts +19 -0
- package/dist/cjs/endpoints/updateThreadState.d.ts +22 -0
- package/dist/cjs/endpoints/wsStream.d.ts +34 -0
- package/dist/cjs/errors.d.ts +212 -0
- package/dist/cjs/index.d.ts +41 -0
- package/dist/cjs/interrupt.d.ts +45 -0
- package/dist/cjs/message.d.ts +173 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/request.d.ts +60 -0
- package/dist/cjs/tools.d.ts +80 -0
- package/dist/cjs/ws.d.ts +47 -0
- package/dist/client.d.ts +95 -40
- package/dist/client.d.ts.map +1 -1
- package/dist/endpoints/addThreadMessages.d.ts +4 -0
- package/dist/endpoints/addThreadMessages.d.ts.map +1 -1
- package/dist/endpoints/clearThreadState.d.ts.map +1 -1
- package/dist/endpoints/deleteFile.d.ts +14 -0
- package/dist/endpoints/deleteFile.d.ts.map +1 -0
- package/dist/endpoints/deleteMemory.d.ts.map +1 -1
- package/dist/endpoints/deleteThread.d.ts.map +1 -1
- package/dist/endpoints/deleteThreadMessage.d.ts.map +1 -1
- package/dist/endpoints/files.d.ts +33 -0
- package/dist/endpoints/files.d.ts.map +1 -1
- package/dist/endpoints/fixGraph.d.ts +8 -3
- package/dist/endpoints/fixGraph.d.ts.map +1 -1
- package/dist/endpoints/forgetMemories.d.ts.map +1 -1
- package/dist/endpoints/getMemory.d.ts.map +1 -1
- package/dist/endpoints/graph.d.ts +20 -8
- package/dist/endpoints/graph.d.ts.map +1 -1
- package/dist/endpoints/graphTools.d.ts.map +1 -1
- package/dist/endpoints/invoke.d.ts +8 -0
- package/dist/endpoints/invoke.d.ts.map +1 -1
- package/dist/endpoints/listMemories.d.ts +6 -0
- package/dist/endpoints/listMemories.d.ts.map +1 -1
- package/dist/endpoints/observability.d.ts +54 -0
- package/dist/endpoints/observability.d.ts.map +1 -1
- package/dist/endpoints/ping.d.ts.map +1 -1
- package/dist/endpoints/realtime.d.ts +25 -4
- package/dist/endpoints/realtime.d.ts.map +1 -1
- package/dist/endpoints/searchMemory.d.ts.map +1 -1
- package/dist/endpoints/stateSchema.d.ts.map +1 -1
- package/dist/endpoints/stopGraph.d.ts +13 -3
- package/dist/endpoints/stopGraph.d.ts.map +1 -1
- package/dist/endpoints/storeMemory.d.ts.map +1 -1
- package/dist/endpoints/stream.d.ts +8 -0
- package/dist/endpoints/stream.d.ts.map +1 -1
- package/dist/endpoints/threadDetails.d.ts.map +1 -1
- package/dist/endpoints/threadMessage.d.ts.map +1 -1
- package/dist/endpoints/threadMessages.d.ts +6 -0
- package/dist/endpoints/threadMessages.d.ts.map +1 -1
- package/dist/endpoints/threadState.d.ts.map +1 -1
- package/dist/endpoints/threads.d.ts +6 -0
- package/dist/endpoints/threads.d.ts.map +1 -1
- package/dist/endpoints/updateMemory.d.ts.map +1 -1
- package/dist/endpoints/updateThreadMessageFeedback.d.ts +20 -0
- package/dist/endpoints/updateThreadMessageFeedback.d.ts.map +1 -0
- package/dist/endpoints/updateThreadState.d.ts +6 -1
- package/dist/endpoints/updateThreadState.d.ts.map +1 -1
- package/dist/endpoints/wsStream.d.ts +2 -0
- package/dist/endpoints/wsStream.d.ts.map +1 -1
- package/dist/errors.d.ts +60 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1742 -1217
- package/dist/index.js.map +1 -1
- package/dist/interrupt.d.ts +46 -0
- package/dist/interrupt.d.ts.map +1 -0
- package/dist/request.d.ts +28 -0
- package/dist/request.d.ts.map +1 -1
- package/dist/tools.d.ts +14 -0
- package/dist/tools.d.ts.map +1 -1
- package/package.json +11 -6
- package/src/agent.ts +17 -4
- package/src/client.ts +248 -128
- package/src/endpoints/addThreadMessages.ts +15 -10
- package/src/endpoints/clearThreadState.ts +19 -20
- package/src/endpoints/deleteFile.ts +65 -0
- package/src/endpoints/deleteMemory.ts +9 -13
- package/src/endpoints/deleteThread.ts +9 -13
- package/src/endpoints/deleteThreadMessage.ts +9 -13
- package/src/endpoints/files.ts +164 -131
- package/src/endpoints/fixGraph.ts +15 -16
- package/src/endpoints/forgetMemories.ts +44 -60
- package/src/endpoints/getMemory.ts +9 -9
- package/src/endpoints/graph.ts +28 -21
- package/src/endpoints/graphTools.ts +7 -13
- package/src/endpoints/invoke.ts +105 -84
- package/src/endpoints/listMemories.ts +18 -13
- package/src/endpoints/observability.ts +77 -34
- package/src/endpoints/ping.ts +7 -13
- package/src/endpoints/realtime.ts +101 -39
- package/src/endpoints/searchMemory.ts +19 -13
- package/src/endpoints/stateSchema.ts +7 -13
- package/src/endpoints/stopGraph.ts +20 -16
- package/src/endpoints/storeMemory.ts +7 -8
- package/src/endpoints/stream.ts +179 -61
- package/src/endpoints/threadDetails.ts +9 -14
- package/src/endpoints/threadMessage.ts +9 -9
- package/src/endpoints/threadMessages.ts +15 -9
- package/src/endpoints/threadState.ts +19 -20
- package/src/endpoints/threads.ts +13 -12
- package/src/endpoints/updateMemory.ts +9 -9
- package/src/endpoints/updateThreadMessageFeedback.ts +80 -0
- package/src/endpoints/updateThreadState.ts +28 -22
- package/src/endpoints/wsStream.ts +167 -42
- package/src/errors.ts +332 -93
- package/src/index.ts +9 -0
- package/src/interrupt.ts +60 -0
- package/src/request.ts +134 -0
- package/src/tools.ts +95 -0
package/src/request.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { WebSocketImpl } from './ws.js';
|
|
2
|
+
import { NetworkError, RequestTimeoutError, TenxGraphError } from './errors.js';
|
|
2
3
|
|
|
3
4
|
export interface TenxGraphBearerAuth {
|
|
4
5
|
type: 'bearer';
|
|
@@ -20,6 +21,30 @@ export interface TenxGraphHeaderAuth {
|
|
|
20
21
|
|
|
21
22
|
export type TenxGraphAuth = TenxGraphBearerAuth | TenxGraphBasicAuth | TenxGraphHeaderAuth;
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Abort `controller` when the caller's `signal` aborts. Returns a cleanup function.
|
|
26
|
+
* A signal that is already aborted aborts the controller immediately.
|
|
27
|
+
*/
|
|
28
|
+
export function linkAbortSignal(
|
|
29
|
+
controller: AbortController,
|
|
30
|
+
signal?: AbortSignal | null
|
|
31
|
+
): () => void {
|
|
32
|
+
if (!signal) return () => {};
|
|
33
|
+
if (signal.aborted) {
|
|
34
|
+
controller.abort();
|
|
35
|
+
return () => {};
|
|
36
|
+
}
|
|
37
|
+
const onAbort = (): void => controller.abort();
|
|
38
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
39
|
+
return () => signal.removeEventListener('abort', onAbort);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Per-call options accepted by every client method that makes a request. */
|
|
43
|
+
export interface RequestOptions {
|
|
44
|
+
/** Abort to cancel the request. Rejects with the signal's AbortError, never as a timeout. */
|
|
45
|
+
signal?: AbortSignal;
|
|
46
|
+
}
|
|
47
|
+
|
|
23
48
|
export interface RequestContext {
|
|
24
49
|
baseUrl: string;
|
|
25
50
|
authToken?: string | null;
|
|
@@ -29,6 +54,8 @@ export interface RequestContext {
|
|
|
29
54
|
timeout: number;
|
|
30
55
|
debug: boolean;
|
|
31
56
|
webSocketImpl?: WebSocketImpl;
|
|
57
|
+
/** Caller's cancellation signal for this call. Set per call by the client, not stored. */
|
|
58
|
+
signal?: AbortSignal;
|
|
32
59
|
}
|
|
33
60
|
|
|
34
61
|
function setHeader(
|
|
@@ -166,3 +193,110 @@ export function headerAuth(
|
|
|
166
193
|
): TenxGraphHeaderAuth {
|
|
167
194
|
return { type: 'header', name, value, prefix };
|
|
168
195
|
}
|
|
196
|
+
|
|
197
|
+
/** Percent-encode one URL path segment (thread, message or memory id). */
|
|
198
|
+
export function encodePathSegment(value: string | number): string {
|
|
199
|
+
return encodeURIComponent(String(value));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Strip trailing slashes so `${baseUrl}/path` never produces `//path`. */
|
|
203
|
+
export function normalizeBaseUrl(baseUrl: string): string {
|
|
204
|
+
// A loop, not /\/+$/: that regex is quadratic on input with many slashes (CodeQL js/polynomial-redos).
|
|
205
|
+
let end = baseUrl.length;
|
|
206
|
+
while (end > 0 && baseUrl.charCodeAt(end - 1) === 47 /* '/' */) end--;
|
|
207
|
+
return baseUrl.slice(0, end);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const MAX_REDIRECTS = 5;
|
|
211
|
+
|
|
212
|
+
function originOf(url: string): string | null {
|
|
213
|
+
try {
|
|
214
|
+
return new URL(url).origin;
|
|
215
|
+
} catch {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function pathOf(url: string): string {
|
|
221
|
+
try {
|
|
222
|
+
return new URL(url).pathname;
|
|
223
|
+
} catch {
|
|
224
|
+
return url;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* fetch with the shared client policy:
|
|
230
|
+
* - the timeout timer is always cleared (also when fetch rejects) and does not keep a Node
|
|
231
|
+
* process alive;
|
|
232
|
+
* - `context.signal` cancels the call (rejects with the AbortError, never as a timeout);
|
|
233
|
+
* - a timeout throws RequestTimeoutError, any other fetch rejection throws NetworkError
|
|
234
|
+
* with the original error as `cause`;
|
|
235
|
+
* - with header-type credentials other than Authorization (e.g. X-API-Key, which fetch does not
|
|
236
|
+
* strip on a redirect)
|
|
237
|
+
* redirects are followed only within the same origin; a cross-origin redirect is refused.
|
|
238
|
+
*/
|
|
239
|
+
export async function fetchWithTimeout(
|
|
240
|
+
context: Pick<RequestContext, 'timeout' | 'signal' | 'auth'>,
|
|
241
|
+
url: string,
|
|
242
|
+
init: RequestInit = {}
|
|
243
|
+
): Promise<Response> {
|
|
244
|
+
const controller = new AbortController();
|
|
245
|
+
const timer =
|
|
246
|
+
context.timeout > 0 ? setTimeout(() => controller.abort(), context.timeout) : undefined;
|
|
247
|
+
(timer as unknown as { unref?: () => void } | undefined)?.unref?.();
|
|
248
|
+
const unlink = linkAbortSignal(controller, context.signal);
|
|
249
|
+
const method = (init.method || 'GET').toUpperCase();
|
|
250
|
+
// fetch strips the standard Authorization header on a cross-origin redirect (checked against
|
|
251
|
+
// Node's undici), but forwards any other custom header, so only those need the guard.
|
|
252
|
+
const guardRedirects =
|
|
253
|
+
context.auth?.type === 'header' && context.auth.name.toLowerCase() !== 'authorization';
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
let currentUrl = url;
|
|
257
|
+
let currentInit: RequestInit = { ...init, signal: controller.signal };
|
|
258
|
+
if (guardRedirects) currentInit.redirect = 'manual';
|
|
259
|
+
|
|
260
|
+
for (let hops = 0; ; hops++) {
|
|
261
|
+
const response = await fetch(currentUrl, currentInit);
|
|
262
|
+
if (guardRedirects && response.type === 'opaqueredirect') {
|
|
263
|
+
// Browsers hide the Location of a manual redirect, so it cannot be followed or checked.
|
|
264
|
+
throw new NetworkError(
|
|
265
|
+
'The server redirected the request and the browser does not expose the target, so it ' +
|
|
266
|
+
'was not followed (header credentials must not be sent to another origin). ' +
|
|
267
|
+
'Point baseUrl at the final URL.',
|
|
268
|
+
pathOf(url),
|
|
269
|
+
method
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
if (!guardRedirects || !(response.status >= 300 && response.status < 400)) {
|
|
273
|
+
return response;
|
|
274
|
+
}
|
|
275
|
+
const location = response.headers?.get('location');
|
|
276
|
+
const target = location ? new URL(location, currentUrl).toString() : null;
|
|
277
|
+
if (!target || originOf(target) !== originOf(url) || hops >= MAX_REDIRECTS) {
|
|
278
|
+
throw new NetworkError(
|
|
279
|
+
'Refusing to follow a redirect that leaves the base URL origin (credentials would be forwarded)',
|
|
280
|
+
pathOf(url),
|
|
281
|
+
method
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
currentUrl = target;
|
|
285
|
+
if (response.status === 303) {
|
|
286
|
+
currentInit = { ...currentInit, method: 'GET', body: undefined };
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
} catch (error) {
|
|
290
|
+
if (error instanceof TenxGraphError) throw error;
|
|
291
|
+
const name = (error as { name?: string } | null)?.name;
|
|
292
|
+
if (name === 'AbortError') {
|
|
293
|
+
if (context.signal?.aborted) throw error;
|
|
294
|
+
throw new RequestTimeoutError(context.timeout, pathOf(url), method, error);
|
|
295
|
+
}
|
|
296
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
297
|
+
throw new NetworkError(`Network request failed: ${detail}`, pathOf(url), method, error);
|
|
298
|
+
} finally {
|
|
299
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
300
|
+
unlink();
|
|
301
|
+
}
|
|
302
|
+
}
|
package/src/tools.ts
CHANGED
|
@@ -52,6 +52,56 @@ export interface ToolRegistration {
|
|
|
52
52
|
description?: string;
|
|
53
53
|
parameters?: ToolParameter;
|
|
54
54
|
handler: ToolHandler;
|
|
55
|
+
/**
|
|
56
|
+
* Runs on the server-sent arguments before the handler (after the declared `parameters`
|
|
57
|
+
* check). Throw, or return `false`, to reject the call: the model receives a failed tool
|
|
58
|
+
* result and the handler is not run.
|
|
59
|
+
*/
|
|
60
|
+
validate?: (args: any) => boolean | void | Promise<boolean | void>;
|
|
61
|
+
/** Reject calls whose JSON-serialised arguments exceed this many bytes. Default 1 MiB. */
|
|
62
|
+
maxArgsBytes?: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Default cap on serialised tool-call arguments. */
|
|
66
|
+
export const DEFAULT_MAX_TOOL_ARGS_BYTES = 1024 * 1024;
|
|
67
|
+
|
|
68
|
+
/** Check `args` against the top level of a declared JSON Schema; returns an error message or null. */
|
|
69
|
+
export function checkToolArguments(args: unknown, parameters?: ToolParameter): string | null {
|
|
70
|
+
if (!parameters) return null;
|
|
71
|
+
if (args === null || typeof args !== 'object' || Array.isArray(args)) {
|
|
72
|
+
return 'arguments must be an object';
|
|
73
|
+
}
|
|
74
|
+
const record = args as Record<string, unknown>;
|
|
75
|
+
for (const key of parameters.required ?? []) {
|
|
76
|
+
if (!(key in record)) return `missing required argument '${key}'`;
|
|
77
|
+
}
|
|
78
|
+
const properties = parameters.properties ?? {};
|
|
79
|
+
if (parameters.additionalProperties === false) {
|
|
80
|
+
for (const key of Object.keys(record)) {
|
|
81
|
+
if (!(key in properties)) return `unexpected argument '${key}'`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
for (const [key, schema] of Object.entries(properties)) {
|
|
85
|
+
const value = record[key];
|
|
86
|
+
const expected = (schema as { type?: unknown } | null)?.type;
|
|
87
|
+
if (value === undefined || typeof expected !== 'string') continue;
|
|
88
|
+
const ok =
|
|
89
|
+
expected === 'string'
|
|
90
|
+
? typeof value === 'string'
|
|
91
|
+
: expected === 'number'
|
|
92
|
+
? typeof value === 'number'
|
|
93
|
+
: expected === 'integer'
|
|
94
|
+
? Number.isInteger(value)
|
|
95
|
+
: expected === 'boolean'
|
|
96
|
+
? typeof value === 'boolean'
|
|
97
|
+
: expected === 'array'
|
|
98
|
+
? Array.isArray(value)
|
|
99
|
+
: expected === 'object'
|
|
100
|
+
? value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
101
|
+
: true;
|
|
102
|
+
if (!ok) return `argument '${key}' must be of type ${expected}`;
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
55
105
|
}
|
|
56
106
|
|
|
57
107
|
// Internal tool definition (extends handler)
|
|
@@ -60,6 +110,8 @@ export interface ToolDefinition extends ToolHandler {
|
|
|
60
110
|
description?: string;
|
|
61
111
|
parameters?: ToolParameter;
|
|
62
112
|
node?: string;
|
|
113
|
+
validate?: ToolRegistration['validate'];
|
|
114
|
+
maxArgsBytes?: number;
|
|
63
115
|
}
|
|
64
116
|
|
|
65
117
|
export class ToolExecutor {
|
|
@@ -108,6 +160,16 @@ export class ToolExecutor {
|
|
|
108
160
|
writable: true,
|
|
109
161
|
configurable: true,
|
|
110
162
|
});
|
|
163
|
+
Object.defineProperty(toolDef, 'validate', {
|
|
164
|
+
value: registration.validate,
|
|
165
|
+
writable: true,
|
|
166
|
+
configurable: true,
|
|
167
|
+
});
|
|
168
|
+
Object.defineProperty(toolDef, 'maxArgsBytes', {
|
|
169
|
+
value: registration.maxArgsBytes,
|
|
170
|
+
writable: true,
|
|
171
|
+
configurable: true,
|
|
172
|
+
});
|
|
111
173
|
Object.defineProperty(toolDef, 'node', {
|
|
112
174
|
value: registration.node,
|
|
113
175
|
writable: true,
|
|
@@ -174,14 +236,47 @@ export class ToolExecutor {
|
|
|
174
236
|
|
|
175
237
|
const results: Message[] = [];
|
|
176
238
|
|
|
239
|
+
const seenCallIds = new Set<string>();
|
|
240
|
+
const failed = (callId: string, error: string): Message =>
|
|
241
|
+
Message.tool_message([
|
|
242
|
+
new ToolResultBlock({
|
|
243
|
+
call_id: callId,
|
|
244
|
+
output: { error },
|
|
245
|
+
status: 'failed',
|
|
246
|
+
is_error: true,
|
|
247
|
+
}),
|
|
248
|
+
]);
|
|
249
|
+
|
|
177
250
|
// Execute each tool call
|
|
178
251
|
for (const call of toolCalls) {
|
|
179
252
|
const toolName = call.name;
|
|
180
253
|
|
|
254
|
+
if (call.id && seenCallIds.has(call.id)) {
|
|
255
|
+
results.push(failed(call.id, `Duplicate tool call id '${call.id}' rejected`));
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (call.id) seenCallIds.add(call.id);
|
|
259
|
+
|
|
181
260
|
if (this.tools.has(toolName)) {
|
|
182
261
|
const tool = this.tools.get(toolName)!;
|
|
183
262
|
|
|
184
263
|
try {
|
|
264
|
+
const maxBytes = tool.maxArgsBytes ?? DEFAULT_MAX_TOOL_ARGS_BYTES;
|
|
265
|
+
const size = JSON.stringify(call.args ?? null)?.length ?? 0;
|
|
266
|
+
if (size > maxBytes) {
|
|
267
|
+
results.push(failed(call.id, `Arguments for '${toolName}' exceed ${maxBytes} bytes`));
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const invalid = checkToolArguments(call.args ?? {}, tool.parameters);
|
|
271
|
+
if (invalid) {
|
|
272
|
+
results.push(failed(call.id, `Invalid arguments for '${toolName}': ${invalid}`));
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
if (tool.validate && (await tool.validate(call.args)) === false) {
|
|
276
|
+
results.push(failed(call.id, `Arguments for '${toolName}' were rejected`));
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
|
|
185
280
|
// Execute the tool
|
|
186
281
|
const result = await tool(call.args);
|
|
187
282
|
|