offrouter-core 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/audit.d.ts +51 -2
  2. package/dist/audit.d.ts.map +1 -1
  3. package/dist/audit.js +60 -3
  4. package/dist/audit.js.map +1 -1
  5. package/dist/config.d.ts +37 -0
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +171 -1
  8. package/dist/config.js.map +1 -1
  9. package/dist/delegation.d.ts +40 -0
  10. package/dist/delegation.d.ts.map +1 -1
  11. package/dist/delegation.js +169 -8
  12. package/dist/delegation.js.map +1 -1
  13. package/dist/index.d.ts +27 -13
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +15 -7
  16. package/dist/index.js.map +1 -1
  17. package/dist/llm-judge.d.ts +41 -0
  18. package/dist/llm-judge.d.ts.map +1 -0
  19. package/dist/llm-judge.js +159 -0
  20. package/dist/llm-judge.js.map +1 -0
  21. package/dist/policy.d.ts +77 -0
  22. package/dist/policy.d.ts.map +1 -1
  23. package/dist/policy.js +81 -0
  24. package/dist/policy.js.map +1 -1
  25. package/dist/provider-health.d.ts +129 -0
  26. package/dist/provider-health.d.ts.map +1 -0
  27. package/dist/provider-health.js +423 -0
  28. package/dist/provider-health.js.map +1 -0
  29. package/dist/providers/catalog-data.d.ts +7 -0
  30. package/dist/providers/catalog-data.d.ts.map +1 -1
  31. package/dist/providers/catalog-data.js +140 -53
  32. package/dist/providers/catalog-data.js.map +1 -1
  33. package/dist/providers/catalog.d.ts +3 -3
  34. package/dist/providers/catalog.d.ts.map +1 -1
  35. package/dist/providers/catalog.js +1 -0
  36. package/dist/providers/catalog.js.map +1 -1
  37. package/dist/proxy/anthropic-mapper.d.ts +585 -0
  38. package/dist/proxy/anthropic-mapper.d.ts.map +1 -0
  39. package/dist/proxy/anthropic-mapper.js +539 -0
  40. package/dist/proxy/anthropic-mapper.js.map +1 -0
  41. package/dist/proxy/anthropic-server.d.ts +24 -0
  42. package/dist/proxy/anthropic-server.d.ts.map +1 -0
  43. package/dist/proxy/anthropic-server.js +606 -0
  44. package/dist/proxy/anthropic-server.js.map +1 -0
  45. package/dist/proxy/classify.d.ts +17 -0
  46. package/dist/proxy/classify.d.ts.map +1 -0
  47. package/dist/proxy/classify.js +65 -0
  48. package/dist/proxy/classify.js.map +1 -0
  49. package/dist/proxy/responses-mapper.d.ts +15 -0
  50. package/dist/proxy/responses-mapper.d.ts.map +1 -1
  51. package/dist/proxy/responses-mapper.js +9 -2
  52. package/dist/proxy/responses-mapper.js.map +1 -1
  53. package/dist/proxy/responses-server.d.ts.map +1 -1
  54. package/dist/proxy/responses-server.js +14 -1
  55. package/dist/proxy/responses-server.js.map +1 -1
  56. package/dist/router.d.ts +36 -2
  57. package/dist/router.d.ts.map +1 -1
  58. package/dist/router.js +158 -23
  59. package/dist/router.js.map +1 -1
  60. package/dist/schemas.d.ts +115 -34
  61. package/dist/schemas.d.ts.map +1 -1
  62. package/dist/schemas.js +35 -0
  63. package/dist/schemas.js.map +1 -1
  64. package/dist/secret-scan.d.ts +40 -0
  65. package/dist/secret-scan.d.ts.map +1 -0
  66. package/dist/secret-scan.js +125 -0
  67. package/dist/secret-scan.js.map +1 -0
  68. package/dist/secrets.d.ts +77 -6
  69. package/dist/secrets.d.ts.map +1 -1
  70. package/dist/secrets.js +356 -32
  71. package/dist/secrets.js.map +1 -1
  72. package/dist/spend.d.ts +122 -0
  73. package/dist/spend.d.ts.map +1 -0
  74. package/dist/spend.js +279 -0
  75. package/dist/spend.js.map +1 -0
  76. package/dist/task-classifier.d.ts +45 -0
  77. package/dist/task-classifier.d.ts.map +1 -0
  78. package/dist/task-classifier.js +153 -0
  79. package/dist/task-classifier.js.map +1 -0
  80. package/dist/types.d.ts +46 -1
  81. package/dist/types.d.ts.map +1 -1
  82. package/dist/usage-file.d.ts +2 -6
  83. package/dist/usage-file.d.ts.map +1 -1
  84. package/dist/usage-file.js +64 -6
  85. package/dist/usage-file.js.map +1 -1
  86. package/dist/usage.d.ts +64 -10
  87. package/dist/usage.d.ts.map +1 -1
  88. package/dist/usage.js +79 -5
  89. package/dist/usage.js.map +1 -1
  90. package/package.json +1 -1
package/dist/spend.js ADDED
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Estimated paid API-key spend rollup for hard spend caps and `status --costs`.
3
+ *
4
+ * Extends the near-limit mechanism: near-limit warns on subscription quota,
5
+ * spend caps hard-block paid API-key candidates. Both read the same usage
6
+ * store; subscription and local tiers are never blocked by spend caps.
7
+ *
8
+ * Accounting window: the usage store today models a single cumulative window
9
+ * (per-account token totals persisted in usage.json; no time bucketing), so
10
+ * rollups cover everything recorded since the usage file was last reset.
11
+ *
12
+ * Spend estimation: per-account usage records (`used` = total tokens, keyed
13
+ * by providerId + accountId, which the delegation runtime sets to the model
14
+ * id) priced with the catalog PricingHint. When a per-model input/output
15
+ * breakdown is present, tokens are priced exactly (input rate × input +
16
+ * output rate × output). The unattributed remainder
17
+ * (`used - sum(model tokens)`) keeps the conservative max(input, output)
18
+ * rate treatment and flags costsIncomplete. Where pricing is unknown the
19
+ * contribution is not guessed: zero for cap math + costsIncomplete. Local
20
+ * runtimes are known-zero (no paid spend by definition).
21
+ */
22
+ import { getBuiltinProvider, } from "./providers/catalog-data.js";
23
+ /** Identifier for the accounting window the usage store currently models. */
24
+ export const SPEND_ACCOUNTING_WINDOW = "cumulative";
25
+ /** Catalog pricing hint for a provider/model pair, when documented. */
26
+ export function pricingHintForModel(providerId, modelId) {
27
+ const provider = getBuiltinProvider(providerId);
28
+ return provider?.knownModels.find((m) => m.modelId === modelId)?.pricing;
29
+ }
30
+ /**
31
+ * Estimate USD for a token total under a pricing hint using the higher of
32
+ * the input/output rates (conservative upper bound). Used for unattributed
33
+ * remainder / legacy totals where the input/output split is unknown.
34
+ * Returns undefined when the hint carries no usable rate — unknown pricing
35
+ * is never guessed.
36
+ */
37
+ export function estimateTokensCostUsd(totalTokens, hint) {
38
+ if (!hint)
39
+ return undefined;
40
+ const rate = Math.max(hint.inputPer1M ?? 0, hint.outputPer1M ?? 0);
41
+ if (rate <= 0)
42
+ return undefined;
43
+ return (totalTokens / 1_000_000) * rate;
44
+ }
45
+ /**
46
+ * Estimate USD from an exact input/output split. Falls back to the
47
+ * single documented rate when only one side is known. Returns undefined
48
+ * when the hint carries no usable rate.
49
+ */
50
+ export function estimateSplitTokensCostUsd(inputTokens, outputTokens, hint) {
51
+ if (!hint)
52
+ return undefined;
53
+ const inputRate = hint.inputPer1M;
54
+ const outputRate = hint.outputPer1M;
55
+ if ((inputRate === undefined || inputRate <= 0) &&
56
+ (outputRate === undefined || outputRate <= 0)) {
57
+ return undefined;
58
+ }
59
+ // When only one rate is documented, apply it to both sides rather than
60
+ // silently dropping the other side.
61
+ const inRate = inputRate !== undefined && inputRate > 0
62
+ ? inputRate
63
+ : outputRate;
64
+ const outRate = outputRate !== undefined && outputRate > 0
65
+ ? outputRate
66
+ : inputRate;
67
+ return (inputTokens / 1_000_000) * inRate + (outputTokens / 1_000_000) * outRate;
68
+ }
69
+ function attributedTokens(models) {
70
+ if (!models)
71
+ return 0;
72
+ let total = 0;
73
+ for (const t of Object.values(models)) {
74
+ total += t.inputTokens + t.outputTokens;
75
+ }
76
+ return total;
77
+ }
78
+ function pricePaidTokens(args) {
79
+ const { providerId, modelId, totalTokens, tier, pricing } = args;
80
+ const isPaidTier = tier === "api-key" || tier === undefined;
81
+ if (!isPaidTier) {
82
+ return { estimatedUsd: 0, pricingKnown: true, exactPricing: true };
83
+ }
84
+ if (getBuiltinProvider(providerId)?.defaultAuthTier === "local") {
85
+ return { estimatedUsd: 0, pricingKnown: true, exactPricing: true };
86
+ }
87
+ const hint = pricing(providerId, modelId);
88
+ const hasSplit = args.inputTokens !== undefined && args.outputTokens !== undefined;
89
+ let estimatedUsd;
90
+ let exactPricing = false;
91
+ if (hint !== undefined) {
92
+ if (hasSplit) {
93
+ estimatedUsd = estimateSplitTokensCostUsd(args.inputTokens, args.outputTokens, hint);
94
+ exactPricing = estimatedUsd !== undefined;
95
+ }
96
+ else {
97
+ estimatedUsd = estimateTokensCostUsd(totalTokens, hint);
98
+ }
99
+ }
100
+ let pricingKnown = estimatedUsd !== undefined;
101
+ // Legacy records without an authTier are counted, but we cannot be sure
102
+ // they were truly paid API-key usage, so mark the estimate incomplete.
103
+ if (tier === undefined) {
104
+ pricingKnown = false;
105
+ }
106
+ return {
107
+ estimatedUsd: estimatedUsd ?? 0,
108
+ pricingKnown,
109
+ exactPricing: exactPricing && pricingKnown,
110
+ };
111
+ }
112
+ /**
113
+ * Build a spend rollup from per-account usage records. Pure and
114
+ * deterministic; providers and models are sorted by id like the usage stores.
115
+ *
116
+ * Only API-key usage counts toward paid spend. Subscription and local tiers
117
+ * are recorded as known-zero. Legacy records with no authTier are counted
118
+ * conservatively (as paid) but always mark the rollup costsIncomplete.
119
+ *
120
+ * When a per-model input/output breakdown is present, those tokens are priced
121
+ * exactly. Any unattributed remainder (aggregate `used` minus attributed
122
+ * tokens) is priced at the conservative max rate under the accountId model
123
+ * and flags costsIncomplete for that remainder.
124
+ */
125
+ export function buildSpendRollup(accounts, options = {}) {
126
+ const pricing = options.pricing ?? pricingHintForModel;
127
+ const caps = options.caps ?? {};
128
+ const byProvider = new Map();
129
+ for (const account of accounts) {
130
+ const { providerId, accountId } = account;
131
+ const tier = account.authTier;
132
+ const models = account.models;
133
+ const linesForAccount = [];
134
+ if (models && Object.keys(models).length > 0) {
135
+ const modelIds = Object.keys(models).sort((a, b) => a.localeCompare(b));
136
+ for (const modelId of modelIds) {
137
+ const breakdown = models[modelId];
138
+ const totalTokens = breakdown.inputTokens + breakdown.outputTokens;
139
+ const priced = pricePaidTokens({
140
+ providerId,
141
+ modelId,
142
+ totalTokens,
143
+ inputTokens: breakdown.inputTokens,
144
+ outputTokens: breakdown.outputTokens,
145
+ tier,
146
+ pricing,
147
+ });
148
+ linesForAccount.push({
149
+ providerId,
150
+ modelId,
151
+ totalTokens,
152
+ inputTokens: breakdown.inputTokens,
153
+ outputTokens: breakdown.outputTokens,
154
+ estimatedUsd: priced.estimatedUsd,
155
+ pricingKnown: priced.pricingKnown,
156
+ exactPricing: priced.exactPricing,
157
+ });
158
+ }
159
+ const remainder = Math.max(0, account.used - attributedTokens(models));
160
+ if (remainder > 0) {
161
+ // Unattributed remainder: price conservatively under the account's
162
+ // model id (best available catalog key) but keep a distinct line id
163
+ // so it never coalesces with an exact-priced attributed line.
164
+ const priced = pricePaidTokens({
165
+ providerId,
166
+ modelId: accountId,
167
+ totalTokens: remainder,
168
+ tier,
169
+ pricing,
170
+ });
171
+ linesForAccount.push({
172
+ providerId,
173
+ modelId: `${accountId}#unattributed`,
174
+ totalTokens: remainder,
175
+ estimatedUsd: priced.estimatedUsd,
176
+ // Remainder is definitionally incomplete: we lack the split.
177
+ pricingKnown: false,
178
+ exactPricing: false,
179
+ });
180
+ }
181
+ }
182
+ else {
183
+ // Legacy / no-breakdown path: single line under accountId, conservative.
184
+ const priced = pricePaidTokens({
185
+ providerId,
186
+ modelId: accountId,
187
+ totalTokens: account.used,
188
+ tier,
189
+ pricing,
190
+ });
191
+ linesForAccount.push({
192
+ providerId,
193
+ modelId: accountId,
194
+ totalTokens: account.used,
195
+ estimatedUsd: priced.estimatedUsd,
196
+ pricingKnown: priced.pricingKnown,
197
+ exactPricing: false,
198
+ });
199
+ }
200
+ const list = byProvider.get(providerId);
201
+ if (list) {
202
+ list.push(...linesForAccount);
203
+ }
204
+ else {
205
+ byProvider.set(providerId, linesForAccount);
206
+ }
207
+ }
208
+ const providers = [];
209
+ for (const [providerId, rawModels] of byProvider) {
210
+ // Coalesce lines that share a modelId (e.g. multiple account writes for
211
+ // the same model, or an exact line plus a remainder under the same key).
212
+ const coalesced = new Map();
213
+ for (const line of rawModels) {
214
+ const existing = coalesced.get(line.modelId);
215
+ if (!existing) {
216
+ coalesced.set(line.modelId, { ...line });
217
+ continue;
218
+ }
219
+ existing.totalTokens += line.totalTokens;
220
+ existing.estimatedUsd += line.estimatedUsd;
221
+ existing.pricingKnown = existing.pricingKnown && line.pricingKnown;
222
+ existing.exactPricing = existing.exactPricing && line.exactPricing;
223
+ if (line.inputTokens !== undefined || existing.inputTokens !== undefined) {
224
+ existing.inputTokens =
225
+ (existing.inputTokens ?? 0) + (line.inputTokens ?? 0);
226
+ }
227
+ if (line.outputTokens !== undefined ||
228
+ existing.outputTokens !== undefined) {
229
+ existing.outputTokens =
230
+ (existing.outputTokens ?? 0) + (line.outputTokens ?? 0);
231
+ }
232
+ }
233
+ const models = [...coalesced.values()].sort((a, b) => a.modelId.localeCompare(b.modelId));
234
+ const estimatedUsd = models.reduce((sum, m) => sum + m.estimatedUsd, 0);
235
+ const capUsd = caps.perProviderUsd?.[providerId] ?? caps.globalUsd;
236
+ providers.push({
237
+ providerId,
238
+ totalTokens: models.reduce((sum, m) => sum + m.totalTokens, 0),
239
+ estimatedUsd,
240
+ costsIncomplete: models.some((m) => !m.pricingKnown),
241
+ ...(capUsd !== undefined
242
+ ? {
243
+ capUsd,
244
+ remainingUsd: Math.max(0, capUsd - estimatedUsd),
245
+ capExceeded: estimatedUsd >= capUsd,
246
+ }
247
+ : { capExceeded: false }),
248
+ models,
249
+ });
250
+ }
251
+ providers.sort((a, b) => a.providerId.localeCompare(b.providerId));
252
+ const totalUsd = providers.reduce((sum, p) => sum + p.estimatedUsd, 0);
253
+ const globalCap = caps.globalUsd;
254
+ return {
255
+ window: SPEND_ACCOUNTING_WINDOW,
256
+ totalUsd,
257
+ costsIncomplete: providers.some((p) => p.costsIncomplete),
258
+ ...(globalCap !== undefined
259
+ ? {
260
+ capUsd: globalCap,
261
+ remainingUsd: Math.max(0, globalCap - totalUsd),
262
+ capExceeded: totalUsd >= globalCap,
263
+ }
264
+ : { capExceeded: false }),
265
+ providers,
266
+ };
267
+ }
268
+ /**
269
+ * Build the `currentSpendByProviderUsd` map that PolicyConfig expects from a
270
+ * usage store. Non-fatal on the caller side: this helper throws when the
271
+ * store cannot be read so the caller can decide whether to swallow the error.
272
+ */
273
+ export async function buildCurrentSpendByProviderUsd(store, options) {
274
+ const rollup = buildSpendRollup(await store.listAccountUsage(), {
275
+ pricing: options?.pricing,
276
+ });
277
+ return Object.fromEntries(rollup.providers.map((p) => [p.providerId, p.estimatedUsd]));
278
+ }
279
+ //# sourceMappingURL=spend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spend.js","sourceRoot":"","sources":["../src/spend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Deterministic task classifier — routing *signal*, never authority.
3
+ *
4
+ * Policy still decides what is allowed. This module only recommends a logical
5
+ * model family (`fast-coder` | `frontier-coder`) from cheap, local heuristics
6
+ * over a prompt preview / length. No network, no LLM, no config keys.
7
+ *
8
+ * Default bias: when the input is ambiguous, prefer `frontier-coder` with
9
+ * `confidence: "low"`. Never under-serve a task by quietly routing complex work
10
+ * to a fast/cheap model. Callers must treat medium/low confidence as
11
+ * informational only — the router only applies a within-tier preference bump
12
+ * when confidence is `"high"`.
13
+ */
14
+ /** Character threshold above which a prompt is treated as "long". */
15
+ export declare const LONG_PROMPT_CHARS = 2000;
16
+ /** Minimum distinct code fences (``` pairs counted as openings) for multi-fence. */
17
+ export declare const MULTI_CODE_FENCE_THRESHOLD = 2;
18
+ /** Minimum multi-step keyword hits required to fire the multi-step signal. */
19
+ export declare const MULTI_STEP_HIT_THRESHOLD = 1;
20
+ /** Short-prompt ceiling for the mechanical / fast path (chars). */
21
+ export declare const SHORT_PROMPT_CHARS = 280;
22
+ export type ClassifierFamily = "fast-coder" | "frontier-coder";
23
+ export type ClassifierConfidence = "low" | "medium" | "high";
24
+ export interface TaskClassification {
25
+ recommendedFamily: ClassifierFamily;
26
+ confidence: ClassifierConfidence;
27
+ /** Short stable rule ids that fired; safe for explain/audit (no prompt text). */
28
+ signals: string[];
29
+ }
30
+ export interface ClassifyTaskInput {
31
+ /** Optional short preview of the prompt (may be truncated upstream). */
32
+ promptPreview?: string;
33
+ /**
34
+ * Optional full prompt length in characters. Prefer this over preview length
35
+ * when available so truncation of the preview does not hide a long prompt.
36
+ */
37
+ promptLengthChars?: number;
38
+ }
39
+ /**
40
+ * Classify a task from prompt preview / length using deterministic heuristics.
41
+ *
42
+ * Same inputs always produce the same output. Never throws on empty input.
43
+ */
44
+ export declare function classifyTask(input?: ClassifyTaskInput): TaskClassification;
45
+ //# sourceMappingURL=task-classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-classifier.d.ts","sourceRoot":"","sources":["../src/task-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,qEAAqE;AACrE,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AAEvC,oFAAoF;AACpF,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C,8EAA8E;AAC9E,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAsB1C,mEAAmE;AACnE,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAE/D,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,EAAE,gBAAgB,CAAC;IACpC,UAAU,EAAE,oBAAoB,CAAC;IACjC,iFAAiF;IACjF,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAsBD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,GAAE,iBAAsB,GAAG,kBAAkB,CAyF9E"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Deterministic task classifier — routing *signal*, never authority.
3
+ *
4
+ * Policy still decides what is allowed. This module only recommends a logical
5
+ * model family (`fast-coder` | `frontier-coder`) from cheap, local heuristics
6
+ * over a prompt preview / length. No network, no LLM, no config keys.
7
+ *
8
+ * Default bias: when the input is ambiguous, prefer `frontier-coder` with
9
+ * `confidence: "low"`. Never under-serve a task by quietly routing complex work
10
+ * to a fast/cheap model. Callers must treat medium/low confidence as
11
+ * informational only — the router only applies a within-tier preference bump
12
+ * when confidence is `"high"`.
13
+ */
14
+ /** Character threshold above which a prompt is treated as "long". */
15
+ export const LONG_PROMPT_CHARS = 2_000;
16
+ /** Minimum distinct code fences (``` pairs counted as openings) for multi-fence. */
17
+ export const MULTI_CODE_FENCE_THRESHOLD = 2;
18
+ /** Minimum multi-step keyword hits required to fire the multi-step signal. */
19
+ export const MULTI_STEP_HIT_THRESHOLD = 1;
20
+ const MULTI_STEP_PATTERNS = [
21
+ { id: "multi_step:refactor", re: /\brefactor(?:ing|s|ed)?\b/i },
22
+ { id: "multi_step:architect", re: /\barchitect(?:ure|ing|ed|s)?\b/i },
23
+ { id: "multi_step:migrate", re: /\bmigrat(?:e|ion|ing|ed|es)\b/i },
24
+ { id: "multi_step:design", re: /\bdesign(?:ing|ed|s)?\b/i },
25
+ // "debug across" is intentionally multi-word to avoid every "debug this" hit.
26
+ { id: "multi_step:debug_across", re: /\bdebug\s+across\b/i },
27
+ { id: "multi_step:investigate", re: /\binvestigat(?:e|ion|ing|ed|es)\b/i },
28
+ ];
29
+ const FAST_MECHANICAL_PATTERNS = [
30
+ { id: "mechanical:rename", re: /\brename\b/i },
31
+ { id: "mechanical:format", re: /\bformat\b/i },
32
+ { id: "mechanical:typo", re: /\btypos?\b/i },
33
+ { id: "mechanical:bump", re: /\bbump\b/i },
34
+ { id: "mechanical:list", re: /\blist\b/i },
35
+ // "extract single" stays multi-word so "extract the auth module" stays open.
36
+ { id: "mechanical:extract_single", re: /\bextract\s+single\b/i },
37
+ ];
38
+ /** Short-prompt ceiling for the mechanical / fast path (chars). */
39
+ export const SHORT_PROMPT_CHARS = 280;
40
+ function countCodeFenceOpenings(text) {
41
+ // Count opening fences only; a lone ``` still counts as one fence block.
42
+ const matches = text.match(/```/g);
43
+ if (!matches)
44
+ return 0;
45
+ // Each fence token is one marker; a complete block uses two. Treat every pair
46
+ // of markers as one fence and a trailing orphan as another block start.
47
+ return Math.ceil(matches.length / 2);
48
+ }
49
+ function collectHits(text, patterns) {
50
+ const hits = [];
51
+ for (const { id, re } of patterns) {
52
+ if (re.test(text))
53
+ hits.push(id);
54
+ }
55
+ return hits;
56
+ }
57
+ /**
58
+ * Classify a task from prompt preview / length using deterministic heuristics.
59
+ *
60
+ * Same inputs always produce the same output. Never throws on empty input.
61
+ */
62
+ export function classifyTask(input = {}) {
63
+ const preview = input.promptPreview ?? "";
64
+ const length = typeof input.promptLengthChars === "number" &&
65
+ Number.isFinite(input.promptLengthChars) &&
66
+ input.promptLengthChars >= 0
67
+ ? Math.floor(input.promptLengthChars)
68
+ : preview.length;
69
+ const signals = [];
70
+ let frontierScore = 0;
71
+ let fastScore = 0;
72
+ // --- Frontier signals ----------------------------------------------------
73
+ if (length > LONG_PROMPT_CHARS) {
74
+ signals.push("long_prompt");
75
+ frontierScore += 2;
76
+ }
77
+ const multiStepHits = collectHits(preview, MULTI_STEP_PATTERNS);
78
+ if (multiStepHits.length >= MULTI_STEP_HIT_THRESHOLD) {
79
+ signals.push(...multiStepHits);
80
+ signals.push("multi_step");
81
+ frontierScore += 1 + Math.min(multiStepHits.length, 2);
82
+ }
83
+ const fenceCount = countCodeFenceOpenings(preview);
84
+ if (fenceCount >= MULTI_CODE_FENCE_THRESHOLD) {
85
+ signals.push("multi_code_fence");
86
+ frontierScore += 2;
87
+ }
88
+ // --- Fast / mechanical signals -------------------------------------------
89
+ const mechanicalHits = collectHits(preview, FAST_MECHANICAL_PATTERNS);
90
+ const isShort = length > 0 && length <= SHORT_PROMPT_CHARS;
91
+ if (isShort) {
92
+ signals.push("short_prompt");
93
+ }
94
+ if (mechanicalHits.length > 0 && frontierScore === 0) {
95
+ signals.push(...mechanicalHits);
96
+ signals.push("mechanical_verb");
97
+ fastScore += 1 + Math.min(mechanicalHits.length, 2);
98
+ if (isShort)
99
+ fastScore += 1;
100
+ }
101
+ else if (mechanicalHits.length > 0 && frontierScore > 0) {
102
+ // Still record mechanical hits for explainability, but do not let them
103
+ // cancel a frontier signal (never under-serve).
104
+ signals.push(...mechanicalHits);
105
+ }
106
+ // Empty / whitespace-only input → ambiguous.
107
+ if (preview.trim().length === 0 && length === 0) {
108
+ return {
109
+ recommendedFamily: "frontier-coder",
110
+ confidence: "low",
111
+ signals: ["ambiguous_empty"],
112
+ };
113
+ }
114
+ if (frontierScore > 0 && frontierScore > fastScore) {
115
+ const confidence = frontierScore >= 3 ? "high" : frontierScore === 2 ? "medium" : "low";
116
+ return {
117
+ recommendedFamily: "frontier-coder",
118
+ confidence,
119
+ signals: dedupe(signals),
120
+ };
121
+ }
122
+ if (fastScore > 0 && fastScore > frontierScore) {
123
+ // High only when short + clear mechanical verb(s) and no frontier signal.
124
+ const confidence = fastScore >= 2 && isShort ? "high" : "medium";
125
+ return {
126
+ recommendedFamily: "fast-coder",
127
+ confidence,
128
+ signals: dedupe(signals),
129
+ };
130
+ }
131
+ // Ambiguous: mixed, missing, or equal signal weight. Default to frontier so
132
+ // we never under-serve. Confidence stays low so the router does not reorder.
133
+ if (!signals.includes("ambiguous")) {
134
+ signals.push("ambiguous");
135
+ }
136
+ return {
137
+ recommendedFamily: "frontier-coder",
138
+ confidence: "low",
139
+ signals: dedupe(signals),
140
+ };
141
+ }
142
+ function dedupe(signals) {
143
+ const seen = new Set();
144
+ const out = [];
145
+ for (const s of signals) {
146
+ if (seen.has(s))
147
+ continue;
148
+ seen.add(s);
149
+ out.push(s);
150
+ }
151
+ return out;
152
+ }
153
+ //# sourceMappingURL=task-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-classifier.js","sourceRoot":"","sources":["../src/task-classifier.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -10,7 +10,7 @@ export type FallbackReason = "primary" | "subscription_exhausted" | "subscriptio
10
10
  export type HarnessKind = "claude" | "codex" | "gemini" | "grok" | "cursor" | "pi" | "other";
11
11
  export type TaskKind = "explain" | "code" | "review" | "plan" | "research" | "image" | "tools" | "other";
12
12
  export type RiskLevel = "low" | "medium" | "high";
13
- export type PolicyDenialCode = "profile_not_allowlisted" | "work_profile_denied" | "provider_denied" | "project_untrusted" | "privacy_label_denied" | "local_only_required" | "cost_cap_exceeded" | "api_key_blocked_by_subscription_first_policy" | "subscription_scope_denied" | "capability_missing";
13
+ export type PolicyDenialCode = "profile_not_allowlisted" | "work_profile_denied" | "provider_denied" | "project_untrusted" | "privacy_label_denied" | "local_only_required" | "cost_cap_exceeded" | "spend_cap_exceeded" | "api_key_blocked_by_subscription_first_policy" | "subscription_scope_denied" | "capability_missing" | "model_not_allowed" | "api_spend_approval_required" | "subscription_switch_requires_ack";
14
14
  export type PolicyDenialTarget = "profile" | "provider" | "model" | "workspace" | "candidate";
15
15
  export interface PolicyDenial {
16
16
  code: PolicyDenialCode;
@@ -18,6 +18,8 @@ export interface PolicyDenial {
18
18
  id: string;
19
19
  message: string;
20
20
  }
21
+ /** Logical model family shared across auth tiers (mirrors catalog). */
22
+ export type LogicalModelFamily = "frontier-coder" | "fast-coder" | "local-coder" | "vision-helper";
21
23
  export interface ProviderCandidate {
22
24
  providerId: string;
23
25
  modelId: string;
@@ -35,6 +37,11 @@ export interface ProviderCandidate {
35
37
  contextWindowTokens?: number;
36
38
  maxOutputTokens?: number;
37
39
  estimatedCostUsd?: number;
40
+ /**
41
+ * Optional logical family used by the heuristic classifier as a same-tier
42
+ * preference signal. Omitted candidates never receive a family preference bump.
43
+ */
44
+ family?: LogicalModelFamily;
38
45
  }
39
46
  export interface HarnessRef {
40
47
  kind: HarnessKind;
@@ -85,7 +92,25 @@ export interface FallbackChainEntry {
85
92
  model: string;
86
93
  authTier: AuthTier;
87
94
  reason: FallbackReason;
95
+ /**
96
+ * Recent-outcome health score used for same-tier re-ordering when a health
97
+ * tracker is attached to routeRequest. Higher is healthier. Unknown /
98
+ * unobserved pairs use the tracker neutral score (0). Omitted when no
99
+ * tracker was provided.
100
+ */
101
+ healthScore?: number;
88
102
  }
103
+ /**
104
+ * Heuristic task classification attached to a route decision for explain/audit.
105
+ * Contains only family / confidence / stable signal ids — never prompt text.
106
+ */
107
+ export interface RouteClassification {
108
+ recommendedFamily: "fast-coder" | "frontier-coder";
109
+ confidence: "low" | "medium" | "high";
110
+ signals: string[];
111
+ }
112
+ /** Which classifier produced the routing signal recorded in audit/decision. */
113
+ export type ClassifierName = "heuristic" | "llm" | "llm-fallback-heuristic";
89
114
  export interface RouteDecision {
90
115
  protocolVersion: "offrouter.route.v1";
91
116
  decisionId: string;
@@ -105,6 +130,26 @@ export interface RouteDecision {
105
130
  needsConfiguration?: boolean;
106
131
  /** Warning when the selected route is a near-limit subscription with no healthy alternative. */
107
132
  nearLimitWarning?: string;
133
+ /**
134
+ * Optional classifier signal used during scoring. Present when the caller
135
+ * supplied a classification (or delegation computed one). Never carries
136
+ * prompt text — family / confidence / signal ids only.
137
+ */
138
+ classification?: RouteClassification;
139
+ /**
140
+ * Which classifier produced the classification signal. Present when the
141
+ * decision carries a classification. Never prompt text.
142
+ */
143
+ classifierName?: ClassifierName;
144
+ /**
145
+ * When a user-defined routing rule matched, the rule index and matched keys.
146
+ * Absent when no rule matched (auto routing).
147
+ */
148
+ routingRule?: {
149
+ index: number;
150
+ matchedKeys: ("role" | "family")[];
151
+ target: "model" | "provider" | "tier";
152
+ };
108
153
  }
109
154
  /**
110
155
  * Outcome of evaluatePolicy: filtered candidates plus structured denials.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,QAAQ,GAAG,cAAc,GAAG,OAAO,GAAG,SAAS,CAAC;AAE5D,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,aAAa,GAAG,SAAS,CAAC;AAElE,MAAM,MAAM,kBAAkB,GAC1B,QAAQ,GACR,YAAY,GACZ,WAAW,GACX,cAAc,GACd,SAAS,GACT,cAAc,GACd,SAAS,CAAC;AAEd,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAE7D,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,wBAAwB,GACxB,uBAAuB,GACvB,2BAA2B,GAC3B,2BAA2B,GAC3B,iBAAiB,GACjB,kBAAkB,GAClB,eAAe,GACf,gBAAgB,CAAC;AAErB,MAAM,MAAM,WAAW,GACrB,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC;AAErE,MAAM,MAAM,QAAQ,GAChB,SAAS,GACT,MAAM,GACN,QAAQ,GACR,MAAM,GACN,UAAU,GACV,OAAO,GACP,OAAO,GACP,OAAO,CAAC;AAEZ,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAElD,MAAM,MAAM,gBAAgB,GACxB,yBAAyB,GACzB,qBAAqB,GACrB,iBAAiB,GACjB,mBAAmB,GACnB,sBAAsB,GACtB,qBAAqB,GACrB,mBAAmB,GACnB,8CAA8C,GAC9C,2BAA2B,GAC3B,oBAAoB,CAAC;AAEzB,MAAM,MAAM,kBAAkB,GAC5B,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,WAAW,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iCAAiC,CAAC,EAAE,MAAM,CAAC;IAC3C,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,eAAe,EAAE,oBAAoB,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,YAAY,CAAC;IACxB,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,oBAAoB,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,KAAK,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACrC,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,gGAAgG;IAChG,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { chmod, mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
2
- import { type AccountUsageSnapshot, type PaidFallbackExplanation, type ProviderUsageSnapshot, type RecordUsageResult, type UsageEvent, type UsageStore } from "./usage.js";
2
+ import { type AccountUsageSnapshot, type PaidFallbackExplanation, type ProviderUsageSnapshot, type RecordUsageInput, type RecordUsageResult, type UsageEvent, type UsageStore } from "./usage.js";
3
3
  export { DEFAULT_NEAR_LIMIT_THRESHOLD } from "./usage.js";
4
4
  export { InMemoryUsageStore } from "./usage.js";
5
5
  export type { UsageStore } from "./usage.js";
@@ -45,11 +45,7 @@ export declare class FileUsageStore implements UsageStore {
45
45
  explainPaidFallback(providerId: string, options?: {
46
46
  hasApiKeyCandidate?: boolean;
47
47
  }): Promise<PaidFallbackExplanation>;
48
- recordUsage(providerId: string, accountId: string, input: {
49
- used?: number;
50
- limit?: number;
51
- at?: Date;
52
- }): Promise<AccountUsageSnapshot>;
48
+ recordUsage(providerId: string, accountId: string, input: RecordUsageInput): Promise<AccountUsageSnapshot>;
53
49
  isNearLimit(providerId: string, accountId: string, threshold?: number): Promise<boolean>;
54
50
  getNearLimitAccounts(threshold?: number): Promise<AccountUsageSnapshot[]>;
55
51
  getAccountUsage(providerId: string, accountId: string): Promise<AccountUsageSnapshot | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"usage-file.d.ts","sourceRoot":"","sources":["../src/usage-file.ts"],"names":[],"mappings":"AAoBA,OAAO,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,MAAM,EACN,SAAS,EACV,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAIL,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,KAAK,EAAE,OAAO,KAAK,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,kFAAkF;IAClF,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC/C,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB;AAoFD;;;GAGG;AACH,qBAAa,cAAe,YAAW,UAAU;;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBASd,OAAO,EAAE,qBAAqB;IA6I1C,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIrD,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;IAI3E,aAAa,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAIjD,oBAAoB,CAClB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,OAAO,YAAY,EAAE,kBAAkB,CAAC;QACjD,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,EAAE,CAAC,EAAE,IAAI,CAAC;KACX,GACA,OAAO,CAAC,qBAAqB,CAAC;IAIjC,mBAAmB,CACjB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;QAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,GACzC,OAAO,CAAC,uBAAuB,CAAC;IAM7B,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,IAAI,CAAA;KAAE,GAClD,OAAO,CAAC,oBAAoB,CAAC;IAuB1B,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC;IASb,oBAAoB,CACxB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAgB5B,eAAe,CACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;IAStC,gBAAgB,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAezD,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQlC"}
1
+ {"version":3,"file":"usage-file.d.ts","sourceRoot":"","sources":["../src/usage-file.ts"],"names":[],"mappings":"AAoBA,OAAO,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,MAAM,EACN,SAAS,EACV,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAKL,KAAK,oBAAoB,EAEzB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,KAAK,EAAE,OAAO,KAAK,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,kFAAkF;IAClF,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC/C,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB;AAgJD;;;GAGG;AACH,qBAAa,cAAe,YAAW,UAAU;;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBASd,OAAO,EAAE,qBAAqB;IA4J1C,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIrD,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;IAI3E,aAAa,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAIjD,oBAAoB,CAClB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,OAAO,YAAY,EAAE,kBAAkB,CAAC;QACjD,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,EAAE,CAAC,EAAE,IAAI,CAAC;KACX,GACA,OAAO,CAAC,qBAAqB,CAAC;IAIjC,mBAAmB,CACjB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;QAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,GACzC,OAAO,CAAC,uBAAuB,CAAC;IAM7B,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,oBAAoB,CAAC;IAqB1B,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC;IASb,oBAAoB,CACxB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAgB5B,eAAe,CACnB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;IAStC,gBAAgB,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAezD,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQlC"}