@qadanm/opencode-smart-router 0.0.0-stage → 0.4.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.
Files changed (65) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/CONTRIBUTING.md +96 -0
  3. package/LICENSE +21 -0
  4. package/README.md +341 -2
  5. package/SECURITY.md +174 -0
  6. package/config.example.json +108 -0
  7. package/dist/allowance.js +487 -0
  8. package/dist/gui-experimental.cjs +1 -0
  9. package/dist/index.js +11111 -0
  10. package/dist/npm/index.js +40 -0
  11. package/dist/tui.js +587 -0
  12. package/docs/ARCHITECTURE.md +104 -0
  13. package/docs/DEBUGGING-GUI.md +70 -0
  14. package/docs/INSTALL.md +120 -0
  15. package/docs/LIMITATIONS.md +213 -0
  16. package/docs/MODELS.md +124 -0
  17. package/docs/OPENDESIGN-INTEGRATION.md +635 -0
  18. package/docs/QA.md +142 -0
  19. package/docs/SHARED-CORE.md +72 -0
  20. package/install +75 -0
  21. package/package.json +92 -4
  22. package/scripts/install.sh +324 -0
  23. package/scripts/uninstall.sh +91 -0
  24. package/src/allowance.ts +135 -0
  25. package/src/core/classify/classifier.ts +305 -0
  26. package/src/core/config-writer.ts +167 -0
  27. package/src/core/config.ts +1030 -0
  28. package/src/core/context/strategy.ts +188 -0
  29. package/src/core/context-health.ts +39 -0
  30. package/src/core/failures.ts +398 -0
  31. package/src/core/history/opencode.ts +173 -0
  32. package/src/core/models/protocol.ts +22 -0
  33. package/src/core/models/registry.ts +203 -0
  34. package/src/core/models/seed.ts +771 -0
  35. package/src/core/offline/mode.ts +321 -0
  36. package/src/core/plan-page.ts +390 -0
  37. package/src/core/plans/catalog.ts +481 -0
  38. package/src/core/policy/calibration.ts +259 -0
  39. package/src/core/policy/eligibility.ts +578 -0
  40. package/src/core/providers/enablement.ts +143 -0
  41. package/src/core/providers/opendesign-credits.ts +206 -0
  42. package/src/core/providers/opendesign-models.ts +628 -0
  43. package/src/core/providers/opendesign.ts +474 -0
  44. package/src/core/quota/calibration.ts +166 -0
  45. package/src/core/quota/commandcode.ts +471 -0
  46. package/src/core/quota/credentials.ts +490 -0
  47. package/src/core/quota/ledger.ts +1273 -0
  48. package/src/core/quota/opencode-go.ts +148 -0
  49. package/src/core/quota/opendesign.ts +1043 -0
  50. package/src/core/quota/reconcile.ts +155 -0
  51. package/src/core/quota/report.ts +261 -0
  52. package/src/core/quota/service.ts +273 -0
  53. package/src/core/reprompt.ts +48 -0
  54. package/src/core/routing/engine.ts +919 -0
  55. package/src/core/types.ts +825 -0
  56. package/src/core/ui.ts +236 -0
  57. package/src/core/util.ts +114 -0
  58. package/src/gui/index.tsx +1670 -0
  59. package/src/gui/viewmodel.ts +456 -0
  60. package/src/index.ts +48 -0
  61. package/src/rpc.ts +204 -0
  62. package/src/server/controller.ts +3281 -0
  63. package/src/server/route-tracker.ts +60 -0
  64. package/src/server/shared-core.ts +671 -0
  65. package/src/tui/index.tsx +168 -0
@@ -0,0 +1,1043 @@
1
+ import type {
2
+ CreditPoolSnapshot,
3
+ ProviderQuotaSnapshot,
4
+ ProviderSettings,
5
+ QuotaWindow,
6
+ UsageEvent,
7
+ } from "../types.js"
8
+ import { clamp, describePlan, pct, redact } from "../util.js"
9
+ import {
10
+ OPENDESIGN_DEFAULT_CONTROL_BASE_URL,
11
+ OPENDESIGN_USER_AGENT,
12
+ failureClassForStatus,
13
+ normalizeOpenDesignControlBaseURL,
14
+ openDesignControlEndpoint,
15
+ type FetchLike,
16
+ } from "../providers/opendesign.js"
17
+ import { OPEN_DESIGN_MODEL_BY_ID } from "../providers/opendesign-models.js"
18
+ import { OPENDESIGN_DESIGN_PLAN_POOL, OPENDESIGN_PLAN_MODEL_POOL, isEscalationOnlyPool, resolvePlan } from "../plans/catalog.js"
19
+ import { creditMultiplierFor } from "../providers/opendesign-credits.js"
20
+ import { calibrationSamples, effectiveMarginPct } from "./calibration.js"
21
+
22
+ /**
23
+ * OpenDesign quota integration.
24
+ *
25
+ * OpenDesign publishes no quota API for an inference key. Re-verified on
26
+ * 2026-10-30 against the live gateway: `GET /v1/models` returns 200 with the
27
+ * same key, while `/v1/usage`, `/v1/me`, `/v1/credits`, `/v1/billing`,
28
+ * `/v1/account`, `/v1/subscription`, `/v1/limits` and `/v1/quota` all return
29
+ * 404. The key is valid and authorized for inference; there is simply no usage
30
+ * surface for it. The account-control host rejects an inference key with HTTP
31
+ * 401. The upstream feature request for a key-readable usage endpoint is still
32
+ * open (nexu-io/open-design#8674), as is the control-key lifecycle request
33
+ * (#8870).
34
+ *
35
+ * Three states are therefore supported:
36
+ *
37
+ * - `verified` A control key was explicitly configured, so the account's own
38
+ * coding-plan usage windows are read directly.
39
+ * - `estimated` Only the inference key is available, so the router models its
40
+ * own credit consumption against the published plan caps.
41
+ * - `unknown` Nothing can be established safely.
42
+ *
43
+ * The estimated state is a lower bound: usage from the OpenDesign desktop app
44
+ * or any other client on the same subscription is invisible to the router. A
45
+ * configurable margin is applied and the uncertainty is reported, never hidden.
46
+ */
47
+
48
+ export type OpenDesignQuotaState =
49
+ | "verified"
50
+ | "estimated"
51
+ | "stale"
52
+ | "unknown"
53
+ | "exhausted"
54
+ | "unavailable"
55
+
56
+ export interface OpenDesignQuotaInput {
57
+ readonly settings: ProviderSettings
58
+ readonly apiKey?: string
59
+ readonly controlKey?: string
60
+ readonly controlBaseURL?: string
61
+ readonly usage: ReadonlyArray<UsageEvent>
62
+ readonly fetchImpl?: FetchLike
63
+ readonly now?: () => number
64
+ readonly multiplierOverrides?: Readonly<Record<string, number>>
65
+ /** Credits per USD as reported by the account. Defaults to the observed value. */
66
+ readonly creditsPerUsd?: number
67
+ /** Extra margin applied to locally observed usage, in percent. */
68
+ readonly uncertaintyMarginPct?: number
69
+ readonly timeoutMs?: number
70
+ }
71
+
72
+ export interface OpenDesignQuotaResult {
73
+ readonly snapshot: ProviderQuotaSnapshot
74
+ readonly state: OpenDesignQuotaState
75
+ }
76
+
77
+ /** Credits per USD observed from the OpenDesign account surface. */
78
+ export const OPENDESIGN_DEFAULT_CREDITS_PER_USD = 10_000
79
+
80
+ export const OPENDESIGN_DEFAULT_UNCERTAINTY_MARGIN_PCT = 20
81
+
82
+ const FIVE_HOURS_MS = 5 * 60 * 60 * 1000
83
+ const WEEK_MS = 7 * 24 * 60 * 60 * 1000
84
+ /**
85
+ * The widest window this module models.
86
+ *
87
+ * Exported because the caller has to hand back at least this much history for
88
+ * the estimate to be complete. Keeping the number in one place stops the two
89
+ * from drifting into a silent under-count.
90
+ */
91
+ export const OPENDESIGN_MONTH_MS = 30 * 24 * 60 * 60 * 1000
92
+ const MONTH_MS = OPENDESIGN_MONTH_MS
93
+
94
+ const unknownWindow: QuotaWindow = { usedPct: 0, remainingPct: 100, source: "unknown" }
95
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
96
+ typeof value === "object" && value !== null && !Array.isArray(value)
97
+
98
+ const numberOr = (value: unknown): number | undefined => {
99
+ if (typeof value === "number" && Number.isFinite(value)) return value
100
+ if (typeof value === "string") {
101
+ const parsed = Number(value)
102
+ if (Number.isFinite(parsed)) return parsed
103
+ }
104
+ return undefined
105
+ }
106
+
107
+ const timeValue = (value: unknown): number | undefined => {
108
+ if (typeof value === "number" && Number.isFinite(value)) return value
109
+ if (typeof value === "string") {
110
+ const parsed = Date.parse(value)
111
+ if (Number.isFinite(parsed)) return parsed
112
+ }
113
+ return undefined
114
+ }
115
+
116
+ /**
117
+ * Estimate the Design Plan credits consumed by one request.
118
+ *
119
+ * This converts token counts into credits using the curated vendor list price
120
+ * for the model and the published Design Plan multiplier. It is an estimate of
121
+ * the underlying usage value, never an observed provider charge.
122
+ *
123
+ * `multiplierApplies` is false for a request funded from plan model credits:
124
+ * OpenDesign documents that Design Plan model multipliers do not
125
+ * automatically apply to that second pool, so applying one would understate
126
+ * its real cost.
127
+ */
128
+ export const estimateDesignPlanCredits = (input: {
129
+ readonly modelID: string
130
+ readonly input: number
131
+ readonly output: number
132
+ readonly cacheRead: number
133
+ readonly cacheWrite?: number
134
+ readonly multiplierOverrides?: Readonly<Record<string, number>>
135
+ readonly now?: number
136
+ readonly multiplierApplies?: boolean
137
+ }): { creditsUsd: number; multiplier: number; evidence: string } => {
138
+ const spec = OPEN_DESIGN_MODEL_BY_ID.get(input.modelID)
139
+ const tier = spec?.cost?.[0]
140
+ const multiplier = creditMultiplierFor(input.modelID, {
141
+ now: input.now,
142
+ ...(input.multiplierOverrides ? { overrides: input.multiplierOverrides } : {}),
143
+ })
144
+ const applies = input.multiplierApplies !== false
145
+ const effectiveMultiplier = applies ? multiplier.multiplier : 1
146
+ if (!tier) {
147
+ return { creditsUsd: 0, multiplier: effectiveMultiplier, evidence: "no-price" }
148
+ }
149
+ const price = (tier.input * Math.max(0, input.input) +
150
+ tier.output * Math.max(0, input.output) +
151
+ (tier.cache?.read ?? 0) * Math.max(0, input.cacheRead) +
152
+ (tier.cache?.write ?? 0) * Math.max(0, input.cacheWrite ?? 0)) /
153
+ 1_000_000
154
+ return {
155
+ creditsUsd: Math.max(0, price) * effectiveMultiplier,
156
+ multiplier: effectiveMultiplier,
157
+ evidence: applies ? multiplier.evidence : "configured",
158
+ }
159
+ }
160
+
161
+ interface LocalWindowTotals {
162
+ readonly rollingUsd: number
163
+ readonly weeklyUsd: number
164
+ readonly monthlyUsd: number
165
+ readonly observedRequests: number
166
+ /** Credits per pool, so the two allowances are never conflated. */
167
+ readonly byPool: Readonly<Record<string, {
168
+ readonly rollingUsd: number
169
+ readonly weeklyUsd: number
170
+ readonly monthlyUsd: number
171
+ }>>
172
+ }
173
+
174
+ /**
175
+ * Estimate local usage, split by the pool that funded each request.
176
+ *
177
+ * A Design Plan model is billed at its Design Plan multiplier while that pool
178
+ * has credit, then at the plain rate from plan model credits. The estimate
179
+ * applies the pool that the model draws from first, which is the correct
180
+ * attribution for forecasting: it asks "which allowance is this consuming?"
181
+ * rather than "what is the cheapest rate this model ever gets?".
182
+ */
183
+ /**
184
+ * Start of the current fixed seven-day Design Plan window.
185
+ *
186
+ * OpenDesign anchors the window to the subscription, which the router cannot
187
+ * read. It can, however, be told: a pasted "resets in 0d 22h" gives the end,
188
+ * and the start is exactly seven days before it. Without that anchor the best
189
+ * available assumption is a window ending seven days from now, which is wrong
190
+ * for everyone but no more wrong than the rolling window it replaces.
191
+ */
192
+ export const weeklyWindowStart = (now: number, resetsAt?: number): number => {
193
+ if (resetsAt !== undefined && Number.isFinite(resetsAt) && resetsAt > now) {
194
+ return resetsAt - WEEK_MS
195
+ }
196
+ return now - WEEK_MS
197
+ }
198
+
199
+ const localTotals = (
200
+ usage: ReadonlyArray<UsageEvent>,
201
+ providerID: string,
202
+ now: number,
203
+ marginPct: number,
204
+ plan: ReturnType<typeof resolvePlan>,
205
+ multiplierOverrides?: Readonly<Record<string, number>>,
206
+ /** When the current seven-day window resets, when the caller knows it. */
207
+ windowResetsAt?: number,
208
+ ): LocalWindowTotals => {
209
+ /**
210
+ * Window boundaries.
211
+ *
212
+ * The seven-day Design Plan window is FIXED: the vendor documents that it
213
+ * starts when the subscription starts and repeats every seven days, so
214
+ * "Wednesday 10:00 to the following Wednesday 10:00" — not "the last seven
215
+ * days". Bucketing by `now - 7 days` is a rolling window and overstates the
216
+ * current window's usage by including events from the previous one, which is
217
+ * the difference between "40% used" and "60% used" for most of a week.
218
+ *
219
+ * The anchor comes from the caller when known (a pasted reset time), because
220
+ * the true start is a property of the subscription, not of the clock.
221
+ */
222
+ const rollingCutoff = now - FIVE_HOURS_MS
223
+ const weekCutoff = weeklyWindowStart(now, windowResetsAt)
224
+ const monthCutoff = now - MONTH_MS
225
+ let rollingUsd = 0
226
+ let weeklyUsd = 0
227
+ let monthlyUsd = 0
228
+ let observedRequests = 0
229
+ const pools: Record<string, { rollingUsd: number; weeklyUsd: number; monthlyUsd: number }> = {}
230
+ const bucket = (poolID: string) =>
231
+ (pools[poolID] ??= { rollingUsd: 0, weeklyUsd: 0, monthlyUsd: 0 })
232
+
233
+ for (const event of usage) {
234
+ if (event.providerID !== providerID) continue
235
+ const designPlan = plan
236
+ ? plan.pools.find((pool) => pool.id === OPENDESIGN_DESIGN_PLAN_POOL)
237
+ : undefined
238
+ const planModels = plan
239
+ ? plan.pools.find((pool) => pool.id === OPENDESIGN_PLAN_MODEL_POOL)
240
+ : undefined
241
+ const inDesignPlan = Boolean(designPlan) && !isEscalationOnlyPool(plan!, event.modelID)
242
+ const poolID = inDesignPlan
243
+ ? OPENDESIGN_DESIGN_PLAN_POOL
244
+ : planModels
245
+ ? OPENDESIGN_PLAN_MODEL_POOL
246
+ : OPENDESIGN_DESIGN_PLAN_POOL
247
+
248
+ /**
249
+ * Prefer what the request actually cost.
250
+ *
251
+ * The host reports a real charge per step and it is stored in the ledger, so
252
+ * recomputing the price from a static table is re-deriving a number that
253
+ * arrived for free — and it drifts whenever the charge does not match the
254
+ * model: a step funded from plan model credits after the Design Plan
255
+ * allowance is spent is charged at the plain rate, while the table still
256
+ * applies the Design Plan multiplier.
257
+ *
258
+ * A reported cost of zero is not a charge, though: some hosts omit pricing,
259
+ * and treating "unknown" as "free" would make the estimate forget real
260
+ * usage. So zero falls back to the table.
261
+ */
262
+ const reported = event.usd > 0 ? event.usd : undefined
263
+ const credits =
264
+ reported !== undefined && poolID === OPENDESIGN_DESIGN_PLAN_POOL
265
+ ? reported * creditMultiplierFor(event.modelID, { now, ...(multiplierOverrides ? { overrides: multiplierOverrides } : {}) }).multiplier
266
+ : reported !== undefined
267
+ ? reported
268
+ : estimateDesignPlanCredits({
269
+ modelID: event.modelID,
270
+ input: event.input,
271
+ output: event.output,
272
+ cacheRead: event.cacheRead,
273
+ cacheWrite: event.cacheWrite,
274
+ now,
275
+ multiplierApplies: poolID === OPENDESIGN_DESIGN_PLAN_POOL,
276
+ ...(multiplierOverrides ? { multiplierOverrides } : {}),
277
+ }).creditsUsd
278
+ if (credits <= 0) continue
279
+ observedRequests += 1
280
+ const target = bucket(poolID)
281
+ if (event.at >= rollingCutoff) {
282
+ rollingUsd += credits
283
+ target.rollingUsd += credits
284
+ }
285
+ if (event.at >= weekCutoff) {
286
+ weeklyUsd += credits
287
+ target.weeklyUsd += credits
288
+ }
289
+ if (event.at >= monthCutoff) {
290
+ monthlyUsd += credits
291
+ target.monthlyUsd += credits
292
+ }
293
+ }
294
+ const margin = 1 + Math.max(0, marginPct) / 100
295
+ const scaled = (value: number) => value * margin
296
+ return {
297
+ rollingUsd: scaled(rollingUsd),
298
+ weeklyUsd: scaled(weeklyUsd),
299
+ monthlyUsd: scaled(monthlyUsd),
300
+ observedRequests,
301
+ byPool: Object.fromEntries(
302
+ Object.entries(pools).map(([poolID, totals]) => [
303
+ poolID,
304
+ {
305
+ rollingUsd: scaled(totals.rollingUsd),
306
+ weeklyUsd: scaled(totals.weeklyUsd),
307
+ monthlyUsd: scaled(totals.monthlyUsd),
308
+ },
309
+ ]),
310
+ ),
311
+ }
312
+ }
313
+
314
+ const windowFrom = (
315
+ usedUsd: number,
316
+ capUsd: number,
317
+ resetsAt: number | undefined,
318
+ source: "provider" | "estimate",
319
+ ): QuotaWindow => {
320
+ const usedPct = capUsd > 0 ? pct(usedUsd, capUsd) : 0
321
+ return {
322
+ usedPct,
323
+ remainingPct: clamp(100 - usedPct, 0, 100),
324
+ usedUsd,
325
+ capUsd,
326
+ ...(resetsAt !== undefined ? { resetsAt } : {}),
327
+ exceeded: capUsd > 0 && usedUsd >= capUsd,
328
+ source,
329
+ }
330
+ }
331
+
332
+ const baseSnapshot = (
333
+ input: OpenDesignQuotaInput,
334
+ now: number,
335
+ error?: string,
336
+ retryAfterMs?: number,
337
+ notes: ReadonlyArray<string> = [],
338
+ ): ProviderQuotaSnapshot => {
339
+ const plan = resolvePlan("opendesign", input.settings.plan)
340
+ return {
341
+ providerID: "opendesign",
342
+ label: plan?.label ?? "OpenDesign",
343
+ plan: describePlan(plan?.planID, input.settings.plan),
344
+ source: "unknown",
345
+ fetchedAt: now,
346
+ stale: false,
347
+ rolling: unknownWindow,
348
+ weekly: unknownWindow,
349
+ monthly: unknownWindow,
350
+ models: {},
351
+ notes: [...notes],
352
+ ...(error ? { error } : {}),
353
+ ...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
354
+ }
355
+ }
356
+
357
+ /**
358
+ * The caps a plan exposes, honoring explicit overrides and any advertised
359
+ * removal of a window.
360
+ *
361
+ * OpenDesign Pro has a seven-day Design Plan window and no five-hour window.
362
+ * An explicit `fiveHourCapUsd` from an older Go configuration must not
363
+ * reintroduce the window the user's plan does not have, which is why the
364
+ * plan shape is consulted before the override.
365
+ */
366
+ const capsFor = (settings: ProviderSettings) => {
367
+ const plan = resolvePlan("opendesign", settings.plan)
368
+ const designPlan = plan?.pools.find((pool) => pool.id === OPENDESIGN_DESIGN_PLAN_POOL)
369
+ const planModels = plan?.pools.find((pool) => pool.id === OPENDESIGN_PLAN_MODEL_POOL)
370
+ const monthly = settings.monthlyCreditsUsd && settings.monthlyCreditsUsd > 0
371
+ ? settings.monthlyCreditsUsd
372
+ : designPlan?.monthlyUsd ?? 0
373
+ const weeklyFromPlan = settings.ignoreWeeklyWindow ? undefined : designPlan?.weeklyUsd
374
+ const fiveFromPlan = settings.ignoreFiveHourWindow ? undefined : designPlan?.fiveHourUsd
375
+ return {
376
+ monthly,
377
+ weekly: weeklyFromPlan ?? (settings.ignoreWeeklyWindow ? undefined : settings.weeklyCapUsd),
378
+ rolling: fiveFromPlan ?? (settings.ignoreFiveHourWindow ? undefined : settings.fiveHourCapUsd),
379
+ planModelsMonthly: planModels?.monthlyUsd ?? 0,
380
+ hasPlanModelPool: Boolean(planModels),
381
+ hasFiveHourWindow: fiveFromPlan !== undefined,
382
+ hasWeeklyWindow: weeklyFromPlan !== undefined,
383
+ plan,
384
+ /**
385
+ * True when the configured plan id matches nothing in the catalog and no
386
+ * explicit cap was supplied. Capacity is then unknown, not zero: reporting
387
+ * zero would look like a fresh, unused allowance and silently let the
388
+ * router over-spend.
389
+ */
390
+ unresolved: !plan && !(settings.monthlyCreditsUsd && settings.monthlyCreditsUsd > 0),
391
+ }
392
+ }
393
+
394
+ interface ControlFetchResult {
395
+ readonly ok: boolean
396
+ readonly body?: unknown
397
+ readonly error?: string
398
+ readonly status?: number
399
+ readonly retryAfterMs?: number
400
+ }
401
+
402
+ const controlFetch = async (
403
+ url: string,
404
+ controlKey: string,
405
+ fetchImpl: FetchLike,
406
+ timeoutMs: number,
407
+ ): Promise<ControlFetchResult> => {
408
+ const controller = new AbortController()
409
+ const timer = setTimeout(() => controller.abort(), timeoutMs)
410
+ try {
411
+ const response = await fetchImpl(url, {
412
+ method: "GET",
413
+ headers: {
414
+ authorization: `Bearer ${controlKey}`,
415
+ accept: "application/json",
416
+ "user-agent": OPENDESIGN_USER_AGENT,
417
+ },
418
+ redirect: "error",
419
+ signal: controller.signal,
420
+ })
421
+ if (!response.ok) {
422
+ const retryAfter = Number(response.headers.get("retry-after"))
423
+ const retryAfterMs =
424
+ Number.isFinite(retryAfter) && retryAfter >= 0 ? Math.min(retryAfter * 1000, 15 * 60_000) : undefined
425
+ return {
426
+ ok: false,
427
+ error: `Account control request returned HTTP ${response.status}`,
428
+ status: response.status,
429
+ ...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
430
+ }
431
+ }
432
+ const text = await response.text()
433
+ if (text.length > 2 * 1024 * 1024) {
434
+ return { ok: false, error: "Account control response was unexpectedly large" }
435
+ }
436
+ try {
437
+ return { ok: true, body: JSON.parse(text) as unknown }
438
+ } catch {
439
+ return { ok: false, error: "Account control response was malformed" }
440
+ }
441
+ } catch (error) {
442
+ return {
443
+ ok: false,
444
+ error: controller.signal.aborted
445
+ ? "Account control request timed out"
446
+ : redact(error instanceof Error ? error.message : String(error)),
447
+ }
448
+ } finally {
449
+ clearTimeout(timer)
450
+ }
451
+ }
452
+
453
+ interface ControlWindow {
454
+ readonly kind: "rolling" | "weekly" | "monthly"
455
+ readonly usedCredits: number
456
+ readonly limitCredits: number
457
+ readonly remainingCredits: number
458
+ readonly resetsAt?: number
459
+ }
460
+
461
+ const classifyWindow = (durationSeconds: number): ControlWindow["kind"] | undefined => {
462
+ if (durationSeconds <= 0) return undefined
463
+ if (durationSeconds <= 6 * 3600) return "rolling"
464
+ if (durationSeconds <= 8 * 86400) return "weekly"
465
+ if (durationSeconds <= 32 * 86400) return "monthly"
466
+ return undefined
467
+ }
468
+
469
+ const parseControlWindows = (value: unknown): ControlWindow[] => {
470
+ if (!Array.isArray(value)) return []
471
+ const out: ControlWindow[] = []
472
+ for (const row of value) {
473
+ if (!isRecord(row)) continue
474
+ const duration = numberOr(row.durationSeconds)
475
+ if (duration === undefined) continue
476
+ const kind = classifyWindow(duration)
477
+ if (!kind) continue
478
+ const usedCredits = numberOr(row.usedCredits) ?? 0
479
+ const limitCredits = numberOr(row.limitCredits) ?? 0
480
+ const remainingCredits = numberOr(row.remainingCredits) ?? Math.max(0, limitCredits - usedCredits)
481
+ const resetsAt = timeValue(row.resetsAt)
482
+ out.push({ kind, usedCredits, limitCredits, remainingCredits, ...(resetsAt !== undefined ? { resetsAt } : {}) })
483
+ }
484
+ return out
485
+ }
486
+
487
+ /**
488
+ * Build one snapshot per funding pool.
489
+ *
490
+ * The pools are reported side by side rather than summed. A plan card that
491
+ * advertises "$480 total" is advertising two allowances with different rules,
492
+ * so adding them into a single balance would tell a user they can spend it in
493
+ * one go, which is not true.
494
+ */
495
+ const buildPoolSnapshots = (input: {
496
+ caps: ReturnType<typeof capsFor>
497
+ used: Readonly<Record<string, { rollingUsd: number; weeklyUsd: number; monthlyUsd: number }>>
498
+ source: "provider" | "estimate"
499
+ creditsPerUsd: number
500
+ resetsAt?: number
501
+ }): CreditPoolSnapshot[] => {
502
+ const { caps, used, source } = input
503
+ const out: CreditPoolSnapshot[] = []
504
+ const designUsed = used[OPENDESIGN_DESIGN_PLAN_POOL] ?? { rollingUsd: 0, weeklyUsd: 0, monthlyUsd: 0 }
505
+ if (caps.monthly > 0) {
506
+ out.push({
507
+ id: OPENDESIGN_DESIGN_PLAN_POOL,
508
+ label: "Design Plan credits",
509
+ source,
510
+ monthlyUsd: caps.monthly,
511
+ usedUsd: designUsed.monthlyUsd,
512
+ remainingUsd: Math.max(0, caps.monthly - designUsed.monthlyUsd),
513
+ usedPct: pct(designUsed.monthlyUsd, caps.monthly),
514
+ ...(caps.weekly !== undefined
515
+ ? { weeklyUsd: caps.weekly, weeklyUsedPct: pct(designUsed.weeklyUsd, caps.weekly) }
516
+ : {}),
517
+ ...(caps.rolling !== undefined
518
+ ? { fiveHourUsd: caps.rolling, fiveHourUsedPct: pct(designUsed.rollingUsd, caps.rolling) }
519
+ : {}),
520
+ resetKind: "fixed-7-day",
521
+ ...(input.resetsAt !== undefined ? { resetsAt: input.resetsAt } : {}),
522
+ note: caps.hasFiveHourWindow
523
+ ? "Five-hour and seven-day ceilings nest inside the monthly maximum."
524
+ : "Seven-day ceiling nests inside the monthly maximum. This plan has no five-hour window.",
525
+ })
526
+ }
527
+ if (caps.hasPlanModelPool && caps.planModelsMonthly > 0) {
528
+ const planUsed = used[OPENDESIGN_PLAN_MODEL_POOL] ?? { rollingUsd: 0, weeklyUsd: 0, monthlyUsd: 0 }
529
+ out.push({
530
+ id: OPENDESIGN_PLAN_MODEL_POOL,
531
+ label: "Plan model credits",
532
+ source,
533
+ monthlyUsd: caps.planModelsMonthly,
534
+ usedUsd: planUsed.monthlyUsd,
535
+ remainingUsd: Math.max(0, caps.planModelsMonthly - planUsed.monthlyUsd),
536
+ usedPct: pct(planUsed.monthlyUsd, caps.planModelsMonthly),
537
+ resetKind: "billing-cycle",
538
+ ...(input.resetsAt !== undefined ? { resetsAt: input.resetsAt } : {}),
539
+ note: "No five-hour or seven-day window. Design Plan multipliers do not apply to this pool.",
540
+ })
541
+ }
542
+ return out
543
+ }
544
+
545
+ const planNotes = (caps: ReturnType<typeof capsFor>): string[] => {
546
+ const notes: string[] = []
547
+ if (caps.plan) notes.push(`Plan: ${caps.plan.label}.`)
548
+ notes.push(
549
+ caps.hasFiveHourWindow
550
+ ? "This plan has a five-hour Design Plan window."
551
+ : "This plan has no five-hour Design Plan window.",
552
+ )
553
+ if (caps.hasPlanModelPool && caps.planModelsMonthly > 0) {
554
+ notes.push(
555
+ `A separate plan model pool of $${caps.planModelsMonthly}/month is reported independently and is never added to the Design Plan allowance.`,
556
+ )
557
+ }
558
+ return notes
559
+ }
560
+
561
+ /**
562
+ * Read the account's coding-plan usage windows and wallet balance.
563
+ *
564
+ * The control key is a privileged credential. It is only used when the owner
565
+ * explicitly configures one; the router never obtains one on its own and never
566
+ * asks for a browser session.
567
+ */
568
+ const probeVerified = async (
569
+ input: OpenDesignQuotaInput,
570
+ now: number,
571
+ ): Promise<OpenDesignQuotaResult> => {
572
+ const fetchImpl = input.fetchImpl ?? fetch
573
+ const timeoutMs = input.timeoutMs ?? 12_000
574
+ const controlBase = normalizeOpenDesignControlBaseURL(input.controlBaseURL ?? OPENDESIGN_DEFAULT_CONTROL_BASE_URL)
575
+ const controlKey = input.controlKey ?? ""
576
+
577
+ const current = await controlFetch(
578
+ openDesignControlEndpoint(controlBase, "/v1/workspaces/current"),
579
+ controlKey,
580
+ fetchImpl,
581
+ timeoutMs,
582
+ )
583
+ if (!current.ok || !isRecord(current.body)) {
584
+ return {
585
+ snapshot: baseSnapshot(input, now, current.error ?? "Could not read the current workspace", current.retryAfterMs, [
586
+ "Verified quota is unavailable.",
587
+ ]),
588
+ state: "unavailable",
589
+ }
590
+ }
591
+ const workspaceId =
592
+ typeof current.body.activeWorkspaceId === "string"
593
+ ? current.body.activeWorkspaceId
594
+ : typeof current.body.workspaceId === "string"
595
+ ? current.body.workspaceId
596
+ : undefined
597
+ if (!workspaceId) {
598
+ return {
599
+ snapshot: baseSnapshot(input, now, "The account did not report an active workspace", undefined, [
600
+ "Verified quota is unavailable.",
601
+ ]),
602
+ state: "unavailable",
603
+ }
604
+ }
605
+
606
+ const usage = await controlFetch(
607
+ openDesignControlEndpoint(controlBase, `/v1/workspaces/${encodeURIComponent(workspaceId)}/billing/coding-plan-usage`),
608
+ controlKey,
609
+ fetchImpl,
610
+ timeoutMs,
611
+ )
612
+ if (!usage.ok || !isRecord(usage.body)) {
613
+ return {
614
+ snapshot: baseSnapshot(input, now, usage.error ?? "Could not read coding-plan usage", usage.retryAfterMs, [
615
+ "Verified quota is unavailable.",
616
+ ]),
617
+ state: "unavailable",
618
+ }
619
+ }
620
+ // Never combine a workspace's usage with another workspace's balance.
621
+ const reportedWorkspace = typeof usage.body.workspaceId === "string" ? usage.body.workspaceId : undefined
622
+ if (reportedWorkspace && reportedWorkspace !== workspaceId) {
623
+ return {
624
+ snapshot: baseSnapshot(input, now, "The usage response did not match the active workspace", undefined, [
625
+ "Balances from different workspaces are never combined.",
626
+ ]),
627
+ state: "unavailable",
628
+ }
629
+ }
630
+
631
+ const summary = await controlFetch(
632
+ openDesignControlEndpoint(controlBase, "/v1/billing/summary"),
633
+ controlKey,
634
+ fetchImpl,
635
+ timeoutMs,
636
+ )
637
+ const summaryBody = summary.ok && isRecord(summary.body) ? summary.body : undefined
638
+ const creditsPerUsd = numberOr(summaryBody?.creditsPerUsd) ?? input.creditsPerUsd ?? OPENDESIGN_DEFAULT_CREDITS_PER_USD
639
+ const balances = isRecord(summaryBody?.balances) ? (summaryBody!.balances as Record<string, unknown>) : undefined
640
+ const rechargeCredits = numberOr(balances?.rechargeCredits) ?? 0
641
+ const subscriptionCredits = numberOr(balances?.subscriptionCredits) ?? 0
642
+ const purchasedUsd = rechargeCredits / creditsPerUsd
643
+
644
+ const windows = parseControlWindows(usage.body.windows)
645
+ const caps = capsFor(input.settings)
646
+ const find = (kind: ControlWindow["kind"]) => windows.find((window) => window.kind === kind)
647
+
648
+ const toWindow = (window: ControlWindow | undefined, fallbackCapUsd: number): QuotaWindow => {
649
+ if (!window || window.limitCredits <= 0) {
650
+ return { usedPct: 0, remainingPct: 100, source: "unknown" }
651
+ }
652
+ const usedPct = pct(window.usedCredits, window.limitCredits)
653
+ return {
654
+ usedPct,
655
+ remainingPct: clamp(100 - usedPct, 0, 100),
656
+ usedUsd: window.usedCredits / creditsPerUsd,
657
+ capUsd: window.limitCredits / creditsPerUsd,
658
+ ...(window.resetsAt !== undefined ? { resetsAt: window.resetsAt } : {}),
659
+ exceeded: window.usedCredits >= window.limitCredits,
660
+ source: "provider",
661
+ }
662
+ }
663
+
664
+ const rolling = toWindow(find("rolling"), caps.rolling ?? 0)
665
+ const weekly = toWindow(find("weekly"), caps.weekly ?? 0)
666
+ const monthlyWindow = find("monthly")
667
+ const monthly = monthlyWindow
668
+ ? toWindow(monthlyWindow, caps.monthly)
669
+ : {
670
+ usedPct: 0,
671
+ remainingPct: 100,
672
+ source: "unknown" as const,
673
+ }
674
+
675
+ const periodStart = timeValue(summaryBody?.subscriptionCurrentPeriodStart)
676
+ const periodEnd = timeValue(summaryBody?.subscriptionCurrentPeriodEnd)
677
+ const monthlyRemainingUsd = monthlyWindow
678
+ ? monthlyWindow.remainingCredits / creditsPerUsd
679
+ : subscriptionCredits > 0
680
+ ? subscriptionCredits / creditsPerUsd
681
+ : undefined
682
+
683
+ const pools = buildPoolSnapshots({
684
+ caps,
685
+ used: {
686
+ [OPENDESIGN_DESIGN_PLAN_POOL]: {
687
+ rollingUsd: rolling.usedUsd ?? 0,
688
+ weeklyUsd: weekly.usedUsd ?? 0,
689
+ monthlyUsd: monthly.usedUsd ?? 0,
690
+ },
691
+ [OPENDESIGN_PLAN_MODEL_POOL]: {
692
+ rollingUsd: 0,
693
+ weeklyUsd: 0,
694
+ // The control surface reports Design Plan consumption; plan model
695
+ // credits are reported as a remaining balance only.
696
+ monthlyUsd: Math.max(0, caps.planModelsMonthly - subscriptionCredits / creditsPerUsd),
697
+ },
698
+ },
699
+ source: "provider",
700
+ creditsPerUsd,
701
+ ...(periodEnd !== undefined ? { resetsAt: periodEnd } : {}),
702
+ })
703
+
704
+ const notes = [
705
+ "Provider-reported OpenDesign coding-plan usage.",
706
+ "Read-only probe; no inference request is made.",
707
+ `Workspace ${workspaceId}.`,
708
+ ...planNotes(caps),
709
+ ]
710
+ if (purchasedUsd > 0) {
711
+ notes.push(
712
+ `Wallet balance ${purchasedUsd.toFixed(2)} USD is separate from the subscription allowance and is not used for automatic routing.`,
713
+ )
714
+ }
715
+
716
+ const snapshot: ProviderQuotaSnapshot = {
717
+ providerID: "opendesign",
718
+ label: caps.plan?.label ?? "OpenDesign",
719
+ plan: describePlan(caps.plan?.planID, input.settings.plan),
720
+ source: "provider",
721
+ fetchedAt: now,
722
+ stale: false,
723
+ rolling,
724
+ weekly,
725
+ monthly,
726
+ // A verified probe reads the real limits from the account, so it reports
727
+ // the provider's own grant when the catalog could not name the plan.
728
+ monthlyGrantUsd: caps.monthly > 0 ? caps.monthly : monthly.capUsd ?? 0,
729
+ ...(monthlyRemainingUsd !== undefined ? { monthlyRemainingUsd } : {}),
730
+ extraCredits: {
731
+ purchasedUsd,
732
+ freeUsd: 0,
733
+ totalUsd: purchasedUsd,
734
+ },
735
+ pools,
736
+ planStatus: typeof summaryBody?.membershipTier === "string" ? summaryBody.membershipTier : undefined,
737
+ ...(periodStart !== undefined ? { periodStart } : {}),
738
+ ...(periodEnd !== undefined ? { periodEnd } : {}),
739
+ models: {},
740
+ notes,
741
+ }
742
+ const exhausted = Boolean(rolling.exceeded || weekly.exceeded || monthly.exceeded)
743
+ return { snapshot, state: exhausted ? "exhausted" : "verified" }
744
+ }
745
+
746
+ /**
747
+ * Model the router's own credit consumption against the published plan caps.
748
+ */
749
+
750
+ /**
751
+ * Fold a user-supplied account reading into the local totals.
752
+ *
753
+ * A baseline is a real figure the user read from their own account, so it is
754
+ * stronger evidence than the router's own traffic — but only inside the window
755
+ * it was taken in. Once a window has reset, the reading describes the previous
756
+ * window and including it would overstate usage just as badly as omitting it
757
+ * understated it. So each window accepts the baseline only while the reading is
758
+ * newer than that window's start.
759
+ */
760
+ const applyBaseline = (
761
+ totals: LocalWindowTotals,
762
+ baseline: ProviderSettings["baseline"],
763
+ now: number,
764
+ caps: {
765
+ readonly weekly?: number
766
+ readonly monthly: number
767
+ readonly planModelsMonthly: number
768
+ },
769
+ ): {
770
+ totals: LocalWindowTotals
771
+ applied: boolean
772
+ windows: string[]
773
+ usedFallbackReset?: boolean
774
+ /** Windows whose percentage could not be converted, with the reason. */
775
+ unconverted?: ReadonlyArray<string>
776
+ } => {
777
+ if (!baseline) return { totals, applied: false, windows: [] }
778
+
779
+ /**
780
+ * Convert a percentage the user copied off the account page into dollars.
781
+ *
782
+ * The page shows a percentage and the router works in dollars, so somebody has
783
+ * to do the division. Doing it here means it is done against the cap for the
784
+ * window the page was describing, which is the part users get wrong: on Pro the
785
+ * seven-day window is $90 and the month is $360, so "42%" means $37.80, not
786
+ * $151.20.
787
+ */
788
+ const unconverted: string[] = []
789
+ const fromPct = (pct: number | undefined, cap: number | undefined, label: string): number => {
790
+ if (pct === undefined) return 0
791
+ if (cap === undefined || cap <= 0) {
792
+ unconverted.push(`the ${label} cap is unknown, so ${pct}% could not be converted`)
793
+ return 0
794
+ }
795
+ return (pct / 100) * cap
796
+ }
797
+ const pctWindow = baseline.pctOf ?? "weekly"
798
+
799
+ /**
800
+ * A reading is meaningful when the user entered it, not when it is above zero.
801
+ *
802
+ * A brand-new account reports 0%, and that is a real reading: it means the
803
+ * allowance is untouched. Treating zero as "no information" would throw away
804
+ * the best possible starting point, and treating a missing field as zero would
805
+ * invent usage the user never reported. So presence decides, not magnitude.
806
+ */
807
+ const hasDesignReading =
808
+ baseline.designPlanUsedUsd !== undefined || baseline.designPlanUsedPct !== undefined
809
+ const hasPlanModelsReading =
810
+ baseline.planModelsUsedUsd !== undefined || baseline.planModelsUsedPct !== undefined
811
+
812
+ const designPlan = hasDesignReading
813
+ ? Math.max(0, baseline.designPlanUsedUsd ?? 0) ||
814
+ fromPct(
815
+ baseline.designPlanUsedPct,
816
+ pctWindow === "weekly" ? (caps.weekly ?? caps.monthly) : caps.monthly,
817
+ pctWindow === "weekly" ? "seven-day Design Plan" : "monthly Design Plan",
818
+ )
819
+ : 0
820
+
821
+ const planModels = hasPlanModelsReading
822
+ ? Math.max(0, baseline.planModelsUsedUsd ?? 0) ||
823
+ fromPct(baseline.planModelsUsedPct, caps.planModelsMonthly, "plan model")
824
+ : 0
825
+
826
+ // Only bail when there was nothing to read. A genuine 0% reading must be
827
+ // applied, because it is the strongest statement of "untouched allowance".
828
+ if (!hasDesignReading && !hasPlanModelsReading) {
829
+ // Carry the reason out even though nothing was applied: a percentage that
830
+ // could not be converted is worth saying, and silently using zero is the
831
+ // failure this whole mechanism exists to avoid.
832
+ return { totals, applied: false, windows: [], ...(unconverted.length > 0 ? { unconverted } : {}) }
833
+ }
834
+
835
+ /**
836
+ * A window accepts the reading until that window RESETS — not merely until the
837
+ * reading is older than the window's length.
838
+ *
839
+ * These differ, and the difference is not academic. A seven-day window that
840
+ * resets 23 hours from now (the account page shows this) means the reading
841
+ * describes the window ending in 23 hours. Seeding it into the window that
842
+ * begins afterwards would attribute a previous window's usage to a fresh one.
843
+ *
844
+ * When the account page gave a reset time, trust it. Otherwise fall back to
845
+ * age, and say that the fallback was used.
846
+ */
847
+ const resetPassed = (resetsAt: number | undefined) => resetsAt !== undefined && now >= resetsAt
848
+ const withinRolling = baseline.at >= now - FIVE_HOURS_MS && !resetPassed(baseline.weeklyResetsAt)
849
+ const withinWeekly = baseline.at >= now - WEEK_MS && !resetPassed(baseline.weeklyResetsAt)
850
+ const withinMonthly = baseline.at >= now - MONTH_MS && !resetPassed(baseline.monthlyResetsAt)
851
+ if (!withinMonthly) return { totals, applied: false, windows: [] }
852
+
853
+ const windows: string[] = []
854
+ if (withinRolling) windows.push("5h")
855
+ if (withinWeekly) windows.push("7d")
856
+ windows.push("monthly")
857
+
858
+ const designRolling = withinRolling ? designPlan : 0
859
+ const designWeekly = withinWeekly ? designPlan : 0
860
+ const planRolling = withinRolling ? planModels : 0
861
+ const planWeekly = withinWeekly ? planModels : 0
862
+
863
+ const byPool = { ...totals.byPool }
864
+ const designBucket = byPool[OPENDESIGN_DESIGN_PLAN_POOL] ?? { rollingUsd: 0, weeklyUsd: 0, monthlyUsd: 0 }
865
+ const planBucket = byPool[OPENDESIGN_PLAN_MODEL_POOL] ?? { rollingUsd: 0, weeklyUsd: 0, monthlyUsd: 0 }
866
+ if (designPlan > 0) {
867
+ byPool[OPENDESIGN_DESIGN_PLAN_POOL] = {
868
+ rollingUsd: designBucket.rollingUsd + designRolling,
869
+ weeklyUsd: designBucket.weeklyUsd + designWeekly,
870
+ monthlyUsd: designBucket.monthlyUsd + designPlan,
871
+ }
872
+ }
873
+ if (planModels > 0) {
874
+ byPool[OPENDESIGN_PLAN_MODEL_POOL] = {
875
+ rollingUsd: planBucket.rollingUsd + planRolling,
876
+ weeklyUsd: planBucket.weeklyUsd + planWeekly,
877
+ monthlyUsd: planBucket.monthlyUsd + planModels,
878
+ }
879
+ }
880
+
881
+ return {
882
+ applied: true,
883
+ windows,
884
+ usedFallbackReset: baseline.weeklyResetsAt === undefined,
885
+ ...(unconverted.length > 0 ? { unconverted } : {}),
886
+ totals: {
887
+ rollingUsd: totals.rollingUsd + designRolling + planRolling,
888
+ weeklyUsd: totals.weeklyUsd + designWeekly + planWeekly,
889
+ monthlyUsd: totals.monthlyUsd + designPlan + planModels,
890
+ observedRequests: totals.observedRequests,
891
+ byPool,
892
+ },
893
+ }
894
+ }
895
+
896
+ const probeEstimated = (input: OpenDesignQuotaInput, now: number): OpenDesignQuotaResult => {
897
+ const caps = capsFor(input.settings)
898
+ /**
899
+ * The margin is measured, not assumed.
900
+ *
901
+ * A fresh install has no evidence, so the default stands. Once the router has
902
+ * routed a few requests it can compare its own arithmetic with the charges the
903
+ * provider reported and shrink the margin to the error it actually observes.
904
+ * That is what removes the need to paste a balance every week: drift is
905
+ * corrected from traffic the router already handled.
906
+ *
907
+ * A caller that states a margin explicitly still wins — configuration is an
908
+ * instruction, and calibration is a convenience.
909
+ */
910
+ const marginPct =
911
+ input.uncertaintyMarginPct ??
912
+ effectiveMarginPct(calibrationSamples(input.usage), OPENDESIGN_DEFAULT_UNCERTAINTY_MARGIN_PCT)
913
+ const local = localTotals(
914
+ input.usage,
915
+ "opendesign",
916
+ now,
917
+ marginPct,
918
+ caps.plan,
919
+ input.multiplierOverrides,
920
+ // The pasted reset time is the only trustworthy anchor for the fixed
921
+ // window; without it the estimator falls back to a week ending now.
922
+ input.settings.baseline?.weeklyResetsAt,
923
+ )
924
+ const seeded = applyBaseline(local, input.settings.baseline, now, {
925
+ ...(caps.weekly !== undefined ? { weekly: caps.weekly } : {}),
926
+ monthly: caps.monthly,
927
+ planModelsMonthly: caps.planModelsMonthly,
928
+ })
929
+ const totals = seeded.totals
930
+ // A window the plan does not have is never reported as a measured 0%.
931
+ // Reporting "0% of a five-hour window" would imply a ceiling that could be
932
+ // hit, when the plan has no such limit.
933
+ const rolling = caps.rolling !== undefined
934
+ ? windowFrom(totals.rollingUsd, caps.rolling, undefined, "estimate")
935
+ : { ...unknownWindow, usedUsd: totals.rollingUsd }
936
+ const weekly = caps.weekly !== undefined
937
+ ? windowFrom(totals.weeklyUsd, caps.weekly, undefined, "estimate")
938
+ : { ...unknownWindow, usedUsd: totals.weeklyUsd }
939
+ const monthly = caps.unresolved
940
+ ? { ...unknownWindow, usedUsd: totals.monthlyUsd }
941
+ : windowFrom(totals.monthlyUsd, caps.monthly, undefined, "estimate")
942
+ const pools = buildPoolSnapshots({
943
+ caps,
944
+ used: totals.byPool,
945
+ source: "estimate",
946
+ creditsPerUsd: OPENDESIGN_DEFAULT_CREDITS_PER_USD,
947
+ })
948
+ const notes = [
949
+ seeded.applied
950
+ ? `Starts from the usage you reported on ${new Date(input.settings.baseline!.at).toISOString().slice(0, 10)} and adds every OpenDesign request this router has routed since.`
951
+ : "Estimated from this router's own OpenDesign usage. OpenDesign publishes no quota API for an inference key.",
952
+ seeded.applied
953
+ ? `The reported reading still excludes other clients, and a ${marginPct}% margin is applied, so this remains a lower bound. There is no exact source without an account control key, and the account API-key page issues inference keys only.`
954
+ : `A ${marginPct}% safety margin is applied. Usage from the OpenDesign app or other clients on the same subscription is not visible, so this is a lower bound.`,
955
+ "Wallet balance is not included and is never used for automatic routing.",
956
+ ...planNotes(caps),
957
+ ]
958
+ for (const reason of seeded.unconverted ?? []) notes.push(`The reported percentage was not used: ${reason}.`)
959
+ if (seeded.applied) {
960
+ notes.push(
961
+ seeded.usedFallbackReset
962
+ ? `The reported reading applies to: ${seeded.windows.join(", ")}. No reset time was supplied, so the router assumes the reading stays valid for its window length. Add baseline.weeklyResetsAt to be exact.`
963
+ : `The reported reading applies to: ${seeded.windows.join(", ")} until that window resets.`,
964
+ )
965
+ }
966
+ if (caps.unresolved) {
967
+ notes.push(
968
+ `The configured plan "${input.settings.plan}" is not in the catalog, so the allowance is unknown rather than zero. Set a plan id from the catalog or an explicit monthlyCreditsUsd.`,
969
+ )
970
+ }
971
+ if (totals.observedRequests === 0) {
972
+ notes.push(
973
+ seeded.applied
974
+ ? "No OpenDesign requests have been routed through this router since that reading, so the figure is still exactly what you reported."
975
+ : "No OpenDesign requests have been routed through this router yet, so the estimate starts at zero.",
976
+ )
977
+ }
978
+ const snapshot: ProviderQuotaSnapshot = {
979
+ providerID: "opendesign",
980
+ label: caps.plan?.label ?? "OpenDesign",
981
+ plan: describePlan(caps.plan?.planID, input.settings.plan),
982
+ source: "estimate",
983
+ fetchedAt: now,
984
+ stale: false,
985
+ rolling,
986
+ weekly,
987
+ monthly,
988
+ monthlyGrantUsd: caps.monthly,
989
+ // An unresolved plan has no known allowance, so a "remaining balance" of
990
+ // zero would be a fabrication. Omitting the field lets the eligibility
991
+ // gate fall through to the unknown-quota policy rather than reporting the
992
+ // provider as exhausted.
993
+ ...(caps.unresolved ? {} : { monthlyRemainingUsd: Math.max(0, caps.monthly - totals.monthlyUsd) }),
994
+ pools,
995
+ models: {},
996
+ notes,
997
+ }
998
+ if (caps.unresolved) return { snapshot, state: "unknown" }
999
+ const exhausted = Boolean(monthly.exceeded || weekly.exceeded)
1000
+ return { snapshot, state: exhausted ? "exhausted" : "estimated" }
1001
+ }
1002
+
1003
+ /**
1004
+ * Resolve the OpenDesign quota state.
1005
+ *
1006
+ * A control key, when explicitly configured, produces verified provider
1007
+ * numbers. Otherwise the router falls back to its own estimate. It never
1008
+ * acquires a control key, never uses a browser session, and never treats a
1009
+ * wallet balance as permission to spend.
1010
+ */
1011
+ export const probeOpenDesignQuota = async (
1012
+ input: OpenDesignQuotaInput,
1013
+ ): Promise<OpenDesignQuotaResult> => {
1014
+ const now = input.now?.() ?? Date.now()
1015
+ if (!input.settings.enabled) {
1016
+ return {
1017
+ snapshot: baseSnapshot(input, now, "OpenDesign is disabled in router settings", undefined, [
1018
+ "The provider is disabled; it takes no part in routing.",
1019
+ ]),
1020
+ state: "unavailable",
1021
+ }
1022
+ }
1023
+ if (input.controlKey) {
1024
+ return probeVerified(input, now)
1025
+ }
1026
+ if (!input.apiKey) {
1027
+ return {
1028
+ snapshot: baseSnapshot(input, now, "No OpenDesign credential is configured", undefined, [
1029
+ "Add an OpenDesign API key, or configure a control key for verified quota.",
1030
+ ]),
1031
+ state: "unavailable",
1032
+ }
1033
+ }
1034
+ return probeEstimated(input, now)
1035
+ }
1036
+
1037
+ export const __opendesignQuotaInternals = {
1038
+ classifyWindow,
1039
+ parseControlWindows,
1040
+ localTotals,
1041
+ windowFrom,
1042
+ failureClassForStatus,
1043
+ }