@axlsdk/axl 0.20.1 → 0.21.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 +7 -0
- package/dist/index.cjs +340 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -50
- package/dist/index.d.ts +64 -50
- package/dist/index.js +340 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -171,6 +171,221 @@ var ValidationError = class extends AxlError {
|
|
|
171
171
|
|
|
172
172
|
// src/tool.ts
|
|
173
173
|
var DEFAULT_MAX_STRING_LENGTH = 1e4;
|
|
174
|
+
var MAX_MODEL_ARGUMENT_ISSUES = 8;
|
|
175
|
+
var MAX_MODEL_ARGUMENT_MESSAGE_LENGTH = 2e3;
|
|
176
|
+
var MAX_MODEL_ARGUMENT_LINE_LENGTH = 220;
|
|
177
|
+
var MAX_MODEL_ARGUMENT_PATH_LENGTH = 160;
|
|
178
|
+
var MAX_UNION_DEPTH = 3;
|
|
179
|
+
var MAX_UNION_BRANCHES = 4;
|
|
180
|
+
var MAX_LITERAL_ALTERNATIVES = 10;
|
|
181
|
+
var SAFE_SCHEMA_TYPES = /* @__PURE__ */ new Set([
|
|
182
|
+
"string",
|
|
183
|
+
"number",
|
|
184
|
+
"boolean",
|
|
185
|
+
"null",
|
|
186
|
+
"array",
|
|
187
|
+
"object",
|
|
188
|
+
"integer"
|
|
189
|
+
]);
|
|
190
|
+
var SAFE_STRING_FORMATS = /* @__PURE__ */ new Set([
|
|
191
|
+
"email",
|
|
192
|
+
"url",
|
|
193
|
+
"emoji",
|
|
194
|
+
"uuid",
|
|
195
|
+
"guid",
|
|
196
|
+
"nanoid",
|
|
197
|
+
"cuid",
|
|
198
|
+
"cuid2",
|
|
199
|
+
"ulid",
|
|
200
|
+
"xid",
|
|
201
|
+
"ksuid",
|
|
202
|
+
"datetime",
|
|
203
|
+
"date",
|
|
204
|
+
"time",
|
|
205
|
+
"duration",
|
|
206
|
+
"ipv4",
|
|
207
|
+
"ipv6",
|
|
208
|
+
"cidrv4",
|
|
209
|
+
"cidrv6",
|
|
210
|
+
"base64",
|
|
211
|
+
"base64url",
|
|
212
|
+
"json_string",
|
|
213
|
+
"e164",
|
|
214
|
+
"lowercase",
|
|
215
|
+
"uppercase",
|
|
216
|
+
"jwt"
|
|
217
|
+
]);
|
|
218
|
+
function truncateModelFeedback(value, maximum) {
|
|
219
|
+
return value.length <= maximum ? value : `${value.slice(0, Math.max(0, maximum - 1))}\u2026`;
|
|
220
|
+
}
|
|
221
|
+
var DISPLAY_CONTROL_CHARACTERS = /[\u061C\u200B-\u200F\u202A-\u202E\u2066-\u2069\u2028\u2029]/g;
|
|
222
|
+
function isJsonSchema(value) {
|
|
223
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
224
|
+
}
|
|
225
|
+
function escapeDisplayControls(value) {
|
|
226
|
+
return value.replace(
|
|
227
|
+
DISPLAY_CONTROL_CHARACTERS,
|
|
228
|
+
(character) => `\\u${character.codePointAt(0).toString(16).padStart(4, "0")}`
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
function quoteModelText(value) {
|
|
232
|
+
return escapeDisplayControls(JSON.stringify(value));
|
|
233
|
+
}
|
|
234
|
+
function schemaNumber(value) {
|
|
235
|
+
return typeof value === "number" && Number.isFinite(value) ? String(value) : void 0;
|
|
236
|
+
}
|
|
237
|
+
function schemaLiteral(value) {
|
|
238
|
+
if (typeof value === "string") {
|
|
239
|
+
const rendered = quoteModelText(value);
|
|
240
|
+
return rendered.length <= 120 ? rendered : '"<literal omitted>"';
|
|
241
|
+
}
|
|
242
|
+
if (typeof value === "number") return Number.isFinite(value) ? String(value) : void 0;
|
|
243
|
+
if (typeof value === "boolean") return String(value);
|
|
244
|
+
if (value === null) return "null";
|
|
245
|
+
return void 0;
|
|
246
|
+
}
|
|
247
|
+
function schemaType(schema) {
|
|
248
|
+
const type = schema.type;
|
|
249
|
+
return typeof type === "string" && SAFE_SCHEMA_TYPES.has(type) ? type : void 0;
|
|
250
|
+
}
|
|
251
|
+
function compositionBranches(schema) {
|
|
252
|
+
const branches = [];
|
|
253
|
+
for (const key of ["anyOf", "oneOf", "allOf"]) {
|
|
254
|
+
const value = schema[key];
|
|
255
|
+
if (!Array.isArray(value)) continue;
|
|
256
|
+
for (const branch of value.slice(0, MAX_UNION_BRANCHES)) {
|
|
257
|
+
if (isJsonSchema(branch)) branches.push(branch);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return branches;
|
|
261
|
+
}
|
|
262
|
+
function unionBranches(schema) {
|
|
263
|
+
const branches = [];
|
|
264
|
+
for (const key of ["anyOf", "oneOf"]) {
|
|
265
|
+
const value = schema[key];
|
|
266
|
+
if (!Array.isArray(value)) continue;
|
|
267
|
+
for (const branch of value.slice(0, MAX_UNION_BRANCHES)) {
|
|
268
|
+
if (isJsonSchema(branch)) branches.push(branch);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return branches;
|
|
272
|
+
}
|
|
273
|
+
function resolvePathSegment(schema, segment, depth = 0) {
|
|
274
|
+
if (depth >= MAX_UNION_DEPTH) return void 0;
|
|
275
|
+
if (typeof segment === "string") {
|
|
276
|
+
const properties = schema.properties;
|
|
277
|
+
if (isJsonSchema(properties) && Object.hasOwn(properties, segment)) {
|
|
278
|
+
const child = properties[segment];
|
|
279
|
+
if (isJsonSchema(child)) return { node: child, renderedSegment: segment };
|
|
280
|
+
}
|
|
281
|
+
if (isJsonSchema(schema.additionalProperties)) {
|
|
282
|
+
return { node: schema.additionalProperties, renderedSegment: "<key>" };
|
|
283
|
+
}
|
|
284
|
+
} else if (typeof segment === "number" && Number.isSafeInteger(segment) && segment >= 0) {
|
|
285
|
+
const prefixItems = schema.prefixItems;
|
|
286
|
+
if (Array.isArray(prefixItems) && isJsonSchema(prefixItems[segment])) {
|
|
287
|
+
return { node: prefixItems[segment], renderedSegment: String(segment) };
|
|
288
|
+
}
|
|
289
|
+
if (isJsonSchema(schema.items)) {
|
|
290
|
+
return { node: schema.items, renderedSegment: "<index>" };
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
for (const branch of compositionBranches(schema)) {
|
|
294
|
+
const resolved = resolvePathSegment(branch, segment, depth + 1);
|
|
295
|
+
if (resolved !== void 0) return resolved;
|
|
296
|
+
}
|
|
297
|
+
return void 0;
|
|
298
|
+
}
|
|
299
|
+
function resolveSchemaPath(providerVisibleSchema, issuePath) {
|
|
300
|
+
if (!isJsonSchema(providerVisibleSchema)) return void 0;
|
|
301
|
+
let node = providerVisibleSchema;
|
|
302
|
+
const segments = [];
|
|
303
|
+
for (const segment of issuePath) {
|
|
304
|
+
const resolved = resolvePathSegment(node, segment);
|
|
305
|
+
if (resolved === void 0) {
|
|
306
|
+
segments.push("<path omitted>");
|
|
307
|
+
return { node, segments };
|
|
308
|
+
}
|
|
309
|
+
node = resolved.node;
|
|
310
|
+
segments.push(resolved.renderedSegment);
|
|
311
|
+
}
|
|
312
|
+
return { node, segments };
|
|
313
|
+
}
|
|
314
|
+
function jsonPointerPath(segments) {
|
|
315
|
+
if (segments.length === 0) return "<root>";
|
|
316
|
+
const pointer = `/${segments.map((segment) => segment.replaceAll("~", "~0").replaceAll("/", "~1")).join("/")}`;
|
|
317
|
+
const rendered = quoteModelText(pointer);
|
|
318
|
+
return rendered.length <= MAX_MODEL_ARGUMENT_PATH_LENGTH ? rendered : '"<path omitted>"';
|
|
319
|
+
}
|
|
320
|
+
function schemaAlternatives(schema, depth = 0) {
|
|
321
|
+
if (depth >= MAX_UNION_DEPTH) return [];
|
|
322
|
+
const constant = "const" in schema ? schemaLiteral(schema.const) : void 0;
|
|
323
|
+
if (constant !== void 0) return [constant];
|
|
324
|
+
if (Array.isArray(schema.enum)) {
|
|
325
|
+
const values = schema.enum.slice(0, MAX_LITERAL_ALTERNATIVES).map(schemaLiteral);
|
|
326
|
+
if (values.every((value) => value !== void 0)) return values;
|
|
327
|
+
}
|
|
328
|
+
const type = schemaType(schema);
|
|
329
|
+
if (type !== void 0) return [type];
|
|
330
|
+
const alternatives = unionBranches(schema).flatMap(
|
|
331
|
+
(branch) => schemaAlternatives(branch, depth + 1)
|
|
332
|
+
);
|
|
333
|
+
return alternatives.slice(0, MAX_LITERAL_ALTERNATIVES);
|
|
334
|
+
}
|
|
335
|
+
function schemaEnumExpectation(schema) {
|
|
336
|
+
if ("const" in schema) {
|
|
337
|
+
const constant = schemaLiteral(schema.const);
|
|
338
|
+
return constant === void 0 ? void 0 : `expected ${constant}`;
|
|
339
|
+
}
|
|
340
|
+
if (!Array.isArray(schema.enum)) return void 0;
|
|
341
|
+
const values = schema.enum.slice(0, MAX_LITERAL_ALTERNATIVES).map(schemaLiteral);
|
|
342
|
+
if (values.some((value) => value === void 0)) return void 0;
|
|
343
|
+
const rendered = values;
|
|
344
|
+
if (rendered.length === 0) return void 0;
|
|
345
|
+
const omission = schema.enum.length > rendered.length ? ", \u2026" : "";
|
|
346
|
+
return `expected ${rendered.length === 1 ? rendered[0] : `one of ${rendered.join(", ")}`}${omission}`;
|
|
347
|
+
}
|
|
348
|
+
function schemaTypeExpectation(schema) {
|
|
349
|
+
const type = schemaType(schema);
|
|
350
|
+
if (type !== void 0) return `expected ${type}`;
|
|
351
|
+
const alternatives = schemaAlternatives(schema);
|
|
352
|
+
return alternatives.length === 0 ? void 0 : `expected one of: ${alternatives.join(", ")}`;
|
|
353
|
+
}
|
|
354
|
+
function schemaSizeExpectation(schema, direction) {
|
|
355
|
+
const type = schemaType(schema);
|
|
356
|
+
const keyword = direction === "small" ? type === "string" ? "minLength" : type === "array" ? "minItems" : "minimum" : type === "string" ? "maxLength" : type === "array" ? "maxItems" : "maximum";
|
|
357
|
+
const value = schemaNumber(schema[keyword]);
|
|
358
|
+
if (value === void 0) return void 0;
|
|
359
|
+
const label = type === "string" ? "string length" : type === "array" ? "array length" : type;
|
|
360
|
+
if (label === void 0) return void 0;
|
|
361
|
+
return `expected ${label} ${direction === "small" ? "at least" : "at most"} ${value}`;
|
|
362
|
+
}
|
|
363
|
+
function schemaExpectation(schema, issueCode) {
|
|
364
|
+
switch (issueCode) {
|
|
365
|
+
case "invalid_type":
|
|
366
|
+
return schemaTypeExpectation(schema) ?? "failed structural validation";
|
|
367
|
+
case "invalid_value":
|
|
368
|
+
return schemaEnumExpectation(schema) ?? schemaTypeExpectation(schema) ?? "failed structural validation";
|
|
369
|
+
case "too_small":
|
|
370
|
+
return schemaSizeExpectation(schema, "small") ?? schemaTypeExpectation(schema) ?? "failed structural validation";
|
|
371
|
+
case "too_big":
|
|
372
|
+
return schemaSizeExpectation(schema, "big") ?? schemaTypeExpectation(schema) ?? "failed structural validation";
|
|
373
|
+
case "not_multiple_of": {
|
|
374
|
+
const multipleOf = schemaNumber(schema.multipleOf);
|
|
375
|
+
return multipleOf === void 0 ? schemaTypeExpectation(schema) ?? "failed structural validation" : `expected a multiple of ${multipleOf}`;
|
|
376
|
+
}
|
|
377
|
+
case "invalid_format": {
|
|
378
|
+
const format = schema.format;
|
|
379
|
+
return typeof format === "string" && SAFE_STRING_FORMATS.has(format) ? `expected valid ${format} format` : schemaTypeExpectation(schema) ?? "failed structural validation";
|
|
380
|
+
}
|
|
381
|
+
case "invalid_union":
|
|
382
|
+
return schemaTypeExpectation(schema) ?? "failed structural validation";
|
|
383
|
+
default: {
|
|
384
|
+
const typeExpectation = schemaTypeExpectation(schema);
|
|
385
|
+
return typeExpectation === void 0 ? "failed structural validation" : `failed structural validation; ${typeExpectation}`;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
174
389
|
var ToolStringLengthError = class extends Error {
|
|
175
390
|
constructor(path, actual, maximum) {
|
|
176
391
|
const renderedPath = path.reduce(
|
|
@@ -186,6 +401,42 @@ var ToolStringLengthError = class extends Error {
|
|
|
186
401
|
this.name = "ToolStringLengthError";
|
|
187
402
|
}
|
|
188
403
|
};
|
|
404
|
+
function toolArgumentModelMessage(error, providerVisibleSchema) {
|
|
405
|
+
try {
|
|
406
|
+
let lines;
|
|
407
|
+
let omitted = false;
|
|
408
|
+
if (error instanceof ZodError) {
|
|
409
|
+
if (error.issues.length === 0) return void 0;
|
|
410
|
+
lines = [];
|
|
411
|
+
for (const issue of error.issues.slice(0, MAX_MODEL_ARGUMENT_ISSUES)) {
|
|
412
|
+
const resolved = resolveSchemaPath(providerVisibleSchema, issue.path);
|
|
413
|
+
if (resolved === void 0) return void 0;
|
|
414
|
+
const path = jsonPointerPath(resolved.segments);
|
|
415
|
+
const expectation = schemaExpectation(resolved.node, issue.code);
|
|
416
|
+
lines.push(
|
|
417
|
+
truncateModelFeedback(`- ${path}: ${expectation}`, MAX_MODEL_ARGUMENT_LINE_LENGTH)
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
omitted = error.issues.length > lines.length;
|
|
421
|
+
} else if (error instanceof ToolStringLengthError) {
|
|
422
|
+
const resolved = resolveSchemaPath(providerVisibleSchema, error.path);
|
|
423
|
+
const maximum = schemaNumber(error.maximum);
|
|
424
|
+
if (resolved === void 0 || maximum === void 0) return void 0;
|
|
425
|
+
const path = jsonPointerPath(resolved.segments);
|
|
426
|
+
lines = [`- ${path}: maximum string length is ${maximum}`];
|
|
427
|
+
} else {
|
|
428
|
+
return void 0;
|
|
429
|
+
}
|
|
430
|
+
const header = "Error: Invalid tool arguments:";
|
|
431
|
+
const footer = "Correct the arguments and try again.";
|
|
432
|
+
const omission = omitted ? "Additional validation issues were omitted." : void 0;
|
|
433
|
+
const parts = [header, ...lines, ...omission ? [omission] : [], footer];
|
|
434
|
+
const message = parts.join("\n");
|
|
435
|
+
return message.length <= MAX_MODEL_ARGUMENT_MESSAGE_LENGTH ? message : void 0;
|
|
436
|
+
} catch {
|
|
437
|
+
return void 0;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
189
440
|
function validateStringLengths(value, maxLen, path = []) {
|
|
190
441
|
if (typeof value === "string") {
|
|
191
442
|
if (value.length > maxLen) {
|
|
@@ -496,7 +747,7 @@ async function fetchWithRetry(input, init, opts) {
|
|
|
496
747
|
for (let attempt = 0; ; attempt++) {
|
|
497
748
|
let res;
|
|
498
749
|
try {
|
|
499
|
-
res = await fetch(input, init);
|
|
750
|
+
res = await fetch(input, { ...init, redirect: "manual" });
|
|
500
751
|
} catch (err) {
|
|
501
752
|
if (isAbortError2(err, init?.signal ?? void 0)) throw err;
|
|
502
753
|
if (attempt >= maxRetries) {
|
|
@@ -702,6 +953,38 @@ function isBuiltinTablePricingEligible(profile, context) {
|
|
|
702
953
|
return typeof effectiveTier === "string" && policy.supportedServiceTiers.includes(effectiveTier);
|
|
703
954
|
}
|
|
704
955
|
|
|
956
|
+
// src/http-transport.ts
|
|
957
|
+
function assertSafeProviderBaseUrl(baseUrl, surface, dangerouslyAllowInsecureHttp = false) {
|
|
958
|
+
assertSafeHttpEndpoint(baseUrl, surface, dangerouslyAllowInsecureHttp, "prompts and credentials");
|
|
959
|
+
}
|
|
960
|
+
function assertSafeHttpEndpoint(endpoint, surface, dangerouslyAllowInsecureHttp = false, exposedData = "sensitive data") {
|
|
961
|
+
let url;
|
|
962
|
+
try {
|
|
963
|
+
url = new URL(endpoint);
|
|
964
|
+
} catch {
|
|
965
|
+
throw unsafeTransportError(surface, "a valid absolute HTTP(S) URL", exposedData);
|
|
966
|
+
}
|
|
967
|
+
if (url.protocol === "https:") return;
|
|
968
|
+
if (url.protocol !== "http:") {
|
|
969
|
+
throw unsafeTransportError(surface, "an HTTPS URL", exposedData);
|
|
970
|
+
}
|
|
971
|
+
if (dangerouslyAllowInsecureHttp || isLiteralLoopbackHost(url.hostname)) return;
|
|
972
|
+
throw unsafeTransportError(
|
|
973
|
+
surface,
|
|
974
|
+
"an HTTPS URL, or set dangerouslyAllowInsecureHttp: true only for a deliberately insecure endpoint",
|
|
975
|
+
exposedData
|
|
976
|
+
);
|
|
977
|
+
}
|
|
978
|
+
function isLiteralLoopbackHost(hostname) {
|
|
979
|
+
return hostname === "localhost" || hostname === "localhost." || /^127(?:\.\d{1,3}){3}$/.test(hostname) || hostname === "[::1]";
|
|
980
|
+
}
|
|
981
|
+
function unsafeTransportError(surface, remediation, exposedData) {
|
|
982
|
+
return new AxlError(
|
|
983
|
+
"UNSAFE_TRANSPORT",
|
|
984
|
+
`${surface} requires ${remediation}. Remote HTTP can expose ${exposedData} in transit.`
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
|
|
705
988
|
// src/providers/openai-compatible.ts
|
|
706
989
|
function resolvePerModel(value, model, fallback) {
|
|
707
990
|
if (value === void 0) return fallback;
|
|
@@ -845,6 +1128,11 @@ var OpenAICompatibleProvider = class {
|
|
|
845
1128
|
const envBase = p.envBaseUrl ? process.env[p.envBaseUrl] : void 0;
|
|
846
1129
|
const explicitBase = options.baseUrl ?? envBase;
|
|
847
1130
|
this.baseUrl = (explicitBase ?? p.defaultBaseUrl).replace(/\/$/, "");
|
|
1131
|
+
assertSafeProviderBaseUrl(
|
|
1132
|
+
this.baseUrl,
|
|
1133
|
+
`${p.label ?? p.name} provider`,
|
|
1134
|
+
options.dangerouslyAllowInsecureHttp
|
|
1135
|
+
);
|
|
848
1136
|
this.governor = options.rateLimit ? new RateLimiter(options.rateLimit) : void 0;
|
|
849
1137
|
const label = p.label ?? p.name;
|
|
850
1138
|
if (p.requireExplicitBaseUrl && explicitBase === void 0) {
|
|
@@ -1745,6 +2033,11 @@ var OpenAIResponsesProvider = class {
|
|
|
1745
2033
|
constructor(options = {}) {
|
|
1746
2034
|
this.apiKeySource = options.apiKey ?? process.env.OPENAI_API_KEY ?? "";
|
|
1747
2035
|
this.baseUrl = (options.baseUrl ?? process.env.OPENAI_BASE_URL ?? "https://api.openai.com/v1").replace(/\/$/, "");
|
|
2036
|
+
assertSafeProviderBaseUrl(
|
|
2037
|
+
this.baseUrl,
|
|
2038
|
+
"OpenAI Responses provider",
|
|
2039
|
+
options.dangerouslyAllowInsecureHttp
|
|
2040
|
+
);
|
|
1748
2041
|
this.governor = options.rateLimit ? new RateLimiter(options.rateLimit) : void 0;
|
|
1749
2042
|
if (typeof this.apiKeySource === "string" && !this.apiKeySource) {
|
|
1750
2043
|
throw new Error("OpenAI API key is required. Set OPENAI_API_KEY or pass apiKey in options.");
|
|
@@ -2500,6 +2793,11 @@ var AnthropicProvider = class {
|
|
|
2500
2793
|
constructor(options = {}) {
|
|
2501
2794
|
this.apiKeySource = options.apiKey ?? process.env.ANTHROPIC_API_KEY ?? "";
|
|
2502
2795
|
this.baseUrl = (options.baseUrl ?? "https://api.anthropic.com/v1").replace(/\/$/, "");
|
|
2796
|
+
assertSafeProviderBaseUrl(
|
|
2797
|
+
this.baseUrl,
|
|
2798
|
+
"Anthropic provider",
|
|
2799
|
+
options.dangerouslyAllowInsecureHttp
|
|
2800
|
+
);
|
|
2503
2801
|
this.governor = options.rateLimit ? new RateLimiter(options.rateLimit) : void 0;
|
|
2504
2802
|
if (typeof this.apiKeySource === "string" && !this.apiKeySource) {
|
|
2505
2803
|
throw new Error(
|
|
@@ -3190,6 +3488,11 @@ var GeminiProvider = class {
|
|
|
3190
3488
|
/\/$/,
|
|
3191
3489
|
""
|
|
3192
3490
|
);
|
|
3491
|
+
assertSafeProviderBaseUrl(
|
|
3492
|
+
this.baseUrl,
|
|
3493
|
+
"Google provider",
|
|
3494
|
+
options.dangerouslyAllowInsecureHttp
|
|
3495
|
+
);
|
|
3193
3496
|
this.governor = options.rateLimit ? new RateLimiter(options.rateLimit) : void 0;
|
|
3194
3497
|
if (typeof this.apiKeySource === "string" && !this.apiKeySource) {
|
|
3195
3498
|
throw new Error("Google API key is required. Set GOOGLE_API_KEY or pass apiKey in options.");
|
|
@@ -4077,6 +4380,7 @@ var builtinFactories = {
|
|
|
4077
4380
|
return new OpenAIProvider({
|
|
4078
4381
|
apiKey: opts.apiKey,
|
|
4079
4382
|
baseUrl: opts.baseUrl,
|
|
4383
|
+
dangerouslyAllowInsecureHttp: opts.dangerouslyAllowInsecureHttp,
|
|
4080
4384
|
rateLimit: opts.rateLimit
|
|
4081
4385
|
});
|
|
4082
4386
|
},
|
|
@@ -4089,6 +4393,7 @@ var builtinFactories = {
|
|
|
4089
4393
|
return new OpenAIResponsesProvider({
|
|
4090
4394
|
apiKey: opts.apiKey,
|
|
4091
4395
|
baseUrl: opts.baseUrl,
|
|
4396
|
+
dangerouslyAllowInsecureHttp: opts.dangerouslyAllowInsecureHttp,
|
|
4092
4397
|
rateLimit: opts.rateLimit
|
|
4093
4398
|
});
|
|
4094
4399
|
},
|
|
@@ -4097,6 +4402,7 @@ var builtinFactories = {
|
|
|
4097
4402
|
return new AnthropicProvider({
|
|
4098
4403
|
apiKey: opts.apiKey,
|
|
4099
4404
|
baseUrl: opts.baseUrl,
|
|
4405
|
+
dangerouslyAllowInsecureHttp: opts.dangerouslyAllowInsecureHttp,
|
|
4100
4406
|
rateLimit: opts.rateLimit
|
|
4101
4407
|
});
|
|
4102
4408
|
},
|
|
@@ -4105,6 +4411,7 @@ var builtinFactories = {
|
|
|
4105
4411
|
return new GeminiProvider({
|
|
4106
4412
|
apiKey: opts.apiKey,
|
|
4107
4413
|
baseUrl: opts.baseUrl,
|
|
4414
|
+
dangerouslyAllowInsecureHttp: opts.dangerouslyAllowInsecureHttp,
|
|
4108
4415
|
rateLimit: opts.rateLimit
|
|
4109
4416
|
});
|
|
4110
4417
|
}
|
|
@@ -4116,6 +4423,7 @@ function presetFactory(profile) {
|
|
|
4116
4423
|
profile,
|
|
4117
4424
|
apiKey: opts.apiKey,
|
|
4118
4425
|
baseUrl: opts.baseUrl,
|
|
4426
|
+
dangerouslyAllowInsecureHttp: opts.dangerouslyAllowInsecureHttp,
|
|
4119
4427
|
authHeader: opts.authHeader,
|
|
4120
4428
|
rateLimit: opts.rateLimit
|
|
4121
4429
|
});
|
|
@@ -6273,7 +6581,15 @@ function cloneToolArguments(value) {
|
|
|
6273
6581
|
}
|
|
6274
6582
|
}
|
|
6275
6583
|
function parseToolInvocation(options) {
|
|
6276
|
-
const {
|
|
6584
|
+
const {
|
|
6585
|
+
toolCall,
|
|
6586
|
+
configuredTool,
|
|
6587
|
+
override,
|
|
6588
|
+
mcpCall,
|
|
6589
|
+
mcpTraceName,
|
|
6590
|
+
availableTools,
|
|
6591
|
+
providerVisibleSchema
|
|
6592
|
+
} = options;
|
|
6277
6593
|
const requestedTool = toolCall.function.name;
|
|
6278
6594
|
if (!override && !configuredTool && !mcpCall) {
|
|
6279
6595
|
return {
|
|
@@ -6333,7 +6649,7 @@ function parseToolInvocation(options) {
|
|
|
6333
6649
|
args: parsedArguments,
|
|
6334
6650
|
issues: toolArgumentIssues(error)
|
|
6335
6651
|
},
|
|
6336
|
-
modelMessage: INVALID_ARGUMENTS_MODEL_MESSAGE
|
|
6652
|
+
modelMessage: toolArgumentModelMessage(error, providerVisibleSchema) ?? INVALID_ARGUMENTS_MODEL_MESSAGE
|
|
6337
6653
|
};
|
|
6338
6654
|
}
|
|
6339
6655
|
}
|
|
@@ -7236,7 +7552,7 @@ var WorkflowContext = class _WorkflowContext {
|
|
|
7236
7552
|
/** Resolve, execute, and observe one non-handoff tool request. Rejections
|
|
7237
7553
|
* never start. Every accepted request emits one terminal event before a
|
|
7238
7554
|
* continuation message or abort escapes this coordinator. */
|
|
7239
|
-
async observeToolInvocation(agent2, toolCall, currentMessages,
|
|
7555
|
+
async observeToolInvocation(agent2, toolCall, currentMessages, toolDefs) {
|
|
7240
7556
|
const signal = this.currentSignal;
|
|
7241
7557
|
signal?.throwIfAborted();
|
|
7242
7558
|
const requestedTool = toolCall.function.name;
|
|
@@ -7246,6 +7562,7 @@ var WorkflowContext = class _WorkflowContext {
|
|
|
7246
7562
|
const override = this.toolOverrides?.get(requestedTool);
|
|
7247
7563
|
const mcpManager = this.mcpManager;
|
|
7248
7564
|
const mcpMatch = !configuredTool ? mcpManager?.getToolsForAgent(agent2._config.mcp, agent2._config.mcpTools).find(({ tool: tool2 }) => tool2.name === requestedTool) : void 0;
|
|
7565
|
+
const providerVisibleSchema = toolDefs.find((tool2) => tool2.function.name === requestedTool)?.function.parameters;
|
|
7249
7566
|
const parsed = parseToolInvocation({
|
|
7250
7567
|
toolCall,
|
|
7251
7568
|
configuredTool,
|
|
@@ -7254,7 +7571,8 @@ var WorkflowContext = class _WorkflowContext {
|
|
|
7254
7571
|
mcpCall: (args) => mcpManager.callTool(requestedTool, args, mcpMatch.server),
|
|
7255
7572
|
mcpTraceName: `${mcpMatch.server}:${requestedTool}`
|
|
7256
7573
|
} : {},
|
|
7257
|
-
availableTools
|
|
7574
|
+
availableTools: toolDefs.map((tool2) => tool2.function.name),
|
|
7575
|
+
...configuredTool ? { providerVisibleSchema } : {}
|
|
7258
7576
|
});
|
|
7259
7577
|
signal?.throwIfAborted();
|
|
7260
7578
|
if ("kind" in parsed) {
|
|
@@ -8065,12 +8383,7 @@ ${appendedSchemaText}`;
|
|
|
8065
8383
|
return await handoffFn();
|
|
8066
8384
|
}
|
|
8067
8385
|
}
|
|
8068
|
-
await this.observeToolInvocation(
|
|
8069
|
-
agent2,
|
|
8070
|
-
toolCall,
|
|
8071
|
-
currentMessages,
|
|
8072
|
-
toolDefs.map((tool2) => tool2.function.name)
|
|
8073
|
-
);
|
|
8386
|
+
await this.observeToolInvocation(agent2, toolCall, currentMessages, toolDefs);
|
|
8074
8387
|
}
|
|
8075
8388
|
continue;
|
|
8076
8389
|
}
|
|
@@ -11126,6 +11439,14 @@ var HttpMcpClient = class {
|
|
|
11126
11439
|
this.config = config;
|
|
11127
11440
|
this.name = config.name;
|
|
11128
11441
|
this.baseUrl = (config.uri ?? "").replace(/\/$/, "");
|
|
11442
|
+
if (this.baseUrl) {
|
|
11443
|
+
assertSafeHttpEndpoint(
|
|
11444
|
+
this.baseUrl,
|
|
11445
|
+
`MCP server "${this.name}"`,
|
|
11446
|
+
config.dangerouslyAllowInsecureHttp,
|
|
11447
|
+
"tool arguments and results"
|
|
11448
|
+
);
|
|
11449
|
+
}
|
|
11129
11450
|
}
|
|
11130
11451
|
name;
|
|
11131
11452
|
tools = [];
|
|
@@ -11155,7 +11476,9 @@ var HttpMcpClient = class {
|
|
|
11155
11476
|
method: "POST",
|
|
11156
11477
|
headers: { "Content-Type": "application/json" },
|
|
11157
11478
|
body: JSON.stringify(request),
|
|
11158
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
11479
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
11480
|
+
// Tool calls can be non-idempotent: never forward or retry their body.
|
|
11481
|
+
redirect: "manual"
|
|
11159
11482
|
});
|
|
11160
11483
|
if (!res.ok) {
|
|
11161
11484
|
throw new Error(`MCP HTTP error (${res.status}): ${await res.text()}`);
|
|
@@ -13947,6 +14270,11 @@ var OpenAIEmbedder = class {
|
|
|
13947
14270
|
}
|
|
13948
14271
|
this.model = options.model ?? "text-embedding-3-small";
|
|
13949
14272
|
this.baseUrl = options.baseUrl ?? "https://api.openai.com";
|
|
14273
|
+
assertSafeProviderBaseUrl(
|
|
14274
|
+
this.baseUrl,
|
|
14275
|
+
"OpenAI embedder",
|
|
14276
|
+
options.dangerouslyAllowInsecureHttp
|
|
14277
|
+
);
|
|
13950
14278
|
this.dimensions = options.dimensions ?? 1536;
|
|
13951
14279
|
}
|
|
13952
14280
|
async embed(texts, signal) {
|