@cherrystudio/provider-registry 0.0.0-stage → 0.1.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 (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 +2722 -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-BcszhEy2.mjs +2172 -0
  23. package/dist/bundled-providers-Bv_iM9AO.cjs +2176 -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,855 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ let zod = require("zod");
24
+ zod = __toESM(zod, 1);
25
+ //#region src/schemas/enums.ts
26
+ /**
27
+ * Canonical enum definitions for the registry system.
28
+ *
29
+ * These are the SINGLE SOURCE OF TRUTH for all enum types.
30
+ * Uses `as const` objects with kebab-case string values for debuggability.
31
+ *
32
+ * - registry/schemas/ uses these via z.enum()
33
+ * - shared/data/types/ re-exports these directly
34
+ */
35
+ const ENDPOINT_TYPE = {
36
+ ANTHROPIC_MESSAGES: "anthropic-messages",
37
+ GOOGLE_GENERATE_CONTENT: "google-generate-content",
38
+ JINA_RERANK: "jina-rerank",
39
+ OLLAMA_CHAT: "ollama-chat",
40
+ OLLAMA_GENERATE: "ollama-generate",
41
+ OPENAI_AUDIO_TRANSCRIPTION: "openai-audio-transcription",
42
+ OPENAI_AUDIO_TRANSLATION: "openai-audio-translation",
43
+ OPENAI_CHAT_COMPLETIONS: "openai-chat-completions",
44
+ OPENAI_EMBEDDINGS: "openai-embeddings",
45
+ OPENAI_IMAGE_EDIT: "openai-image-edit",
46
+ OPENAI_IMAGE_GENERATION: "openai-image-generation",
47
+ OPENAI_RESPONSES: "openai-responses",
48
+ OPENAI_TEXT_COMPLETIONS: "openai-text-completions",
49
+ OPENAI_TEXT_TO_SPEECH: "openai-text-to-speech",
50
+ OPENAI_VIDEO_GENERATION: "openai-video-generation"
51
+ };
52
+ const MODEL_CAPABILITY = {
53
+ FUNCTION_CALL: "function-call",
54
+ REASONING: "reasoning",
55
+ IMAGE_RECOGNITION: "image-recognition",
56
+ IMAGE_GENERATION: "image-generation",
57
+ AUDIO_RECOGNITION: "audio-recognition",
58
+ AUDIO_GENERATION: "audio-generation",
59
+ EMBEDDING: "embedding",
60
+ RERANK: "rerank",
61
+ AUDIO_TRANSCRIPT: "audio-transcript",
62
+ VIDEO_RECOGNITION: "video-recognition",
63
+ VIDEO_GENERATION: "video-generation",
64
+ STRUCTURED_OUTPUT: "structured-output",
65
+ FILE_INPUT: "file-input",
66
+ CODE_EXECUTION: "code-execution",
67
+ FILE_SEARCH: "file-search",
68
+ COMPUTER_USE: "computer-use"
69
+ };
70
+ const SERVER_TOOL = {
71
+ WEB_SEARCH: "web-search",
72
+ URL_CONTEXT: "url-context"
73
+ };
74
+ const SERVER_TOOL_MODEL_SCOPE = {
75
+ /** The provider supplies the tool for every chat model it serves. */
76
+ ALL_CHAT_MODELS: "all-chat-models",
77
+ /** Tool-specific model eligibility must also pass. */
78
+ MODEL_DEPENDENT: "model-dependent"
79
+ };
80
+ /**
81
+ * The closed vocabulary of image-generation param keys. A model declares a
82
+ * subset of these under `imageGeneration.modes[mode].supports` (see
83
+ * `ImageModeDefSchema`), and they flow end-to-end as `painting.params` keys.
84
+ *
85
+ * Unlike the other enums, the VALUES are camelCase on purpose: they ARE the
86
+ * runtime param-bag keys and must match `painting.params`/registry data
87
+ * verbatim — do NOT kebab-case them (it would break the wire contract).
88
+ *
89
+ * This is the single source of truth that ties together the registry schema,
90
+ * the form's `KEY_LABELS`/`OPTION_LABELS`, and `canonicalGenerate`'s
91
+ * `POSITIONAL_RENAME`. Adding a new canonical param is a deliberate change:
92
+ * add the member here, give it a label in `KEY_LABELS`, and declare it on the
93
+ * relevant models in registry data.
94
+ */
95
+ const CANONICAL_PARAM_KEY = {
96
+ ADD_WATERMARK: "addWatermark",
97
+ ASPECT_RATIO: "aspectRatio",
98
+ BACKGROUND: "background",
99
+ BOTTOM_SCALE: "bottomScale",
100
+ CFG: "cfg",
101
+ CUSTOM_SIZE: "customSize",
102
+ DETAIL: "detail",
103
+ ENABLE_INTERLEAVE: "enableInterleave",
104
+ FUNCTION: "function",
105
+ GUIDANCE_SCALE: "guidanceScale",
106
+ IMAGE_RESOLUTION: "imageResolution",
107
+ IMAGE_WEIGHT: "imageWeight",
108
+ IS_SKETCH: "isSketch",
109
+ LEFT_SCALE: "leftScale",
110
+ MAGIC_PROMPT_OPTION: "magicPromptOption",
111
+ MAX_IMAGES: "maxImages",
112
+ MODERATION: "moderation",
113
+ NEGATIVE_PROMPT: "negativePrompt",
114
+ NUM_IMAGES: "numImages",
115
+ NUM_INFERENCE_STEPS: "numInferenceSteps",
116
+ OUTPUT_FORMAT: "outputFormat",
117
+ OUTPUT_COMPRESSION: "outputCompression",
118
+ PERSON_GENERATION: "personGeneration",
119
+ PROMPT_ENHANCEMENT: "promptEnhancement",
120
+ PROMPT_EXTEND: "promptExtend",
121
+ QUALITY: "quality",
122
+ RESOLUTION: "resolution",
123
+ REF_MODE: "refMode",
124
+ REF_STRENGTH: "refStrength",
125
+ RENDERING_SPEED: "renderingSpeed",
126
+ RESEMBLANCE: "resemblance",
127
+ RIGHT_SCALE: "rightScale",
128
+ SAFETY_TOLERANCE: "safetyTolerance",
129
+ SEED: "seed",
130
+ SEQUENTIAL_IMAGE_GENERATION: "sequentialImageGeneration",
131
+ SIZE: "size",
132
+ SOURCE_LANG: "sourceLang",
133
+ STRENGTH: "strength",
134
+ STYLE: "style",
135
+ STYLE_TYPE: "styleType",
136
+ TARGET_LANG: "targetLang",
137
+ THINKING_MODE: "thinkingMode",
138
+ TOP_SCALE: "topScale",
139
+ UPSCALE_FACTOR: "upscaleFactor"
140
+ };
141
+ const MODALITY = {
142
+ TEXT: "text",
143
+ IMAGE: "image",
144
+ AUDIO: "audio",
145
+ VIDEO: "video",
146
+ VECTOR: "vector"
147
+ };
148
+ const CURRENCY = {
149
+ USD: "USD",
150
+ CNY: "CNY"
151
+ };
152
+ const REASONING_EFFORT = {
153
+ NONE: "none",
154
+ MINIMAL: "minimal",
155
+ LOW: "low",
156
+ MEDIUM: "medium",
157
+ HIGH: "high",
158
+ XHIGH: "xhigh",
159
+ MAX: "max",
160
+ ULTRA: "ultra",
161
+ AUTO: "auto"
162
+ };
163
+ /**
164
+ * Intensity ladder for nearest-match fallback when a persisted effort is not
165
+ * in a model's vocabulary (model switch / vocabulary shrink). `auto` is
166
+ * deliberately last — it is a mode, not an intensity.
167
+ */
168
+ const REASONING_EFFORT_ORDER = [
169
+ "none",
170
+ "minimal",
171
+ "low",
172
+ "medium",
173
+ "high",
174
+ "xhigh",
175
+ "max",
176
+ "ultra",
177
+ "auto"
178
+ ];
179
+ /** Extract the value tuple from a const object for use with z.enum(). */
180
+ function objectValues(obj) {
181
+ return Object.values(obj);
182
+ }
183
+ //#endregion
184
+ //#region src/schemas/common.ts
185
+ /**
186
+ * Common type definitions for the registry system
187
+ * Shared across model, provider, and override schemas
188
+ */
189
+ const EndpointTypeSchema = zod.enum(objectValues(ENDPOINT_TYPE));
190
+ const ModelIdSchema = zod.string().min(1);
191
+ const ProviderIdSchema = zod.string().min(1);
192
+ /**
193
+ * Opaque change-detection token for a generated artifact. The generator stamps it with a hash of the
194
+ * artifact's content, so equal content ⇒ equal version and ANY content change ⇒ new version — that's
195
+ * the contract seeders rely on (`SeedRunner` skips a seeder whose journal version matches). Older
196
+ * artifacts carried a generation date; treat the value as opaque, never parse it.
197
+ */
198
+ const VersionSchema = zod.string().min(1);
199
+ zod.iso.datetime();
200
+ const NumericRangeSchema = zod.object({
201
+ min: zod.number(),
202
+ max: zod.number()
203
+ }).refine((r) => r.min <= r.max, { message: "min must be less than or equal to max" });
204
+ zod.object({
205
+ min: zod.string(),
206
+ max: zod.string()
207
+ });
208
+ const ZodCurrencySchema = zod.enum(objectValues(CURRENCY)).optional();
209
+ const PricePerTokenSchema = zod.object({
210
+ perMillionTokens: zod.number().nonnegative().nullable(),
211
+ currency: ZodCurrencySchema
212
+ });
213
+ const MetadataSchema = zod.record(zod.string(), zod.unknown()).optional();
214
+ //#endregion
215
+ //#region src/schemas/forwardCompat.ts
216
+ /**
217
+ * Forward compatibility for the wire contract — a catalog emitted by a NEWER
218
+ * generator must stay readable by THIS client.
219
+ *
220
+ * `z.object` already strips unknown keys, so additive fields were always safe.
221
+ * The remaining break was vocabulary growth: one unknown member of a closed
222
+ * `z.enum` failed its whole document, which is why every new effort/capability
223
+ * used to force a {@link REGISTRY_SCHEMA_VERSION} bump. {@link looseArray}
224
+ * degrades that failure to the smallest unit that can be dropped:
225
+ *
226
+ * - inside a list of enum values → drop the unknown member, keep the entry
227
+ * - inside a list of entries (models/providers/overrides) → drop the entry
228
+ * the client cannot represent, keep the rest of the catalog
229
+ *
230
+ * Values this client cannot *execute* (a new adapter family, endpoint type,
231
+ * wire behavior) are still gated — by `REGISTRY_MIN_APP_VERSION`, not by
232
+ * parse failure.
233
+ */
234
+ /**
235
+ * Like `z.array(item)`, but silently drops members that fail to parse.
236
+ *
237
+ * @param min Minimum members required AFTER dropping — the entry is rejected
238
+ * (and dropped by its own enclosing `looseArray`) when too few survive.
239
+ */
240
+ function looseArray(item, { min } = {}) {
241
+ const array = zod.array(zod.unknown()).transform((values) => values.reduce((kept, value) => {
242
+ const parsed = item.safeParse(value);
243
+ if (parsed.success) kept.push(parsed.data);
244
+ return kept;
245
+ }, []));
246
+ return min === void 0 ? array : array.refine((values) => values.length >= min, { message: `expected at least ${min} recognized value(s)` });
247
+ }
248
+ //#endregion
249
+ //#region src/schemas/model.ts
250
+ /**
251
+ * Model configuration schema definitions
252
+ * Defines the structure for model metadata, capabilities, and configurations
253
+ */
254
+ const ModalitySchema = zod.enum(objectValues(MODALITY));
255
+ const ModelCapabilityTypeSchema = zod.enum(objectValues(MODEL_CAPABILITY));
256
+ const CanonicalParamKeySchema = zod.enum(objectValues(CANONICAL_PARAM_KEY));
257
+ const ThinkingTokenLimitsSchema = zod.object({
258
+ min: zod.number().nonnegative().optional(),
259
+ max: zod.number().positive().optional(),
260
+ default: zod.number().nonnegative().optional()
261
+ }).refine((d) => d.min == null === (d.max == null), { message: "min and max must be both present or both absent" }).refine((d) => d.min == null || d.max == null || d.min <= d.max, { message: "min must be less than or equal to max" });
262
+ /** Reasoning effort levels shared across providers */
263
+ const ReasoningEffortSchema = zod.enum(objectValues(REASONING_EFFORT));
264
+ /**
265
+ * Per-model reasoning control declaration — the SOURCE from which the legacy
266
+ * pair (`supportedEfforts` / `thinkingTokenLimits`) is DERIVED at generation
267
+ * time (`deriveLegacyReasoningFields`). Kinds align 1:1 with models.dev
268
+ * `reasoning_options` so upstream ingestion is lossless.
269
+ */
270
+ const ReasoningControlSchema = zod.discriminatedUnion("kind", [
271
+ zod.object({
272
+ /** Discrete effort knob. `values` is the model's intrinsic vocabulary, in
273
+ * UI display order. The active endpoint profile may map those values to a
274
+ * narrower wire vocabulary (`'none'` present ⇔ reasoning can be disabled). */
275
+ kind: zod.literal("effort"),
276
+ values: looseArray(ReasoningEffortSchema, { min: 1 }),
277
+ default: ReasoningEffortSchema.optional()
278
+ }),
279
+ zod.object({
280
+ /** Numeric thinking-token budget knob. */
281
+ kind: zod.literal("budget"),
282
+ min: zod.number().nonnegative(),
283
+ max: zod.number().positive(),
284
+ default: zod.number().nonnegative().optional()
285
+ }),
286
+ zod.object({
287
+ /** On/off only — no effort levels, no budget. */
288
+ kind: zod.literal("toggle"),
289
+ default: zod.boolean().optional()
290
+ })
291
+ ]);
292
+ /**
293
+ * Which dialect variant of its endpoint's native protocol a model generation
294
+ * speaks. NOT a wire format — the format still follows the serving endpoint.
295
+ * This only disambiguates when one protocol carries two mutually exclusive
296
+ * parameter shapes across model generations, and the older generation
297
+ * hard-rejects the newer field:
298
+ * - `google-generate-content`: Gemini 3 `thinkingLevel` vs 2.x `thinkingBudget`
299
+ * - `anthropic-messages`: Claude 4.6+ `thinking.type=adaptive` vs <=4.5
300
+ * `thinking.type=enabled` + `budget_tokens`
301
+ *
302
+ * Opus 5.5 always uses adaptive thinking; Sonnet 5.5 also supports `between_tools`.
303
+ * It has effect only where the format profile declares the matching alternative, so open-weight models on openai-compatible endpoints are
304
+ * unaffected (their dialect really does follow the provider — see the rule
305
+ * on {@link ReasoningFamilyRuleSchema}).
306
+ */
307
+ const ReasoningWireDialectSchema = zod.enum([
308
+ "effort",
309
+ "budget",
310
+ "adaptive-always",
311
+ "adaptive-between-tools"
312
+ ]);
313
+ /**
314
+ * A creator-declared reasoning FAMILY rule — ID-pattern knowledge as DATA
315
+ * (#16598). Creators declare these next to their models (`Creator.
316
+ * reasoningFamilies`); generation compiles them into per-model `controls`
317
+ * and the shipped `patterns/reasoning-families.gen.ts` artifact consumed by
318
+ * the zero-knowledge matchers.
319
+ *
320
+ * Every rule is one of two semantic kinds:
321
+ * - PROFILE (default): "this pattern IS a reasoning SKU (with knobs K)".
322
+ * Membership is implied — the ingest gate (`inferReasoningMembership`)
323
+ * accepts any id a profile rule matches. A profile may carry no knobs at
324
+ * all (a fixed reasoner: reasons, nothing to tune).
325
+ * - TEMPLATE (`template: true`): "models of this family that DO reason use
326
+ * knob shape K". Deliberately broader than membership (e.g. the `^qwen`
327
+ * toggle) — contributes knobs only, never membership; SKUs are admitted
328
+ * by profile rules, the generic id shapes, or a declared capability.
329
+ *
330
+ * A rule carries MODEL KNOBS ONLY — never a reasoning format/wire field:
331
+ * open-weight models are served by many providers and the serialization
332
+ * dialect follows the serving endpoint, not a runtime model-id match. The one
333
+ * narrow exception is `wireDialect`, which does NOT name a format: it picks
334
+ * between the generation-dialects a single first-party protocol defines
335
+ * for itself (see {@link ReasoningWireDialectSchema}). That fact is the
336
+ * vendor's own API contract and holds across every provider proxying it, so
337
+ * it belongs to the model, not the endpoint.
338
+ *
339
+ * Matching: `pattern` is a case-insensitive regex SOURCE tested against the
340
+ * lowercased, namespace-stripped id (vocabulary part) and the raw id string
341
+ * (budget part — token-limit callers pass `provider::model` unique ids, so
342
+ * budget-only rules should stay unanchored). Patterns must be
343
+ * vendor-specific (same discipline as `idPrefixes`). Within a creator,
344
+ * declaration order is match priority — first rule wins per part.
345
+ */
346
+ const compilableRegexSource = zod.string().refine((source) => {
347
+ try {
348
+ new RegExp(source, "i");
349
+ return true;
350
+ } catch {
351
+ return false;
352
+ }
353
+ }, { message: "pattern must be a valid regular expression" });
354
+ zod.object({
355
+ /** Case-insensitive regex source. Must compile. */
356
+ pattern: compilableRegexSource,
357
+ /** Intrinsic effort vocabulary, in UI display order. */
358
+ effort: looseArray(ReasoningEffortSchema, { min: 1 }).optional(),
359
+ /**
360
+ * Thinking on/off switch. `false` is an EXPLICIT "always-on, no switch"
361
+ * declaration that stops broader family rules below from applying
362
+ * (e.g. qwen3 `*-thinking` SKUs vs the generic qwen toggle).
363
+ */
364
+ toggle: zod.boolean().optional(),
365
+ /** Thinking-token budget range. */
366
+ budget: zod.object({
367
+ min: zod.number().nonnegative(),
368
+ max: zod.number().positive()
369
+ }).refine((b) => b.min <= b.max, { message: "budget min must be <= max" }).optional(),
370
+ /** Knob-shape template for a broad family — contributes NO membership. */
371
+ template: zod.literal(true).optional(),
372
+ /** Native-protocol dialect for this model generation. */
373
+ wireDialect: ReasoningWireDialectSchema.optional()
374
+ }).refine((rule) => rule.template !== true || rule.effort !== void 0 || rule.toggle !== void 0 || rule.budget !== void 0 || rule.wireDialect !== void 0, { message: "a template rule with no knobs declares nothing — drop it or make it a profile" });
375
+ const CommonReasoningFieldsSchema = {
376
+ /** Source of truth for the model's reasoning knobs (at most one per kind).
377
+ * The legacy fields below are DERIVED from it when present. */
378
+ controls: looseArray(ReasoningControlSchema).optional(),
379
+ thinkingTokenLimits: ThinkingTokenLimitsSchema.optional(),
380
+ supportedEfforts: looseArray(ReasoningEffortSchema).optional(),
381
+ /** What the API does when no reasoning param is sent. */
382
+ defaultEffort: ReasoningEffortSchema.optional(),
383
+ /** Native-protocol dialect this model generation speaks, when its protocol
384
+ * defines more than one. Selects the endpoint profile's wire variant. */
385
+ wireDialect: ReasoningWireDialectSchema.optional()
386
+ };
387
+ /**
388
+ * Reasoning support schema — describes model-level reasoning capabilities.
389
+ *
390
+ * This only captures WHAT the model supports (effort levels, token limits).
391
+ * HOW to invoke reasoning is defined by the provider's reasoning format
392
+ * (see provider.ts ProviderReasoningFormatSchema).
393
+ */
394
+ const ReasoningSupportSchema = zod.object({ ...CommonReasoningFieldsSchema }).superRefine((r, ctx) => {
395
+ const kinds = (r.controls ?? []).map((c) => c.kind);
396
+ if (new Set(kinds).size !== kinds.length) ctx.addIssue({
397
+ code: "custom",
398
+ message: "at most one reasoning control per kind"
399
+ });
400
+ for (const c of r.controls ?? []) {
401
+ if (c.kind === "effort" && c.default != null && !c.values.includes(c.default)) ctx.addIssue({
402
+ code: "custom",
403
+ message: "effort default must be a member of values"
404
+ });
405
+ if (c.kind === "budget" && (c.min > c.max || c.default != null && (c.default < c.min || c.default > c.max))) ctx.addIssue({
406
+ code: "custom",
407
+ message: "budget range must satisfy min <= default <= max"
408
+ });
409
+ }
410
+ });
411
+ /**
412
+ * Image-generation support describes what controls a model accepts, in a
413
+ * shape uniform across all models so the painting page can render the
414
+ * right controls without per-vendor branching.
415
+ *
416
+ * `supports` is a flat map of canonical param keys to widget specs — the
417
+ * renderer dispatches by `spec.type`. `size` / `numImages` / `customSize`
418
+ * are no longer top-level fields; they're entries inside `supports` like
419
+ * everything else. `modes` is `Record<Mode, ModeDef>` (always an object,
420
+ * never an array) so single-mode models declare `{ generate: { ... } }`
421
+ * uniformly; multi-mode models with different params per mode (Ideogram
422
+ * V_*) declare each mode's complete `ModeDef` explicitly.
423
+ *
424
+ * Vendor wire transforms (snake_case keys, `'ASPECT_X_Y' → 'X:Y'` strings,
425
+ * `Uint8Array → base64`) live in the AI SDK image-model adapters under
426
+ * `aiCore/provider/custom/`; this schema carries canonical names only.
427
+ * Per-mode transport routing (PPIO endpoint URL + sync/async flag) lives
428
+ * on `ModeDef.vendorTransport` so it travels with the registry data.
429
+ */
430
+ const ImageGenerationModeSchema = zod.enum([
431
+ "generate",
432
+ "edit",
433
+ "remix",
434
+ "upscale",
435
+ "merge"
436
+ ]);
437
+ const SwitchSpecSchema = zod.object({
438
+ type: zod.literal("switch"),
439
+ default: zod.boolean().optional()
440
+ });
441
+ const EnumSpecSchema = zod.object({
442
+ type: zod.literal("enum"),
443
+ options: zod.array(zod.string()).min(1),
444
+ default: zod.string().optional(),
445
+ /** `'chips'` for compact button rows (size / aspectRatio / imageResolution);
446
+ * defaults to `'select'` (dropdown) when omitted. */
447
+ render: zod.enum(["select", "chips"]).optional(),
448
+ columns: zod.number().int().positive().optional()
449
+ });
450
+ const RangeSpecSchema = zod.object({
451
+ type: zod.literal("range"),
452
+ min: zod.number(),
453
+ max: zod.number(),
454
+ default: zod.number().optional(),
455
+ /** Omitted means the numeric input accepts any precision; renderers may
456
+ * still choose an interaction step for controls such as sliders. */
457
+ step: zod.number().optional()
458
+ }).refine((r) => r.min <= r.max, { message: "min must be ≤ max" });
459
+ const RangeIntSpecSchema = zod.object({
460
+ type: zod.literal("range"),
461
+ min: zod.number().int(),
462
+ max: zod.number().int(),
463
+ default: zod.number().int().optional(),
464
+ step: zod.number().int().positive().default(1)
465
+ }).refine((r) => r.min <= r.max, { message: "min must be ≤ max" });
466
+ const SizeSpecSchema = zod.object({
467
+ type: zod.literal("size"),
468
+ /** Both width and height share this bound. */
469
+ minSide: zod.number(),
470
+ maxSide: zod.number(),
471
+ /** When set, the size widget only renders when the named enum is at
472
+ * `'custom'` (CogView pattern: pick the `'custom'` chip on the size
473
+ * enum to reveal width/height inputs). */
474
+ pairedEnumKey: zod.string().optional()
475
+ });
476
+ const TextSpecSchema = zod.object({
477
+ type: zod.literal("text"),
478
+ multiline: zod.boolean().optional()
479
+ });
480
+ const SupportSpecSchema = zod.discriminatedUnion("type", [
481
+ SwitchSpecSchema,
482
+ EnumSpecSchema,
483
+ RangeSpecSchema,
484
+ SizeSpecSchema,
485
+ TextSpecSchema
486
+ ]);
487
+ const INTEGER_RANGE_PARAM_KEYS = [
488
+ CANONICAL_PARAM_KEY.NUM_IMAGES,
489
+ CANONICAL_PARAM_KEY.MAX_IMAGES,
490
+ CANONICAL_PARAM_KEY.NUM_INFERENCE_STEPS,
491
+ CANONICAL_PARAM_KEY.SAFETY_TOLERANCE,
492
+ CANONICAL_PARAM_KEY.OUTPUT_COMPRESSION
493
+ ];
494
+ const ImageSupportsSchema = zod.partialRecord(CanonicalParamKeySchema, SupportSpecSchema).transform((supports, ctx) => {
495
+ const normalized = { ...supports };
496
+ for (const key of INTEGER_RANGE_PARAM_KEYS) {
497
+ const spec = supports[key];
498
+ if (spec === void 0) continue;
499
+ const result = RangeIntSpecSchema.safeParse(spec);
500
+ if (result.success) normalized[key] = result.data;
501
+ else for (const issue of result.error.issues) ctx.addIssue({
502
+ ...issue,
503
+ path: [key, ...issue.path]
504
+ });
505
+ }
506
+ return normalized;
507
+ });
508
+ /**
509
+ * Per-mode model capability declaration. The renderer iterates `supports`
510
+ * and dispatches `specToField` by `spec.type`; no per-vendor logic. `supports`
511
+ * keys are drawn from the closed `CanonicalParamKey` vocabulary (see
512
+ * `CANONICAL_PARAM_KEY` in `enums.ts`) — an unknown key fails to parse, and
513
+ * the same vocabulary types the form's `KEY_LABELS`/`OPTION_LABELS` and
514
+ * `canonicalGenerate`'s `POSITIONAL_RENAME`, so a typo/rename is a compile or
515
+ * parse error rather than a silent raw-key render. Adding a new canonical
516
+ * param: (1) add the member to `CANONICAL_PARAM_KEY`, (2) add a label to
517
+ * `KEY_LABELS` in `imageGenerationToFields`, (3) declare it on models'
518
+ * `supports`.
519
+ *
520
+ * `vendorTransport` carries PPIO-style per-model endpoint routing — the
521
+ * AI SDK adapter for that vendor reads endpoint + isSync off the registry
522
+ * instead of a hand-maintained routing table.
523
+ */
524
+ const ImageModeDefSchema = zod.object({
525
+ supports: ImageSupportsSchema,
526
+ maxInputImages: zod.number().int().positive().optional(),
527
+ vendorTransport: zod.object({
528
+ endpoint: zod.string().regex(/^\/(?!\/)/, "vendor transport endpoint must be a root-relative path, not a URL"),
529
+ isSync: zod.boolean().optional()
530
+ }).optional(),
531
+ /**
532
+ * When `false`, the generic painting pipeline does NOT enforce a non-empty
533
+ * `painting.prompt` before submitting. Set on models like DashScope's
534
+ * `qwen-mt-image` (image-text translation: no prompt, just source/target
535
+ * languages) or PPIO's image-upscaler / image-eraser / image-remove-bg
536
+ * variants. Default is `true` (prompt required).
537
+ */
538
+ requirePrompt: zod.boolean().optional()
539
+ });
540
+ const ImageGenerationSupportSchema = zod.object({ modes: zod.partialRecord(ImageGenerationModeSchema, ImageModeDefSchema) });
541
+ const ParameterSupportSchema = zod.object({
542
+ temperature: zod.object({
543
+ supported: zod.boolean(),
544
+ range: NumericRangeSchema.optional()
545
+ }).default({ supported: true }),
546
+ topP: zod.object({
547
+ supported: zod.boolean(),
548
+ range: NumericRangeSchema.optional()
549
+ }).default({ supported: true }),
550
+ topK: zod.object({
551
+ supported: zod.boolean(),
552
+ range: NumericRangeSchema.optional()
553
+ }).default({ supported: false }),
554
+ frequencyPenalty: zod.boolean().default(true),
555
+ presencePenalty: zod.boolean().default(true),
556
+ maxTokens: zod.boolean().default(true),
557
+ stopSequences: zod.boolean().default(true),
558
+ systemMessage: zod.boolean().default(true)
559
+ });
560
+ /**
561
+ * Model pricing configuration.
562
+ *
563
+ * Pricing tiers based on actual provider billing models:
564
+ * - input/output per-token: OpenAI, Anthropic, Google, all major LLM providers
565
+ * - cacheRead/cacheWrite: Anthropic prompt caching, OpenAI cached tokens
566
+ * - perImage: DALL-E (per-image), Midjourney (per-image)
567
+ * - perMinute: Whisper, ElevenLabs (per-minute audio billing)
568
+ */
569
+ const ModelPricingObjectSchema = zod.object({
570
+ input: PricePerTokenSchema,
571
+ output: PricePerTokenSchema,
572
+ cacheRead: PricePerTokenSchema.optional(),
573
+ cacheWrite: PricePerTokenSchema.optional(),
574
+ inputTokenTiers: zod.array(zod.object({
575
+ minInputTokens: zod.number().int().positive().refine(Number.isSafeInteger),
576
+ input: PricePerTokenSchema,
577
+ output: PricePerTokenSchema,
578
+ cacheRead: PricePerTokenSchema.optional(),
579
+ cacheWrite: PricePerTokenSchema.optional()
580
+ })).optional(),
581
+ perImage: zod.object({
582
+ price: zod.number(),
583
+ currency: ZodCurrencySchema,
584
+ unit: zod.enum(["image", "pixel"]).optional()
585
+ }).optional(),
586
+ perMinute: zod.object({
587
+ price: zod.number(),
588
+ currency: ZodCurrencySchema
589
+ }).optional()
590
+ });
591
+ function validateInputTokenPricingTiers(pricing, ctx) {
592
+ for (let index = 1; index < (pricing.inputTokenTiers?.length ?? 0); index++) if (pricing.inputTokenTiers[index].minInputTokens <= pricing.inputTokenTiers[index - 1].minInputTokens) ctx.addIssue({
593
+ code: "custom",
594
+ path: [
595
+ "inputTokenTiers",
596
+ index,
597
+ "minInputTokens"
598
+ ],
599
+ message: "minInputTokens must be strictly increasing"
600
+ });
601
+ if (!pricing.inputTokenTiers?.length) return;
602
+ const rates = [
603
+ ...pricing.input ? [{
604
+ rate: pricing.input,
605
+ path: ["input"]
606
+ }] : [],
607
+ ...pricing.output ? [{
608
+ rate: pricing.output,
609
+ path: ["output"]
610
+ }] : [],
611
+ ...pricing.cacheRead ? [{
612
+ rate: pricing.cacheRead,
613
+ path: ["cacheRead"]
614
+ }] : [],
615
+ ...pricing.cacheWrite ? [{
616
+ rate: pricing.cacheWrite,
617
+ path: ["cacheWrite"]
618
+ }] : [],
619
+ ...pricing.inputTokenTiers.flatMap((tier, index) => [
620
+ {
621
+ rate: tier.input,
622
+ path: [
623
+ "inputTokenTiers",
624
+ index,
625
+ "input"
626
+ ]
627
+ },
628
+ {
629
+ rate: tier.output,
630
+ path: [
631
+ "inputTokenTiers",
632
+ index,
633
+ "output"
634
+ ]
635
+ },
636
+ ...tier.cacheRead ? [{
637
+ rate: tier.cacheRead,
638
+ path: [
639
+ "inputTokenTiers",
640
+ index,
641
+ "cacheRead"
642
+ ]
643
+ }] : [],
644
+ ...tier.cacheWrite ? [{
645
+ rate: tier.cacheWrite,
646
+ path: [
647
+ "inputTokenTiers",
648
+ index,
649
+ "cacheWrite"
650
+ ]
651
+ }] : []
652
+ ])
653
+ ];
654
+ const currency = rates[0]?.rate.currency ?? CURRENCY.USD;
655
+ for (const { rate, path } of rates) if ((rate.currency ?? CURRENCY.USD) !== currency) ctx.addIssue({
656
+ code: "custom",
657
+ path: [...path, "currency"],
658
+ message: "pricing currencies must match"
659
+ });
660
+ }
661
+ const ModelPricingSchema = ModelPricingObjectSchema.superRefine(validateInputTokenPricingTiers);
662
+ const PartialModelPricingSchema = ModelPricingObjectSchema.partial().superRefine(validateInputTokenPricingTiers);
663
+ const ModelConfigSchema = zod.object({
664
+ id: ModelIdSchema,
665
+ name: zod.string(),
666
+ description: zod.string().optional(),
667
+ capabilities: looseArray(ModelCapabilityTypeSchema).refine((arr) => new Set(arr).size === arr.length, { message: "Capabilities must be unique" }).optional(),
668
+ inputModalities: looseArray(ModalitySchema).refine((arr) => new Set(arr).size === arr.length, { message: "Input modalities must be unique" }).optional(),
669
+ outputModalities: looseArray(ModalitySchema).refine((arr) => new Set(arr).size === arr.length, { message: "Output modalities must be unique" }).optional(),
670
+ endpointTypes: looseArray(EndpointTypeSchema).optional(),
671
+ contextWindow: zod.number().optional(),
672
+ maxOutputTokens: zod.number().optional(),
673
+ maxInputTokens: zod.number().optional(),
674
+ pricing: ModelPricingSchema.optional(),
675
+ reasoning: ReasoningSupportSchema.optional(),
676
+ parameterSupport: ParameterSupportSchema.optional(),
677
+ imageGeneration: ImageGenerationSupportSchema.optional(),
678
+ family: zod.string().optional(),
679
+ ownedBy: zod.string().optional(),
680
+ openWeights: zod.boolean().optional(),
681
+ metadata: MetadataSchema
682
+ });
683
+ const ModelListSchema = zod.object({
684
+ version: VersionSchema,
685
+ models: looseArray(ModelConfigSchema)
686
+ });
687
+ //#endregion
688
+ Object.defineProperty(exports, "CANONICAL_PARAM_KEY", {
689
+ enumerable: true,
690
+ get: function() {
691
+ return CANONICAL_PARAM_KEY;
692
+ }
693
+ });
694
+ Object.defineProperty(exports, "CURRENCY", {
695
+ enumerable: true,
696
+ get: function() {
697
+ return CURRENCY;
698
+ }
699
+ });
700
+ Object.defineProperty(exports, "ENDPOINT_TYPE", {
701
+ enumerable: true,
702
+ get: function() {
703
+ return ENDPOINT_TYPE;
704
+ }
705
+ });
706
+ Object.defineProperty(exports, "EndpointTypeSchema", {
707
+ enumerable: true,
708
+ get: function() {
709
+ return EndpointTypeSchema;
710
+ }
711
+ });
712
+ Object.defineProperty(exports, "ImageGenerationModeSchema", {
713
+ enumerable: true,
714
+ get: function() {
715
+ return ImageGenerationModeSchema;
716
+ }
717
+ });
718
+ Object.defineProperty(exports, "ImageGenerationSupportSchema", {
719
+ enumerable: true,
720
+ get: function() {
721
+ return ImageGenerationSupportSchema;
722
+ }
723
+ });
724
+ Object.defineProperty(exports, "MODALITY", {
725
+ enumerable: true,
726
+ get: function() {
727
+ return MODALITY;
728
+ }
729
+ });
730
+ Object.defineProperty(exports, "MODEL_CAPABILITY", {
731
+ enumerable: true,
732
+ get: function() {
733
+ return MODEL_CAPABILITY;
734
+ }
735
+ });
736
+ Object.defineProperty(exports, "MetadataSchema", {
737
+ enumerable: true,
738
+ get: function() {
739
+ return MetadataSchema;
740
+ }
741
+ });
742
+ Object.defineProperty(exports, "ModalitySchema", {
743
+ enumerable: true,
744
+ get: function() {
745
+ return ModalitySchema;
746
+ }
747
+ });
748
+ Object.defineProperty(exports, "ModelCapabilityTypeSchema", {
749
+ enumerable: true,
750
+ get: function() {
751
+ return ModelCapabilityTypeSchema;
752
+ }
753
+ });
754
+ Object.defineProperty(exports, "ModelConfigSchema", {
755
+ enumerable: true,
756
+ get: function() {
757
+ return ModelConfigSchema;
758
+ }
759
+ });
760
+ Object.defineProperty(exports, "ModelIdSchema", {
761
+ enumerable: true,
762
+ get: function() {
763
+ return ModelIdSchema;
764
+ }
765
+ });
766
+ Object.defineProperty(exports, "ModelListSchema", {
767
+ enumerable: true,
768
+ get: function() {
769
+ return ModelListSchema;
770
+ }
771
+ });
772
+ Object.defineProperty(exports, "ParameterSupportSchema", {
773
+ enumerable: true,
774
+ get: function() {
775
+ return ParameterSupportSchema;
776
+ }
777
+ });
778
+ Object.defineProperty(exports, "PartialModelPricingSchema", {
779
+ enumerable: true,
780
+ get: function() {
781
+ return PartialModelPricingSchema;
782
+ }
783
+ });
784
+ Object.defineProperty(exports, "ProviderIdSchema", {
785
+ enumerable: true,
786
+ get: function() {
787
+ return ProviderIdSchema;
788
+ }
789
+ });
790
+ Object.defineProperty(exports, "REASONING_EFFORT", {
791
+ enumerable: true,
792
+ get: function() {
793
+ return REASONING_EFFORT;
794
+ }
795
+ });
796
+ Object.defineProperty(exports, "REASONING_EFFORT_ORDER", {
797
+ enumerable: true,
798
+ get: function() {
799
+ return REASONING_EFFORT_ORDER;
800
+ }
801
+ });
802
+ Object.defineProperty(exports, "ReasoningControlSchema", {
803
+ enumerable: true,
804
+ get: function() {
805
+ return ReasoningControlSchema;
806
+ }
807
+ });
808
+ Object.defineProperty(exports, "ReasoningSupportSchema", {
809
+ enumerable: true,
810
+ get: function() {
811
+ return ReasoningSupportSchema;
812
+ }
813
+ });
814
+ Object.defineProperty(exports, "SERVER_TOOL", {
815
+ enumerable: true,
816
+ get: function() {
817
+ return SERVER_TOOL;
818
+ }
819
+ });
820
+ Object.defineProperty(exports, "SERVER_TOOL_MODEL_SCOPE", {
821
+ enumerable: true,
822
+ get: function() {
823
+ return SERVER_TOOL_MODEL_SCOPE;
824
+ }
825
+ });
826
+ Object.defineProperty(exports, "VersionSchema", {
827
+ enumerable: true,
828
+ get: function() {
829
+ return VersionSchema;
830
+ }
831
+ });
832
+ Object.defineProperty(exports, "ZodCurrencySchema", {
833
+ enumerable: true,
834
+ get: function() {
835
+ return ZodCurrencySchema;
836
+ }
837
+ });
838
+ Object.defineProperty(exports, "__toESM", {
839
+ enumerable: true,
840
+ get: function() {
841
+ return __toESM;
842
+ }
843
+ });
844
+ Object.defineProperty(exports, "looseArray", {
845
+ enumerable: true,
846
+ get: function() {
847
+ return looseArray;
848
+ }
849
+ });
850
+ Object.defineProperty(exports, "objectValues", {
851
+ enumerable: true,
852
+ get: function() {
853
+ return objectValues;
854
+ }
855
+ });