@absolutejs/ai 0.6.5 → 0.6.7
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 +12 -0
- package/README.md +18 -0
- package/changelog.json +26 -0
- package/dist/ai/index.js +363 -188
- package/dist/ai/index.js.map +17 -16
- package/dist/ai/providers/anthropic.js +147 -104
- package/dist/ai/providers/anthropic.js.map +8 -8
- package/dist/ai/providers/gemini.js +146 -103
- package/dist/ai/providers/gemini.js.map +7 -7
- package/dist/ai/providers/ollama.js +61 -20
- package/dist/ai/providers/ollama.js.map +5 -5
- package/dist/ai/providers/openai.js +245 -151
- package/dist/ai/providers/openai.js.map +11 -10
- package/dist/ai/providers/openaiCompatible.js +245 -151
- package/dist/ai/providers/openaiCompatible.js.map +11 -10
- package/dist/ai/providers/openaiResponses.js +243 -149
- package/dist/ai/providers/openaiResponses.js.map +10 -9
- package/dist/ai/providers/openrouter.js +246 -152
- package/dist/ai/providers/openrouter.js.map +12 -11
- package/dist/src/ai/contextPolicy.d.ts +2 -0
- package/dist/src/ai/errors/providerError.d.ts +2 -0
- package/dist/src/ai/index.d.ts +3 -0
- package/dist/src/ai/inputCapacity.d.ts +4 -2
- package/dist/src/ai/prepareTextInput.d.ts +2 -0
- package/dist/src/ai/providerFallback.d.ts +27 -8
- package/dist/src/ai/providers/openaiSchema.d.ts +4 -0
- package/package.json +1 -1
|
@@ -1,14 +1,201 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// src/ai/providers/openaiSchema.ts
|
|
3
|
+
var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4
|
+
var openaiSchema = (schema) => {
|
|
5
|
+
const result = { ...schema };
|
|
6
|
+
for (const key of [
|
|
7
|
+
"properties",
|
|
8
|
+
"$defs",
|
|
9
|
+
"definitions",
|
|
10
|
+
"patternProperties"
|
|
11
|
+
]) {
|
|
12
|
+
const value = result[key];
|
|
13
|
+
if (record(value))
|
|
14
|
+
result[key] = Object.fromEntries(Object.entries(value).map(([name, child]) => [
|
|
15
|
+
name,
|
|
16
|
+
record(child) ? openaiSchema(child) : child
|
|
17
|
+
]));
|
|
18
|
+
}
|
|
19
|
+
for (const key of [
|
|
20
|
+
"items",
|
|
21
|
+
"additionalProperties",
|
|
22
|
+
"not",
|
|
23
|
+
"if",
|
|
24
|
+
"then",
|
|
25
|
+
"else"
|
|
26
|
+
])
|
|
27
|
+
if (record(result[key]))
|
|
28
|
+
result[key] = openaiSchema(result[key]);
|
|
29
|
+
for (const key of ["anyOf", "oneOf", "allOf", "prefixItems"])
|
|
30
|
+
if (Array.isArray(result[key]))
|
|
31
|
+
result[key] = result[key].map((child) => record(child) ? openaiSchema(child) : child);
|
|
32
|
+
const names = result.propertyNames;
|
|
33
|
+
if (record(names) && Array.isArray(names.enum) && names.enum.every((key) => typeof key === "string") && Object.keys(names).every((key) => ["enum", "type", "description", "title"].includes(key)) && !result.patternProperties) {
|
|
34
|
+
const existing = record(result.properties) ? result.properties : {};
|
|
35
|
+
const additional = result.additionalProperties;
|
|
36
|
+
const entries = names.enum.filter((key) => Object.hasOwn(existing, key) || additional !== false).map((key) => [
|
|
37
|
+
key,
|
|
38
|
+
Object.hasOwn(existing, key) ? existing[key] : record(additional) ? additional : {}
|
|
39
|
+
]);
|
|
40
|
+
result.properties = Object.fromEntries(entries);
|
|
41
|
+
result.additionalProperties = false;
|
|
42
|
+
delete result.propertyNames;
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
var isStrictCompatible = (schema) => {
|
|
47
|
+
if (Array.isArray(schema))
|
|
48
|
+
return schema.every(isStrictCompatible);
|
|
49
|
+
if (!record(schema))
|
|
50
|
+
return true;
|
|
51
|
+
if (schema.propertyNames || schema.patternProperties)
|
|
52
|
+
return false;
|
|
53
|
+
const properties = record(schema.properties) ? schema.properties : {};
|
|
54
|
+
if (schema.type === "object" || schema.properties || schema.additionalProperties !== undefined) {
|
|
55
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
56
|
+
if (schema.additionalProperties !== false || !Object.keys(properties).every((key) => required.includes(key)))
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const nested = [
|
|
60
|
+
schema.items,
|
|
61
|
+
schema.anyOf,
|
|
62
|
+
schema.oneOf,
|
|
63
|
+
schema.allOf,
|
|
64
|
+
schema.additionalProperties
|
|
65
|
+
];
|
|
66
|
+
for (const map of [properties, schema.$defs, schema.definitions])
|
|
67
|
+
if (record(map))
|
|
68
|
+
nested.push(...Object.values(map));
|
|
69
|
+
return nested.every(isStrictCompatible);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/ai/errors/providerError.ts
|
|
73
|
+
var PROVIDER_STATUS_PAGES = {
|
|
74
|
+
anthropic: "https://status.claude.com",
|
|
75
|
+
gemini: "https://status.cloud.google.com",
|
|
76
|
+
google: "https://status.cloud.google.com",
|
|
77
|
+
openai: "https://status.openai.com",
|
|
78
|
+
openrouter: "https://status.openrouter.ai"
|
|
79
|
+
};
|
|
80
|
+
var RETRYABLE_STATUSES = new Set([
|
|
81
|
+
408,
|
|
82
|
+
409,
|
|
83
|
+
425,
|
|
84
|
+
429,
|
|
85
|
+
500,
|
|
86
|
+
502,
|
|
87
|
+
503,
|
|
88
|
+
504,
|
|
89
|
+
529
|
|
90
|
+
]);
|
|
91
|
+
var CONNECTION_ERROR_PATTERNS = [
|
|
92
|
+
"econnreset",
|
|
93
|
+
"econnrefused",
|
|
94
|
+
"etimedout",
|
|
95
|
+
"enotfound",
|
|
96
|
+
"eai_again",
|
|
97
|
+
"socket hang up",
|
|
98
|
+
"fetch failed",
|
|
99
|
+
"network",
|
|
100
|
+
"terminated",
|
|
101
|
+
"timed out",
|
|
102
|
+
"timeout",
|
|
103
|
+
"and not retryable",
|
|
104
|
+
"no response body"
|
|
105
|
+
];
|
|
106
|
+
var isAbortError = (err) => err instanceof Error && (err.name === "AbortError" || /\babort(ed)?\b/i.test(err.message));
|
|
107
|
+
var providerStatusPage = (provider) => PROVIDER_STATUS_PAGES[provider] ?? null;
|
|
108
|
+
var BILLING_ERROR_TYPES = new Set([
|
|
109
|
+
"credit_balance_exhausted",
|
|
110
|
+
"insufficient_quota",
|
|
111
|
+
"billing_hard_limit_reached",
|
|
112
|
+
"billing_not_active",
|
|
113
|
+
"insufficient_credits"
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
class ProviderError extends Error {
|
|
117
|
+
provider;
|
|
118
|
+
status;
|
|
119
|
+
type;
|
|
120
|
+
retryable;
|
|
121
|
+
billingUnavailable;
|
|
122
|
+
notSent;
|
|
123
|
+
metadata;
|
|
124
|
+
statusPageUrl;
|
|
125
|
+
constructor(init) {
|
|
126
|
+
super(init.message, init.cause === undefined ? undefined : { cause: init.cause });
|
|
127
|
+
this.name = "ProviderError";
|
|
128
|
+
this.provider = init.provider;
|
|
129
|
+
this.status = init.status ?? null;
|
|
130
|
+
this.type = init.type ?? (typeof init.metadata?.code === "string" ? init.metadata.code : typeof init.metadata?.type === "string" ? init.metadata.type : null);
|
|
131
|
+
this.billingUnavailable = BILLING_ERROR_TYPES.has(this.type ?? "") || init.status === 402 || init.provider === "anthropic" && init.status === 400 && /credit balance is too low/i.test(String(init.metadata?.message ?? init.message));
|
|
132
|
+
this.notSent = init.notSent === true;
|
|
133
|
+
this.retryable = !this.billingUnavailable && init.retryable;
|
|
134
|
+
this.metadata = init.metadata;
|
|
135
|
+
this.statusPageUrl = providerStatusPage(init.provider);
|
|
136
|
+
}
|
|
137
|
+
static fromResponse(provider, status, body, type) {
|
|
138
|
+
let metadata;
|
|
139
|
+
try {
|
|
140
|
+
const parsed = JSON.parse(body);
|
|
141
|
+
const details = parsed?.error ?? parsed;
|
|
142
|
+
if (details && typeof details === "object" && !Array.isArray(details))
|
|
143
|
+
metadata = details;
|
|
144
|
+
} catch {}
|
|
145
|
+
return new ProviderError({
|
|
146
|
+
metadata,
|
|
147
|
+
message: `${capitalize(provider)} API error ${status}: ${body}`,
|
|
148
|
+
provider,
|
|
149
|
+
retryable: RETRYABLE_STATUSES.has(status),
|
|
150
|
+
status,
|
|
151
|
+
type: type ?? null
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
static from(err, provider) {
|
|
155
|
+
if (err instanceof ProviderError)
|
|
156
|
+
return err;
|
|
157
|
+
if (isProviderError(err))
|
|
158
|
+
return new ProviderError({
|
|
159
|
+
provider: err.provider,
|
|
160
|
+
message: err.message,
|
|
161
|
+
status: err.status,
|
|
162
|
+
type: err.type,
|
|
163
|
+
retryable: err.retryable,
|
|
164
|
+
notSent: err.notSent,
|
|
165
|
+
metadata: err.metadata,
|
|
166
|
+
cause: err
|
|
167
|
+
});
|
|
168
|
+
if (isAbortError(err))
|
|
169
|
+
throw err;
|
|
170
|
+
const rawMessage = err instanceof Error ? err.message : String(err ?? "");
|
|
171
|
+
const lower = rawMessage.toLowerCase();
|
|
172
|
+
const statusMatch = lower.match(/api error\s+(\d{3})/);
|
|
173
|
+
const status = statusMatch ? Number(statusMatch[1]) : null;
|
|
174
|
+
const retryable = status !== null && RETRYABLE_STATUSES.has(status) || status === null && CONNECTION_ERROR_PATTERNS.some((pattern) => lower.includes(pattern));
|
|
175
|
+
return new ProviderError({
|
|
176
|
+
cause: err,
|
|
177
|
+
message: rawMessage || `${capitalize(provider)} request failed`,
|
|
178
|
+
provider,
|
|
179
|
+
retryable,
|
|
180
|
+
status
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
var capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);
|
|
185
|
+
var isProviderError = (error) => error instanceof Error && error.name === "ProviderError" && ("provider" in error) && typeof error.provider === "string" && ("status" in error) && (error.status === null || typeof error.status === "number") && ("retryable" in error) && typeof error.retryable === "boolean" && ("billingUnavailable" in error) && typeof error.billingUnavailable === "boolean" && ("notSent" in error) && typeof error.notSent === "boolean";
|
|
186
|
+
|
|
2
187
|
// src/ai/inputCapacity.ts
|
|
3
188
|
class AIInputError extends Error {
|
|
4
189
|
code;
|
|
5
190
|
providerStatus;
|
|
6
191
|
requestId;
|
|
7
|
-
|
|
192
|
+
providerError;
|
|
193
|
+
constructor(code, message, providerStatus, requestId, providerError) {
|
|
8
194
|
super(message);
|
|
9
195
|
this.code = code;
|
|
10
196
|
this.providerStatus = providerStatus;
|
|
11
197
|
this.requestId = requestId;
|
|
198
|
+
this.providerError = providerError;
|
|
12
199
|
this.name = "AIInputError";
|
|
13
200
|
}
|
|
14
201
|
}
|
|
@@ -31,7 +218,7 @@ var inspectAIInput = async (provider, params) => {
|
|
|
31
218
|
provider.inputCapacity.countTokens(params)
|
|
32
219
|
]).catch((error) => {
|
|
33
220
|
if (error instanceof Error && error.name === "AIInputError" && "code" in error && (error.code === "capacity_unavailable" || error.code === "input_too_large" || error.code === "unsupported_content"))
|
|
34
|
-
throw new AIInputError(error.code, error.message, "providerStatus" in error && typeof error.providerStatus === "number" ? error.providerStatus : undefined, "requestId" in error && typeof error.requestId === "string" ? error.requestId : undefined);
|
|
221
|
+
throw new AIInputError(error.code, error.message, "providerStatus" in error && typeof error.providerStatus === "number" ? error.providerStatus : undefined, "requestId" in error && typeof error.requestId === "string" ? error.requestId : undefined, "providerError" in error && isProviderError(error.providerError) ? ProviderError.from(error.providerError, error.providerError.provider) : undefined);
|
|
35
222
|
throw error;
|
|
36
223
|
});
|
|
37
224
|
const inputTokens = inputTokenCount(tokens);
|
|
@@ -63,7 +250,7 @@ var cacheModelLimits = (load, ttlMs = 300000) => {
|
|
|
63
250
|
return limits;
|
|
64
251
|
};
|
|
65
252
|
};
|
|
66
|
-
var capacityJson = async (response) => {
|
|
253
|
+
var capacityJson = async (response, provider = "unknown") => {
|
|
67
254
|
if (!response.ok) {
|
|
68
255
|
const payload = await response.json().catch(() => {
|
|
69
256
|
return;
|
|
@@ -74,7 +261,7 @@ var capacityJson = async (response) => {
|
|
|
74
261
|
const message = nested?.message ?? record?.message;
|
|
75
262
|
const detail = typeof message === "string" ? message.slice(0, 1000) : undefined;
|
|
76
263
|
const id = response.headers.get("request-id") ?? response.headers.get("x-request-id") ?? record?.request_id;
|
|
77
|
-
throw new AIInputError("capacity_unavailable", `Model capacity request failed (${response.status}).${detail ? ` ${detail}` : ""}`, response.status, typeof id === "string" ? id.slice(0, 200) : undefined);
|
|
264
|
+
throw new AIInputError("capacity_unavailable", `Model capacity request failed (${response.status}).${detail ? ` ${detail}` : ""}`, response.status, typeof id === "string" ? id.slice(0, 200) : undefined, ProviderError.fromResponse(provider, response.status, JSON.stringify({ error: nested ?? record ?? {} })));
|
|
78
265
|
}
|
|
79
266
|
const value = await response.json();
|
|
80
267
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
@@ -304,113 +491,10 @@ var openaiInputCapacity = (config) => ({
|
|
|
304
491
|
body: JSON.stringify(counted),
|
|
305
492
|
signal: params.signal ? AbortSignal.any([params.signal, AbortSignal.timeout(15000)]) : AbortSignal.timeout(15000)
|
|
306
493
|
});
|
|
307
|
-
return inputTokenCount((await capacityJson(response)).input_tokens);
|
|
494
|
+
return inputTokenCount((await capacityJson(response, "openai")).input_tokens);
|
|
308
495
|
}
|
|
309
496
|
});
|
|
310
497
|
|
|
311
|
-
// src/ai/errors/providerError.ts
|
|
312
|
-
var PROVIDER_STATUS_PAGES = {
|
|
313
|
-
anthropic: "https://status.claude.com",
|
|
314
|
-
gemini: "https://status.cloud.google.com",
|
|
315
|
-
google: "https://status.cloud.google.com",
|
|
316
|
-
openai: "https://status.openai.com",
|
|
317
|
-
openrouter: "https://status.openrouter.ai"
|
|
318
|
-
};
|
|
319
|
-
var RETRYABLE_STATUSES = new Set([
|
|
320
|
-
408,
|
|
321
|
-
409,
|
|
322
|
-
425,
|
|
323
|
-
429,
|
|
324
|
-
500,
|
|
325
|
-
502,
|
|
326
|
-
503,
|
|
327
|
-
504,
|
|
328
|
-
529
|
|
329
|
-
]);
|
|
330
|
-
var CONNECTION_ERROR_PATTERNS = [
|
|
331
|
-
"econnreset",
|
|
332
|
-
"econnrefused",
|
|
333
|
-
"etimedout",
|
|
334
|
-
"enotfound",
|
|
335
|
-
"eai_again",
|
|
336
|
-
"socket hang up",
|
|
337
|
-
"fetch failed",
|
|
338
|
-
"network",
|
|
339
|
-
"terminated",
|
|
340
|
-
"timed out",
|
|
341
|
-
"timeout",
|
|
342
|
-
"and not retryable",
|
|
343
|
-
"no response body"
|
|
344
|
-
];
|
|
345
|
-
var isAbortError = (err) => err instanceof Error && (err.name === "AbortError" || /\babort(ed)?\b/i.test(err.message));
|
|
346
|
-
var providerStatusPage = (provider) => PROVIDER_STATUS_PAGES[provider] ?? null;
|
|
347
|
-
var BILLING_ERROR_TYPES = new Set([
|
|
348
|
-
"credit_balance_exhausted",
|
|
349
|
-
"insufficient_quota",
|
|
350
|
-
"billing_hard_limit_reached",
|
|
351
|
-
"billing_not_active",
|
|
352
|
-
"insufficient_credits"
|
|
353
|
-
]);
|
|
354
|
-
|
|
355
|
-
class ProviderError extends Error {
|
|
356
|
-
provider;
|
|
357
|
-
status;
|
|
358
|
-
type;
|
|
359
|
-
retryable;
|
|
360
|
-
billingUnavailable;
|
|
361
|
-
notSent;
|
|
362
|
-
metadata;
|
|
363
|
-
statusPageUrl;
|
|
364
|
-
constructor(init) {
|
|
365
|
-
super(init.message, init.cause === undefined ? undefined : { cause: init.cause });
|
|
366
|
-
this.name = "ProviderError";
|
|
367
|
-
this.provider = init.provider;
|
|
368
|
-
this.status = init.status ?? null;
|
|
369
|
-
this.type = init.type ?? (typeof init.metadata?.code === "string" ? init.metadata.code : typeof init.metadata?.type === "string" ? init.metadata.type : null);
|
|
370
|
-
this.billingUnavailable = BILLING_ERROR_TYPES.has(this.type ?? "") || init.status === 402;
|
|
371
|
-
this.notSent = init.notSent === true;
|
|
372
|
-
this.retryable = !this.billingUnavailable && init.retryable;
|
|
373
|
-
this.metadata = init.metadata;
|
|
374
|
-
this.statusPageUrl = providerStatusPage(init.provider);
|
|
375
|
-
}
|
|
376
|
-
static fromResponse(provider, status, body, type) {
|
|
377
|
-
let metadata;
|
|
378
|
-
try {
|
|
379
|
-
const parsed = JSON.parse(body);
|
|
380
|
-
const details = parsed?.error ?? parsed;
|
|
381
|
-
if (details && typeof details === "object" && !Array.isArray(details))
|
|
382
|
-
metadata = details;
|
|
383
|
-
} catch {}
|
|
384
|
-
return new ProviderError({
|
|
385
|
-
metadata,
|
|
386
|
-
message: `${capitalize(provider)} API error ${status}: ${body}`,
|
|
387
|
-
provider,
|
|
388
|
-
retryable: RETRYABLE_STATUSES.has(status),
|
|
389
|
-
status,
|
|
390
|
-
type: type ?? null
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
static from(err, provider) {
|
|
394
|
-
if (err instanceof ProviderError)
|
|
395
|
-
return err;
|
|
396
|
-
if (isAbortError(err))
|
|
397
|
-
throw err;
|
|
398
|
-
const rawMessage = err instanceof Error ? err.message : String(err ?? "");
|
|
399
|
-
const lower = rawMessage.toLowerCase();
|
|
400
|
-
const statusMatch = lower.match(/api error\s+(\d{3})/);
|
|
401
|
-
const status = statusMatch ? Number(statusMatch[1]) : null;
|
|
402
|
-
const retryable = status !== null && RETRYABLE_STATUSES.has(status) || status === null && CONNECTION_ERROR_PATTERNS.some((pattern) => lower.includes(pattern));
|
|
403
|
-
return new ProviderError({
|
|
404
|
-
cause: err,
|
|
405
|
-
message: rawMessage || `${capitalize(provider)} request failed`,
|
|
406
|
-
provider,
|
|
407
|
-
retryable,
|
|
408
|
-
status
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
var capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);
|
|
413
|
-
|
|
414
498
|
// src/ai/resilience.ts
|
|
415
499
|
var DEFAULT_CONFIG = {
|
|
416
500
|
baseDelayMs: 500,
|
|
@@ -540,6 +624,29 @@ var withResilience = (provider, providerName = "unknown") => {
|
|
|
540
624
|
let billingFailure = null;
|
|
541
625
|
let billingRetryAt = 0;
|
|
542
626
|
let billingProbe = false;
|
|
627
|
+
const inspectAvailable = async (inspect) => {
|
|
628
|
+
if (billingFailure && Date.now() < billingRetryAt) {
|
|
629
|
+
throw new ProviderError({
|
|
630
|
+
provider: providerName,
|
|
631
|
+
message: "Provider billing is unavailable",
|
|
632
|
+
type: billingFailure.type,
|
|
633
|
+
status: billingFailure.status,
|
|
634
|
+
metadata: billingFailure.metadata,
|
|
635
|
+
retryable: false,
|
|
636
|
+
notSent: true
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
try {
|
|
640
|
+
return await inspect();
|
|
641
|
+
} catch (error) {
|
|
642
|
+
const nested = error instanceof Error && "providerError" in error ? error.providerError : error;
|
|
643
|
+
if (isProviderError(nested) && nested.billingUnavailable) {
|
|
644
|
+
billingFailure = ProviderError.from(nested, providerName);
|
|
645
|
+
billingRetryAt = Date.now() + billingCooldownMs;
|
|
646
|
+
}
|
|
647
|
+
throw error;
|
|
648
|
+
}
|
|
649
|
+
};
|
|
543
650
|
const billingCooldownMs = 5 * 60000;
|
|
544
651
|
const attempt = async function* (params, attemptNo) {
|
|
545
652
|
let yielded = false;
|
|
@@ -567,33 +674,39 @@ var withResilience = (provider, providerName = "unknown") => {
|
|
|
567
674
|
if (providerError.retryable)
|
|
568
675
|
noteFailure(providerName, providerError);
|
|
569
676
|
throw providerError;
|
|
677
|
+
} finally {
|
|
678
|
+
billingProbe = false;
|
|
570
679
|
}
|
|
571
680
|
};
|
|
572
681
|
return {
|
|
573
682
|
...provider,
|
|
574
|
-
|
|
683
|
+
...provider.inputCapacity ? {
|
|
684
|
+
inputCapacity: {
|
|
685
|
+
...provider.inputCapacity,
|
|
686
|
+
getLimits: (params) => inspectAvailable(() => provider.inputCapacity.getLimits(params)),
|
|
687
|
+
countTokens: (params) => inspectAvailable(() => provider.inputCapacity.countTokens(params))
|
|
688
|
+
}
|
|
689
|
+
} : {},
|
|
690
|
+
stream: async function* (params) {
|
|
575
691
|
if (billingFailure && (Date.now() < billingRetryAt || billingProbe)) {
|
|
576
692
|
const failure = billingFailure;
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
}();
|
|
693
|
+
throw new ProviderError({
|
|
694
|
+
provider: providerName,
|
|
695
|
+
message: "Provider billing is unavailable",
|
|
696
|
+
type: failure.type,
|
|
697
|
+
status: failure.status,
|
|
698
|
+
metadata: failure.metadata,
|
|
699
|
+
retryable: false,
|
|
700
|
+
notSent: true
|
|
701
|
+
});
|
|
587
702
|
}
|
|
588
|
-
if (billingFailure)
|
|
589
|
-
billingProbe = true;
|
|
590
703
|
const tripped = circuitOpen(providerName);
|
|
591
704
|
if (tripped) {
|
|
592
|
-
|
|
593
|
-
throw tripped;
|
|
594
|
-
}();
|
|
705
|
+
throw tripped;
|
|
595
706
|
}
|
|
596
|
-
|
|
707
|
+
if (billingFailure)
|
|
708
|
+
billingProbe = true;
|
|
709
|
+
yield* attempt(params, 0);
|
|
597
710
|
}
|
|
598
711
|
};
|
|
599
712
|
};
|
|
@@ -602,7 +715,7 @@ var withResilience = (provider, providerName = "unknown") => {
|
|
|
602
715
|
var instrumentAIProvider = (provider, providerName) => {
|
|
603
716
|
const resilient = withResilience(provider, providerName);
|
|
604
717
|
return {
|
|
605
|
-
...
|
|
718
|
+
...resilient,
|
|
606
719
|
stream: (params) => {
|
|
607
720
|
if (!params.onUsage && !params.onSpan) {
|
|
608
721
|
return resilient.stream(params);
|
|
@@ -962,30 +1075,11 @@ var buildInput = (messages) => {
|
|
|
962
1075
|
}
|
|
963
1076
|
return input;
|
|
964
1077
|
};
|
|
965
|
-
var isStrictCompatible = (schema) => {
|
|
966
|
-
if (Array.isArray(schema))
|
|
967
|
-
return schema.every(isStrictCompatible);
|
|
968
|
-
if (!isRecord(schema))
|
|
969
|
-
return true;
|
|
970
|
-
const { properties } = schema;
|
|
971
|
-
if (isRecord(properties)) {
|
|
972
|
-
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
973
|
-
if (schema.additionalProperties !== false)
|
|
974
|
-
return false;
|
|
975
|
-
if (!Object.keys(properties).every((key) => required.includes(key)))
|
|
976
|
-
return false;
|
|
977
|
-
}
|
|
978
|
-
const nested = [schema.items, schema.anyOf];
|
|
979
|
-
for (const map of [properties, schema.$defs, schema.definitions])
|
|
980
|
-
if (isRecord(map))
|
|
981
|
-
nested.push(...Object.values(map));
|
|
982
|
-
return nested.every(isStrictCompatible);
|
|
983
|
-
};
|
|
984
1078
|
var mapToolDefinition = (tool) => ({
|
|
985
1079
|
description: tool.description,
|
|
986
1080
|
name: tool.name,
|
|
987
|
-
parameters: tool.input_schema,
|
|
988
|
-
strict: isStrictCompatible(tool.input_schema),
|
|
1081
|
+
parameters: openaiSchema(tool.input_schema),
|
|
1082
|
+
strict: isStrictCompatible(openaiSchema(tool.input_schema)),
|
|
989
1083
|
type: "function"
|
|
990
1084
|
});
|
|
991
1085
|
var buildTools = (tools, isImageModel) => {
|
|
@@ -1042,7 +1136,7 @@ var buildResponsesRequestBody = (params, isImageModel, capabilityModel = params.
|
|
|
1042
1136
|
body.text = {
|
|
1043
1137
|
format: {
|
|
1044
1138
|
name: params.responseFormat.name,
|
|
1045
|
-
schema: params.responseFormat.schema,
|
|
1139
|
+
schema: openaiSchema(params.responseFormat.schema),
|
|
1046
1140
|
strict: params.responseFormat.strict ?? true,
|
|
1047
1141
|
type: "json_schema"
|
|
1048
1142
|
}
|
|
@@ -1509,7 +1603,7 @@ var mapToolDefinitions = (tools) => tools.map((tool) => ({
|
|
|
1509
1603
|
function: {
|
|
1510
1604
|
description: tool.description,
|
|
1511
1605
|
name: tool.name,
|
|
1512
|
-
parameters: tool.input_schema
|
|
1606
|
+
parameters: openaiSchema(tool.input_schema)
|
|
1513
1607
|
},
|
|
1514
1608
|
type: "function"
|
|
1515
1609
|
}));
|
|
@@ -1635,7 +1729,7 @@ var buildRequestBody = (params, capabilityModel = params.model, providerName = "
|
|
|
1635
1729
|
body.response_format = {
|
|
1636
1730
|
json_schema: {
|
|
1637
1731
|
name: params.responseFormat.name,
|
|
1638
|
-
schema: params.responseFormat.schema,
|
|
1732
|
+
schema: openaiSchema(params.responseFormat.schema),
|
|
1639
1733
|
strict: params.responseFormat.strict ?? true
|
|
1640
1734
|
},
|
|
1641
1735
|
type: "json_schema"
|
|
@@ -2028,5 +2122,5 @@ export {
|
|
|
2028
2122
|
openai
|
|
2029
2123
|
};
|
|
2030
2124
|
|
|
2031
|
-
//# debugId=
|
|
2125
|
+
//# debugId=E5102C547733AF4E64756E2164756E21
|
|
2032
2126
|
//# sourceMappingURL=openai.js.map
|