@juspay/neurolink 12.5.0 → 12.5.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 (46) hide show
  1. package/CHANGELOG.md +1 -5
  2. package/dist/adapters/providerImageAdapter.js +43 -19
  3. package/dist/browser/neurolink.min.js +414 -414
  4. package/dist/cli/commands/setup.d.ts +12 -7
  5. package/dist/cli/commands/setup.js +17 -16
  6. package/dist/constants/contextWindows.js +23 -95
  7. package/dist/constants/enums.d.ts +111 -216
  8. package/dist/constants/enums.js +124 -240
  9. package/dist/factories/providerDescriptors.d.ts +2 -4
  10. package/dist/factories/providerDescriptors.js +83 -127
  11. package/dist/models/manifestRegistry.js +53 -4
  12. package/dist/providers/catalog/cerebras.json +75 -0
  13. package/dist/providers/catalog/cloudflare.json +121 -0
  14. package/dist/providers/catalog/fireworks.json +124 -0
  15. package/dist/providers/catalog/groq.json +127 -0
  16. package/dist/providers/catalog/index.generated.d.ts +3 -0
  17. package/dist/providers/catalog/index.generated.js +33 -0
  18. package/dist/providers/catalog/loader.d.ts +6 -0
  19. package/dist/providers/catalog/loader.js +115 -0
  20. package/dist/providers/catalog/mistral.json +244 -0
  21. package/dist/providers/catalog/perplexity.json +103 -0
  22. package/dist/providers/catalog/provider-catalog.schema.json +351 -0
  23. package/dist/providers/catalog/sambanova.json +129 -0
  24. package/dist/providers/catalog/schema.d.ts +123 -0
  25. package/dist/providers/catalog/schema.js +310 -0
  26. package/dist/providers/catalog/together-ai.json +172 -0
  27. package/dist/providers/catalog/xai.json +108 -0
  28. package/dist/providers/openaiCompatCatalog.d.ts +13 -13
  29. package/dist/providers/openaiCompatCatalog.js +15 -326
  30. package/dist/types/index.d.ts +2 -0
  31. package/dist/types/index.js +2 -0
  32. package/dist/types/providerCatalog.d.ts +149 -0
  33. package/dist/types/providerCatalog.generated.d.ts +2 -0
  34. package/dist/types/providerCatalog.generated.js +1 -0
  35. package/dist/types/providerCatalog.js +7 -0
  36. package/dist/types/providers.d.ts +14 -14
  37. package/dist/utils/modelChoices.d.ts +11 -3
  38. package/dist/utils/modelChoices.js +84 -190
  39. package/dist/utils/pricing.js +92 -127
  40. package/dist/utils/providerConfig.d.ts +1 -1
  41. package/dist/utils/providerConfig.js +24 -108
  42. package/package.json +2 -1
  43. package/dist/models/manifests/cerebras.d.ts +0 -9
  44. package/dist/models/manifests/cerebras.js +0 -19
  45. package/dist/models/manifests/sambanova.d.ts +0 -11
  46. package/dist/models/manifests/sambanova.js +0 -42
@@ -1,11 +1,4 @@
1
- import { AIProviderName } from "../constants/enums.js";
2
- import { CerebrasModels, SambanovaModels, CloudflareModels, FireworksModels, GroqModels, MistralModels, PerplexityModels, TogetherAIModels, XaiModels, } from "../constants/enums.js";
3
- import { AuthenticationError, InvalidModelError, ProviderError, } from "../types/index.js";
4
- import { DEFAULT_ERROR_RULES } from "../utils/errorClassifier.js";
5
- import { createCerebrasConfig, createSambanovaConfig, createCloudflareConfig, createFireworksConfig, createGroqConfig, createMistralConfig, createPerplexityConfig, createTogetherAIConfig, createXaiConfig, } from "../utils/providerConfig.js";
6
- function buildCloudflareBaseURL(accountId) {
7
- return `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1`;
8
- }
1
+ import { buildCatalogEntries } from "./catalog/loader.js";
9
2
  /**
10
3
  * Config-driven catalog of the 9 zero-quirk OpenAI-compatible providers.
11
4
  * Each entry fully replaces what used to be a hand-written
@@ -13,323 +6,19 @@ function buildCloudflareBaseURL(accountId) {
13
6
  * for the class that reads these entries, and providerRegistry.ts for the
14
7
  * registration loop that consumes this array.
15
8
  *
16
- * `errorRules` mirrors each provider's LIVE `formatProviderError` rule array
17
- * (post plan-07/wave-2 migration), not the original hand-rolled ladder these
18
- * providers had when plan 05 was first drafted: every provider below now
19
- * keeps only its bespoke rule(s) auth, plus Groq's model_decommissioned and
20
- * xAI's insufficient_quota before spreading the SAME exported
21
- * `DEFAULT_ERROR_RULES` constant that the live subclasses spread (never an
22
- * inlined copy, so this catalog cannot drift from that table independently).
23
- * See plan-05/progress.md Ruling R4 for the full rationale.
9
+ * The entries themselves are derived from the JSON catalog
10
+ * (src/lib/providers/catalog/<id>.json) via buildCatalogEntries() that
11
+ * JSON is now the single source of truth for these 9 providers' identity,
12
+ * models, error rules and wire config. See
13
+ * src/lib/providers/catalog/loader.ts for the derivation logic and
14
+ * docs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md for the
15
+ * authoring format.
24
16
  *
25
- * To add a new zero-quirk OpenAI-compatible provider: add one entry here.
26
- * Do NOT add a provider here if it needs any hook override beyond the 3
27
- * mandatory ones (getProviderName/getDefaultModel/formatProviderError)
28
- * write a dedicated subclass instead (see deepseek.ts, azureOpenai.ts, and
29
- * Task 14's docs task for the deciding criteria).
17
+ * To add a new zero-quirk OpenAI-compatible provider: add one JSON file
18
+ * under src/lib/providers/catalog/ (see provider-catalog.schema.json) and
19
+ * run `pnpm run codegen:catalog`. Do NOT add a provider here if it needs
20
+ * any hook override beyond the 3 mandatory ones
21
+ * (getProviderName/getDefaultModel/formatProviderError) write a
22
+ * dedicated subclass instead (see deepseek.ts, azureOpenai.ts).
30
23
  */
31
- export const OPENAI_COMPAT_CATALOG = [
32
- {
33
- providerName: AIProviderName.SAMBANOVA,
34
- aliases: ["sambanova"],
35
- apiKeyEnvVar: "SAMBANOVA_API_KEY",
36
- baseURLEnvVar: "SAMBANOVA_BASE_URL",
37
- defaultBaseURL: "https://api.sambanova.ai/v1",
38
- configOptions: createSambanovaConfig(),
39
- modelEnvVar: "SAMBANOVA_MODEL",
40
- defaultModel: SambanovaModels.META_LLAMA_3_3_70B_INSTRUCT,
41
- registryDefaultModel: SambanovaModels.META_LLAMA_3_3_70B_INSTRUCT,
42
- registryDefaultModelChecksEnvVar: true,
43
- fallbackModelName: SambanovaModels.GPT_OSS_120B,
44
- fallbackModels: [
45
- SambanovaModels.META_LLAMA_3_3_70B_INSTRUCT,
46
- SambanovaModels.GPT_OSS_120B,
47
- ],
48
- errorRules: [
49
- {
50
- // Probed live 2026-08-27: a bad key gets HTTP 401 with an
51
- // OpenAI-shaped body {"error":{"message":"Incorrect API key
52
- // provided: ...","type":"authentication_error","code":
53
- // "invalid_api_key"}}.
54
- match: (ctx) => ctx.statusCode === 401 ||
55
- /invalid_api_key|Incorrect API key|authentication_error/i.test(ctx.message),
56
- errorClass: AuthenticationError,
57
- message: "Invalid SambaNova API key. Check SAMBANOVA_API_KEY. Get one at https://cloud.sambanova.ai/apis",
58
- },
59
- {
60
- // Probed live 2026-08-27: a zero-balance account gets HTTP 402 with
61
- // {"error":{"balance_units":0,"code":"PAYMENT_METHOD_REQUIRED",
62
- // "billing_portal_url":"https://cloud.sambanova.ai/plans/billing"}}.
63
- // New accounts have NO free allowance — credits must be purchased.
64
- match: (ctx) => ctx.statusCode === 402 ||
65
- /PAYMENT_METHOD_REQUIRED|balance_units/i.test(ctx.message),
66
- errorClass: ProviderError,
67
- message: "SambaNova account has no credits (new accounts have no free allowance). Add a payment method and purchase credits at https://cloud.sambanova.ai/plans/billing",
68
- },
69
- ...DEFAULT_ERROR_RULES,
70
- ],
71
- },
72
- {
73
- providerName: AIProviderName.CEREBRAS,
74
- aliases: ["cerebras"],
75
- apiKeyEnvVar: "CEREBRAS_API_KEY",
76
- baseURLEnvVar: "CEREBRAS_BASE_URL",
77
- defaultBaseURL: "https://api.cerebras.ai/v1",
78
- configOptions: createCerebrasConfig(),
79
- modelEnvVar: "CEREBRAS_MODEL",
80
- defaultModel: CerebrasModels.GPT_OSS_120B,
81
- registryDefaultModel: CerebrasModels.GPT_OSS_120B,
82
- registryDefaultModelChecksEnvVar: true,
83
- fallbackModelName: CerebrasModels.GEMMA_4_31B,
84
- fallbackModels: [CerebrasModels.GPT_OSS_120B, CerebrasModels.GEMMA_4_31B],
85
- errorRules: [
86
- {
87
- // Probed live 2026-08-26: a bad key gets HTTP 401 with body
88
- // {"message":"Wrong API Key","type":"invalid_request_error",
89
- // "param":"api_key","code":"wrong_api_key"}.
90
- match: (ctx) => ctx.statusCode === 401 ||
91
- /wrong_api_key|Wrong API Key|invalid_api_key/i.test(ctx.message),
92
- errorClass: AuthenticationError,
93
- message: "Invalid Cerebras API key. Check CEREBRAS_API_KEY. Get one at https://cloud.cerebras.ai",
94
- },
95
- ...DEFAULT_ERROR_RULES,
96
- ],
97
- },
98
- {
99
- providerName: AIProviderName.GROQ,
100
- aliases: ["groq"],
101
- apiKeyEnvVar: "GROQ_API_KEY",
102
- baseURLEnvVar: "GROQ_BASE_URL",
103
- defaultBaseURL: "https://api.groq.com/openai/v1",
104
- configOptions: createGroqConfig(),
105
- modelEnvVar: "GROQ_MODEL",
106
- defaultModel: GroqModels.LLAMA_3_3_70B_VERSATILE,
107
- registryDefaultModel: GroqModels.LLAMA_3_3_70B_VERSATILE,
108
- registryDefaultModelChecksEnvVar: true,
109
- fallbackModelName: GroqModels.LLAMA_3_1_8B_INSTANT,
110
- fallbackModels: [
111
- GroqModels.LLAMA_3_3_70B_VERSATILE,
112
- GroqModels.LLAMA_3_1_8B_INSTANT,
113
- GroqModels.GEMMA_2_9B_IT,
114
- GroqModels.MIXTRAL_8X7B_32768,
115
- GroqModels.LLAMA_3_2_90B_VISION_PREVIEW,
116
- GroqModels.LLAMA_3_2_11B_VISION_PREVIEW,
117
- ],
118
- // Groq's pre-migration subclass intercepted TimeoutError itself and
119
- // returned a plain ProviderError, ahead of classifyProviderError's own
120
- // non-overridable TimeoutError -> NetworkError default. Expressed here
121
- // as data — see OpenAICompatCatalogEntry.timeoutErrorClass and
122
- // ConfiguredOpenAICompatProvider.formatProviderError, which consults
123
- // this field before ever delegating to the shared classifier. No other
124
- // entry in this catalog sets it, so every other provider still gets
125
- // the classifier's unmodified default.
126
- timeoutErrorClass: ProviderError,
127
- errorRules: [
128
- {
129
- match: (ctx) => ctx.statusCode === 401 ||
130
- /Invalid API key|Authentication|invalid_api_key/i.test(ctx.message),
131
- errorClass: AuthenticationError,
132
- message: "Invalid Groq API key. Check GROQ_API_KEY. Get one at https://console.groq.com/keys",
133
- },
134
- {
135
- match: (ctx) => /model_decommissioned/i.test(ctx.message),
136
- errorClass: InvalidModelError,
137
- message: (ctx) => `Groq model '${ctx.modelName}' was decommissioned. Pick a current model from https://console.groq.com/docs/models.`,
138
- },
139
- ...DEFAULT_ERROR_RULES,
140
- ],
141
- },
142
- {
143
- providerName: AIProviderName.XAI,
144
- aliases: ["xai", "grok"],
145
- apiKeyEnvVar: "XAI_API_KEY",
146
- baseURLEnvVar: "XAI_BASE_URL",
147
- defaultBaseURL: "https://api.x.ai/v1",
148
- configOptions: createXaiConfig(),
149
- modelEnvVar: "XAI_MODEL",
150
- defaultModel: XaiModels.GROK_3,
151
- registryDefaultModel: XaiModels.GROK_3,
152
- registryDefaultModelChecksEnvVar: true,
153
- fallbackModelName: XaiModels.GROK_3_MINI,
154
- fallbackModels: [
155
- XaiModels.GROK_3,
156
- XaiModels.GROK_3_MINI,
157
- XaiModels.GROK_2_LATEST,
158
- XaiModels.GROK_2_VISION_LATEST,
159
- XaiModels.GROK_BETA,
160
- ],
161
- errorRules: [
162
- {
163
- match: (ctx) => ctx.statusCode === 401 ||
164
- /Invalid API key|Authentication|invalid_api_key/i.test(ctx.message),
165
- errorClass: AuthenticationError,
166
- message: "Invalid xAI API key. Please check your XAI_API_KEY environment variable. Get one at https://console.x.ai/",
167
- },
168
- {
169
- match: (ctx) => /insufficient_quota|quota exceeded/i.test(ctx.message),
170
- errorClass: ProviderError,
171
- message: "xAI account has insufficient quota. Top up at https://console.x.ai/",
172
- },
173
- ...DEFAULT_ERROR_RULES,
174
- ],
175
- },
176
- {
177
- providerName: AIProviderName.TOGETHER_AI,
178
- aliases: ["together-ai", "together"],
179
- apiKeyEnvVar: "TOGETHER_API_KEY",
180
- baseURLEnvVar: "TOGETHER_BASE_URL",
181
- defaultBaseURL: "https://api.together.xyz/v1",
182
- configOptions: createTogetherAIConfig(),
183
- modelEnvVar: "TOGETHER_MODEL",
184
- defaultModel: TogetherAIModels.LLAMA_3_3_70B_INSTRUCT_TURBO,
185
- registryDefaultModel: TogetherAIModels.LLAMA_3_3_70B_INSTRUCT_TURBO,
186
- registryDefaultModelChecksEnvVar: true,
187
- fallbackModelName: TogetherAIModels.LLAMA_3_1_8B_INSTRUCT_TURBO,
188
- fallbackModels: [
189
- TogetherAIModels.LLAMA_3_3_70B_INSTRUCT_TURBO,
190
- TogetherAIModels.LLAMA_3_1_405B_INSTRUCT_TURBO,
191
- TogetherAIModels.LLAMA_3_1_70B_INSTRUCT_TURBO,
192
- TogetherAIModels.LLAMA_3_1_8B_INSTRUCT_TURBO,
193
- TogetherAIModels.MIXTRAL_8X22B_INSTRUCT,
194
- TogetherAIModels.QWEN_2_5_72B_INSTRUCT_TURBO,
195
- TogetherAIModels.DEEPSEEK_R1,
196
- TogetherAIModels.DEEPSEEK_V3,
197
- ],
198
- errorRules: [
199
- {
200
- match: (ctx) => ctx.statusCode === 401 ||
201
- /Invalid API key|Authentication/i.test(ctx.message),
202
- errorClass: AuthenticationError,
203
- message: "Invalid Together AI API key. Get one at https://api.together.xyz/settings/api-keys",
204
- },
205
- ...DEFAULT_ERROR_RULES,
206
- ],
207
- },
208
- {
209
- providerName: AIProviderName.FIREWORKS,
210
- aliases: ["fireworks"],
211
- apiKeyEnvVar: "FIREWORKS_API_KEY",
212
- baseURLEnvVar: "FIREWORKS_BASE_URL",
213
- defaultBaseURL: "https://api.fireworks.ai/inference/v1",
214
- configOptions: createFireworksConfig(),
215
- modelEnvVar: "FIREWORKS_MODEL",
216
- defaultModel: FireworksModels.DEEPSEEK_V4_PRO,
217
- registryDefaultModel: FireworksModels.DEEPSEEK_V4_PRO,
218
- registryDefaultModelChecksEnvVar: true,
219
- fallbackModelName: FireworksModels.DEEPSEEK_V4_PRO,
220
- fallbackModels: [
221
- FireworksModels.DEEPSEEK_V4_PRO,
222
- FireworksModels.GLM_5P1,
223
- FireworksModels.GLM_5,
224
- FireworksModels.KIMI_K2P6,
225
- FireworksModels.KIMI_K2P5,
226
- FireworksModels.GPT_OSS_120B,
227
- ],
228
- errorRules: [
229
- {
230
- match: (ctx) => ctx.statusCode === 401 ||
231
- /Invalid API key|Authentication/i.test(ctx.message),
232
- errorClass: AuthenticationError,
233
- message: "Invalid Fireworks API key. Get one at https://fireworks.ai/account/api-keys",
234
- },
235
- ...DEFAULT_ERROR_RULES,
236
- ],
237
- },
238
- {
239
- providerName: AIProviderName.PERPLEXITY,
240
- aliases: ["perplexity", "pplx"],
241
- apiKeyEnvVar: "PERPLEXITY_API_KEY",
242
- baseURLEnvVar: "PERPLEXITY_BASE_URL",
243
- defaultBaseURL: "https://api.perplexity.ai",
244
- configOptions: createPerplexityConfig(),
245
- modelEnvVar: "PERPLEXITY_MODEL",
246
- defaultModel: PerplexityModels.SONAR,
247
- registryDefaultModel: PerplexityModels.SONAR,
248
- registryDefaultModelChecksEnvVar: true,
249
- // Perplexity's live class does NOT override getFallbackModelName() — it
250
- // inherits the base class default "gpt-3.5-turbo". Preserved here
251
- // verbatim, not "fixed" to a Perplexity model — that's a real,
252
- // pre-existing quirk this plan is not authorized to change.
253
- fallbackModelName: "gpt-3.5-turbo",
254
- fallbackModels: [
255
- PerplexityModels.SONAR,
256
- PerplexityModels.SONAR_PRO,
257
- PerplexityModels.SONAR_REASONING,
258
- PerplexityModels.SONAR_REASONING_PRO,
259
- PerplexityModels.SONAR_DEEP_RESEARCH,
260
- ],
261
- errorRules: [
262
- {
263
- match: (ctx) => ctx.statusCode === 401 ||
264
- /Invalid API key|Authentication/i.test(ctx.message),
265
- errorClass: AuthenticationError,
266
- message: "Invalid Perplexity API key. Get one at https://www.perplexity.ai/settings/api",
267
- },
268
- ...DEFAULT_ERROR_RULES,
269
- ],
270
- },
271
- {
272
- providerName: AIProviderName.MISTRAL,
273
- aliases: ["mistral"],
274
- apiKeyEnvVar: "MISTRAL_API_KEY",
275
- baseURLEnvVar: "MISTRAL_BASE_URL",
276
- defaultBaseURL: "https://api.mistral.ai/v1",
277
- configOptions: createMistralConfig(),
278
- modelEnvVar: "MISTRAL_MODEL",
279
- defaultModel: MistralModels.MISTRAL_SMALL_2506,
280
- // The one documented registry-vs-class default-model quirk (see this
281
- // plan's "Design reference" section): the registry passes the bare
282
- // literal MISTRAL_LARGE_LATEST with no env-var check, while
283
- // MistralProvider.getDefaultModel() checks MISTRAL_MODEL and defaults to
284
- // MISTRAL_SMALL_2506. Preserved exactly, not reconciled.
285
- registryDefaultModel: MistralModels.MISTRAL_LARGE_LATEST,
286
- registryDefaultModelChecksEnvVar: false,
287
- fallbackModelName: MistralModels.MISTRAL_SMALL_2506,
288
- fallbackModels: [
289
- MistralModels.MISTRAL_SMALL_2506,
290
- MistralModels.MISTRAL_LARGE_LATEST,
291
- ],
292
- errorRules: [
293
- {
294
- match: (ctx) => ctx.statusCode === 401 ||
295
- /API_KEY_INVALID|Invalid API key|Unauthorized/i.test(ctx.message),
296
- errorClass: AuthenticationError,
297
- message: "Invalid Mistral API key. Please check your MISTRAL_API_KEY environment variable.",
298
- },
299
- ...DEFAULT_ERROR_RULES,
300
- ],
301
- },
302
- {
303
- providerName: AIProviderName.CLOUDFLARE,
304
- aliases: ["cloudflare", "workers-ai", "cf-ai"],
305
- apiKeyEnvVar: "CLOUDFLARE_API_KEY",
306
- computedBaseURL: {
307
- envVar: "CLOUDFLARE_ACCOUNT_ID",
308
- missingValueMessage: "CLOUDFLARE_ACCOUNT_ID is required (or pass credentials.cloudflare.accountId). Get the account id from https://dash.cloudflare.com/",
309
- build: buildCloudflareBaseURL,
310
- },
311
- configOptions: createCloudflareConfig(),
312
- modelEnvVar: "CLOUDFLARE_MODEL",
313
- defaultModel: CloudflareModels.LLAMA_3_3_70B_FAST,
314
- registryDefaultModel: CloudflareModels.LLAMA_3_3_70B_FAST,
315
- registryDefaultModelChecksEnvVar: true,
316
- fallbackModelName: CloudflareModels.LLAMA_3_1_8B_FAST,
317
- fallbackModels: [
318
- CloudflareModels.LLAMA_3_3_70B_FAST,
319
- CloudflareModels.LLAMA_3_1_70B_INSTRUCT,
320
- CloudflareModels.LLAMA_3_1_8B_FAST,
321
- CloudflareModels.LLAMA_3_2_11B_VISION,
322
- CloudflareModels.MISTRAL_7B_INSTRUCT_V0_2,
323
- CloudflareModels.QWEN_1P5_14B_CHAT_AWQ,
324
- ],
325
- errorRules: [
326
- {
327
- match: (ctx) => ctx.statusCode === 401 ||
328
- /Invalid API key|Authentication/i.test(ctx.message),
329
- errorClass: AuthenticationError,
330
- message: "Invalid Cloudflare API key. Use a token with Workers AI Read+Write scope. Get one at https://dash.cloudflare.com/profile/api-tokens",
331
- },
332
- ...DEFAULT_ERROR_RULES,
333
- ],
334
- },
335
- ];
24
+ export const OPENAI_COMPAT_CATALOG = buildCatalogEntries();
@@ -48,6 +48,8 @@ export * from "./observability.js";
48
48
  export * from "./openaiCompatible.js";
49
49
  export * from "./ppt.js";
50
50
  export * from "./processor.js";
51
+ export * from "./providerCatalog.js";
52
+ export * from "./providerCatalog.generated.js";
51
53
  export * from "./providers.js";
52
54
  export * from "./proxy.js";
53
55
  export * from "./proxyClient.js";
@@ -52,6 +52,8 @@ export * from "./observability.js";
52
52
  export * from "./openaiCompatible.js";
53
53
  export * from "./ppt.js";
54
54
  export * from "./processor.js";
55
+ export * from "./providerCatalog.js";
56
+ export * from "./providerCatalog.generated.js";
55
57
  export * from "./providers.js";
56
58
  export * from "./proxy.js";
57
59
  export * from "./proxyClient.js";
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Single-JSON provider catalog — the authoring format for Tier-2
3
+ * (zero-quirk OpenAI-compatible) providers. One
4
+ * src/lib/providers/catalog/<id>.json file per provider is the single
5
+ * source of truth; see docs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md.
6
+ */
7
+ export type CatalogPricingPerMTok = {
8
+ input: number;
9
+ output: number;
10
+ cachedInput?: number;
11
+ };
12
+ export type CatalogModelStatus = "production" | "preview" | "retired";
13
+ export type CatalogModelSpec = {
14
+ contextWindow?: number;
15
+ maxOutputTokens?: number;
16
+ pricingPerMTok?: CatalogPricingPerMTok;
17
+ vision: boolean;
18
+ status: CatalogModelStatus;
19
+ description: string;
20
+ /**
21
+ * Enum member name override. Default is the derived constant-case of the
22
+ * model id; REQUIRED where the derived name differs from a pre-existing
23
+ * exported member (public-surface compatibility).
24
+ */
25
+ enumMember?: string;
26
+ };
27
+ export type CatalogWire = {
28
+ baseURL?: string;
29
+ baseURLTemplate?: string;
30
+ extraCredentials?: string[];
31
+ missingCredentialMessage?: string;
32
+ envOverrides?: {
33
+ apiKey?: string;
34
+ baseURL?: string;
35
+ model?: string;
36
+ };
37
+ };
38
+ export type CatalogErrorRuleClass = "authentication" | "rate-limit" | "invalid-model" | "network" | "provider";
39
+ export type CatalogErrorRuleJson = {
40
+ status?: number;
41
+ pattern?: string;
42
+ class: CatalogErrorRuleClass;
43
+ message: string;
44
+ };
45
+ export type CatalogQuirks = {
46
+ timeoutErrorClass?: "provider";
47
+ registryDefaultIgnoresModelEnvVar?: boolean;
48
+ };
49
+ export type CatalogBillingPolicy = "free-tier" | "free-with-card" | "no-free-tier";
50
+ export type CatalogSetup = {
51
+ url: string;
52
+ apiKeyFormat: string | null;
53
+ billingPolicy: CatalogBillingPolicy;
54
+ instructions: string[];
55
+ /**
56
+ * Config-options description shown to callers for this credential.
57
+ * Default: "API key". Set explicitly where the legacy entry's
58
+ * description carries real information a generic "API key" loses
59
+ * (e.g. Cloudflare's "API token (Workers AI Read+Write scope)").
60
+ */
61
+ description?: string;
62
+ };
63
+ export type CatalogProbeEvidence = {
64
+ date: string;
65
+ status?: number;
66
+ code?: string;
67
+ method?: string;
68
+ };
69
+ export type CatalogEvidence = {
70
+ rosterVerified: CatalogProbeEvidence;
71
+ authProbe?: CatalogProbeEvidence;
72
+ billingProbe?: CatalogProbeEvidence;
73
+ liveMatrix: {
74
+ date: string;
75
+ result: string;
76
+ } | null;
77
+ addedInPR: string;
78
+ };
79
+ export type CatalogCapabilities = {
80
+ text: boolean;
81
+ streaming: boolean;
82
+ tools: boolean;
83
+ toolsWithStreaming: boolean;
84
+ structuredOutput: boolean;
85
+ structuredOutputWithTools: boolean;
86
+ embeddings: boolean;
87
+ thinking: boolean;
88
+ };
89
+ export type ProviderCatalogJson = {
90
+ /** Editor-only pointer to provider-catalog.schema.json — accepted and ignored. */
91
+ $schema?: string;
92
+ id: string;
93
+ displayName: string;
94
+ /**
95
+ * Exported <Name>Models enum name override. Default: PascalCase(id) +
96
+ * "Models". REQUIRED where the derived name differs from a pre-existing
97
+ * export ("together-ai" derives "TogetherAiModels"; the legacy export is
98
+ * "TogetherAIModels").
99
+ */
100
+ enumTypeName?: string;
101
+ /**
102
+ * NeurolinkCredentials key override. Default: toCamelCase(id). REQUIRED
103
+ * where the derived key differs from a pre-existing public credential
104
+ * field ("together-ai" derives "togetherAi"; the shipped public key is
105
+ * "together" — renaming it would break any caller passing
106
+ * `credentials: { together: {...} } }`, a public API break rule 5
107
+ * forbids).
108
+ */
109
+ credentialsKey?: string;
110
+ aliases: string[];
111
+ tier: 2;
112
+ wire: CatalogWire;
113
+ models: {
114
+ default: string;
115
+ fallbacks: string[];
116
+ /** Default: fallbacks[1] ?? fallbacks[0]. Set explicitly where the
117
+ * legacy entry differs (behavior preservation — e.g. Groq). */
118
+ fallbackModelName?: string;
119
+ /** Default: models.default. Set explicitly where the legacy entry's
120
+ * registry-level default differs (behavior preservation — Mistral's
121
+ * registryDefaultModel is MISTRAL_LARGE_LATEST while its defaultModel
122
+ * is not). Must be a models.catalog key (validated). */
123
+ registryDefaultModel?: string;
124
+ defaultContextWindow: number;
125
+ defaultMaxOutputTokens: number;
126
+ catalog: Record<string, CatalogModelSpec>;
127
+ /** Ordered curated subset of `catalog` keys for wizard/choice surfaces
128
+ * (e.g. the CLI setup wizard's top-N model picker). When absent, choice
129
+ * surfaces fall back to the full catalog in file order. */
130
+ topModels?: string[];
131
+ /** The live-verified vision-capable model for capability tests, for
132
+ * providers whose `default` model is text-only. Must be a
133
+ * models.catalog key with vision: true (validated). When absent, the
134
+ * first vision:true model in `catalog` file order is used. */
135
+ visionModel?: string;
136
+ /** The live-verified model the capability matrix drives, for providers
137
+ * whose `default` is retired upstream or gated off the testing account
138
+ * (Fireworks serverless deployment, Groq's roster purges). May name a
139
+ * model outside `catalog` — current account reality, not transcribed
140
+ * history. When absent, the matrix drives `default`. Never affects the
141
+ * runtime default. */
142
+ testModel?: string;
143
+ };
144
+ capabilities: CatalogCapabilities;
145
+ errorRules: CatalogErrorRuleJson[];
146
+ quirks?: CatalogQuirks;
147
+ setup: CatalogSetup;
148
+ evidence: CatalogEvidence;
149
+ };
@@ -0,0 +1,2 @@
1
+ export type CatalogProviderName = "cerebras" | "cloudflare" | "fireworks" | "groq" | "mistral" | "perplexity" | "sambanova" | "together-ai" | "xai";
2
+ export type CatalogCredentialKey = "cerebras" | "cloudflare" | "fireworks" | "groq" | "mistral" | "perplexity" | "sambanova" | "together" | "xai";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Single-JSON provider catalog — the authoring format for Tier-2
3
+ * (zero-quirk OpenAI-compatible) providers. One
4
+ * src/lib/providers/catalog/<id>.json file per provider is the single
5
+ * source of truth; see docs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md.
6
+ */
7
+ export {};
@@ -130,10 +130,6 @@ export type NeurolinkCredentials = {
130
130
  apiVersion?: string;
131
131
  useMaxCompletionTokens?: boolean;
132
132
  };
133
- mistral?: {
134
- apiKey?: string;
135
- baseURL?: string;
136
- };
137
133
  huggingFace?: {
138
134
  apiKey?: string;
139
135
  baseURL?: string;
@@ -170,41 +166,45 @@ export type NeurolinkCredentials = {
170
166
  apiKey?: string;
171
167
  baseURL?: string;
172
168
  };
173
- xai?: {
169
+ cerebras?: {
174
170
  apiKey?: string;
175
171
  baseURL?: string;
176
172
  };
177
- groq?: {
173
+ cloudflare?: {
178
174
  apiKey?: string;
179
175
  baseURL?: string;
176
+ accountId?: string;
180
177
  };
181
- cerebras?: {
178
+ fireworks?: {
182
179
  apiKey?: string;
183
180
  baseURL?: string;
184
181
  };
185
- sambanova?: {
182
+ groq?: {
186
183
  apiKey?: string;
187
184
  baseURL?: string;
188
185
  };
189
- cohere?: {
186
+ mistral?: {
190
187
  apiKey?: string;
191
188
  baseURL?: string;
192
189
  };
193
- together?: {
190
+ perplexity?: {
194
191
  apiKey?: string;
195
192
  baseURL?: string;
196
193
  };
197
- fireworks?: {
194
+ sambanova?: {
198
195
  apiKey?: string;
199
196
  baseURL?: string;
200
197
  };
201
- perplexity?: {
198
+ together?: {
202
199
  apiKey?: string;
203
200
  baseURL?: string;
204
201
  };
205
- cloudflare?: {
202
+ xai?: {
203
+ apiKey?: string;
204
+ baseURL?: string;
205
+ };
206
+ cohere?: {
206
207
  apiKey?: string;
207
- accountId?: string;
208
208
  baseURL?: string;
209
209
  };
210
210
  replicate?: {
@@ -3,11 +3,19 @@
3
3
  * Derives choices from model enums to ensure consistency
4
4
  */
5
5
  import { AIProviderName } from "../constants/enums.js";
6
- import type { ModelChoice } from "../types/index.js";
6
+ import type { CatalogProviderName, ModelChoice } from "../types/index.js";
7
7
  /**
8
- * Default models per provider (first choice/recommended)
8
+ * Default models per provider (first choice/recommended).
9
+ *
10
+ * Covers every provider EXCEPT the 9 JSON-catalog providers — those default
11
+ * models come from `models.default` in the catalog JSON, read directly by
12
+ * `getDefaultModel()` below. (Two of the 9 — cerebras, sambanova — never had
13
+ * a hand entry here at all; `getDefaultModel()` now resolves them too.)
14
+ *
15
+ * AUTO is also excluded — it never had an entry here either (matches
16
+ * pre-existing behavior: `getDefaultModel(AUTO)` returns `undefined`).
9
17
  */
10
- export declare const DEFAULT_MODELS: Record<string, string>;
18
+ export declare const DEFAULT_MODELS: Record<Exclude<AIProviderName, CatalogProviderName | AIProviderName.AUTO>, string>;
11
19
  /**
12
20
  * Get top model choices for a provider (for CLI prompts)
13
21
  * Returns models formatted for inquirer list prompts