@qadanm/opencode-smart-router 0.0.0-stage → 0.6.1

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 (62) hide show
  1. package/CHANGELOG.md +286 -0
  2. package/CONTRIBUTING.md +103 -0
  3. package/LICENSE +21 -0
  4. package/README.md +425 -2
  5. package/SECURITY.md +174 -0
  6. package/config.example.json +107 -0
  7. package/dist/npm/index.js +40 -0
  8. package/docs/ARCHITECTURE.md +104 -0
  9. package/docs/DEBUGGING-GUI.md +70 -0
  10. package/docs/INSTALL.md +151 -0
  11. package/docs/LIMITATIONS.md +230 -0
  12. package/docs/MODELS.md +124 -0
  13. package/docs/OPENDESIGN-INTEGRATION.md +635 -0
  14. package/docs/QA.md +142 -0
  15. package/docs/SHARED-CORE.md +114 -0
  16. package/install +75 -0
  17. package/package.json +94 -4
  18. package/scripts/install.sh +324 -0
  19. package/scripts/uninstall.sh +91 -0
  20. package/src/allowance.ts +135 -0
  21. package/src/core/classify/classifier.ts +305 -0
  22. package/src/core/config-writer.ts +167 -0
  23. package/src/core/config.ts +1047 -0
  24. package/src/core/context/strategy.ts +188 -0
  25. package/src/core/context-health.ts +39 -0
  26. package/src/core/failures.ts +398 -0
  27. package/src/core/history/opencode.ts +173 -0
  28. package/src/core/models/protocol.ts +22 -0
  29. package/src/core/models/registry.ts +204 -0
  30. package/src/core/models/seed.ts +781 -0
  31. package/src/core/offline/mode.ts +321 -0
  32. package/src/core/plan-page.ts +390 -0
  33. package/src/core/plans/catalog.ts +487 -0
  34. package/src/core/policy/calibration.ts +259 -0
  35. package/src/core/policy/eligibility.ts +630 -0
  36. package/src/core/providers/enablement.ts +143 -0
  37. package/src/core/providers/opendesign-credits.ts +206 -0
  38. package/src/core/providers/opendesign-models.ts +654 -0
  39. package/src/core/providers/opendesign.ts +474 -0
  40. package/src/core/quota/calibration.ts +166 -0
  41. package/src/core/quota/commandcode.ts +471 -0
  42. package/src/core/quota/credentials.ts +490 -0
  43. package/src/core/quota/ledger.ts +1304 -0
  44. package/src/core/quota/opencode-go.ts +148 -0
  45. package/src/core/quota/opendesign.ts +1043 -0
  46. package/src/core/quota/reconcile.ts +155 -0
  47. package/src/core/quota/report.ts +261 -0
  48. package/src/core/quota/service.ts +273 -0
  49. package/src/core/reprompt.ts +48 -0
  50. package/src/core/routing/engine.ts +978 -0
  51. package/src/core/types.ts +866 -0
  52. package/src/core/ui.ts +236 -0
  53. package/src/core/util.ts +114 -0
  54. package/src/gui/index.tsx +1675 -0
  55. package/src/gui/viewmodel.ts +456 -0
  56. package/src/index.ts +33 -0
  57. package/src/rpc.ts +204 -0
  58. package/src/server/containment.ts +131 -0
  59. package/src/server/controller.ts +3405 -0
  60. package/src/server/route-tracker.ts +60 -0
  61. package/src/server/shared-core.ts +701 -0
  62. package/src/tui/index.tsx +168 -0
@@ -0,0 +1,630 @@
1
+ import type {
2
+ Mode,
3
+ ModelQuotaSnapshot,
4
+ ModelRecord,
5
+ PremiumState,
6
+ ProviderQuotaSnapshot,
7
+ QuotaWindow,
8
+ RouterSettings,
9
+ SessionState,
10
+ TaskClass,
11
+ } from "../types.js"
12
+ import { keyOfRef, modelKey, pct } from "../util.js"
13
+ import {
14
+ CONTEXT_ELIGIBILITY_MARGIN_TOKENS,
15
+ CONTEXT_SAFE_WINDOW_FRACTION,
16
+ replyMarginFor,
17
+ } from "../context/strategy.js"
18
+ import { OFFLINE_PROVIDER_ID } from "../offline/mode.js"
19
+
20
+ export interface PremiumDecision {
21
+ readonly allowed: boolean
22
+ readonly requiresApproval: boolean
23
+ readonly reason: string
24
+ }
25
+
26
+ export const decidePremium = (input: {
27
+ settings: RouterSettings
28
+ mode: Mode
29
+ task: TaskClass
30
+ session?: SessionState
31
+ premium: PremiumState
32
+ }): PremiumDecision => {
33
+ const { settings, mode, task, session, premium } = input
34
+ const premiumTask = task.tier === 3 || task.constraints.requestPremium
35
+ if (!premiumTask) {
36
+ return { allowed: false, requiresApproval: false, reason: "Premium models are reserved for premium-tier work." }
37
+ }
38
+ if (settings.premium.mode === "off") {
39
+ return { allowed: false, requiresApproval: false, reason: "Premium routing is off in settings." }
40
+ }
41
+ if (mode === "efficiency") {
42
+ return { allowed: false, requiresApproval: false, reason: "Maximum Efficiency locks premium models unless you select one manually." }
43
+ }
44
+ /**
45
+ * Standing escalation: mode "auto" is the owner's pre-granted approval for
46
+ * tier-3 work, funded from the plan-model pool while it lasts. Exhaustion
47
+ * degrades to an approval gate, never a hard block, because a routing refusal
48
+ * cannot put credits back.
49
+ */
50
+ if (premium.mode === "auto") {
51
+ // Auto escalation is funded from the plan-model pool, and only from it:
52
+ // auto requires a resolvable pool. Without one (OpenDesign disabled or an
53
+ // unknown plan), falling back to the legacy premium budget would let auto
54
+ // spend premium models from other providers that no ledger attributes, so
55
+ // the gate degrades to an approval request instead.
56
+ if ((premium.planPoolRemainingUsd ?? 0) > 0) {
57
+ return {
58
+ allowed: true,
59
+ requiresApproval: false,
60
+ reason: "Auto escalation: the plan-model pool has remaining budget for premium-tier work.",
61
+ }
62
+ }
63
+ return {
64
+ allowed: false,
65
+ requiresApproval: true,
66
+ reason:
67
+ premium.planPoolRemainingUsd === undefined
68
+ ? "Auto escalation needs a resolvable plan-model pool (set providers.opendesign.plan); approval is required for this request."
69
+ : "Auto escalation is out of plan-model budget; approval is required for this request.",
70
+ }
71
+ }
72
+ if (session?.premiumOneShot && settings.premium.oneShotApproval) {
73
+ return { allowed: true, requiresApproval: false, reason: "A one-shot premium approval is active for this session." }
74
+ }
75
+ if (mode === "premium" && settings.premium.mode === "allowed" && premium.remainingUsd > 0) {
76
+ return {
77
+ allowed: true,
78
+ requiresApproval: false,
79
+ reason: "Premium Allowed mode has a remaining premium budget.",
80
+ }
81
+ }
82
+ if (premium.remainingUsd > 0 && settings.premium.mode === "allowed") {
83
+ return { allowed: false, requiresApproval: true, reason: "Premium is available but requires this session's approval." }
84
+ }
85
+ return {
86
+ allowed: false,
87
+ requiresApproval: true,
88
+ reason: "Premium escalation is disabled or has no remaining budget; approval is required.",
89
+ }
90
+ }
91
+
92
+ export interface EligibilityInput {
93
+ readonly model: ModelRecord
94
+ readonly task: TaskClass
95
+ readonly settings: RouterSettings
96
+ readonly mode: Mode
97
+ readonly contextTokens: number
98
+ readonly providerQuota?: ProviderQuotaSnapshot
99
+ /**
100
+ * Whether any provider reported fresh quota for this decision. Lets the
101
+ * eligibility check tell "this provider is genuinely fine" apart from "we have
102
+ * not probed anyone yet", which are not the same thing.
103
+ */
104
+ readonly quotaIsKnown?: boolean
105
+ readonly modelQuota?: ModelQuotaSnapshot
106
+ readonly premium: PremiumDecision
107
+ readonly currentModelKey?: string
108
+ readonly allowDesignRelaxation?: boolean
109
+ /** Estimated cost of the request, used by the subscription-only guard. */
110
+ readonly projectedUsd?: number
111
+ /**
112
+ * True when an ordinary-allowance route can serve this task. A model funded
113
+ * from an escalation pool is then refused, so routine work cannot drain the
114
+ * capacity reserved for hard problems.
115
+ */
116
+ readonly escalationPoolProtected?: boolean
117
+ /**
118
+ * The intelligence floor to enforce, when it differs from the configured one.
119
+ *
120
+ * Calibration derives the floor from recorded spend, so the gate cannot read
121
+ * `settings.routing.intelligenceFloor` directly: that value is the ceiling
122
+ * calibration is bounded by, not necessarily the value in force. Passing it
123
+ * explicitly keeps one source of truth for the request in progress.
124
+ */
125
+ readonly intelligenceFloor?: number
126
+ }
127
+
128
+ export interface EligibilityResult {
129
+ readonly eligible: boolean
130
+ readonly reason: string
131
+ readonly warnings: string[]
132
+ /**
133
+ * Why the model was rejected, when that reason is worth reporting to a user.
134
+ * `context` is the case that matters: the model is a good route but the
135
+ * transcript no longer fits, which is a different situation from being
136
+ * unqualified or over budget.
137
+ */
138
+ readonly rejectedFor?: "context"
139
+ readonly contextRequiredTokens?: number
140
+ readonly contextWindowTokens?: number
141
+ }
142
+
143
+ const providerAuthFailure = (snapshot: ProviderQuotaSnapshot | undefined): boolean => {
144
+ if (!snapshot?.error) return false
145
+ return /authoriz|authenticat|unauthorized|forbidden|401|403|credential/i.test(snapshot.error)
146
+ }
147
+
148
+ /**
149
+ * Decide whether a provider's allowance is spent.
150
+ *
151
+ * `quotaIsKnown` says whether ANY provider reported fresh quota this decision.
152
+ * That distinction matters: when every provider is unknown we are blind and must
153
+ * not change behaviour, but when some providers have fresh data and this one does
154
+ * not, the asymmetry is a hole. An exhausted provider whose snapshot has not been
155
+ * probed yet looks identical to one that is fine, so a decision made in the ~1.5s
156
+ * before the quota service starts can route straight into a full allowance. That
157
+ * is exactly what happened on 2026-11-02 when GOAT's five-hour window was at 100%.
158
+ */
159
+ const providerLimitReached = (
160
+ snapshot: ProviderQuotaSnapshot | undefined,
161
+ settings: RouterSettings,
162
+ providerID = "",
163
+ quotaIsKnown = false,
164
+ ): string | undefined => {
165
+ if (!snapshot) {
166
+ // Fail CLOSED only in the one case that is actually a hole: this provider is
167
+ // configured to be probed, another provider already has a real reading, and
168
+ // this one has none yet. That is the window before the quota service starts
169
+ // (~1.5s after plugin load), where an exhausted provider is indistinguishable
170
+ // from a healthy one and a decision can route straight into a full allowance.
171
+ //
172
+ // A provider that is simply not probed is NOT an error: absence from the
173
+ // array is how "we do not track this one" is expressed, and refusing there
174
+ // would break legitimate fallbacks to providers with no quota model at all.
175
+ const providerSettings = settings.providers[providerID]
176
+ const expectedProbe = providerSettings?.enabled === true && providerSettings?.probeUsage === true
177
+ // Unconditional, and deliberately not tied to routing.failClosed. That
178
+ // setting governs what happens when THIS PLUGIN breaks; this check governs
179
+ // whether it is safe to spend on a provider it cannot see. An owner asking
180
+ // the router to keep working through its own faults is not asking it to
181
+ // route into a provider that may be full.
182
+ if (expectedProbe && quotaIsKnown) {
183
+ return "Provider quota has not been probed yet; refusing rather than assuming it has room"
184
+ }
185
+ return undefined
186
+ }
187
+ const providerSettings = settings.providers[snapshot.providerID]
188
+ if (!providerSettings) return undefined
189
+ const reserveMonthly = providerSettings.reserveMonthlyPct
190
+ const reserveWeekly = providerSettings.reserveWeeklyPct
191
+ const reserveFive = providerSettings.reserveFiveHourPct
192
+ const extras = snapshot.extraCredits?.totalUsd ?? 0
193
+ // A refusal already outlives the reading that produced it: `exceeded` is
194
+ // checked before anything looks at `stale`, so an allowed-out snapshot keeps
195
+ // blocking until a fresh probe clears the flag. `stale` only softens COST
196
+ // (see providerPressure); it never softens a refusal. Verified by reverting a
197
+ // special-case branch for stale+exceeded and watching the tests still pass,
198
+ // which is how that branch was proved dead and removed.
199
+ const windowExceeded = Boolean(snapshot.monthly.exceeded || snapshot.weekly.exceeded || snapshot.rolling.exceeded)
200
+ if (windowExceeded) {
201
+ if (extras > 0 && providerSettings.allowExtraUsage) return undefined
202
+ if (extras > 0) return "Provider would spend purchased credits; automatic extra-credit use is disabled"
203
+ return "Provider allowance is exhausted"
204
+ }
205
+ // Some providers report a zero remaining balance slightly before they set
206
+ // the window's exceeded flag. Treat the balance as authoritative so a
207
+ // request cannot knowingly roll into purchased credits.
208
+ if (snapshot.monthlyRemainingUsd !== undefined && snapshot.monthlyRemainingUsd <= 0) {
209
+ if (extras > 0 && providerSettings.allowExtraUsage) return undefined
210
+ if (extras > 0) return "Provider included credits are exhausted; automatic extra-credit use is disabled"
211
+ return "Provider allowance is exhausted"
212
+ }
213
+ if (snapshot.monthly.source !== "unknown" && snapshot.monthly.usedPct >= 100 - reserveMonthly) {
214
+ return "Provider monthly allowance is at or near its configured reserve"
215
+ }
216
+ if (snapshot.weekly.source !== "unknown" && snapshot.weekly.usedPct >= 100 - reserveWeekly) {
217
+ return "Provider weekly allowance is at or near its configured reserve"
218
+ }
219
+ if (snapshot.rolling.source !== "unknown" && snapshot.rolling.usedPct >= 100 - reserveFive) {
220
+ return "Provider five-hour allowance is at or near its configured reserve"
221
+ }
222
+ return undefined
223
+ }
224
+
225
+ const modelLimitReached = (quota: ModelQuotaSnapshot | undefined, settings: RouterSettings): string | undefined => {
226
+ if (!quota) return undefined
227
+ const provider = settings.providers[quota.model.providerID]
228
+ if (!provider) return undefined
229
+ if (quota.monthlyAllowanceUsd > 0 && quota.monthlyUsedPct >= 100 - provider.reserveMonthlyPct) {
230
+ return "Estimated model monthly allowance is at or near its configured reserve"
231
+ }
232
+ if (quota.fiveHourCapUsd > 0 && quota.fiveHourUsedPct >= 100 - provider.reserveFiveHourPct) {
233
+ return "Estimated model five-hour allowance is at or near its configured reserve"
234
+ }
235
+ if (quota.weeklyCapUsd > 0 && quota.weeklyUsedPct >= 100 - provider.reserveWeeklyPct) {
236
+ return "Estimated model weekly allowance is at or near its configured reserve"
237
+ }
238
+ if (quota.blocked) return quota.blockReason ?? "Estimated model allowance is exhausted"
239
+ return undefined
240
+ }
241
+
242
+ /**
243
+ * Subscription-only guard.
244
+ *
245
+ * When the provider bills from a subscription allowance and purchased balance
246
+ * is off limits, a request is only routed when it fits inside what is left of
247
+ * the subscription. This is a client-side guard: OpenDesign's gateway makes
248
+ * the final funding decision per request, so the router must never assume it
249
+ * can prevent a server-side wallet charge. It only avoids sending a request
250
+ * that it can already see would not fit.
251
+ */
252
+ const subscriptionOnlyLimit = (
253
+ snapshot: ProviderQuotaSnapshot | undefined,
254
+ settings: RouterSettings,
255
+ projectedUsd: number | undefined,
256
+ ): string | undefined => {
257
+ if (!snapshot) return undefined
258
+ const providerSettings = settings.providers[snapshot.providerID]
259
+ if (!providerSettings?.subscriptionOnly) return undefined
260
+ if (projectedUsd === undefined || !Number.isFinite(projectedUsd) || projectedUsd <= 0) return undefined
261
+
262
+ const windows: ReadonlyArray<{ readonly label: string; readonly window: QuotaWindow }> = [
263
+ { label: "five-hour", window: snapshot.rolling },
264
+ { label: "weekly", window: snapshot.weekly },
265
+ { label: "monthly", window: snapshot.monthly },
266
+ ]
267
+ for (const { label, window } of windows) {
268
+ if (window.source === "unknown") continue
269
+ const cap = window.capUsd
270
+ if (cap === undefined || cap <= 0) continue
271
+ const used = window.usedUsd ?? 0
272
+ const remaining = Math.max(0, cap - used)
273
+ if (projectedUsd > remaining) {
274
+ return `Subscription-only policy: the projected request cost ($${projectedUsd.toFixed(4)}) exceeds the remaining ${label} allowance ($${remaining.toFixed(2)})`
275
+ }
276
+ }
277
+ return undefined
278
+ }
279
+
280
+ /**
281
+ * Policy for a provider whose quota state could not be established.
282
+ */
283
+ const unknownQuotaLimit = (
284
+ snapshot: ProviderQuotaSnapshot | undefined,
285
+ settings: RouterSettings,
286
+ ): string | undefined => {
287
+ if (!snapshot) return undefined
288
+ const providerSettings = settings.providers[snapshot.providerID]
289
+ if (!providerSettings) return undefined
290
+ const state = snapshot.quotaState ?? (snapshot.source === "unknown" ? "unknown" : undefined)
291
+ if (state !== "unknown" && state !== "unavailable") return undefined
292
+ const policy = providerSettings.unknownQuotaPolicy ?? "route"
293
+ if (policy === "route") return undefined
294
+ if (policy === "ask") {
295
+ return "Provider quota state is unknown; the configured policy requires explicit approval before routing here"
296
+ }
297
+ return "Provider quota state is unknown; the configured policy blocks routing here"
298
+ }
299
+
300
+ /**
301
+ * True when the online intelligence floor should be enforced for this model.
302
+ *
303
+ * Offline mode deliberately exempts local models: the owner has chosen to work
304
+ * with what runs on the machine, and no model small enough to fit alongside a
305
+ * simulator scores at the hosted standard floor.
306
+ */
307
+ const substanceFloorApplies = (settings: RouterSettings, model: ModelRecord): boolean => {
308
+ if (settings.offline?.enabled !== true) return true
309
+ return model.providerID !== OFFLINE_PROVIDER_ID
310
+ }
311
+
312
+ /**
313
+ * Hard-requirement gate. A model is eligible only when every requirement is
314
+ * met; expected-cost ranking happens later and never overrides these rules.
315
+ */
316
+ export const evaluateEligibility = (input: EligibilityInput): EligibilityResult => {
317
+ const { model, task, settings, mode, providerQuota, modelQuota, premium } = input
318
+ const warnings: string[] = []
319
+ const providerSettings = settings.providers[model.providerID]
320
+ if (!providerSettings?.enabled) return { eligible: false, reason: "Provider is disabled in router settings", warnings }
321
+ if (providerAuthFailure(providerQuota)) {
322
+ return { eligible: false, reason: "Provider authentication is failing; fix the connection before routing here", warnings }
323
+ }
324
+
325
+ /**
326
+ * Approval is an online-policy concept: it means "may this model serve paid
327
+ * work alongside the hosted floor". A local model is excluded from that list
328
+ * on purpose so it never competes with hosted models when the network is up.
329
+ *
330
+ * Offline mode therefore skips this check for local models. The candidate
331
+ * list has already been restricted to them, so this cannot admit a hosted
332
+ * model that would otherwise be refused; it only stops an unapproved local
333
+ * model from being rejected for a reason that does not apply to it.
334
+ */
335
+ const offlineLocal = settings.offline?.enabled === true && model.providerID === OFFLINE_PROVIDER_ID
336
+ if (!model.approved && !offlineLocal) {
337
+ return { eligible: false, reason: "Model is unclassified or not approved", warnings }
338
+ }
339
+ if (model.training && !settings.privacy.allowTrainingModels) {
340
+ return { eligible: false, reason: "Training-enabled model is blocked by privacy policy", warnings }
341
+ }
342
+ if (model.free && !settings.privacy.allowFreeModels) {
343
+ return { eligible: false, reason: "Free promotional model is blocked by privacy policy", warnings }
344
+ }
345
+ if (task.requiresVision && !model.inputModalities.includes("image")) {
346
+ return { eligible: false, reason: "Task includes an image and this model has no native image input", warnings }
347
+ }
348
+ if (!model.tools) {
349
+ return { eligible: false, reason: "Model does not support tool calling", warnings }
350
+ }
351
+
352
+ // The margin and the safety fraction are shared with the compaction strategy
353
+ // rather than repeated as literals. They used to be written out here as
354
+ // `20_000` and `0.95`, which meant editing the constants in strategy.ts would
355
+ // move the compaction threshold while leaving this routing gate behind, so a
356
+ // session would compact at a different size than the router refuses to route
357
+ // at. For DeepSeek V4.1 Flash that boundary is 975,600 of an advertised
358
+ // 1,048,000 window, and the remaining 72,400 tokens are deliberate headroom
359
+ // for the reply, tokenizer differences, and transcript growth mid-loop.
360
+ const requiredContext =
361
+ Math.max(input.contextTokens, task.scope.promptTokens) + replyMarginFor(model.context)
362
+ if (model.context > 0 && requiredContext > model.context * CONTEXT_SAFE_WINDOW_FRACTION) {
363
+ return {
364
+ eligible: false,
365
+ reason: `Context requirement ${requiredContext.toLocaleString()} exceeds this model's safe window`,
366
+ warnings,
367
+ // Machine-readable so callers can explain *this* rejection without
368
+ // pattern-matching the message above.
369
+ rejectedFor: "context",
370
+ contextRequiredTokens: requiredContext,
371
+ contextWindowTokens: model.context,
372
+ }
373
+ }
374
+
375
+ const substantive = task.tier >= 2
376
+ /**
377
+ * The intelligence floor exists so substantive work reaches a capable model.
378
+ * Offline mode is a deliberate exception: the owner has chosen to work with
379
+ * whatever runs locally, and enforcing the hosted floor would make offline
380
+ * mode permanently unusable, because no 4B model on this machine scores 39.5.
381
+ *
382
+ * The exception is scoped to local models only. A hosted model reached while
383
+ * offline is already refused upstream, so this cannot lower the floor for
384
+ * online routing.
385
+ */
386
+ const offlineFloorApplies = substanceFloorApplies(settings, model)
387
+ const floor = input.intelligenceFloor ?? settings.routing.intelligenceFloor
388
+ if (substantive && offlineFloorApplies && model.intelligence < floor) {
389
+ return {
390
+ eligible: false,
391
+ reason: `Intelligence ${model.intelligence.toFixed(1)} is below the ${settings.routing.intelligenceFloor.toFixed(1)} floor for substantive work`,
392
+ warnings,
393
+ }
394
+ }
395
+ if (task.tier <= 1 && model.tier === 3) {
396
+ return { eligible: false, reason: "Premium models are not used for trivial or mechanical work", warnings }
397
+ }
398
+
399
+ let designFallbackThreshold: number | undefined
400
+ if (task.designIntensive) {
401
+ const threshold = task.sophisticatedDesign ? settings.routing.sophisticatedDesignFloor : settings.routing.designFloor
402
+ if (model.design < threshold) {
403
+ if (input.allowDesignRelaxation) {
404
+ designFallbackThreshold = threshold
405
+ warnings.push(
406
+ `Design capability ${model.design} is below the preferred ${threshold} threshold; selected as the best available fallback`,
407
+ )
408
+ } else {
409
+ return {
410
+ eligible: false,
411
+ reason: `Design capability ${model.design} is below the ${threshold} threshold`,
412
+ warnings,
413
+ }
414
+ }
415
+ }
416
+ }
417
+
418
+ if (model.premium) {
419
+ if (!premium.allowed) {
420
+ return { eligible: false, reason: premium.reason, warnings }
421
+ }
422
+ if (task.tier < 3 && !task.constraints.requestPremium) {
423
+ return { eligible: false, reason: "Premium models are reserved for premium-tier work", warnings }
424
+ }
425
+ }
426
+
427
+ // The mirror gate: while escalation is available, tier-3 work draws on the
428
+ // plan-model pool and ordinary models stand down. A tier-3 task served by a
429
+ // standard model runs at ~0.7 expected success by construction - that is
430
+ // precisely the situation the pool exists to prevent, and no cost ranking
431
+ // should be able to quietly trade 24 points of success probability for a
432
+ // few cents. "Insufficient benefit" is answered by the classifier (a task
433
+ // ordinary models serve well is not classified tier 3) and by the budget
434
+ // gate (escalation that cannot be paid for does not happen), not by letting
435
+ // a cheap model absorb hard work. When this gate leaves no route at all,
436
+ // the engine's premiumFallback deliberately picks the strongest ordinary
437
+ // model, so exhaustion degrades instead of failing the task.
438
+ if (task.tier === 3 && premium.allowed && !model.premium) {
439
+ return {
440
+ eligible: false,
441
+ reason: "Premium-tier work escalates to the plan-model pool while escalation budget remains",
442
+ warnings,
443
+ }
444
+ }
445
+
446
+ // An escalation pool is capacity, not routine allowance. When an
447
+ // ordinary-allowance route can already serve the task, spending the
448
+ // escalation pool on it converts a cheap request into a scarce one.
449
+ if (model.escalationOnly && input.escalationPoolProtected) {
450
+ return {
451
+ eligible: false,
452
+ reason:
453
+ "This model is funded from an escalation pool, and an ordinary-allowance route can serve this task",
454
+ warnings,
455
+ }
456
+ }
457
+
458
+ const providerLimit = providerLimitReached(providerQuota, settings, model.providerID, input.quotaIsKnown === true)
459
+ if (providerLimit) return { eligible: false, reason: providerLimit, warnings }
460
+ const unknownLimit = unknownQuotaLimit(providerQuota, settings)
461
+ if (unknownLimit) return { eligible: false, reason: unknownLimit, warnings }
462
+ const subscriptionLimit = subscriptionOnlyLimit(providerQuota, settings, input.projectedUsd)
463
+ if (subscriptionLimit) return { eligible: false, reason: subscriptionLimit, warnings }
464
+ const modelLimit = modelLimitReached(modelQuota, settings)
465
+ if (modelLimit) return { eligible: false, reason: modelLimit, warnings }
466
+
467
+ // Maximum Efficiency mode prefers economy for qualifying work but still
468
+ // permits standard models when the task clears the standard floor.
469
+ if (mode === "efficiency" && task.tier >= 2 && model.tier === 1) {
470
+ return { eligible: false, reason: "Economy models cannot handle substantive engineering in Maximum Efficiency mode", warnings }
471
+ }
472
+
473
+ if (designFallbackThreshold !== undefined) {
474
+ return {
475
+ eligible: true,
476
+ reason: `Eligible only as a design fallback: design ${model.design} is below the ${designFallbackThreshold} threshold`,
477
+ warnings,
478
+ }
479
+ }
480
+
481
+ return { eligible: true, reason: "Meets every hard requirement", warnings }
482
+ }
483
+
484
+ /**
485
+ * How close to its reset a window must be for its remaining allowance to count
486
+ * as at risk. Further out than this is ordinary quota, not a fire sale.
487
+ */
488
+ const EXPIRY_HORIZON_MS = 24 * 60 * 60 * 1000
489
+
490
+ /**
491
+ * Nominal duration of each quota window, used to turn "spent so far" into a
492
+ * burn rate.
493
+ *
494
+ * The providers report a reset time but not the window's start, so elapsed time
495
+ * is derived from the window's own length: a weekly pool that resets in 21 hours
496
+ * has been running for 147. This is a modelling assumption and it is the reason
497
+ * the waste estimate is a fraction rather than a certainty.
498
+ */
499
+ const WINDOW_LENGTH_MS: Readonly<Record<"rolling" | "weekly" | "monthly", number>> = {
500
+ rolling: 5 * 60 * 60 * 1000,
501
+ weekly: 7 * 24 * 60 * 60 * 1000,
502
+ monthly: 30 * 24 * 60 * 60 * 1000,
503
+ }
504
+
505
+ /**
506
+ * The fraction of a pool's remaining allowance that is on track to expire unused.
507
+ *
508
+ * Zero means the window is being consumed fast enough that the next request
509
+ * displaces real work. One means the window will reset having used none of what
510
+ * it has left, so spending it costs nothing that was not already lost.
511
+ *
512
+ * Derived from the burn rate rather than from fill level alone. A pool at 87%
513
+ * with 21 hours left is not "about to waste its last 13%" if it has been burning
514
+ * 13% every 21 hours; a pool at 50% with three hours left of a week is.
515
+ */
516
+ export const quotaWasteFraction = (
517
+ snapshot: ProviderQuotaSnapshot | undefined,
518
+ now: number,
519
+ ): number => {
520
+ if (!snapshot) return 0
521
+ let worst = 0
522
+ for (const key of ["rolling", "weekly", "monthly"] as const) {
523
+ const window = snapshot[key]
524
+ if (!window || window.source === "unknown") continue
525
+ if (typeof window.resetsAt !== "number") continue
526
+ const remainingMs = window.resetsAt - now
527
+ // Already reset, or so far out that nothing is at risk today.
528
+ if (remainingMs <= 0 || remainingMs > EXPIRY_HORIZON_MS) continue
529
+ // Nothing has been committed to this pool, so there is nothing to recover.
530
+ if (window.usedPct <= 0) continue
531
+ // Without a dollar figure there is no burn rate to read, and guessing one
532
+ // from the percentage alone would assume a window length we were not told.
533
+ if (typeof window.usedUsd !== "number" || typeof window.capUsd !== "number" || window.capUsd <= 0) continue
534
+
535
+ const lengthMs = WINDOW_LENGTH_MS[key]
536
+ const elapsedMs = Math.max(0, lengthMs - remainingMs)
537
+ // Too early in the window for a burn rate to mean anything: a single request
538
+ // in the first minute would project to an absurd rate.
539
+ if (elapsedMs < 0.05 * lengthMs) continue
540
+
541
+ // This also covers a pool that is already out: with nothing left there is no
542
+ // marginal price to lower, and chasing the last percent would strand a task.
543
+ const remainingUsd = Math.max(0, window.capUsd - window.usedUsd)
544
+ if (remainingUsd <= 0) continue
545
+ const burnPerMs = window.usedUsd / elapsedMs
546
+ const projectedSpend = burnPerMs * remainingMs
547
+ worst = Math.max(worst, Math.min(1, Math.max(0, 1 - projectedSpend / remainingUsd)))
548
+ }
549
+ return worst
550
+ }
551
+
552
+ /**
553
+ * The factor to apply to an estimate for spending expiring prepaid allowance,
554
+ * where one means "this is fresh money and costs full price".
555
+ *
556
+ * This is the near-zero marginal pricing the flat pressure discount could not
557
+ * express. A dollar of prepaid allowance that is on track to be abandoned is
558
+ * worth about its own probability of being lost, so a provider about to waste
559
+ * its pool becomes genuinely competitive against a cheaper provider with no
560
+ * deadline.
561
+ *
562
+ * It is a floor rather than a zero on purpose: a provider priced at nothing
563
+ * would win every comparison regardless of how little headroom it had left, and
564
+ * a request that runs the pool dry mid-task is worse than paying full price
565
+ * elsewhere.
566
+ */
567
+ export const quotaMarginalPriceFactor = (
568
+ snapshot: ProviderQuotaSnapshot | undefined,
569
+ now: number,
570
+ ): number => {
571
+ if (!snapshot) return 1
572
+ // The pool must be able to carry real work. Where a window has headroom
573
+ // recorded, refuse to treat the last few percent as a bargain.
574
+ const tightest = [snapshot.rolling, snapshot.weekly, snapshot.monthly]
575
+ .filter((window) => window.source !== "unknown" && typeof window.resetsAt === "number")
576
+ if (tightest.length === 0) return 1
577
+ const usable = tightest.some((window) => window.remainingPct > 0)
578
+ if (!usable) return 1
579
+ const waste = quotaWasteFraction(snapshot, now)
580
+ if (waste <= 0) return 1
581
+ // Bounded well below one so expiring quota is cheap, never free.
582
+ return 1 - MARGINAL_PRICE_DISCOUNT_MAX * waste
583
+ }
584
+
585
+ /** The most of an estimate that can be forgiven for expiring allowance. */
586
+ const MARGINAL_PRICE_DISCOUNT_MAX = 0.95
587
+
588
+ export const providerPressure = (snapshot: ProviderQuotaSnapshot | undefined, now = Date.now()): number => {
589
+ if (!snapshot) return 1.5
590
+ const allUnknown =
591
+ snapshot.monthly.source === "unknown" && snapshot.weekly.source === "unknown" && snapshot.rolling.source === "unknown"
592
+ if (allUnknown) return 1.5
593
+ const monthly = snapshot.monthly.source === "unknown" ? 0 : snapshot.monthly.usedPct
594
+ const weekly = snapshot.weekly.source === "unknown" ? 0 : snapshot.weekly.usedPct
595
+ const rolling = snapshot.rolling.source === "unknown" ? 0 : snapshot.rolling.usedPct
596
+ const base =
597
+ 1 +
598
+ 1.5 * (monthly / 100) ** 2 +
599
+ 2.5 * (weekly / 100) ** 2 +
600
+ 2.5 * (rolling / 100) ** 2 +
601
+ (snapshot.stale ? 0.15 : 0)
602
+ // Fill level only. Expiring allowance is priced where it belongs, in
603
+ // quotaMarginalPriceFactor: pressure is a multiplier on an already-ranked cost,
604
+ // so expressing urgency here could never close a price gap, and counting it in
605
+ // both places charged the same fact twice.
606
+ return base
607
+ }
608
+
609
+ export const modelPressure = (quota: ModelQuotaSnapshot | undefined): number => {
610
+ if (!quota) return 1
611
+ return (
612
+ 1 +
613
+ 1.5 * (quota.monthlyUsedPct / 100) ** 2 +
614
+ 1 * (quota.fiveHourUsedPct / 100) ** 2 +
615
+ 1 * (quota.weeklyUsedPct / 100) ** 2
616
+ )
617
+ }
618
+
619
+ export const providerUtilization = (snapshot: ProviderQuotaSnapshot | undefined): number => {
620
+ if (!snapshot) return 0
621
+ return Math.max(
622
+ snapshot.monthly.source === "unknown" ? 0 : snapshot.monthly.usedPct,
623
+ snapshot.weekly.source === "unknown" ? 0 : snapshot.weekly.usedPct,
624
+ snapshot.rolling.source === "unknown" ? 0 : snapshot.rolling.usedPct,
625
+ )
626
+ }
627
+
628
+ export const modelKeyFor = (model: ModelRecord) => modelKey(model.providerID, model.modelID)
629
+ export const currentKey = (current: { providerID: string; id: string } | undefined) => keyOfRef(current)
630
+ export const utilizationPct = (used: number, cap: number) => pct(used, cap)