offrouter-core 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit.d.ts +137 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +320 -0
- package/dist/audit.js.map +1 -0
- package/dist/auth/credential-chain.d.ts +84 -0
- package/dist/auth/credential-chain.d.ts.map +1 -0
- package/dist/auth/credential-chain.js +150 -0
- package/dist/auth/credential-chain.js.map +1 -0
- package/dist/auth/index.d.ts +10 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +7 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/keychain.d.ts +60 -0
- package/dist/auth/keychain.d.ts.map +1 -0
- package/dist/auth/keychain.js +104 -0
- package/dist/auth/keychain.js.map +1 -0
- package/dist/auth/oauth-pkce.d.ts +138 -0
- package/dist/auth/oauth-pkce.d.ts.map +1 -0
- package/dist/auth/oauth-pkce.js +375 -0
- package/dist/auth/oauth-pkce.js.map +1 -0
- package/dist/auth/oauth-server.d.ts +36 -0
- package/dist/auth/oauth-server.d.ts.map +1 -0
- package/dist/auth/oauth-server.js +210 -0
- package/dist/auth/oauth-server.js.map +1 -0
- package/dist/config.d.ts +76 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +355 -0
- package/dist/config.js.map +1 -0
- package/dist/delegation.d.ts +123 -0
- package/dist/delegation.d.ts.map +1 -0
- package/dist/delegation.js +455 -0
- package/dist/delegation.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/policy.d.ts +45 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +318 -0
- package/dist/policy.js.map +1 -0
- package/{src/protocol.ts → dist/protocol.d.ts} +2 -2
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +6 -0
- package/dist/protocol.js.map +1 -0
- package/dist/providers/adapter.d.ts +137 -0
- package/dist/providers/adapter.d.ts.map +1 -0
- package/dist/providers/adapter.js +163 -0
- package/dist/providers/adapter.js.map +1 -0
- package/dist/providers/catalog-data.d.ts +128 -0
- package/dist/providers/catalog-data.d.ts.map +1 -0
- package/dist/providers/catalog-data.js +397 -0
- package/dist/providers/catalog-data.js.map +1 -0
- package/dist/providers/catalog.d.ts +63 -0
- package/dist/providers/catalog.d.ts.map +1 -0
- package/dist/providers/catalog.js +394 -0
- package/dist/providers/catalog.js.map +1 -0
- package/dist/providers/fake.d.ts +46 -0
- package/dist/providers/fake.d.ts.map +1 -0
- package/dist/providers/fake.js +234 -0
- package/dist/providers/fake.js.map +1 -0
- package/dist/providers/openai-compatible.d.ts +65 -0
- package/dist/providers/openai-compatible.d.ts.map +1 -0
- package/dist/providers/openai-compatible.js +434 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/proxy/responses-mapper.d.ts +366 -0
- package/dist/proxy/responses-mapper.d.ts.map +1 -0
- package/dist/proxy/responses-mapper.js +517 -0
- package/dist/proxy/responses-mapper.js.map +1 -0
- package/dist/proxy/responses-server.d.ts +29 -0
- package/dist/proxy/responses-server.d.ts.map +1 -0
- package/dist/proxy/responses-server.js +360 -0
- package/dist/proxy/responses-server.js.map +1 -0
- package/dist/router.d.ts +18 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +296 -0
- package/dist/router.js.map +1 -0
- package/dist/schemas.d.ts +560 -0
- package/dist/schemas.d.ts.map +1 -0
- package/{src/schemas.ts → dist/schemas.js} +83 -103
- package/dist/schemas.js.map +1 -0
- package/dist/secrets.d.ts +112 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +326 -0
- package/dist/secrets.js.map +1 -0
- package/dist/types.d.ts +117 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/usage-file.d.ts +59 -0
- package/dist/usage-file.d.ts.map +1 -0
- package/dist/usage-file.js +316 -0
- package/dist/usage-file.js.map +1 -0
- package/dist/usage.d.ts +235 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +517 -0
- package/dist/usage.js.map +1 -0
- package/package.json +7 -2
- package/src/audit.test.ts +0 -302
- package/src/audit.ts +0 -553
- package/src/auth/credential-chain.test.ts +0 -326
- package/src/auth/credential-chain.ts +0 -235
- package/src/auth/index.ts +0 -45
- package/src/auth/keychain.test.ts +0 -265
- package/src/auth/keychain.ts +0 -168
- package/src/auth/oauth-pkce.test.ts +0 -329
- package/src/auth/oauth-pkce.ts +0 -571
- package/src/auth/oauth-server.test.ts +0 -83
- package/src/auth/oauth-server.ts +0 -296
- package/src/config.test.ts +0 -479
- package/src/config.ts +0 -505
- package/src/delegation.test.ts +0 -368
- package/src/delegation.ts +0 -605
- package/src/index.ts +0 -280
- package/src/policy.test.ts +0 -634
- package/src/policy.ts +0 -420
- package/src/providers/adapter.test.ts +0 -293
- package/src/providers/adapter.ts +0 -328
- package/src/providers/catalog-data.test.ts +0 -258
- package/src/providers/catalog-data.ts +0 -498
- package/src/providers/catalog.test.ts +0 -84
- package/src/providers/catalog.ts +0 -483
- package/src/providers/fake.ts +0 -312
- package/src/providers/openai-compatible.test.ts +0 -366
- package/src/providers/openai-compatible.ts +0 -554
- package/src/proxy/responses-mapper.test.ts +0 -290
- package/src/proxy/responses-mapper.ts +0 -736
- package/src/proxy/responses-server.test.ts +0 -322
- package/src/proxy/responses-server.ts +0 -469
- package/src/router.test.ts +0 -699
- package/src/router.ts +0 -352
- package/src/schemas.test.ts +0 -291
- package/src/secrets.test.ts +0 -271
- package/src/secrets.ts +0 -461
- package/src/types.ts +0 -173
- package/src/usage-file.test.ts +0 -243
- package/src/usage-file.ts +0 -435
- package/src/usage.test.ts +0 -335
- package/src/usage.ts +0 -859
- package/tsconfig.json +0 -9
package/src/providers/catalog.ts
DELETED
|
@@ -1,483 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Static provider/model catalog for offline subscription-first routing tests.
|
|
3
|
-
* No credential scraping; entries describe discovery shapes only.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
AuthScope,
|
|
8
|
-
AuthTier,
|
|
9
|
-
ProviderCandidate,
|
|
10
|
-
ProviderHealth,
|
|
11
|
-
SubscriptionStatus,
|
|
12
|
-
} from "../types.js";
|
|
13
|
-
import {
|
|
14
|
-
selectBuiltinProviders,
|
|
15
|
-
type BuiltinCatalogConfig,
|
|
16
|
-
type BuiltinProviderEntry,
|
|
17
|
-
} from "./catalog-data.js";
|
|
18
|
-
|
|
19
|
-
/** Logical model family shared across auth tiers for preference testing. */
|
|
20
|
-
export type LogicalModelFamily =
|
|
21
|
-
"frontier-coder" | "fast-coder" | "local-coder" | "vision-helper";
|
|
22
|
-
|
|
23
|
-
export interface CatalogEntry {
|
|
24
|
-
providerId: string;
|
|
25
|
-
modelId: string;
|
|
26
|
-
displayName: string;
|
|
27
|
-
family: LogicalModelFamily;
|
|
28
|
-
authTier: AuthTier;
|
|
29
|
-
authScope: AuthScope;
|
|
30
|
-
subscriptionStatus?: SubscriptionStatus;
|
|
31
|
-
health: ProviderHealth;
|
|
32
|
-
supportsTools: boolean;
|
|
33
|
-
supportsStreaming: boolean;
|
|
34
|
-
supportsJson: boolean;
|
|
35
|
-
supportsImages: boolean;
|
|
36
|
-
contextWindowTokens?: number;
|
|
37
|
-
maxOutputTokens?: number;
|
|
38
|
-
estimatedCostUsd?: number;
|
|
39
|
-
notes?: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Built-in catalog: for several families, ship subscription + local + api-key
|
|
44
|
-
* candidates so routing prefers subscription without live credentials.
|
|
45
|
-
*/
|
|
46
|
-
export const STATIC_CATALOG: readonly CatalogEntry[] = [
|
|
47
|
-
// frontier-coder across all three tiers
|
|
48
|
-
{
|
|
49
|
-
providerId: "claude-subscription",
|
|
50
|
-
modelId: "claude-sonnet-4",
|
|
51
|
-
displayName: "Claude Sonnet (subscription)",
|
|
52
|
-
family: "frontier-coder",
|
|
53
|
-
authTier: "subscription",
|
|
54
|
-
authScope: "first-party",
|
|
55
|
-
subscriptionStatus: "active",
|
|
56
|
-
health: "healthy",
|
|
57
|
-
supportsTools: true,
|
|
58
|
-
supportsStreaming: true,
|
|
59
|
-
supportsJson: true,
|
|
60
|
-
supportsImages: true,
|
|
61
|
-
contextWindowTokens: 200_000,
|
|
62
|
-
maxOutputTokens: 32_000,
|
|
63
|
-
estimatedCostUsd: 0,
|
|
64
|
-
notes: "Official harness subscription capacity",
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
providerId: "ollama",
|
|
68
|
-
modelId: "qwen2.5-coder:32b",
|
|
69
|
-
displayName: "Qwen2.5 Coder 32B (local)",
|
|
70
|
-
family: "frontier-coder",
|
|
71
|
-
authTier: "local",
|
|
72
|
-
authScope: "first-party",
|
|
73
|
-
health: "healthy",
|
|
74
|
-
supportsTools: true,
|
|
75
|
-
supportsStreaming: true,
|
|
76
|
-
supportsJson: true,
|
|
77
|
-
supportsImages: false,
|
|
78
|
-
contextWindowTokens: 32_768,
|
|
79
|
-
maxOutputTokens: 8_192,
|
|
80
|
-
estimatedCostUsd: 0,
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
providerId: "openrouter",
|
|
84
|
-
modelId: "anthropic/claude-sonnet-4",
|
|
85
|
-
displayName: "Claude Sonnet via OpenRouter",
|
|
86
|
-
family: "frontier-coder",
|
|
87
|
-
authTier: "api-key",
|
|
88
|
-
authScope: "third-party",
|
|
89
|
-
health: "healthy",
|
|
90
|
-
supportsTools: true,
|
|
91
|
-
supportsStreaming: true,
|
|
92
|
-
supportsJson: true,
|
|
93
|
-
supportsImages: true,
|
|
94
|
-
contextWindowTokens: 200_000,
|
|
95
|
-
maxOutputTokens: 32_000,
|
|
96
|
-
estimatedCostUsd: 0.03,
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
providerId: "xai",
|
|
100
|
-
modelId: "grok-code-fast-1",
|
|
101
|
-
displayName: "Grok Code Fast (api-key)",
|
|
102
|
-
family: "frontier-coder",
|
|
103
|
-
authTier: "api-key",
|
|
104
|
-
authScope: "first-party",
|
|
105
|
-
health: "healthy",
|
|
106
|
-
supportsTools: true,
|
|
107
|
-
supportsStreaming: true,
|
|
108
|
-
supportsJson: true,
|
|
109
|
-
supportsImages: false,
|
|
110
|
-
contextWindowTokens: 131_072,
|
|
111
|
-
maxOutputTokens: 16_384,
|
|
112
|
-
estimatedCostUsd: 0.02,
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
// fast-coder across tiers
|
|
116
|
-
{
|
|
117
|
-
providerId: "codex-subscription",
|
|
118
|
-
modelId: "gpt-5-codex",
|
|
119
|
-
displayName: "GPT Codex (subscription)",
|
|
120
|
-
family: "fast-coder",
|
|
121
|
-
authTier: "subscription",
|
|
122
|
-
authScope: "first-party",
|
|
123
|
-
subscriptionStatus: "active",
|
|
124
|
-
health: "healthy",
|
|
125
|
-
supportsTools: true,
|
|
126
|
-
supportsStreaming: true,
|
|
127
|
-
supportsJson: true,
|
|
128
|
-
supportsImages: false,
|
|
129
|
-
contextWindowTokens: 128_000,
|
|
130
|
-
maxOutputTokens: 16_384,
|
|
131
|
-
estimatedCostUsd: 0,
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
providerId: "lmstudio",
|
|
135
|
-
modelId: "local-fast-coder",
|
|
136
|
-
displayName: "Local Fast Coder",
|
|
137
|
-
family: "fast-coder",
|
|
138
|
-
authTier: "local",
|
|
139
|
-
authScope: "first-party",
|
|
140
|
-
health: "healthy",
|
|
141
|
-
supportsTools: true,
|
|
142
|
-
supportsStreaming: true,
|
|
143
|
-
supportsJson: true,
|
|
144
|
-
supportsImages: false,
|
|
145
|
-
contextWindowTokens: 16_384,
|
|
146
|
-
maxOutputTokens: 4_096,
|
|
147
|
-
estimatedCostUsd: 0,
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
providerId: "openrouter",
|
|
151
|
-
modelId: "openai/gpt-4.1-mini",
|
|
152
|
-
displayName: "GPT-4.1 Mini (OpenRouter)",
|
|
153
|
-
family: "fast-coder",
|
|
154
|
-
authTier: "api-key",
|
|
155
|
-
authScope: "third-party",
|
|
156
|
-
health: "healthy",
|
|
157
|
-
supportsTools: true,
|
|
158
|
-
supportsStreaming: true,
|
|
159
|
-
supportsJson: true,
|
|
160
|
-
supportsImages: false,
|
|
161
|
-
contextWindowTokens: 128_000,
|
|
162
|
-
maxOutputTokens: 16_384,
|
|
163
|
-
estimatedCostUsd: 0.005,
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
// local-coder family (local preferred; still include subscription / api-key siblings)
|
|
167
|
-
{
|
|
168
|
-
providerId: "ollama",
|
|
169
|
-
modelId: "deepseek-coder-v2:lite",
|
|
170
|
-
displayName: "DeepSeek Coder Lite (local)",
|
|
171
|
-
family: "local-coder",
|
|
172
|
-
authTier: "local",
|
|
173
|
-
authScope: "first-party",
|
|
174
|
-
health: "healthy",
|
|
175
|
-
supportsTools: true,
|
|
176
|
-
supportsStreaming: true,
|
|
177
|
-
supportsJson: true,
|
|
178
|
-
supportsImages: false,
|
|
179
|
-
contextWindowTokens: 16_384,
|
|
180
|
-
maxOutputTokens: 4_096,
|
|
181
|
-
estimatedCostUsd: 0,
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
providerId: "gemini-subscription",
|
|
185
|
-
modelId: "gemini-2.5-flash",
|
|
186
|
-
displayName: "Gemini Flash (subscription)",
|
|
187
|
-
family: "local-coder",
|
|
188
|
-
authTier: "subscription",
|
|
189
|
-
authScope: "first-party",
|
|
190
|
-
subscriptionStatus: "active",
|
|
191
|
-
health: "healthy",
|
|
192
|
-
supportsTools: true,
|
|
193
|
-
supportsStreaming: true,
|
|
194
|
-
supportsJson: true,
|
|
195
|
-
supportsImages: false,
|
|
196
|
-
contextWindowTokens: 1_000_000,
|
|
197
|
-
maxOutputTokens: 8_192,
|
|
198
|
-
estimatedCostUsd: 0,
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
providerId: "openrouter",
|
|
202
|
-
modelId: "deepseek/deepseek-coder",
|
|
203
|
-
displayName: "DeepSeek Coder (OpenRouter)",
|
|
204
|
-
family: "local-coder",
|
|
205
|
-
authTier: "api-key",
|
|
206
|
-
authScope: "third-party",
|
|
207
|
-
health: "healthy",
|
|
208
|
-
supportsTools: true,
|
|
209
|
-
supportsStreaming: true,
|
|
210
|
-
supportsJson: true,
|
|
211
|
-
supportsImages: false,
|
|
212
|
-
contextWindowTokens: 64_000,
|
|
213
|
-
maxOutputTokens: 8_192,
|
|
214
|
-
estimatedCostUsd: 0.002,
|
|
215
|
-
},
|
|
216
|
-
|
|
217
|
-
// vision-helper
|
|
218
|
-
{
|
|
219
|
-
providerId: "claude-subscription",
|
|
220
|
-
modelId: "claude-sonnet-4-vision",
|
|
221
|
-
displayName: "Claude Vision (subscription)",
|
|
222
|
-
family: "vision-helper",
|
|
223
|
-
authTier: "subscription",
|
|
224
|
-
authScope: "first-party",
|
|
225
|
-
subscriptionStatus: "active",
|
|
226
|
-
health: "healthy",
|
|
227
|
-
supportsTools: true,
|
|
228
|
-
supportsStreaming: true,
|
|
229
|
-
supportsJson: true,
|
|
230
|
-
supportsImages: true,
|
|
231
|
-
contextWindowTokens: 200_000,
|
|
232
|
-
maxOutputTokens: 16_384,
|
|
233
|
-
estimatedCostUsd: 0,
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
providerId: "openrouter",
|
|
237
|
-
modelId: "openai/gpt-4o",
|
|
238
|
-
displayName: "GPT-4o Vision (api-key)",
|
|
239
|
-
family: "vision-helper",
|
|
240
|
-
authTier: "api-key",
|
|
241
|
-
authScope: "third-party",
|
|
242
|
-
health: "healthy",
|
|
243
|
-
supportsTools: true,
|
|
244
|
-
supportsStreaming: true,
|
|
245
|
-
supportsJson: true,
|
|
246
|
-
supportsImages: true,
|
|
247
|
-
contextWindowTokens: 128_000,
|
|
248
|
-
maxOutputTokens: 16_384,
|
|
249
|
-
estimatedCostUsd: 0.04,
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
providerId: "ollama",
|
|
253
|
-
modelId: "llava:latest",
|
|
254
|
-
displayName: "LLaVA (local vision)",
|
|
255
|
-
family: "vision-helper",
|
|
256
|
-
authTier: "local",
|
|
257
|
-
authScope: "first-party",
|
|
258
|
-
health: "healthy",
|
|
259
|
-
supportsTools: false,
|
|
260
|
-
supportsStreaming: true,
|
|
261
|
-
supportsJson: false,
|
|
262
|
-
supportsImages: true,
|
|
263
|
-
contextWindowTokens: 4_096,
|
|
264
|
-
maxOutputTokens: 2_048,
|
|
265
|
-
estimatedCostUsd: 0,
|
|
266
|
-
},
|
|
267
|
-
|
|
268
|
-
// Degraded / unconfigured samples for status tests
|
|
269
|
-
{
|
|
270
|
-
providerId: "claude-subscription",
|
|
271
|
-
modelId: "claude-opus-4",
|
|
272
|
-
displayName: "Claude Opus (subscription exhausted)",
|
|
273
|
-
family: "frontier-coder",
|
|
274
|
-
authTier: "subscription",
|
|
275
|
-
authScope: "first-party",
|
|
276
|
-
subscriptionStatus: "exhausted",
|
|
277
|
-
health: "degraded",
|
|
278
|
-
supportsTools: true,
|
|
279
|
-
supportsStreaming: true,
|
|
280
|
-
supportsJson: true,
|
|
281
|
-
supportsImages: true,
|
|
282
|
-
contextWindowTokens: 200_000,
|
|
283
|
-
maxOutputTokens: 32_000,
|
|
284
|
-
estimatedCostUsd: 0,
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
providerId: "codex-subscription",
|
|
288
|
-
modelId: "o3",
|
|
289
|
-
displayName: "o3 (subscription unconfigured)",
|
|
290
|
-
family: "fast-coder",
|
|
291
|
-
authTier: "subscription",
|
|
292
|
-
authScope: "first-party",
|
|
293
|
-
subscriptionStatus: "unconfigured",
|
|
294
|
-
health: "dead",
|
|
295
|
-
supportsTools: true,
|
|
296
|
-
supportsStreaming: true,
|
|
297
|
-
supportsJson: true,
|
|
298
|
-
supportsImages: false,
|
|
299
|
-
contextWindowTokens: 200_000,
|
|
300
|
-
maxOutputTokens: 32_000,
|
|
301
|
-
estimatedCostUsd: 0,
|
|
302
|
-
},
|
|
303
|
-
] as const;
|
|
304
|
-
|
|
305
|
-
export interface LoadCatalogOptions {
|
|
306
|
-
/** Optional filter by provider id. */
|
|
307
|
-
providerIds?: string[];
|
|
308
|
-
/** Optional filter by logical family. */
|
|
309
|
-
families?: LogicalModelFamily[];
|
|
310
|
-
/** Optional filter by auth tier. */
|
|
311
|
-
authTiers?: AuthTier[];
|
|
312
|
-
/** Include degraded/dead by default true. */
|
|
313
|
-
includeUnhealthy?: boolean;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
export function loadStaticCatalog(
|
|
317
|
-
options: LoadCatalogOptions = {},
|
|
318
|
-
): CatalogEntry[] {
|
|
319
|
-
const includeUnhealthy = options.includeUnhealthy ?? true;
|
|
320
|
-
return STATIC_CATALOG.filter((entry) => {
|
|
321
|
-
if (
|
|
322
|
-
options.providerIds &&
|
|
323
|
-
!options.providerIds.includes(entry.providerId)
|
|
324
|
-
) {
|
|
325
|
-
return false;
|
|
326
|
-
}
|
|
327
|
-
if (options.families && !options.families.includes(entry.family)) {
|
|
328
|
-
return false;
|
|
329
|
-
}
|
|
330
|
-
if (options.authTiers && !options.authTiers.includes(entry.authTier)) {
|
|
331
|
-
return false;
|
|
332
|
-
}
|
|
333
|
-
if (!includeUnhealthy && entry.health !== "healthy") {
|
|
334
|
-
return false;
|
|
335
|
-
}
|
|
336
|
-
return true;
|
|
337
|
-
}).map((e) => ({ ...e }));
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
export function catalogToCandidates(
|
|
341
|
-
entries: readonly CatalogEntry[] = STATIC_CATALOG,
|
|
342
|
-
): ProviderCandidate[] {
|
|
343
|
-
return entries.map((e) => ({
|
|
344
|
-
providerId: e.providerId,
|
|
345
|
-
modelId: e.modelId,
|
|
346
|
-
displayName: e.displayName,
|
|
347
|
-
authTier: e.authTier,
|
|
348
|
-
authScope: e.authScope,
|
|
349
|
-
subscriptionStatus: e.subscriptionStatus,
|
|
350
|
-
health: e.health,
|
|
351
|
-
supportsTools: e.supportsTools,
|
|
352
|
-
supportsStreaming: e.supportsStreaming,
|
|
353
|
-
supportsJson: e.supportsJson,
|
|
354
|
-
supportsImages: e.supportsImages,
|
|
355
|
-
contextWindowTokens: e.contextWindowTokens,
|
|
356
|
-
maxOutputTokens: e.maxOutputTokens,
|
|
357
|
-
estimatedCostUsd: e.estimatedCostUsd,
|
|
358
|
-
}));
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/** Families that must expose all three auth tiers for offline preference tests. */
|
|
362
|
-
export const MULTI_TIER_FAMILIES: readonly LogicalModelFamily[] = [
|
|
363
|
-
"frontier-coder",
|
|
364
|
-
"fast-coder",
|
|
365
|
-
"local-coder",
|
|
366
|
-
"vision-helper",
|
|
367
|
-
];
|
|
368
|
-
|
|
369
|
-
export function familyAuthTiers(family: LogicalModelFamily): Set<AuthTier> {
|
|
370
|
-
const tiers = new Set<AuthTier>();
|
|
371
|
-
for (const e of STATIC_CATALOG) {
|
|
372
|
-
if (e.family === family) tiers.add(e.authTier);
|
|
373
|
-
}
|
|
374
|
-
return tiers;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// ---------------------------------------------------------------------------
|
|
378
|
-
// Built-in catalog: merge static entries with built-in provider metadata.
|
|
379
|
-
// Keeps existing static loading behavior intact; subscription-first invariant
|
|
380
|
-
// is preserved because builtin entries only add api-key/local candidates and
|
|
381
|
-
// never replace the subscription rows already present in STATIC_CATALOG.
|
|
382
|
-
// ---------------------------------------------------------------------------
|
|
383
|
-
|
|
384
|
-
export interface LoadBuiltinCatalogOptions {
|
|
385
|
-
/** Per-provider overrides keyed by providerId (mirrors config providers map). */
|
|
386
|
-
providers?: BuiltinCatalogConfig;
|
|
387
|
-
/** Optional filter by logical family. */
|
|
388
|
-
families?: LogicalModelFamily[];
|
|
389
|
-
/** Optional filter by auth tier. */
|
|
390
|
-
authTiers?: AuthTier[];
|
|
391
|
-
/** Include degraded/dead by default true. */
|
|
392
|
-
includeUnhealthy?: boolean;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/** Flatten built-in provider metadata into catalog rows (copies). */
|
|
396
|
-
function builtinProvidersToEntries(
|
|
397
|
-
providers: readonly BuiltinProviderEntry[],
|
|
398
|
-
): CatalogEntry[] {
|
|
399
|
-
const entries: CatalogEntry[] = [];
|
|
400
|
-
for (const provider of providers) {
|
|
401
|
-
for (const model of provider.knownModels) {
|
|
402
|
-
entries.push({
|
|
403
|
-
providerId: provider.providerId,
|
|
404
|
-
modelId: model.modelId,
|
|
405
|
-
displayName:
|
|
406
|
-
model.displayName ??
|
|
407
|
-
`${provider.displayName} ${model.modelId}`,
|
|
408
|
-
family: model.family,
|
|
409
|
-
authTier: provider.defaultAuthTier,
|
|
410
|
-
authScope: provider.defaultAuthScope,
|
|
411
|
-
health: "healthy",
|
|
412
|
-
supportsTools: model.supportsTools ?? true,
|
|
413
|
-
supportsStreaming: model.supportsStreaming ?? true,
|
|
414
|
-
supportsJson: model.supportsJson ?? true,
|
|
415
|
-
supportsImages: model.supportsImages ?? false,
|
|
416
|
-
contextWindowTokens: model.contextWindowTokens,
|
|
417
|
-
maxOutputTokens: model.maxOutputTokens,
|
|
418
|
-
notes: provider.subscriptionSurfaceNote,
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
return entries;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* Structured dedup key for catalog rows. Serializes the discriminating fields
|
|
427
|
-
* as a JSON tuple so there is no ad hoc delimiter parsing or collision risk.
|
|
428
|
-
*/
|
|
429
|
-
function catalogEntryDedupKey(entry: CatalogEntry): string {
|
|
430
|
-
return JSON.stringify([
|
|
431
|
-
entry.providerId,
|
|
432
|
-
entry.modelId,
|
|
433
|
-
entry.authTier,
|
|
434
|
-
entry.family,
|
|
435
|
-
]);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
/**
|
|
439
|
-
* Load the merged built-in catalog: static rows plus built-in provider
|
|
440
|
-
* metadata, with provider enable/disable and base URL overrides applied.
|
|
441
|
-
* Existing static loading behavior (loadStaticCatalog) is unchanged.
|
|
442
|
-
*/
|
|
443
|
-
export function loadBuiltinCatalog(
|
|
444
|
-
options: LoadBuiltinCatalogOptions = {},
|
|
445
|
-
): CatalogEntry[] {
|
|
446
|
-
const includeUnhealthy = options.includeUnhealthy ?? true;
|
|
447
|
-
const config = options.providers ?? {};
|
|
448
|
-
const providerEnabled = (providerId: string): boolean =>
|
|
449
|
-
config[providerId]?.enabled ?? true;
|
|
450
|
-
|
|
451
|
-
const builtinEntries = builtinProvidersToEntries(
|
|
452
|
-
selectBuiltinProviders(config),
|
|
453
|
-
);
|
|
454
|
-
|
|
455
|
-
// Merge static catalog with built-in entries, applying the provider
|
|
456
|
-
// enable/disable filter to both sources and deduping identical rows.
|
|
457
|
-
const merged: CatalogEntry[] = [];
|
|
458
|
-
const seen = new Set<string>();
|
|
459
|
-
const sources: readonly CatalogEntry[] = [
|
|
460
|
-
...STATIC_CATALOG.map((entry) => ({ ...entry })),
|
|
461
|
-
...builtinEntries,
|
|
462
|
-
];
|
|
463
|
-
for (const entry of sources) {
|
|
464
|
-
if (!providerEnabled(entry.providerId)) continue;
|
|
465
|
-
const key = catalogEntryDedupKey(entry);
|
|
466
|
-
if (seen.has(key)) continue;
|
|
467
|
-
seen.add(key);
|
|
468
|
-
merged.push(entry);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
return merged.filter((entry) => {
|
|
472
|
-
if (options.families && !options.families.includes(entry.family)) {
|
|
473
|
-
return false;
|
|
474
|
-
}
|
|
475
|
-
if (options.authTiers && !options.authTiers.includes(entry.authTier)) {
|
|
476
|
-
return false;
|
|
477
|
-
}
|
|
478
|
-
if (!includeUnhealthy && entry.health !== "healthy") {
|
|
479
|
-
return false;
|
|
480
|
-
}
|
|
481
|
-
return true;
|
|
482
|
-
});
|
|
483
|
-
}
|