@tokenbuddy/tokenbuddy 1.0.9 → 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.
Files changed (71) hide show
  1. package/dist/src/buyer-store.d.ts +13 -0
  2. package/dist/src/buyer-store.d.ts.map +1 -1
  3. package/dist/src/buyer-store.js +21 -2
  4. package/dist/src/buyer-store.js.map +1 -1
  5. package/dist/src/cli.d.ts.map +1 -1
  6. package/dist/src/cli.js +54 -0
  7. package/dist/src/cli.js.map +1 -1
  8. package/dist/src/credit-tracker.d.ts +118 -0
  9. package/dist/src/credit-tracker.d.ts.map +1 -0
  10. package/dist/src/credit-tracker.js +220 -0
  11. package/dist/src/credit-tracker.js.map +1 -0
  12. package/dist/src/daemon.d.ts +49 -4
  13. package/dist/src/daemon.d.ts.map +1 -1
  14. package/dist/src/daemon.js +541 -405
  15. package/dist/src/daemon.js.map +1 -1
  16. package/dist/src/model-index.d.ts +86 -0
  17. package/dist/src/model-index.d.ts.map +1 -0
  18. package/dist/src/model-index.js +214 -0
  19. package/dist/src/model-index.js.map +1 -0
  20. package/dist/src/prewarm-cache.d.ts +149 -0
  21. package/dist/src/prewarm-cache.d.ts.map +1 -0
  22. package/dist/src/prewarm-cache.js +288 -0
  23. package/dist/src/prewarm-cache.js.map +1 -0
  24. package/dist/src/prewarm-scheduler.d.ts +150 -0
  25. package/dist/src/prewarm-scheduler.d.ts.map +1 -0
  26. package/dist/src/prewarm-scheduler.js +484 -0
  27. package/dist/src/prewarm-scheduler.js.map +1 -0
  28. package/dist/src/provider-install.d.ts.map +1 -1
  29. package/dist/src/provider-install.js +9 -1
  30. package/dist/src/provider-install.js.map +1 -1
  31. package/dist/src/route-failover.d.ts +96 -0
  32. package/dist/src/route-failover.d.ts.map +1 -0
  33. package/dist/src/route-failover.js +177 -0
  34. package/dist/src/route-failover.js.map +1 -0
  35. package/dist/src/seller-catalog.d.ts +26 -0
  36. package/dist/src/seller-catalog.d.ts.map +1 -1
  37. package/dist/src/seller-catalog.js +40 -0
  38. package/dist/src/seller-catalog.js.map +1 -1
  39. package/dist/src/seller-pool.d.ts +127 -0
  40. package/dist/src/seller-pool.d.ts.map +1 -0
  41. package/dist/src/seller-pool.js +243 -0
  42. package/dist/src/seller-pool.js.map +1 -0
  43. package/dist/src/stream-failover.d.ts +78 -0
  44. package/dist/src/stream-failover.d.ts.map +1 -0
  45. package/dist/src/stream-failover.js +93 -0
  46. package/dist/src/stream-failover.js.map +1 -0
  47. package/package.json +1 -1
  48. package/src/buyer-store.ts +32 -2
  49. package/src/cli.ts +61 -0
  50. package/src/credit-tracker.test.ts +165 -0
  51. package/src/credit-tracker.ts +269 -0
  52. package/src/daemon.ts +569 -445
  53. package/src/model-index.test.ts +184 -0
  54. package/src/model-index.ts +266 -0
  55. package/src/prewarm-cache.test.ts +281 -0
  56. package/src/prewarm-cache.ts +373 -0
  57. package/src/prewarm-scheduler.test.ts +367 -0
  58. package/src/prewarm-scheduler.ts +581 -0
  59. package/src/provider-install.ts +9 -1
  60. package/src/route-failover.test.ts +193 -0
  61. package/src/route-failover.ts +233 -0
  62. package/src/seller-catalog-413.test.ts +61 -0
  63. package/src/seller-catalog.ts +47 -0
  64. package/src/seller-pool.test.ts +231 -0
  65. package/src/seller-pool.ts +333 -0
  66. package/src/stream-failover.test.ts +52 -0
  67. package/src/stream-failover.ts +129 -0
  68. package/src/thousand-seller.test.ts +151 -0
  69. package/tests/daemon-413-fallback.test.ts +92 -0
  70. package/tests/e2e.test.ts +3 -2
  71. 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":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAKzD,MAAM,MAAM,GAAG,kBAAkB,CAAC,0BAA0B,CAAC,CAAC;AAyC9D,MAAM,QAAQ,GAAG;IACf,iBAAiB,EAAE,CAAC;IACpB,oBAAoB,EAAE,GAAG;IACzB,oBAAoB,EAAE,GAAG;CAC1B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,OAAO,aAAa;IACP,IAAI,CAAa;IACjB,aAAa,CAAgB;IAC7B,iBAAiB,CAAS;IAC1B,oBAAoB,CAAS;IAC7B,oBAAoB,CAAS;IAC7B,MAAM,CAAe;IACrB,GAAG,CAAe;IAEnC,YAAY,OAA6B;QACvC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,IAAI,QAAQ,CAAC,iBAAiB,CAAC;QACjF,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,IAAI,QAAQ,CAAC,oBAAoB,CAAC;QAC1F,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,IAAI,QAAQ,CAAC,oBAAoB,CAAC;QAC1F,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;QAC5C,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACrC,CAAC;IAED;;;;;;OAMG;IACH,QAAQ,CAAC,OAAe,EAAE,QAAgB,EAAE,aAAqB,EAAE,QAAgB,CAAC;QAClF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3E,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACnC,OAAO;YACL,UAAU,EAAE,CAAC;YACb,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ;YAC9B,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG;SACrB,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAC,QAAgB,EAAE,aAAqB;QACnD,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,OAAsB,EAAE,eAAuB;QACpD,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,KAAK,UAAU,IAAI,OAAO,CAAC,SAAS,KAAK,cAAc,IAAI,OAAO,CAAC,SAAS,KAAK,eAAe,CAAC;QACjI,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,KAAK,UAAU,IAAI,OAAO,CAAC,SAAS,KAAK,UAAU,CAAC;QACpF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QACzC,MAAM,cAAc,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAEvE,qEAAqE;QACrE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,EAAE;YAC3E,MAAM,EAAE,OAAO,CAAC,YAAY;YAC5B,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE;SAChB,CAAC,CAAC;QAEH,IAAI,MAAM,EAAE,CAAC;YACX,gEAAgE;YAChE,8DAA8D;YAC9D,+BAA+B;YAC/B,OAAO;gBACL,MAAM,EAAE,eAAe;gBACvB,MAAM,EAAE,gBAAgB,OAAO,CAAC,SAAS,EAAE;gBAC3C,kBAAkB,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,oBAAoB;gBACvF,aAAa;gBACb,2BAA2B,EAAE,OAAO,CAAC,OAAO;gBAC5C,cAAc;aACf,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,IAAI,aAAa,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACxE,gEAAgE;YAChE,oEAAoE;YACpE,wDAAwD;YACxD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,CAAC,CAAC;YAChF,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;YAC3E,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,6DAA6D,EAAE;gBACzG,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;YACH,OAAO;gBACL,MAAM,EAAE,mBAAmB;gBAC3B,YAAY,EAAE,KAAK;gBACnB,MAAM,EAAE,oCAAoC;gBAC5C,aAAa,EAAE,IAAI;gBACnB,2BAA2B,EAAE,OAAO,CAAC,OAAO;gBAC5C,cAAc;aACf,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvD,iEAAiE;YACjE,oEAAoE;YACpE,kEAAkE;YAClE,yDAAyD;YACzD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,CAAC,CAAC;YAChF,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;YAC3E,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,kDAAkD,EAAE;gBAC9F,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;YACH,OAAO;gBACL,MAAM,EAAE,mBAAmB;gBAC3B,YAAY,EAAE,KAAK;gBACnB,MAAM,EAAE,oBAAoB;gBAC5B,aAAa,EAAE,KAAK;gBACpB,2BAA2B,EAAE,OAAO,CAAC,OAAO;gBAC5C,cAAc;aACf,CAAC;QACJ,CAAC;QAED,oEAAoE;QACpE,kEAAkE;QAClE,kEAAkE;QAClE,qEAAqE;QACrE,2BAA2B;QAC3B,MAAM,MAAM,GAAG,OAAO,EAAE,UAAU;YAChC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,oBAAoB;YACrE,CAAC,CAAC,SAAS,CAAC;QACd,OAAO;YACL,MAAM,EAAE,eAAe;YACvB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,EAAE;YAC1E,kBAAkB,EAAE,MAAM;YAC1B,aAAa;YACb,2BAA2B,EAAE,OAAO,CAAC,OAAO;YAC5C,cAAc;SACf,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,eAAuB,EAAE,iBAA0B;QAC7D,OAAO,CAAC,iBAAiB,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACxD,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,QAAgB;QAC9B,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,IAAI,CAAC,CAAC;IAC1E,CAAC;CACF"}
@@ -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":"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"}
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":"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"}
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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"}