@tokenbuddy/tokenbuddy 1.0.8 → 1.0.11
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/src/buyer-store.d.ts +13 -0
- package/dist/src/buyer-store.d.ts.map +1 -1
- package/dist/src/buyer-store.js +21 -2
- package/dist/src/buyer-store.js.map +1 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +54 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/credit-tracker.d.ts +118 -0
- package/dist/src/credit-tracker.d.ts.map +1 -0
- package/dist/src/credit-tracker.js +220 -0
- package/dist/src/credit-tracker.js.map +1 -0
- package/dist/src/daemon.d.ts +49 -4
- package/dist/src/daemon.d.ts.map +1 -1
- package/dist/src/daemon.js +541 -405
- package/dist/src/daemon.js.map +1 -1
- package/dist/src/model-index.d.ts +86 -0
- package/dist/src/model-index.d.ts.map +1 -0
- package/dist/src/model-index.js +214 -0
- package/dist/src/model-index.js.map +1 -0
- package/dist/src/prewarm-cache.d.ts +149 -0
- package/dist/src/prewarm-cache.d.ts.map +1 -0
- package/dist/src/prewarm-cache.js +288 -0
- package/dist/src/prewarm-cache.js.map +1 -0
- package/dist/src/prewarm-scheduler.d.ts +150 -0
- package/dist/src/prewarm-scheduler.d.ts.map +1 -0
- package/dist/src/prewarm-scheduler.js +484 -0
- package/dist/src/prewarm-scheduler.js.map +1 -0
- package/dist/src/provider-install.d.ts.map +1 -1
- package/dist/src/provider-install.js +9 -1
- package/dist/src/provider-install.js.map +1 -1
- package/dist/src/route-failover.d.ts +96 -0
- package/dist/src/route-failover.d.ts.map +1 -0
- package/dist/src/route-failover.js +177 -0
- package/dist/src/route-failover.js.map +1 -0
- package/dist/src/seller-catalog.d.ts +26 -0
- package/dist/src/seller-catalog.d.ts.map +1 -1
- package/dist/src/seller-catalog.js +40 -0
- package/dist/src/seller-catalog.js.map +1 -1
- package/dist/src/seller-pool.d.ts +127 -0
- package/dist/src/seller-pool.d.ts.map +1 -0
- package/dist/src/seller-pool.js +243 -0
- package/dist/src/seller-pool.js.map +1 -0
- package/dist/src/stream-failover.d.ts +78 -0
- package/dist/src/stream-failover.d.ts.map +1 -0
- package/dist/src/stream-failover.js +93 -0
- package/dist/src/stream-failover.js.map +1 -0
- package/package.json +1 -1
- package/src/buyer-store.ts +32 -2
- package/src/cli.ts +61 -0
- package/src/credit-tracker.test.ts +165 -0
- package/src/credit-tracker.ts +269 -0
- package/src/daemon.ts +569 -445
- package/src/model-index.test.ts +184 -0
- package/src/model-index.ts +266 -0
- package/src/prewarm-cache.test.ts +281 -0
- package/src/prewarm-cache.ts +373 -0
- package/src/prewarm-scheduler.test.ts +367 -0
- package/src/prewarm-scheduler.ts +581 -0
- package/src/provider-install.ts +9 -1
- package/src/route-failover.test.ts +193 -0
- package/src/route-failover.ts +233 -0
- package/src/seller-catalog-413.test.ts +61 -0
- package/src/seller-catalog.ts +47 -0
- package/src/seller-pool.test.ts +231 -0
- package/src/seller-pool.ts +333 -0
- package/src/stream-failover.test.ts +52 -0
- package/src/stream-failover.ts +129 -0
- package/src/thousand-seller.test.ts +151 -0
- package/tests/daemon-413-fallback.test.ts +92 -0
- package/tests/e2e.test.ts +3 -2
- package/tests/tokenbuddy.test.ts +68 -11
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { RegistrySeller } from "./seller-catalog.js";
|
|
2
|
+
import type { SellerPool, FailureKind, PoolEntry } from "./seller-pool.js";
|
|
3
|
+
import type { CreditTracker } from "./credit-tracker.js";
|
|
4
|
+
export type RouteAction = "retry_same_seller" | "failover_next" | "fail_fast" | "abort";
|
|
5
|
+
export interface FailoverDecision {
|
|
6
|
+
action: RouteAction;
|
|
7
|
+
retryDelayMs?: number;
|
|
8
|
+
reason: string;
|
|
9
|
+
wastedCreditMicros?: number;
|
|
10
|
+
freshPurchase: boolean;
|
|
11
|
+
retryAttemptsBeforeFailover: number;
|
|
12
|
+
budgetExceeded: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface RouteCandidate {
|
|
15
|
+
routeIndex: number;
|
|
16
|
+
entry: PoolEntry;
|
|
17
|
+
registrySeller: RegistrySeller;
|
|
18
|
+
sellerId: string;
|
|
19
|
+
url: string;
|
|
20
|
+
}
|
|
21
|
+
export interface DecideContext {
|
|
22
|
+
sellerId: string;
|
|
23
|
+
status?: number;
|
|
24
|
+
errorKind: FailureKind;
|
|
25
|
+
errorMessage?: string;
|
|
26
|
+
attempt: number;
|
|
27
|
+
}
|
|
28
|
+
export interface RouteFailoverOptions {
|
|
29
|
+
pool: SellerPool;
|
|
30
|
+
creditTracker: CreditTracker;
|
|
31
|
+
softRetryAttempts?: number;
|
|
32
|
+
softRetryJitterMinMs?: number;
|
|
33
|
+
softRetryJitterMaxMs?: number;
|
|
34
|
+
random?: () => number;
|
|
35
|
+
now?: () => number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Decision engine that wraps the v2 `SellerPool` and the
|
|
39
|
+
* `CreditTracker`. v1.2 §17.3 - §17.8 defines the rules: the controller
|
|
40
|
+
* calls `decide()` after a failure to learn whether to retry the same
|
|
41
|
+
* seller, fail over to the next candidate, fail fast, or give up.
|
|
42
|
+
*
|
|
43
|
+
* The controller is intentionally side-effect-light: it delegates
|
|
44
|
+
* bookkeeping (circuit transitions, wasted-credit transfer) to the pool
|
|
45
|
+
* and tracker via `recordFailure`, and only returns a structured
|
|
46
|
+
* decision. This makes the rules unit-testable without a live HTTP server.
|
|
47
|
+
*/
|
|
48
|
+
export declare class RouteFailover {
|
|
49
|
+
private readonly pool;
|
|
50
|
+
private readonly creditTracker;
|
|
51
|
+
private readonly softRetryAttempts;
|
|
52
|
+
private readonly softRetryJitterMinMs;
|
|
53
|
+
private readonly softRetryJitterMaxMs;
|
|
54
|
+
private readonly random;
|
|
55
|
+
private readonly now;
|
|
56
|
+
constructor(options: RouteFailoverOptions);
|
|
57
|
+
/**
|
|
58
|
+
* Pick the next candidate from the pool. Returns `undefined` when the
|
|
59
|
+
* pool is exhausted, which the caller treats as `abort` (no more routes
|
|
60
|
+
* to try). The returned `routeIndex` is informational (used for log
|
|
61
|
+
* lines) and tracks the absolute ordering across attempts; the controller
|
|
62
|
+
* maintains its own counter.
|
|
63
|
+
*/
|
|
64
|
+
pickNext(modelId: string, protocol: string, paymentMethod: string, limit?: number): RouteCandidate | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Mark a successful inference against `sellerId` with the latest known
|
|
67
|
+
* balance. Mirrors `SellerPool.recordSuccess` semantics: resets the
|
|
68
|
+
* failure counter, closes the circuit, and reports the spend to the
|
|
69
|
+
* credit tracker.
|
|
70
|
+
*/
|
|
71
|
+
recordSuccess(sellerId: string, balanceMicros: number): void;
|
|
72
|
+
/**
|
|
73
|
+
* Decide what to do after a failure. Returns a structured
|
|
74
|
+
* `FailoverDecision`; the controller (daemon.ts) executes the action.
|
|
75
|
+
* The decision also drives accounting: on a failover, the wasted
|
|
76
|
+
* balance is reported in `wastedCreditMicros` for the doctor's summary.
|
|
77
|
+
*/
|
|
78
|
+
decide(context: DecideContext, totalCandidates: number): FailoverDecision;
|
|
79
|
+
/**
|
|
80
|
+
* Convenience: returns true when the next request should be aborted
|
|
81
|
+
* outright (no more candidates).
|
|
82
|
+
*/
|
|
83
|
+
shouldAbort(totalCandidates: number, hasMoreCandidates: boolean): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Inspect the auto-purchase budget. The controller calls this before
|
|
86
|
+
* triggering a fresh `purchase/create` round-trip so it can refuse to
|
|
87
|
+
* auto-purchase once the session is at risk.
|
|
88
|
+
*/
|
|
89
|
+
canAutoPurchase(): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Surface the wasted credit so far for the route currently failing over.
|
|
92
|
+
* Returned in micros.
|
|
93
|
+
*/
|
|
94
|
+
wastedMicrosFor(sellerId: string): number;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=route-failover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-failover.d.ts","sourceRoot":"","sources":["../../src/route-failover.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIzD,MAAM,MAAM,WAAW,GAAG,mBAAmB,GAAG,eAAe,GAAG,WAAW,GAAG,OAAO,CAAC;AAExF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,WAAW,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,OAAO,CAAC;IACvB,2BAA2B,EAAE,MAAM,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,WAAW,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,UAAU,CAAC;IACjB,aAAa,EAAE,aAAa,CAAC;IAE7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAQD;;;;;;;;;;GAUG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEvB,OAAO,EAAE,oBAAoB;IAUzC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,cAAc,GAAG,SAAS;IAejH;;;;;OAKG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAI5D;;;;;OAKG;IACH,MAAM,CAAC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,GAAG,gBAAgB;IAwFzE;;;OAGG;IACH,WAAW,CAAC,eAAe,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,GAAG,OAAO;IAIzE;;;;OAIG;IACH,eAAe,IAAI,OAAO;IAI1B;;;OAGG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAG1C"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { createModuleLogger } from "@tokenbuddy/logging";
|
|
2
|
+
const logger = createModuleLogger("tb-proxyd:route-failover");
|
|
3
|
+
const DEFAULTS = {
|
|
4
|
+
softRetryAttempts: 2,
|
|
5
|
+
softRetryJitterMinMs: 100,
|
|
6
|
+
softRetryJitterMaxMs: 400
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Decision engine that wraps the v2 `SellerPool` and the
|
|
10
|
+
* `CreditTracker`. v1.2 §17.3 - §17.8 defines the rules: the controller
|
|
11
|
+
* calls `decide()` after a failure to learn whether to retry the same
|
|
12
|
+
* seller, fail over to the next candidate, fail fast, or give up.
|
|
13
|
+
*
|
|
14
|
+
* The controller is intentionally side-effect-light: it delegates
|
|
15
|
+
* bookkeeping (circuit transitions, wasted-credit transfer) to the pool
|
|
16
|
+
* and tracker via `recordFailure`, and only returns a structured
|
|
17
|
+
* decision. This makes the rules unit-testable without a live HTTP server.
|
|
18
|
+
*/
|
|
19
|
+
export class RouteFailover {
|
|
20
|
+
pool;
|
|
21
|
+
creditTracker;
|
|
22
|
+
softRetryAttempts;
|
|
23
|
+
softRetryJitterMinMs;
|
|
24
|
+
softRetryJitterMaxMs;
|
|
25
|
+
random;
|
|
26
|
+
now;
|
|
27
|
+
constructor(options) {
|
|
28
|
+
this.pool = options.pool;
|
|
29
|
+
this.creditTracker = options.creditTracker;
|
|
30
|
+
this.softRetryAttempts = options.softRetryAttempts ?? DEFAULTS.softRetryAttempts;
|
|
31
|
+
this.softRetryJitterMinMs = options.softRetryJitterMinMs ?? DEFAULTS.softRetryJitterMinMs;
|
|
32
|
+
this.softRetryJitterMaxMs = options.softRetryJitterMaxMs ?? DEFAULTS.softRetryJitterMaxMs;
|
|
33
|
+
this.random = options.random ?? Math.random;
|
|
34
|
+
this.now = options.now ?? Date.now;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Pick the next candidate from the pool. Returns `undefined` when the
|
|
38
|
+
* pool is exhausted, which the caller treats as `abort` (no more routes
|
|
39
|
+
* to try). The returned `routeIndex` is informational (used for log
|
|
40
|
+
* lines) and tracks the absolute ordering across attempts; the controller
|
|
41
|
+
* maintains its own counter.
|
|
42
|
+
*/
|
|
43
|
+
pickNext(modelId, protocol, paymentMethod, limit = 4) {
|
|
44
|
+
const result = this.pool.pick({ modelId, protocol, paymentMethod, limit });
|
|
45
|
+
if (result.candidates.length === 0) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
const first = result.candidates[0];
|
|
49
|
+
return {
|
|
50
|
+
routeIndex: 0,
|
|
51
|
+
entry: first.entry,
|
|
52
|
+
registrySeller: first.registrySeller,
|
|
53
|
+
sellerId: first.entry.sellerId,
|
|
54
|
+
url: first.entry.url
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Mark a successful inference against `sellerId` with the latest known
|
|
59
|
+
* balance. Mirrors `SellerPool.recordSuccess` semantics: resets the
|
|
60
|
+
* failure counter, closes the circuit, and reports the spend to the
|
|
61
|
+
* credit tracker.
|
|
62
|
+
*/
|
|
63
|
+
recordSuccess(sellerId, balanceMicros) {
|
|
64
|
+
this.pool.recordSuccess(sellerId, balanceMicros, this.now());
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Decide what to do after a failure. Returns a structured
|
|
68
|
+
* `FailoverDecision`; the controller (daemon.ts) executes the action.
|
|
69
|
+
* The decision also drives accounting: on a failover, the wasted
|
|
70
|
+
* balance is reported in `wastedCreditMicros` for the doctor's summary.
|
|
71
|
+
*/
|
|
72
|
+
decide(context, totalCandidates) {
|
|
73
|
+
const isHard = context.errorKind === "hard_4xx" || context.errorKind === "auth_invalid" || context.errorKind === "no_compatible";
|
|
74
|
+
const isSoft = context.errorKind === "soft_5xx" || context.errorKind === "deadline";
|
|
75
|
+
const info = this.pool.inspect(context.sellerId);
|
|
76
|
+
const freshPurchase = info.freshPurchase;
|
|
77
|
+
const budgetExceeded = !this.creditTracker.canAutoPurchase(this.now());
|
|
78
|
+
// Always mark the failure on the pool so circuit thresholds advance.
|
|
79
|
+
const updated = this.pool.recordFailure(context.sellerId, context.errorKind, {
|
|
80
|
+
reason: context.errorMessage,
|
|
81
|
+
now: this.now()
|
|
82
|
+
});
|
|
83
|
+
if (isHard) {
|
|
84
|
+
// Hard failures are not eligible for retry; the seller is wrong
|
|
85
|
+
// for this request. The pool has already transferred leftover
|
|
86
|
+
// credit to the wasted bucket.
|
|
87
|
+
return {
|
|
88
|
+
action: "failover_next",
|
|
89
|
+
reason: `hard_failure:${context.errorKind}`,
|
|
90
|
+
wastedCreditMicros: this.creditTracker.getEntry(context.sellerId)?.leftoverCreditMicros,
|
|
91
|
+
freshPurchase,
|
|
92
|
+
retryAttemptsBeforeFailover: context.attempt,
|
|
93
|
+
budgetExceeded
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (isSoft && freshPurchase && context.attempt < this.softRetryAttempts) {
|
|
97
|
+
// Soft failure inside the fresh-purchase window: retry the same
|
|
98
|
+
// seller with jittered backoff. This is the v1.1 protection against
|
|
99
|
+
// throwing freshly bought credit onto a flaky upstream.
|
|
100
|
+
const span = Math.max(0, this.softRetryJitterMaxMs - this.softRetryJitterMinMs);
|
|
101
|
+
const delay = this.softRetryJitterMinMs + Math.floor(this.random() * span);
|
|
102
|
+
logger.info("route.retry_same_seller.soft", "soft failure in fresh-purchase window; retrying same seller", {
|
|
103
|
+
sellerId: context.sellerId,
|
|
104
|
+
attempt: context.attempt,
|
|
105
|
+
delayMs: delay
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
action: "retry_same_seller",
|
|
109
|
+
retryDelayMs: delay,
|
|
110
|
+
reason: "soft_failure_fresh_purchase_window",
|
|
111
|
+
freshPurchase: true,
|
|
112
|
+
retryAttemptsBeforeFailover: context.attempt,
|
|
113
|
+
budgetExceeded
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (isSoft && context.attempt < this.softRetryAttempts) {
|
|
117
|
+
// Soft failure but not in the fresh-purchase window: still retry
|
|
118
|
+
// once (caller asked for `attempt < softRetryAttempts`) but log the
|
|
119
|
+
// reason. This keeps the "give the seller a second chance" window
|
|
120
|
+
// available for cold sellers without burning any credit.
|
|
121
|
+
const span = Math.max(0, this.softRetryJitterMaxMs - this.softRetryJitterMinMs);
|
|
122
|
+
const delay = this.softRetryJitterMinMs + Math.floor(this.random() * span);
|
|
123
|
+
logger.info("route.retry_same_seller.soft", "soft failure retry outside fresh-purchase window", {
|
|
124
|
+
sellerId: context.sellerId,
|
|
125
|
+
attempt: context.attempt,
|
|
126
|
+
delayMs: delay
|
|
127
|
+
});
|
|
128
|
+
return {
|
|
129
|
+
action: "retry_same_seller",
|
|
130
|
+
retryDelayMs: delay,
|
|
131
|
+
reason: "soft_failure_retry",
|
|
132
|
+
freshPurchase: false,
|
|
133
|
+
retryAttemptsBeforeFailover: context.attempt,
|
|
134
|
+
budgetExceeded
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
// Default: fail over. The wasted credit is whatever current balance
|
|
138
|
+
// remained on the seller after the failure was recorded (the pool
|
|
139
|
+
// transfers it to the leftover bucket for hard failures; for soft
|
|
140
|
+
// failures we surface the *pre-failure* balance so the user sees the
|
|
141
|
+
// impact of the cut-over).
|
|
142
|
+
const wasted = updated?.lastFailAt
|
|
143
|
+
? this.creditTracker.getEntry(context.sellerId)?.currentBalanceMicros
|
|
144
|
+
: undefined;
|
|
145
|
+
return {
|
|
146
|
+
action: "failover_next",
|
|
147
|
+
reason: isSoft ? "soft_failure_exhausted_retries" : `${context.errorKind}`,
|
|
148
|
+
wastedCreditMicros: wasted,
|
|
149
|
+
freshPurchase,
|
|
150
|
+
retryAttemptsBeforeFailover: context.attempt,
|
|
151
|
+
budgetExceeded
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Convenience: returns true when the next request should be aborted
|
|
156
|
+
* outright (no more candidates).
|
|
157
|
+
*/
|
|
158
|
+
shouldAbort(totalCandidates, hasMoreCandidates) {
|
|
159
|
+
return !hasMoreCandidates;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Inspect the auto-purchase budget. The controller calls this before
|
|
163
|
+
* triggering a fresh `purchase/create` round-trip so it can refuse to
|
|
164
|
+
* auto-purchase once the session is at risk.
|
|
165
|
+
*/
|
|
166
|
+
canAutoPurchase() {
|
|
167
|
+
return this.creditTracker.canAutoPurchase(this.now());
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Surface the wasted credit so far for the route currently failing over.
|
|
171
|
+
* Returned in micros.
|
|
172
|
+
*/
|
|
173
|
+
wastedMicrosFor(sellerId) {
|
|
174
|
+
return this.creditTracker.getEntry(sellerId)?.currentBalanceMicros ?? 0;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=route-failover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-failover.js","sourceRoot":"","sources":["../../src/route-failover.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,13 @@ export interface RegistrySeller {
|
|
|
5
5
|
url: string;
|
|
6
6
|
supportedProtocols?: string[];
|
|
7
7
|
paymentMethods?: string[];
|
|
8
|
+
/**
|
|
9
|
+
* v1.2: authoritative model list for buyer-side model-index routing.
|
|
10
|
+
* Optional at the buyer boundary for backward compatibility with older
|
|
11
|
+
* registry payloads, but the upstream wallet-bootstrap registry schema
|
|
12
|
+
* requires it. Missing entries are reported via `models_refresh.seller_missing_models`.
|
|
13
|
+
*/
|
|
14
|
+
models?: string[];
|
|
8
15
|
}
|
|
9
16
|
export interface SellerRegistryDocument {
|
|
10
17
|
version: number;
|
|
@@ -70,6 +77,25 @@ export declare function normalizeSellerUrl(seller: RegistrySeller): string;
|
|
|
70
77
|
export declare function manifestProtocols(manifest: SellerManifest, seller: RegistrySeller): string[];
|
|
71
78
|
export declare function manifestPaymentMethods(manifest: SellerManifest, seller: RegistrySeller): string[];
|
|
72
79
|
export declare function manifestModelIds(manifest: SellerManifest): string[];
|
|
80
|
+
/**
|
|
81
|
+
* v1.2 §18.9: thrown when the bootstrap's `/registry/sellers` endpoint
|
|
82
|
+
* returns HTTP 413 with the `X-TokenBuddy-Registry-Too-Large: 1` header.
|
|
83
|
+
* The daemon catches this in `TokenbuddyDaemon.fetchRegistry` and falls
|
|
84
|
+
* back to the last-known snapshot so the buyer stays routable while the
|
|
85
|
+
* operator shrinks the registry below the 1MB cap.
|
|
86
|
+
*/
|
|
87
|
+
export declare class RegistryTooLargeError extends Error {
|
|
88
|
+
readonly status: number;
|
|
89
|
+
readonly sizeBytes: number;
|
|
90
|
+
readonly sellerCount: number;
|
|
91
|
+
readonly maxBytes: number;
|
|
92
|
+
constructor(detail: {
|
|
93
|
+
status: number;
|
|
94
|
+
sizeBytes: number;
|
|
95
|
+
sellerCount: number;
|
|
96
|
+
maxBytes: number;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
73
99
|
export declare function fetchSellerRegistry(registryUrl: string): Promise<SellerRegistryDocument>;
|
|
74
100
|
export declare function fetchSellerManifest(seller: RegistrySeller): Promise<SellerManifest>;
|
|
75
101
|
export declare function discoverSellerBackedModels(registryUrl: string): Promise<SellerCatalogResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seller-catalog.d.ts","sourceRoot":"","sources":["../../src/seller-catalog.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,kBAAkB,GAAG,kBAAkB,GAAG,WAAW,GAAG,UAAU,CAAC;AAE/E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"seller-catalog.d.ts","sourceRoot":"","sources":["../../src/seller-catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,8 +25,48 @@ function manifestModels(manifest) {
|
|
|
25
25
|
return (manifest.models || [])
|
|
26
26
|
.filter((model) => Boolean(model?.id && typeof model.id === "string"));
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* v1.2 §18.9: thrown when the bootstrap's `/registry/sellers` endpoint
|
|
30
|
+
* returns HTTP 413 with the `X-TokenBuddy-Registry-Too-Large: 1` header.
|
|
31
|
+
* The daemon catches this in `TokenbuddyDaemon.fetchRegistry` and falls
|
|
32
|
+
* back to the last-known snapshot so the buyer stays routable while the
|
|
33
|
+
* operator shrinks the registry below the 1MB cap.
|
|
34
|
+
*/
|
|
35
|
+
export class RegistryTooLargeError extends Error {
|
|
36
|
+
status;
|
|
37
|
+
sizeBytes;
|
|
38
|
+
sellerCount;
|
|
39
|
+
maxBytes;
|
|
40
|
+
constructor(detail) {
|
|
41
|
+
super(`registry response exceeds ${detail.maxBytes} bytes (got ${detail.sizeBytes}, ${detail.sellerCount} sellers, status ${detail.status})`);
|
|
42
|
+
this.name = "RegistryTooLargeError";
|
|
43
|
+
this.status = detail.status;
|
|
44
|
+
this.sizeBytes = detail.sizeBytes;
|
|
45
|
+
this.sellerCount = detail.sellerCount;
|
|
46
|
+
this.maxBytes = detail.maxBytes;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
28
49
|
export async function fetchSellerRegistry(registryUrl) {
|
|
29
50
|
const response = await fetch(registryUrl);
|
|
51
|
+
if (response.status === 413) {
|
|
52
|
+
// v1.2 §18.9: parse the structured 413 body so the caller can
|
|
53
|
+
// decide whether to fall back to a stale snapshot.
|
|
54
|
+
let sizeBytes = 0;
|
|
55
|
+
let sellerCount = 0;
|
|
56
|
+
let maxBytes = 0;
|
|
57
|
+
try {
|
|
58
|
+
const body = (await response.json());
|
|
59
|
+
sizeBytes = body.sizeBytes ?? 0;
|
|
60
|
+
sellerCount = body.sellerCount ?? 0;
|
|
61
|
+
maxBytes = body.maxBytes ?? 0;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Fall through with zeroes; the error message still carries the
|
|
65
|
+
// status code which is enough for the daemon's stale-cache
|
|
66
|
+
// branch to fire.
|
|
67
|
+
}
|
|
68
|
+
throw new RegistryTooLargeError({ status: response.status, sizeBytes, sellerCount, maxBytes });
|
|
69
|
+
}
|
|
30
70
|
if (!response.ok) {
|
|
31
71
|
throw new Error(`registry returned ${response.status}`);
|
|
32
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seller-catalog.js","sourceRoot":"","sources":["../../src/seller-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,MAAM,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"seller-catalog.js","sourceRoot":"","sources":["../../src/seller-catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { RegistrySeller } from "./seller-catalog.js";
|
|
2
|
+
import type { ModelIndex } from "./model-index.js";
|
|
3
|
+
import type { PrewarmCache, PrewarmEntry } from "./prewarm-cache.js";
|
|
4
|
+
import type { CreditTracker } from "./credit-tracker.js";
|
|
5
|
+
export type CircuitState = "closed" | "half_open" | "open";
|
|
6
|
+
export type FailureKind = "hard_4xx" | "auth_invalid" | "insufficient_funds" | "soft_5xx" | "deadline" | "stream_aborted" | "no_compatible";
|
|
7
|
+
export interface PoolEntry {
|
|
8
|
+
sellerId: string;
|
|
9
|
+
url: string;
|
|
10
|
+
registrySeller: RegistrySeller;
|
|
11
|
+
circuit: CircuitState;
|
|
12
|
+
consecutiveFailures: number;
|
|
13
|
+
recentFailures: number[];
|
|
14
|
+
lastSuccessAt: number;
|
|
15
|
+
lastFailAt: number;
|
|
16
|
+
lastProbeAt: number;
|
|
17
|
+
healthScore: number;
|
|
18
|
+
avgLatencyMs: number;
|
|
19
|
+
}
|
|
20
|
+
export interface PickOptions {
|
|
21
|
+
modelId: string;
|
|
22
|
+
protocol: string;
|
|
23
|
+
paymentMethod: string;
|
|
24
|
+
limit?: number;
|
|
25
|
+
now?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface PickResult {
|
|
28
|
+
candidates: Array<{
|
|
29
|
+
entry: PoolEntry;
|
|
30
|
+
registrySeller: RegistrySeller;
|
|
31
|
+
}>;
|
|
32
|
+
reason: string;
|
|
33
|
+
resolved: ModelIndexResolution;
|
|
34
|
+
}
|
|
35
|
+
export interface ModelIndexResolution {
|
|
36
|
+
modelId: string;
|
|
37
|
+
matched: boolean;
|
|
38
|
+
candidates: RegistrySeller[];
|
|
39
|
+
missingModelsFlag: number;
|
|
40
|
+
}
|
|
41
|
+
export interface SellerPoolOptions {
|
|
42
|
+
modelIndex: ModelIndex;
|
|
43
|
+
cache: PrewarmCache;
|
|
44
|
+
creditTracker: CreditTracker;
|
|
45
|
+
failureThreshold?: number;
|
|
46
|
+
windowMs?: number;
|
|
47
|
+
windowFailureRate?: number;
|
|
48
|
+
openStateMs?: number;
|
|
49
|
+
now?: () => number;
|
|
50
|
+
applyRegistry?: (entries: PoolEntry[], registry: RegistrySeller[]) => PoolEntry[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* v2 SellerPool: combines `ModelIndex` (registry index), `PrewarmCache`
|
|
54
|
+
* (probe results), and `CreditTracker` (balance protection) into a single
|
|
55
|
+
* source of truth used by the route-failover controller. The pool is
|
|
56
|
+
* process-local and rebuilds its entry list from the cache whenever the
|
|
57
|
+
* cache mutates; entries not yet present in the cache are not in the pool.
|
|
58
|
+
*/
|
|
59
|
+
export declare class SellerPool {
|
|
60
|
+
private readonly modelIndex;
|
|
61
|
+
private readonly cache;
|
|
62
|
+
private readonly creditTracker;
|
|
63
|
+
private readonly failureThreshold;
|
|
64
|
+
private readonly windowMs;
|
|
65
|
+
private readonly windowFailureRate;
|
|
66
|
+
private readonly openStateMs;
|
|
67
|
+
private readonly now;
|
|
68
|
+
private entries;
|
|
69
|
+
constructor(options: SellerPoolOptions);
|
|
70
|
+
/**
|
|
71
|
+
* Rebuild entries from the current prewarm cache. Called by
|
|
72
|
+
* `route-failover` whenever the cache is mutated (commit, invalidate,
|
|
73
|
+
* etc.) so the pool always reflects the latest probe results.
|
|
74
|
+
*/
|
|
75
|
+
sync(): number;
|
|
76
|
+
/**
|
|
77
|
+
* Pick up to `limit` candidates for a (model, protocol, payment) triple.
|
|
78
|
+
* Sellers in the `open` circuit are skipped unless their open state has
|
|
79
|
+
* expired (they are flipped to `half_open` and included). Candidates are
|
|
80
|
+
* sorted by health score (descending) so the strongest seller goes first.
|
|
81
|
+
*/
|
|
82
|
+
pick(options: PickOptions): PickResult;
|
|
83
|
+
/**
|
|
84
|
+
* Record a successful inference against `sellerId`. The circuit closes
|
|
85
|
+
* (if it was half-open) and the credit tracker observes the latest
|
|
86
|
+
* balance via `recordSpend`.
|
|
87
|
+
*/
|
|
88
|
+
recordSuccess(sellerId: string, balanceMicros: number, now?: number): PoolEntry | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* Record a failure against `sellerId`. Returns the new PoolEntry. The
|
|
91
|
+
* caller (route-failover) uses the returned `entry.circuit` and the
|
|
92
|
+
* entry's `lastFailAt` to decide whether to fail over, retry, or stop.
|
|
93
|
+
* On a non-recoverable failure (`hard_4xx`, `auth_invalid`,
|
|
94
|
+
* `insufficient_funds`) the credit is also transferred to the wasted
|
|
95
|
+
* bucket so the wasted-micros counter stays accurate.
|
|
96
|
+
*/
|
|
97
|
+
recordFailure(sellerId: string, kind: FailureKind, options?: {
|
|
98
|
+
transferLeftover?: boolean;
|
|
99
|
+
reason?: string;
|
|
100
|
+
now?: number;
|
|
101
|
+
}): PoolEntry | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Expose a per-seller credit / circuit snapshot to the route-failover.
|
|
104
|
+
* Used to decide whether a soft failure should retry on the same seller
|
|
105
|
+
* (刚买窗口保护) or fail over immediately.
|
|
106
|
+
*/
|
|
107
|
+
inspect(sellerId: string): {
|
|
108
|
+
entry?: PoolEntry;
|
|
109
|
+
freshPurchase: boolean;
|
|
110
|
+
autoPurchaseAvailable: boolean;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Manually mark an entry as `open`. Used by the registry loop when a
|
|
114
|
+
* seller is removed from the registry: the entry lingers for a grace
|
|
115
|
+
* period but is unreachable, so opening the circuit prevents any
|
|
116
|
+
* further selection.
|
|
117
|
+
*/
|
|
118
|
+
markOpen(sellerId: string, reason: string, now?: number): void;
|
|
119
|
+
/**
|
|
120
|
+
* List all known pool entries. Used by `tb doctor` and tests.
|
|
121
|
+
*/
|
|
122
|
+
snapshot(): PoolEntry[];
|
|
123
|
+
size(): number;
|
|
124
|
+
private maybeRecycleFromOpen;
|
|
125
|
+
}
|
|
126
|
+
export type { PrewarmEntry };
|
|
127
|
+
//# sourceMappingURL=seller-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seller-pool.d.ts","sourceRoot":"","sources":["../../src/seller-pool.ts"],"names":[],"mappings":"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"}
|