@cherrystudio/provider-registry 0.0.0-stage → 0.1.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 (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +166 -2
  3. package/data/models.json +22694 -0
  4. package/data/provider-models.json +41090 -0
  5. package/data/providers.json +2716 -0
  6. package/dist/bundled-catalog.cjs +12 -0
  7. package/dist/bundled-catalog.d.cts +5 -0
  8. package/dist/bundled-catalog.d.mts +5 -0
  9. package/dist/bundled-catalog.mjs +11 -0
  10. package/dist/bundled-models--P3b6A6o.mjs +25220 -0
  11. package/dist/bundled-models-uS9C7ldF.cjs +25224 -0
  12. package/dist/bundled-models.cjs +3 -0
  13. package/dist/bundled-models.d.cts +5 -0
  14. package/dist/bundled-models.d.mts +5 -0
  15. package/dist/bundled-models.mjs +2 -0
  16. package/dist/bundled-provider-models-CT2Ha5w2.cjs +37586 -0
  17. package/dist/bundled-provider-models-y-RYjBUH.mjs +37582 -0
  18. package/dist/bundled-provider-models.cjs +3 -0
  19. package/dist/bundled-provider-models.d.cts +5 -0
  20. package/dist/bundled-provider-models.d.mts +5 -0
  21. package/dist/bundled-provider-models.mjs +2 -0
  22. package/dist/bundled-providers-BZisTfNC.cjs +2174 -0
  23. package/dist/bundled-providers-BiPpU5W4.mjs +2170 -0
  24. package/dist/bundled-providers.cjs +3 -0
  25. package/dist/bundled-providers.d.cts +5 -0
  26. package/dist/bundled-providers.d.mts +5 -0
  27. package/dist/bundled-providers.mjs +2 -0
  28. package/dist/catalog-DElG_l-8.mjs +369 -0
  29. package/dist/catalog-DurdOhD0.cjs +442 -0
  30. package/dist/catalog-XJyrtwI9.d.cts +53 -0
  31. package/dist/catalog-XJyrtwI9.d.mts +53 -0
  32. package/dist/index.cjs +2620 -0
  33. package/dist/index.d.cts +3932 -0
  34. package/dist/index.d.mts +3932 -0
  35. package/dist/index.mjs +2549 -0
  36. package/dist/model-NFEbqWMs.mjs +665 -0
  37. package/dist/model-kwW2vWDI.cjs +855 -0
  38. package/dist/provider-D14qMZsE.mjs +431 -0
  39. package/dist/provider-DkSIaann.cjs +527 -0
  40. package/dist/provider-models-BjKC53mr.cjs +85 -0
  41. package/dist/provider-models-BkxD9T17.mjs +67 -0
  42. package/dist/provider-models-DuZBXGmP.d.cts +28692 -0
  43. package/dist/provider-models-DuZBXGmP.d.mts +28692 -0
  44. package/dist/registry-BjETdicx.d.mts +35 -0
  45. package/dist/registry-Di5ULW6Z.d.cts +35 -0
  46. package/dist/registry-loader.cjs +170 -0
  47. package/dist/registry-loader.d.cts +64 -0
  48. package/dist/registry-loader.d.mts +64 -0
  49. package/dist/registry-loader.mjs +156 -0
  50. package/package.json +146 -3
@@ -0,0 +1,431 @@
1
+ import { C as REASONING_EFFORT, D as objectValues, E as SERVER_TOOL_MODEL_SCOPE, T as SERVER_TOOL, _ as ZodCurrencySchema, a as ModelConfigSchema, b as ENDPOINT_TYPE, d as looseArray, f as EndpointTypeSchema, g as VersionSchema, h as ProviderIdSchema, p as MetadataSchema } from "./model-NFEbqWMs.mjs";
2
+ import * as z from "zod";
3
+ //#region src/patterns/vendor-patterns.ts
4
+ /**
5
+ * Vendor identity regex patterns — the single source of truth for
6
+ * "which vendor does this raw model ID belong to".
7
+ *
8
+ * Shared across three call sites:
9
+ * - `@shared/utils/model` — vendor check functions (`isAnthropicModel`
10
+ * etc.) and capability inference (e.g. deciding which IDs to mark
11
+ * `REASONING` in the schema).
12
+ * - `@cherrystudio/ui` icon registry — vendor-level icon routing for
13
+ * models whose ID doesn't have a dedicated SKU icon.
14
+ * - Future callers doing vendor dispatch.
15
+ *
16
+ * Keeping these regex in the registry layer means both capability
17
+ * inference and icon lookup stay in lockstep when a new vendor /
18
+ * naming convention lands.
19
+ *
20
+ * Scope: **vendor identity only**. SKU-level patterns (`gpt-5.1-codex-mini`,
21
+ * `claude-sonnet-4-6`, etc.) stay in their specific consumer modules —
22
+ * those are dispatch details rather than shared vendor taxonomy.
23
+ *
24
+ * Normalization note: patterns assume the id has already been lowercased
25
+ * and had the leading namespace stripped (e.g. `deepseek/deepseek-r1` →
26
+ * `deepseek-r1`). Pair with `getLowerBaseModelName` (in `@shared`) or
27
+ * `normalizeModelId` (in this package).
28
+ */
29
+ /**
30
+ * Match raw model IDs to their vendor. Keys are vendor slugs; order is
31
+ * not significant because every pattern is anchored to the start of the
32
+ * (namespace-stripped) id, so they stay mutually exclusive — a model
33
+ * belongs to at most one vendor. Keep new patterns anchored (`^…`) so a
34
+ * cross-vendor id like `deepseek-grok` resolves by its leading token, not
35
+ * by insertion order.
36
+ */
37
+ const VENDOR_PATTERNS = {
38
+ /** Anthropic / Claude family. Also matches the AWS Bedrock `anthropic.claude-*` prefix. */
39
+ anthropic: /^(?:anthropic\.)?claude/i,
40
+ /** Google Gemini family. */
41
+ gemini: /^(?:gemini|palm|veo|imagen|learnlm|lyria)/i,
42
+ /** Google Gemma family (gemma-*, gemma2/3/4, and the Ollama-style `gemma:2b` tag). */
43
+ gemma: /^gemma(?:[-:\d]|$)/i,
44
+ /** xAI Grok family. */
45
+ grok: /^grok/i,
46
+ /**
47
+ * OpenAI (chat + reasoning + legacy + media + embeddings). GPT-n, ChatGPT, the bare o<digit> series,
48
+ * codex/davinci/babbage, DALL·E, moderation, and OpenAI's `text-embedding-3*` / `-ada` embeddings.
49
+ * `text-embedding` is scoped to the `-3`/`-ada` SKUs on purpose — bare `text-embedding-0xx` is Google's,
50
+ * and `VENDOR_PATTERNS` is a flat set with no per-creator disambiguation.
51
+ */
52
+ openai: /\bgpt\b|^o[134]|^chatgpt|^codex|^davinci|^babbage|^dall-e|^text-moderation|^text-embedding-(?:3|ada)/i,
53
+ /** Alibaba Qwen family (qwen, qwq, qvq). */
54
+ qwen: /^qwen|^qwq|^qvq|^tongyi/i,
55
+ /** ByteDance Doubao family. */
56
+ doubao: /^(?:doubao|skylark|seed|seedance|seedream|ep-)/i,
57
+ /** Tencent Hunyuan family — `hunyuan-*`, the `hy-*` SKUs, and the versioned `hyN` namespace (`hy3-preview`). */
58
+ hunyuan: /^(?:hunyuan|hy-|hy\d)/i,
59
+ /** Moonshot / Kimi family, including Kimi Code's bare K3 model IDs. */
60
+ kimi: /^(?:kimi|moonshot|k3(?:[-_.]|$))/i,
61
+ /** DeepSeek family. */
62
+ deepseek: /^deepseek/i,
63
+ /** Perplexity (sonar family). */
64
+ perplexity: /^sonar/i,
65
+ /** Baichuan family. */
66
+ baichuan: /^baichuan/i,
67
+ /** Xiaomi MiMo family. */
68
+ mimo: /^mimo-/i,
69
+ /** Ant Group Ling / Ring family. */
70
+ ling: /^(?:ling|ring)-/i,
71
+ /** MiniMax family — current `minimax-*` plus the legacy `abab-*` SKUs the creator still claims. */
72
+ minimax: /^(?:minimax|abab)/i,
73
+ /** StepFun family. */
74
+ step: /^step-/i,
75
+ /** Zhipu / GLM family. */
76
+ zhipu: /^(?:glm|chatglm|cogview|cogvideo|codegeex)/i,
77
+ /** Mistral family — incl. the `open-*` open-weight line (`open-mistral-7b`, `open-mixtral-8x22b`) and `labs-*`. */
78
+ mistral: /^(?:open-|labs-)?(?:mistral|pixtral|codestral|ministral|voxtral|devstral|mixtral|magistral)/i
79
+ };
80
+ /**
81
+ * Return the vendor slug for a normalized model ID, or `undefined` if
82
+ * no vendor pattern matches. Iteration order is stable (key insertion
83
+ * order) but not semantically important — patterns don't overlap.
84
+ */
85
+ function matchVendor(normalizedId) {
86
+ for (const [vendor, pattern] of Object.entries(VENDOR_PATTERNS)) if (pattern.test(normalizedId)) return vendor;
87
+ }
88
+ /**
89
+ * Lightweight vendor predicate factory. Exported primarily so consumers
90
+ * can spell the check as `isVendor('anthropic')(id)` when composing
91
+ * higher-level logic.
92
+ */
93
+ function isVendor(vendor) {
94
+ const pattern = VENDOR_PATTERNS[vendor];
95
+ return (id) => pattern.test(id);
96
+ }
97
+ //#endregion
98
+ //#region src/schemas/reasoningWire.ts
99
+ /** Closed set of leaves the main-process reasoning interpreter may write. */
100
+ const REASONING_WIRE_TARGETS = [
101
+ "reasoningEffort",
102
+ "reasoningSummary",
103
+ "reasoning_effort",
104
+ "reasoning.effort",
105
+ "reasoning.enabled",
106
+ "reasoning.exclude",
107
+ "reasoning.max_tokens",
108
+ "thinking.type",
109
+ "thinking.budget_tokens",
110
+ "thinking.budgetTokens",
111
+ "thinking.display",
112
+ "effort",
113
+ "sendReasoning",
114
+ "enable_thinking",
115
+ "thinking_budget",
116
+ "incremental_output",
117
+ "disable_reasoning",
118
+ "reasoning_budget",
119
+ "chat_template_kwargs.enable_thinking",
120
+ "chat_template_kwargs.thinking",
121
+ "chat_template_kwargs.thinking_mode",
122
+ "chat_template_kwargs.thinking_budget",
123
+ "extra_body.google.thinking_config.thinking_budget",
124
+ "extra_body.google.thinking_config.include_thoughts",
125
+ "extra_body.thinking.type",
126
+ "extra_body.thinking_budget",
127
+ "extra_body.reasoning_effort",
128
+ "thinkingConfig.includeThoughts",
129
+ "thinkingConfig.thinkingBudget",
130
+ "thinkingConfig.thinkingLevel",
131
+ "reasoningConfig.type",
132
+ "reasoningConfig.budgetTokens",
133
+ "reasoningConfig.maxReasoningEffort",
134
+ "think"
135
+ ];
136
+ const ReasoningWireTargetSchema = z.enum(REASONING_WIRE_TARGETS);
137
+ const ReasoningEffortSchema = z.enum(objectValues(REASONING_EFFORT));
138
+ const ReasoningWireValueSchema = z.discriminatedUnion("source", [
139
+ z.object({
140
+ source: z.literal("literal"),
141
+ value: z.union([
142
+ z.string(),
143
+ z.number(),
144
+ z.boolean()
145
+ ])
146
+ }),
147
+ z.object({ source: z.literal("effort") }),
148
+ z.object({ source: z.literal("budget") }),
149
+ z.object({ source: z.literal("assistant-summary") })
150
+ ]);
151
+ const ReasoningWireOperationSchema = z.object({
152
+ target: ReasoningWireTargetSchema,
153
+ value: ReasoningWireValueSchema
154
+ });
155
+ const NonBudgetReasoningWireValueSchema = z.discriminatedUnion("source", [
156
+ z.object({
157
+ source: z.literal("literal"),
158
+ value: z.union([
159
+ z.string(),
160
+ z.number(),
161
+ z.boolean()
162
+ ])
163
+ }),
164
+ z.object({ source: z.literal("effort") }),
165
+ z.object({ source: z.literal("assistant-summary") })
166
+ ]);
167
+ const NonBudgetReasoningWireOperationSchema = z.object({
168
+ target: ReasoningWireTargetSchema,
169
+ value: NonBudgetReasoningWireValueSchema
170
+ });
171
+ const ReasoningBudgetPolicySchema = z.object({
172
+ min: z.number().nonnegative().optional(),
173
+ autoValue: z.number().optional(),
174
+ clampToMaxTokens: z.boolean().optional(),
175
+ missing: z.discriminatedUnion("type", [
176
+ z.object({ type: z.literal("omit-value") }),
177
+ z.object({ type: z.literal("omit-mode") }),
178
+ z.object({
179
+ type: z.literal("fallback"),
180
+ value: z.number()
181
+ })
182
+ ])
183
+ });
184
+ const ReasoningEffortMapSchema = z.partialRecord(ReasoningEffortSchema, ReasoningEffortSchema).optional();
185
+ const ReasoningWireModeSchema = z.union([z.object({
186
+ operations: z.array(NonBudgetReasoningWireOperationSchema).min(1),
187
+ effortMap: ReasoningEffortMapSchema
188
+ }), z.object({
189
+ operations: z.array(ReasoningWireOperationSchema).min(1).refine((operations) => operations.some((operation) => operation.value.source === "budget"), { message: "reasoning budget mode must contain a budget operation" }),
190
+ effortMap: ReasoningEffortMapSchema,
191
+ budget: ReasoningBudgetPolicySchema
192
+ })]);
193
+ const ReasoningWireProfileSchema = z.object({
194
+ /** Endpoint deliberately emits no reasoning parameters. */
195
+ disabled: z.literal(true).optional(),
196
+ default: ReasoningWireModeSchema.optional(),
197
+ off: ReasoningWireModeSchema.optional(),
198
+ auto: ReasoningWireModeSchema.optional(),
199
+ effort: ReasoningWireModeSchema.optional()
200
+ }).refine((profile) => profile.disabled === true || profile.default || profile.off || profile.auto || profile.effort, { message: "reasoning wire profile must declare a mode or be disabled" });
201
+ const ReasoningFormatWireProfileSchema = z.object({
202
+ wire: ReasoningWireProfileSchema,
203
+ budgetWire: ReasoningWireProfileSchema.optional(),
204
+ alwaysOnWire: ReasoningWireProfileSchema.optional(),
205
+ betweenToolsWire: ReasoningWireProfileSchema.optional()
206
+ });
207
+ //#endregion
208
+ //#region src/schemas/provider.ts
209
+ /**
210
+ * Provider configuration schema definitions
211
+ * Defines the structure for provider connections and API configurations
212
+ */
213
+ const endpointTypeValues = objectValues(ENDPOINT_TYPE);
214
+ const ProviderEditionSchema = z.enum(["global", "cn"]);
215
+ /**
216
+ * Provider-owned transport used to request faster processing.
217
+ *
218
+ * Model availability remains a provider-model concern; this only describes
219
+ * how the provider carries an enabled Fast request. `openai-priority` means the
220
+ * `serviceTier` provider option on the OpenAI namespace — the tier *value* is
221
+ * vendor-specific and travels in `fastMode.serviceTier` (OpenAI's `priority`,
222
+ * Ark's `fast`), so a new vendor never has to expand this enum: enum expansion
223
+ * is a breaking wire change, an optional field is not.
224
+ */
225
+ const FastModeTransportSchema = z.enum(["openai-priority", "claude-code"]);
226
+ const ServiceTierSelectionSchema = z.enum([
227
+ "standard",
228
+ "auto",
229
+ "fast",
230
+ "flex"
231
+ ]);
232
+ const ServiceTierOptionsSchema = z.array(ServiceTierSelectionSchema).min(1).refine((options) => new Set(options).size === options.length, { message: "service tier options must be unique" }).refine((options) => options.includes("standard"), { message: "service tier options must include standard" });
233
+ const ServiceTierDeliverySchema = z.discriminatedUnion("type", [z.object({
234
+ type: z.literal("provider-option"),
235
+ key: z.string().min(1)
236
+ }), z.object({
237
+ type: z.literal("request-body"),
238
+ key: z.string().min(1)
239
+ })]);
240
+ const ServiceTierRequestControlSchema = z.object({
241
+ default: ServiceTierSelectionSchema,
242
+ options: ServiceTierOptionsSchema,
243
+ wire: z.object({
244
+ delivery: ServiceTierDeliverySchema,
245
+ values: z.partialRecord(ServiceTierSelectionSchema, z.string().min(1))
246
+ })
247
+ }).superRefine((control, context) => {
248
+ if (!control.options.includes(control.default)) context.addIssue({
249
+ code: "custom",
250
+ message: "service tier default must be one of its options",
251
+ path: ["default"]
252
+ });
253
+ for (const option of control.options) if (!control.wire.values[option]) context.addIssue({
254
+ code: "custom",
255
+ message: `service tier option '${option}' must have a wire value`,
256
+ path: [
257
+ "wire",
258
+ "values",
259
+ option
260
+ ]
261
+ });
262
+ });
263
+ /** A provider-native tool plus the scope of models on which the host serves it. */
264
+ const ServerToolConfigSchema = z.object({
265
+ id: z.enum(objectValues(SERVER_TOOL)),
266
+ modelScope: z.enum(objectValues(SERVER_TOOL_MODEL_SCOPE)).default(SERVER_TOOL_MODEL_SCOPE.MODEL_DEPENDENT),
267
+ /** Endpoint protocols on which the host serves the tool. Absent ⇒ all configured endpoints. */
268
+ endpointTypes: looseArray(EndpointTypeSchema).optional(),
269
+ /**
270
+ * Vendor families the host actually serves the tool for, when narrower than
271
+ * the tool's model eligibility (e.g. Vertex url-context is Gemini-only: the
272
+ * vertex-anthropic SDK exposes no webFetch tool). Absent ⇒ no narrowing.
273
+ */
274
+ vendors: looseArray(z.enum(Object.keys(VENDOR_PATTERNS))).optional()
275
+ });
276
+ const reasoningFormat = (type) => z.object({
277
+ type: z.literal(type),
278
+ /** Endpoint-wide wire behavior, interpreted only in Main. */
279
+ wire: ReasoningWireProfileSchema.optional()
280
+ });
281
+ /** Provider reasoning format — discriminated union by format type. */
282
+ const ProviderReasoningFormatSchema = z.discriminatedUnion("type", [
283
+ reasoningFormat("openai-chat"),
284
+ reasoningFormat("openai-responses"),
285
+ reasoningFormat("anthropic"),
286
+ reasoningFormat("gemini"),
287
+ reasoningFormat("ollama"),
288
+ reasoningFormat("none")
289
+ ]);
290
+ const REASONING_FORMAT_TYPES = ProviderReasoningFormatSchema.options.map((option) => option.shape.type.value);
291
+ const ProviderWebsiteSchema = z.object({ website: z.object({
292
+ official: z.url().optional(),
293
+ docs: z.url().optional(),
294
+ apiKey: z.url().optional(),
295
+ models: z.url().optional()
296
+ }) });
297
+ /**
298
+ * How a host deviates from one endpoint's dialect. These are properties of the
299
+ * protocol, not of the vendor: a provider serving both chat-completions and
300
+ * Responses may answer differently for each.
301
+ */
302
+ const EndpointDialectSchema = z.object({
303
+ /** Accepts chat-completions `stream_options` for usage data. Absent ⇒ true. */
304
+ streamOptions: z.boolean().optional(),
305
+ /** Accepts messages with `role: "developer"`. Absent ⇒ false. */
306
+ developerRole: z.boolean().optional(),
307
+ /** Accepts OpenAI Responses `reasoning.summary`. Absent ⇒ use the registry wire. */
308
+ reasoningSummary: z.boolean().optional()
309
+ });
310
+ /** Per-endpoint-type configuration in registry */
311
+ const RegistryEndpointConfigSchema = z.object({
312
+ /** Base URL for this endpoint type's API */
313
+ baseUrl: z.url().optional(),
314
+ /** URLs for fetching available models via this endpoint type */
315
+ modelsApiUrls: z.object({
316
+ /** Default models listing endpoint */
317
+ default: z.url().optional(),
318
+ /** Embedding models listing endpoint (if separate from default) */
319
+ embedding: z.url().optional(),
320
+ /** Image models listing endpoint (if separate from default) */
321
+ image: z.url().optional(),
322
+ /** Reranker models listing endpoint (if separate from default) */
323
+ reranker: z.url().optional()
324
+ }).optional(),
325
+ /** How this endpoint type expects reasoning parameters to be formatted */
326
+ reasoningFormat: ProviderReasoningFormatSchema.optional(),
327
+ /**
328
+ * AI SDK adapter family that handles this endpoint. Aligns with the IDs
329
+ * registered in `appProviderIds`. Resolvers should prefer this over
330
+ * heuristic id/baseUrl inference when present.
331
+ */
332
+ adapterFamily: z.string().optional(),
333
+ /** Dialect deviations of this host's implementation of the endpoint. */
334
+ dialect: EndpointDialectSchema.optional(),
335
+ /** User-selectable request controls supported by this endpoint. */
336
+ requestControls: z.object({ serviceTier: ServiceTierRequestControlSchema.optional() }).optional()
337
+ });
338
+ const ProviderConfigSchema = z.object({
339
+ /** Unique provider identifier */
340
+ id: ProviderIdSchema,
341
+ presetProviderId: ProviderIdSchema.optional(),
342
+ /** Display name */
343
+ name: z.string(),
344
+ /** App editions where this provider is available. Omitted means all editions. */
345
+ availableInEditions: looseArray(ProviderEditionSchema, { min: 1 }).optional(),
346
+ /** Provider description */
347
+ description: z.string().optional(),
348
+ /** Per-endpoint-type configuration (partial record — not all endpoint types need to be present) */
349
+ endpointConfigs: z.record(z.string().refine((k) => endpointTypeValues.includes(k), { message: `Invalid endpoint type key, must be one of: ${objectValues(ENDPOINT_TYPE).join(", ")}` }), RegistryEndpointConfigSchema).optional(),
350
+ /** Default endpoint type for chat requests — null for providers not bound by this (e.g. AWS, Vertex) */
351
+ defaultChatEndpoint: EndpointTypeSchema.nullable().default(null),
352
+ /**
353
+ * Where this provider's model list comes from. `'registry'` means it cannot
354
+ * be enumerated over an API (login-based subscription providers); the shipped
355
+ * registry catalog is returned by the model-list chokepoint instead. Defaults
356
+ * to `'api'` (the provider exposes a `/models` endpoint).
357
+ */
358
+ modelListSource: z.enum(["api", "registry"]).default("api"),
359
+ /** Append registry-only models omitted by the API list. Absent means API-only. */
360
+ supplementModelsFromRegistry: z.boolean().optional(),
361
+ /** Provider-local resource IDs must never match global catalog model names. */
362
+ modelResolution: z.discriminatedUnion("source", [z.object({ source: z.literal("catalog") }), z.object({
363
+ source: z.literal("provider"),
364
+ defaults: ModelConfigSchema.pick({
365
+ capabilities: true,
366
+ inputModalities: true,
367
+ outputModalities: true,
368
+ endpointTypes: true,
369
+ imageGeneration: true
370
+ }).required({
371
+ capabilities: true,
372
+ inputModalities: true,
373
+ outputModalities: true,
374
+ endpointTypes: true
375
+ }).extend({ supportsStreaming: z.boolean() })
376
+ })]).optional(),
377
+ /**
378
+ * Which credential kinds the provider accepts — the auth UIs to surface and
379
+ * the runtime credential semantics. A *set*, because a provider can offer
380
+ * more than one (CherryIN takes both a user API key and an app-managed OAuth
381
+ * login). Members:
382
+ * - `'api-key'` — user-entered key (the api-key/host inputs).
383
+ * - `'oauth'` — app-managed OAuth session the app holds and refreshes.
384
+ * - `'external-cli'` — credential lives in an external CLI's store and only
385
+ * works through that CLI's runtime (e.g. `claude-code`); drives env
386
+ * stripping and chat-picker hiding.
387
+ *
388
+ * Absent ⇒ the default `['api-key']`. "Login-based" (suppress the api-key
389
+ * inputs) is the derived `!includes('api-key')`, not a value of its own.
390
+ */
391
+ authMethods: looseArray(z.enum([
392
+ "api-key",
393
+ "oauth",
394
+ "external-cli"
395
+ ])).optional(),
396
+ /**
397
+ * The provider serves requests without any credential — a local server
398
+ * (ollama / lmstudio / gpustack / ovms) reachable over a baseUrl with no API
399
+ * key or login. Drives the "no API key required" guards: model sync, painting
400
+ * and OpenClaw gating skip the missing-key check. Distinct from login-based
401
+ * (`authMethods` without `'api-key'`), which also suppresses the host UI — a
402
+ * local provider still needs its baseUrl input. Defaults false.
403
+ */
404
+ authOptional: z.boolean().default(false),
405
+ /** Provider-native (server-executed) built-in tools served by this host. */
406
+ serverTools: looseArray(ServerToolConfigSchema).default([]),
407
+ /** Whether usage responses carry the actual billed amount. */
408
+ reportsActualCost: z.boolean().default(false),
409
+ /**
410
+ * Registry-owned currency for provider-reported costs whose wire payload
411
+ * carries an amount but no currency. Absent means the amount stays
412
+ * unpriced; consumers must not infer a default currency.
413
+ */
414
+ reportedCostCurrency: ZodCurrencySchema,
415
+ /** Provider-owned Fast request transport. Effective support is declared per provider-model pair. */
416
+ fastMode: z.object({
417
+ transport: FastModeTransportSchema,
418
+ serviceTier: z.string().optional()
419
+ }).optional(),
420
+ /** Additional metadata including website URLs */
421
+ metadata: MetadataSchema.and(ProviderWebsiteSchema)
422
+ }).refine((data) => {
423
+ if (data.endpointConfigs && data.defaultChatEndpoint) return data.defaultChatEndpoint in data.endpointConfigs;
424
+ return true;
425
+ }, { message: "defaultChatEndpoint must exist as a key in endpointConfigs" });
426
+ const ProviderListSchema = z.object({
427
+ version: VersionSchema,
428
+ providers: looseArray(ProviderConfigSchema)
429
+ });
430
+ //#endregion
431
+ export { REASONING_FORMAT_TYPES as a, ServiceTierOptionsSchema as c, REASONING_WIRE_TARGETS as d, ReasoningFormatWireProfileSchema as f, matchVendor as g, isVendor as h, ProviderListSchema as i, ServiceTierRequestControlSchema as l, VENDOR_PATTERNS as m, ProviderConfigSchema as n, ServerToolConfigSchema as o, ReasoningWireProfileSchema as p, ProviderEditionSchema as r, ServiceTierDeliverySchema as s, FastModeTransportSchema as t, ServiceTierSelectionSchema as u };