@absolutejs/ai 0.6.2 → 0.6.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/CHANGELOG.md +10 -0
- package/README.md +3 -0
- package/changelog.json +23 -2
- package/dist/ai/index.js +68 -3
- package/dist/ai/index.js.map +8 -7
- package/dist/ai/providers/anthropic.js +42 -3
- package/dist/ai/providers/anthropic.js.map +4 -4
- package/dist/ai/providers/gemini.js +42 -3
- package/dist/ai/providers/gemini.js.map +4 -4
- package/dist/ai/providers/ollama.js +42 -3
- package/dist/ai/providers/ollama.js.map +4 -4
- package/dist/ai/providers/openai.js +42 -3
- package/dist/ai/providers/openai.js.map +4 -4
- package/dist/ai/providers/openaiCompatible.js +42 -3
- package/dist/ai/providers/openaiCompatible.js.map +4 -4
- package/dist/ai/providers/openaiResponses.js +42 -3
- package/dist/ai/providers/openaiResponses.js.map +4 -4
- package/dist/ai/providers/openrouter.js +42 -3
- package/dist/ai/providers/openrouter.js.map +4 -4
- package/dist/src/ai/errors/providerError.d.ts +4 -0
- package/dist/src/ai/index.d.ts +1 -0
- package/dist/src/ai/providerFallback.d.ts +14 -0
- package/package.json +1 -1
|
@@ -344,12 +344,21 @@ var CONNECTION_ERROR_PATTERNS = [
|
|
|
344
344
|
];
|
|
345
345
|
var isAbortError = (err) => err instanceof Error && (err.name === "AbortError" || /\babort(ed)?\b/i.test(err.message));
|
|
346
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
|
+
]);
|
|
347
354
|
|
|
348
355
|
class ProviderError extends Error {
|
|
349
356
|
provider;
|
|
350
357
|
status;
|
|
351
358
|
type;
|
|
352
359
|
retryable;
|
|
360
|
+
billingUnavailable;
|
|
361
|
+
notSent;
|
|
353
362
|
metadata;
|
|
354
363
|
statusPageUrl;
|
|
355
364
|
constructor(init) {
|
|
@@ -357,8 +366,10 @@ class ProviderError extends Error {
|
|
|
357
366
|
this.name = "ProviderError";
|
|
358
367
|
this.provider = init.provider;
|
|
359
368
|
this.status = init.status ?? null;
|
|
360
|
-
this.type = init.type ?? null;
|
|
361
|
-
this.
|
|
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;
|
|
362
373
|
this.metadata = init.metadata;
|
|
363
374
|
this.statusPageUrl = providerStatusPage(init.provider);
|
|
364
375
|
}
|
|
@@ -504,6 +515,7 @@ var circuitOpen = (provider) => {
|
|
|
504
515
|
message: `${provider} API is reported down${record.external.reason ? `: ${record.external.reason}` : ""}`,
|
|
505
516
|
provider,
|
|
506
517
|
retryable: true,
|
|
518
|
+
notSent: true,
|
|
507
519
|
status: null,
|
|
508
520
|
type: record.external.indicator
|
|
509
521
|
});
|
|
@@ -519,11 +531,16 @@ var circuitOpen = (provider) => {
|
|
|
519
531
|
message: `${provider} is temporarily unavailable (circuit open after ${record.consecutiveFailures} failures): ${detail}`,
|
|
520
532
|
provider,
|
|
521
533
|
retryable: true,
|
|
534
|
+
notSent: true,
|
|
522
535
|
status: record.lastError?.status ?? null,
|
|
523
536
|
type: record.lastError?.type ?? null
|
|
524
537
|
});
|
|
525
538
|
};
|
|
526
539
|
var withResilience = (provider, providerName = "unknown") => {
|
|
540
|
+
let billingFailure = null;
|
|
541
|
+
let billingRetryAt = 0;
|
|
542
|
+
let billingProbe = false;
|
|
543
|
+
const billingCooldownMs = 5 * 60000;
|
|
527
544
|
const attempt = async function* (params, attemptNo) {
|
|
528
545
|
let yielded = false;
|
|
529
546
|
try {
|
|
@@ -531,9 +548,16 @@ var withResilience = (provider, providerName = "unknown") => {
|
|
|
531
548
|
yielded = true;
|
|
532
549
|
yield chunk;
|
|
533
550
|
}
|
|
551
|
+
billingFailure = null;
|
|
552
|
+
billingProbe = false;
|
|
534
553
|
noteSuccess(providerName);
|
|
535
554
|
} catch (err) {
|
|
536
555
|
const providerError = ProviderError.from(err, providerName);
|
|
556
|
+
if (providerError.billingUnavailable) {
|
|
557
|
+
billingFailure = providerError;
|
|
558
|
+
billingRetryAt = Date.now() + billingCooldownMs;
|
|
559
|
+
}
|
|
560
|
+
billingProbe = false;
|
|
537
561
|
const canRetry = !yielded && providerError.retryable && attemptNo < (params.maxRetries === undefined ? config.maxRetries : Math.max(0, Math.min(config.maxRetries, params.maxRetries))) && !params.signal?.aborted;
|
|
538
562
|
if (canRetry) {
|
|
539
563
|
await sleep(backoffDelay(attemptNo), params.signal);
|
|
@@ -548,6 +572,21 @@ var withResilience = (provider, providerName = "unknown") => {
|
|
|
548
572
|
return {
|
|
549
573
|
...provider,
|
|
550
574
|
stream: (params) => {
|
|
575
|
+
if (billingFailure && (Date.now() < billingRetryAt || billingProbe)) {
|
|
576
|
+
const failure = billingFailure;
|
|
577
|
+
return async function* () {
|
|
578
|
+
throw new ProviderError({
|
|
579
|
+
provider: providerName,
|
|
580
|
+
message: "Provider billing is unavailable",
|
|
581
|
+
type: failure.type,
|
|
582
|
+
status: failure.status,
|
|
583
|
+
retryable: false,
|
|
584
|
+
notSent: true
|
|
585
|
+
});
|
|
586
|
+
}();
|
|
587
|
+
}
|
|
588
|
+
if (billingFailure)
|
|
589
|
+
billingProbe = true;
|
|
551
590
|
const tripped = circuitOpen(providerName);
|
|
552
591
|
if (tripped) {
|
|
553
592
|
return async function* () {
|
|
@@ -1989,5 +2028,5 @@ export {
|
|
|
1989
2028
|
openai
|
|
1990
2029
|
};
|
|
1991
2030
|
|
|
1992
|
-
//# debugId=
|
|
2031
|
+
//# debugId=0CC011402536F35664756E2164756E21
|
|
1993
2032
|
//# sourceMappingURL=openai.js.map
|