floe-guard 0.6.0 → 0.7.0
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/index.cjs +40 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +38 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -514,4 +514,33 @@ interface BudgetGuardMiddleware {
|
|
|
514
514
|
*/
|
|
515
515
|
declare function budgetGuardMiddleware(guard: BudgetGuard): BudgetGuardMiddleware;
|
|
516
516
|
|
|
517
|
-
|
|
517
|
+
interface RetryPlan<T> {
|
|
518
|
+
/** Operation to run for this retry attempt. */
|
|
519
|
+
call: () => T | Promise<T>;
|
|
520
|
+
/**
|
|
521
|
+
* Estimated retry cost passed to `guard.check()` before the retry runs.
|
|
522
|
+
* Leave undefined to use the guard's default last-call estimate.
|
|
523
|
+
*/
|
|
524
|
+
estimatedCost?: number;
|
|
525
|
+
}
|
|
526
|
+
interface BudgetRetryOptions<T> {
|
|
527
|
+
/** Estimated cost for retrying the original call. */
|
|
528
|
+
estimatedCost?: number;
|
|
529
|
+
/** Total attempts, including the first call. Default: 2. */
|
|
530
|
+
maxAttempts?: number;
|
|
531
|
+
/** Choose a cheaper retry plan when `guard.advisory().nearLimit` is true. */
|
|
532
|
+
onDegrade?: (error: unknown, advisory: BudgetAdvisory) => RetryPlan<T> | Promise<RetryPlan<T> | undefined> | undefined;
|
|
533
|
+
/** Decide whether an error is retryable. Defaults to all non-budget errors. */
|
|
534
|
+
retryIf?: (error: unknown) => boolean;
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Run `call` with budget-aware retries.
|
|
538
|
+
*
|
|
539
|
+
* The first attempt runs unchanged. If it fails with a retryable error, the
|
|
540
|
+
* helper retries as-is with ample budget, asks `onDegrade` for a cheaper plan
|
|
541
|
+
* when near the limit, and always calls `guard.check(estimatedCost)` before a
|
|
542
|
+
* retry so an over-budget retry is blocked before it runs.
|
|
543
|
+
*/
|
|
544
|
+
declare function withBudgetRetry<T>(guard: BudgetGuard, call: () => T | Promise<T>, options?: BudgetRetryOptions<T>): Promise<T>;
|
|
545
|
+
|
|
546
|
+
export { type BudgetAdvisory, BudgetExceeded, BudgetGuard, type BudgetGuardMiddleware, type BudgetGuardOptions, type BudgetRetryOptions, DeadlineExceeded, FloeGuardError, type LatencyAdvisory, LatencyBudget, type LatencyBudgetOptions, type ManualPrice, type PricedModel, type RetryPlan, type SpendEvent, UnpriceableModelError, budgetGuardMiddleware, priceTokens, pricing, resolvePrice, withBudgetRetry };
|
package/dist/index.js
CHANGED
|
@@ -1624,6 +1624,42 @@ function budgetGuardMiddleware(guard) {
|
|
|
1624
1624
|
}
|
|
1625
1625
|
};
|
|
1626
1626
|
}
|
|
1627
|
+
|
|
1628
|
+
// src/retry.ts
|
|
1629
|
+
function defaultRetryIf(error) {
|
|
1630
|
+
return !(error instanceof BudgetExceeded);
|
|
1631
|
+
}
|
|
1632
|
+
async function withBudgetRetry(guard, call, options = {}) {
|
|
1633
|
+
const maxAttempts = options.maxAttempts ?? 2;
|
|
1634
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {
|
|
1635
|
+
throw new RangeError(`maxAttempts must be an integer >= 1, got ${maxAttempts}`);
|
|
1636
|
+
}
|
|
1637
|
+
const retryIf = options.retryIf ?? defaultRetryIf;
|
|
1638
|
+
let plan = { call, estimatedCost: options.estimatedCost };
|
|
1639
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
1640
|
+
try {
|
|
1641
|
+
return await plan.call();
|
|
1642
|
+
} catch (error) {
|
|
1643
|
+
if (attempt >= maxAttempts || !retryIf(error)) {
|
|
1644
|
+
throw error;
|
|
1645
|
+
}
|
|
1646
|
+
plan = await nextPlan(guard, error, plan, options.onDegrade);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
throw new Error("unreachable");
|
|
1650
|
+
}
|
|
1651
|
+
async function nextPlan(guard, error, current, onDegrade) {
|
|
1652
|
+
const advisory = guard.advisory();
|
|
1653
|
+
if (advisory.nearLimit && onDegrade !== void 0) {
|
|
1654
|
+
const degraded = await onDegrade(error, advisory);
|
|
1655
|
+
if (degraded !== void 0) {
|
|
1656
|
+
guard.check(degraded.estimatedCost);
|
|
1657
|
+
return degraded;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
guard.check(current.estimatedCost);
|
|
1661
|
+
return current;
|
|
1662
|
+
}
|
|
1627
1663
|
export {
|
|
1628
1664
|
BudgetExceeded,
|
|
1629
1665
|
BudgetGuard,
|
|
@@ -1634,6 +1670,7 @@ export {
|
|
|
1634
1670
|
budgetGuardMiddleware,
|
|
1635
1671
|
priceTokens,
|
|
1636
1672
|
pricing_exports as pricing,
|
|
1637
|
-
resolvePrice
|
|
1673
|
+
resolvePrice,
|
|
1674
|
+
withBudgetRetry
|
|
1638
1675
|
};
|
|
1639
1676
|
//# sourceMappingURL=index.js.map
|