llm-strings 1.4.0 → 1.5.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.
@@ -24,7 +24,6 @@ __export(providers_exports, {
24
24
  CACHE_TTLS: () => CACHE_TTLS,
25
25
  CACHE_VALUES: () => CACHE_VALUES,
26
26
  CANONICAL_PARAM_SPECS: () => CANONICAL_PARAM_SPECS,
27
- DURATION_RE: () => DURATION_RE,
28
27
  HOST_ALIASES: () => HOST_ALIASES,
29
28
  PARAM_SPECS: () => PARAM_SPECS,
30
29
  PROVIDER_META: () => PROVIDER_META,
@@ -37,6 +36,7 @@ __export(providers_exports, {
37
36
  detectProvider: () => detectProvider,
38
37
  isGatewayProvider: () => isGatewayProvider,
39
38
  isReasoningModel: () => isReasoningModel,
39
+ modelMatchesFamily: () => modelMatchesFamily,
40
40
  providerFromHostAlias: () => providerFromHostAlias,
41
41
  resolveHostAlias: () => resolveHostAlias
42
42
  });
@@ -157,44 +157,92 @@ function providerFromHostAlias(alias) {
157
157
  }
158
158
  return void 0;
159
159
  }
160
+ function canonicalHostName(host) {
161
+ return normalizeHostValue(host).toLowerCase().split(":")[0] ?? host;
162
+ }
163
+ function hostMatches(host, ...domains) {
164
+ return domains.some((domain) => {
165
+ const normalizedDomain = domain.toLowerCase();
166
+ return host === normalizedDomain || host.endsWith(`.${normalizedDomain}`);
167
+ });
168
+ }
169
+ function hostHasLabel(host, ...labels) {
170
+ const hostLabels = host.split(".");
171
+ return labels.some((label) => hostLabels.includes(label.toLowerCase()));
172
+ }
173
+ function hostHasLabelPrefix(host, ...prefixes) {
174
+ const hostLabels = host.split(".");
175
+ return prefixes.some(
176
+ (prefix) => hostLabels.some((label) => label.startsWith(prefix.toLowerCase()))
177
+ );
178
+ }
179
+ var MODEL_FAMILY_DELIMITERS = /* @__PURE__ */ new Set(["-", "."]);
180
+ function normalizeModelForMatching(model) {
181
+ return model.trim().toLowerCase();
182
+ }
183
+ function modelLeafName(model) {
184
+ const normalized = normalizeModelForMatching(model);
185
+ const slash = normalized.lastIndexOf("/");
186
+ return slash >= 0 ? normalized.slice(slash + 1) : normalized;
187
+ }
188
+ function modelMatchesFamily(model, family) {
189
+ const name = modelLeafName(model);
190
+ const normalizedFamily = normalizeModelForMatching(family);
191
+ if (!name || !normalizedFamily) return false;
192
+ if (name === normalizedFamily) return true;
193
+ const delimiter = name[normalizedFamily.length];
194
+ return name.startsWith(normalizedFamily) && delimiter !== void 0 && MODEL_FAMILY_DELIMITERS.has(delimiter);
195
+ }
160
196
  function detectProvider(host) {
161
- host = host.toLowerCase();
162
- if (host.includes("openrouter")) return "openrouter";
163
- if (host.includes("gateway.ai.vercel")) return "vercel";
164
- if (host.includes("amazonaws") || host.includes("bedrock")) return "bedrock";
165
- if (host.includes("aiplatform.googleapis")) return "google-vertex";
166
- if (host.includes("api.x.ai")) return "xai";
167
- if (host.includes("groq")) return "groq";
168
- if (host.includes("fal.run") || host.includes("fal.ai")) return "fal";
169
- if (host.includes("deepinfra")) return "deepinfra";
170
- if (host.includes("bfl.ai")) return "black-forest-labs";
171
- if (host.includes("together")) return "together";
172
- if (host.includes("fireworks")) return "fireworks";
173
- if (host.includes("deepseek")) return "deepseek";
174
- if (host.includes("moonshot")) return "moonshotai";
175
- if (host.includes("perplexity")) return "perplexity";
176
- if (host.includes("dashscope") || host.includes("aliyuncs")) return "alibaba";
177
- if (host.includes("cerebras")) return "cerebras";
178
- if (host.includes("replicate")) return "replicate";
179
- if (host.includes("prodia")) return "prodia";
180
- if (host.includes("lumalabs") || host.includes("luma")) return "luma";
181
- if (host.includes("volces") || host.includes("bytedance")) return "bytedance";
182
- if (host.includes("kling")) return "kling";
183
- if (host.includes("elevenlabs")) return "elevenlabs";
184
- if (host.includes("assemblyai")) return "assemblyai";
185
- if (host.includes("deepgram")) return "deepgram";
186
- if (host.includes("gladia")) return "gladia";
187
- if (host.includes("lmnt")) return "lmnt";
188
- if (host.includes("hume")) return "hume";
189
- if (host.includes("rev.ai")) return "revai";
190
- if (host.includes("baseten")) return "baseten";
191
- if (host.includes("huggingface")) return "huggingface";
192
- if (host.includes("azure")) return "azure";
193
- if (host.includes("openai")) return "openai";
194
- if (host.includes("anthropic") || host.includes("claude")) return "anthropic";
195
- if (host.includes("googleapis") || host.includes("google")) return "google";
196
- if (host.includes("mistral")) return "mistral";
197
- if (host.includes("cohere")) return "cohere";
197
+ host = canonicalHostName(host);
198
+ if (hostMatches(host, "openrouter", "openrouter.ai")) return "openrouter";
199
+ if (hostMatches(host, "vercel", "gateway.ai.vercel.app", "gateway.ai.vercel.sh")) {
200
+ return "vercel";
201
+ }
202
+ if (hostMatches(host, "bedrock", "amazonaws.com") || hostHasLabelPrefix(host, "bedrock")) {
203
+ return "bedrock";
204
+ }
205
+ if (hostMatches(host, "aiplatform.googleapis.com")) return "google-vertex";
206
+ if (hostMatches(host, "xai", "x.ai", "api.x.ai")) return "xai";
207
+ if (hostMatches(host, "groq", "groq.com", "api.groq.com")) return "groq";
208
+ if (hostMatches(host, "fal", "fal.run", "fal.ai")) return "fal";
209
+ if (hostMatches(host, "deepinfra", "deepinfra.com")) return "deepinfra";
210
+ if (hostMatches(host, "bfl", "bfl.ai", "api.bfl.ai")) {
211
+ return "black-forest-labs";
212
+ }
213
+ if (hostMatches(host, "together", "together.xyz")) return "together";
214
+ if (hostMatches(host, "fireworks", "fireworks.ai")) return "fireworks";
215
+ if (hostMatches(host, "deepseek", "deepseek.com")) return "deepseek";
216
+ if (hostMatches(host, "moonshot", "moonshot.ai")) return "moonshotai";
217
+ if (hostMatches(host, "perplexity", "perplexity.ai")) return "perplexity";
218
+ if (hostMatches(host, "alibaba", "aliyuncs.com") || hostHasLabelPrefix(host, "dashscope")) {
219
+ return "alibaba";
220
+ }
221
+ if (hostMatches(host, "cerebras", "cerebras.ai")) return "cerebras";
222
+ if (hostMatches(host, "replicate", "replicate.com")) return "replicate";
223
+ if (hostMatches(host, "prodia", "prodia.com")) return "prodia";
224
+ if (hostMatches(host, "luma", "lumalabs.ai")) return "luma";
225
+ if (hostMatches(host, "bytedance", "volces.com") || hostHasLabel(host, "bytedance")) {
226
+ return "bytedance";
227
+ }
228
+ if (hostMatches(host, "kling", "klingai.com")) return "kling";
229
+ if (hostMatches(host, "elevenlabs", "elevenlabs.io")) return "elevenlabs";
230
+ if (hostMatches(host, "assemblyai", "assemblyai.com")) return "assemblyai";
231
+ if (hostMatches(host, "deepgram", "deepgram.com")) return "deepgram";
232
+ if (hostMatches(host, "gladia", "gladia.io")) return "gladia";
233
+ if (hostMatches(host, "lmnt", "lmnt.com")) return "lmnt";
234
+ if (hostMatches(host, "hume", "hume.ai")) return "hume";
235
+ if (hostMatches(host, "revai", "rev.ai")) return "revai";
236
+ if (hostMatches(host, "baseten", "baseten.co")) return "baseten";
237
+ if (hostMatches(host, "huggingface", "huggingface.co")) return "huggingface";
238
+ if (hostMatches(host, "azure", "azure.com")) return "azure";
239
+ if (hostMatches(host, "openai", "openai.com")) return "openai";
240
+ if (hostMatches(host, "anthropic", "anthropic.com", "claude.ai")) {
241
+ return "anthropic";
242
+ }
243
+ if (hostMatches(host, "google", "googleapis.com")) return "google";
244
+ if (hostMatches(host, "mistral", "mistral.ai")) return "mistral";
245
+ if (hostMatches(host, "cohere", "cohere.com")) return "cohere";
198
246
  return void 0;
199
247
  }
200
248
  var ALIASES = {
@@ -237,7 +285,10 @@ var ALIASES = {
237
285
  num_completions: "n",
238
286
  // effort / reasoning
239
287
  reasoning_effort: "effort",
288
+ reasoningEffort: "effort",
240
289
  reasoning: "effort",
290
+ thinking_effort: "effort",
291
+ thinkingEffort: "effort",
241
292
  // cache
242
293
  cache_control: "cache",
243
294
  cacheControl: "cache",
@@ -247,6 +298,7 @@ var ALIASES = {
247
298
  var OPENAI_COMPATIBLE_PARAMS = {
248
299
  temperature: "temperature",
249
300
  max_tokens: "max_tokens",
301
+ max_completion_tokens: "max_completion_tokens",
250
302
  top_p: "top_p",
251
303
  top_k: "top_k",
252
304
  frequency_penalty: "frequency_penalty",
@@ -257,6 +309,90 @@ var OPENAI_COMPATIBLE_PARAMS = {
257
309
  stream: "stream",
258
310
  effort: "reasoning_effort"
259
311
  };
312
+ var COMMON_IMAGE_PARAMS = {
313
+ prompt: "prompt",
314
+ negative_prompt: "negative_prompt",
315
+ seed: "seed",
316
+ image_size: "image_size",
317
+ aspect_ratio: "aspect_ratio",
318
+ output_format: "output_format",
319
+ width: "width",
320
+ height: "height"
321
+ };
322
+ var FAL_PARAMS = {
323
+ ...COMMON_IMAGE_PARAMS,
324
+ num_images: "num_images",
325
+ enable_safety_checker: "enable_safety_checker",
326
+ enable_safety_checks: "enable_safety_checks",
327
+ enable_prompt_expansion: "enable_prompt_expansion",
328
+ expand_prompt: "expand_prompt"
329
+ };
330
+ var REPLICATE_PARAMS = {
331
+ ...COMMON_IMAGE_PARAMS,
332
+ input: "input",
333
+ version: "version",
334
+ num_outputs: "num_outputs",
335
+ num_inference_steps: "num_inference_steps",
336
+ guidance_scale: "guidance_scale",
337
+ stream: "stream",
338
+ webhook: "webhook",
339
+ webhook_events_filter: "webhook_events_filter"
340
+ };
341
+ var PRODIA_PARAMS = {
342
+ ...COMMON_IMAGE_PARAMS,
343
+ model: "model",
344
+ style_preset: "style_preset",
345
+ steps: "steps",
346
+ cfg_scale: "cfg_scale",
347
+ upscale: "upscale",
348
+ sampler: "sampler",
349
+ type: "type",
350
+ config: "config",
351
+ price: "price"
352
+ };
353
+ var LUMA_PARAMS = {
354
+ prompt: "prompt",
355
+ model: "model",
356
+ aspect_ratio: "aspect_ratio",
357
+ keyframes: "keyframes",
358
+ loop: "loop",
359
+ duration: "duration",
360
+ type: "type",
361
+ image_ref: "image_ref",
362
+ video: "video",
363
+ source: "source"
364
+ };
365
+ var OPENROUTER_ROUTING_PARAMS = {
366
+ provider: "provider",
367
+ order: "order",
368
+ "provider.order": "provider.order",
369
+ only: "only",
370
+ "provider.only": "provider.only",
371
+ ignore: "ignore",
372
+ "provider.ignore": "provider.ignore",
373
+ allow_fallbacks: "allow_fallbacks",
374
+ "provider.allow_fallbacks": "provider.allow_fallbacks",
375
+ require_parameters: "require_parameters",
376
+ "provider.require_parameters": "provider.require_parameters",
377
+ data_collection: "data_collection",
378
+ "provider.data_collection": "provider.data_collection",
379
+ zdr: "zdr",
380
+ "provider.zdr": "provider.zdr",
381
+ enforce_distillable_text: "enforce_distillable_text",
382
+ "provider.enforce_distillable_text": "provider.enforce_distillable_text",
383
+ quantizations: "quantizations",
384
+ "provider.quantizations": "provider.quantizations",
385
+ sort: "sort",
386
+ "provider.sort": "provider.sort",
387
+ preferred_min_throughput: "preferred_min_throughput",
388
+ "provider.preferred_min_throughput": "provider.preferred_min_throughput",
389
+ preferred_max_latency: "preferred_max_latency",
390
+ "provider.preferred_max_latency": "provider.preferred_max_latency",
391
+ max_price: "max_price",
392
+ "provider.max_price": "provider.max_price",
393
+ transforms: "transforms",
394
+ plugins: "plugins"
395
+ };
260
396
  var GOOGLE_COMPATIBLE_PARAMS = {
261
397
  temperature: "temperature",
262
398
  max_tokens: "maxOutputTokens",
@@ -275,6 +411,7 @@ var PROVIDER_PARAMS = {
275
411
  openai: {
276
412
  temperature: "temperature",
277
413
  max_tokens: "max_tokens",
414
+ max_completion_tokens: "max_completion_tokens",
278
415
  top_p: "top_p",
279
416
  frequency_penalty: "frequency_penalty",
280
417
  presence_penalty: "presence_penalty",
@@ -351,6 +488,7 @@ var PROVIDER_PARAMS = {
351
488
  // OpenAI-compatible API with extra routing params
352
489
  temperature: "temperature",
353
490
  max_tokens: "max_tokens",
491
+ max_completion_tokens: "max_completion_tokens",
354
492
  top_p: "top_p",
355
493
  top_k: "top_k",
356
494
  frequency_penalty: "frequency_penalty",
@@ -359,12 +497,14 @@ var PROVIDER_PARAMS = {
359
497
  n: "n",
360
498
  seed: "seed",
361
499
  stream: "stream",
362
- effort: "reasoning_effort"
500
+ effort: "reasoning_effort",
501
+ ...OPENROUTER_ROUTING_PARAMS
363
502
  },
364
503
  vercel: {
365
504
  // OpenAI-compatible gateway
366
505
  temperature: "temperature",
367
506
  max_tokens: "max_tokens",
507
+ max_completion_tokens: "max_completion_tokens",
368
508
  top_p: "top_p",
369
509
  top_k: "top_k",
370
510
  frequency_penalty: "frequency_penalty",
@@ -377,7 +517,7 @@ var PROVIDER_PARAMS = {
377
517
  },
378
518
  xai: OPENAI_COMPATIBLE_PARAMS,
379
519
  groq: OPENAI_COMPATIBLE_PARAMS,
380
- fal: {},
520
+ fal: FAL_PARAMS,
381
521
  deepinfra: OPENAI_COMPATIBLE_PARAMS,
382
522
  "black-forest-labs": {},
383
523
  together: OPENAI_COMPATIBLE_PARAMS,
@@ -387,9 +527,9 @@ var PROVIDER_PARAMS = {
387
527
  perplexity: OPENAI_COMPATIBLE_PARAMS,
388
528
  alibaba: OPENAI_COMPATIBLE_PARAMS,
389
529
  cerebras: OPENAI_COMPATIBLE_PARAMS,
390
- replicate: {},
391
- prodia: {},
392
- luma: {},
530
+ replicate: REPLICATE_PARAMS,
531
+ prodia: PRODIA_PARAMS,
532
+ luma: LUMA_PARAMS,
393
533
  bytedance: {},
394
534
  kling: {},
395
535
  elevenlabs: {},
@@ -402,6 +542,15 @@ var PROVIDER_PARAMS = {
402
542
  baseten: OPENAI_COMPATIBLE_PARAMS,
403
543
  huggingface: OPENAI_COMPATIBLE_PARAMS
404
544
  };
545
+ var REASONING_EFFORT_VALUES = [
546
+ "none",
547
+ "minimal",
548
+ "low",
549
+ "medium",
550
+ "high",
551
+ "xhigh",
552
+ "max"
553
+ ];
405
554
  var OPENAI_COMPATIBLE_PARAM_SPECS = {
406
555
  temperature: {
407
556
  type: "number",
@@ -416,6 +565,12 @@ var OPENAI_COMPATIBLE_PARAM_SPECS = {
416
565
  default: 4096,
417
566
  description: "Maximum output tokens"
418
567
  },
568
+ max_completion_tokens: {
569
+ type: "number",
570
+ min: 1,
571
+ default: 4096,
572
+ description: "Maximum completion tokens (reasoning models)"
573
+ },
419
574
  top_p: {
420
575
  type: "number",
421
576
  min: 0,
@@ -449,11 +604,221 @@ var OPENAI_COMPATIBLE_PARAM_SPECS = {
449
604
  stream: { type: "boolean", default: false, description: "Stream response" },
450
605
  reasoning_effort: {
451
606
  type: "string",
452
- values: ["none", "minimal", "low", "medium", "high", "xhigh"],
607
+ values: REASONING_EFFORT_VALUES,
453
608
  default: "medium",
454
609
  description: "Reasoning effort"
455
610
  }
456
611
  };
612
+ var OPENROUTER_ROUTING_PARAM_SPECS = {
613
+ provider: { type: "string", description: "Provider routing preferences" },
614
+ order: { type: "string", description: "Provider order" },
615
+ "provider.order": { type: "string", description: "Provider order" },
616
+ only: { type: "string", description: "Provider allowlist" },
617
+ "provider.only": { type: "string", description: "Provider allowlist" },
618
+ ignore: { type: "string", description: "Provider blocklist" },
619
+ "provider.ignore": { type: "string", description: "Provider blocklist" },
620
+ allow_fallbacks: {
621
+ type: "boolean",
622
+ default: true,
623
+ description: "Allow fallback providers"
624
+ },
625
+ "provider.allow_fallbacks": {
626
+ type: "boolean",
627
+ default: true,
628
+ description: "Allow fallback providers"
629
+ },
630
+ require_parameters: {
631
+ type: "boolean",
632
+ default: false,
633
+ description: "Only route to providers that support all request params"
634
+ },
635
+ "provider.require_parameters": {
636
+ type: "boolean",
637
+ default: false,
638
+ description: "Only route to providers that support all request params"
639
+ },
640
+ data_collection: {
641
+ type: "string",
642
+ values: ["allow", "deny"],
643
+ default: "allow",
644
+ description: "Provider data collection policy"
645
+ },
646
+ "provider.data_collection": {
647
+ type: "string",
648
+ values: ["allow", "deny"],
649
+ default: "allow",
650
+ description: "Provider data collection policy"
651
+ },
652
+ zdr: {
653
+ type: "boolean",
654
+ description: "Require zero data retention providers"
655
+ },
656
+ "provider.zdr": {
657
+ type: "boolean",
658
+ description: "Require zero data retention providers"
659
+ },
660
+ enforce_distillable_text: {
661
+ type: "boolean",
662
+ description: "Require providers that allow text distillation"
663
+ },
664
+ "provider.enforce_distillable_text": {
665
+ type: "boolean",
666
+ description: "Require providers that allow text distillation"
667
+ },
668
+ quantizations: {
669
+ type: "string",
670
+ description: "Allowed provider quantization levels"
671
+ },
672
+ "provider.quantizations": {
673
+ type: "string",
674
+ description: "Allowed provider quantization levels"
675
+ },
676
+ sort: {
677
+ type: "string",
678
+ values: ["price", "throughput", "latency", "cost", "ttft", "tps"],
679
+ description: "Provider sort strategy"
680
+ },
681
+ "provider.sort": {
682
+ type: "string",
683
+ values: ["price", "throughput", "latency", "cost", "ttft", "tps"],
684
+ description: "Provider sort strategy"
685
+ },
686
+ preferred_min_throughput: {
687
+ type: "number",
688
+ min: 0,
689
+ description: "Preferred minimum provider throughput"
690
+ },
691
+ "provider.preferred_min_throughput": {
692
+ type: "number",
693
+ min: 0,
694
+ description: "Preferred minimum provider throughput"
695
+ },
696
+ preferred_max_latency: {
697
+ type: "number",
698
+ min: 0,
699
+ description: "Preferred maximum provider latency"
700
+ },
701
+ "provider.preferred_max_latency": {
702
+ type: "number",
703
+ min: 0,
704
+ description: "Preferred maximum provider latency"
705
+ },
706
+ max_price: {
707
+ type: "string",
708
+ description: "Maximum provider price filter"
709
+ },
710
+ "provider.max_price": {
711
+ type: "string",
712
+ description: "Maximum provider price filter"
713
+ },
714
+ transforms: {
715
+ type: "string",
716
+ description: "Legacy OpenRouter message transforms"
717
+ },
718
+ plugins: {
719
+ type: "string",
720
+ description: "OpenRouter request plugins"
721
+ }
722
+ };
723
+ var FAL_PARAM_SPECS = {
724
+ prompt: { type: "string", description: "Prompt" },
725
+ negative_prompt: { type: "string", description: "Negative prompt" },
726
+ seed: { type: "number", description: "Random seed" },
727
+ num_images: {
728
+ type: "number",
729
+ min: 1,
730
+ description: "Number of images to generate"
731
+ },
732
+ image_size: { type: "string", description: "Output image size" },
733
+ aspect_ratio: { type: "string", description: "Output aspect ratio" },
734
+ enable_safety_checker: {
735
+ type: "boolean",
736
+ description: "Enable safety checker"
737
+ },
738
+ enable_safety_checks: {
739
+ type: "boolean",
740
+ description: "Enable safety checker"
741
+ },
742
+ enable_prompt_expansion: {
743
+ type: "boolean",
744
+ description: "Enable prompt expansion"
745
+ },
746
+ expand_prompt: {
747
+ type: "boolean",
748
+ description: "Enable prompt expansion"
749
+ },
750
+ output_format: {
751
+ type: "string",
752
+ values: ["jpeg", "jpg", "png", "webp", "gif"],
753
+ description: "Output image format"
754
+ },
755
+ width: { type: "number", min: 1, description: "Image width" },
756
+ height: { type: "number", min: 1, description: "Image height" }
757
+ };
758
+ var REPLICATE_PARAM_SPECS = {
759
+ prompt: { type: "string", description: "Prompt" },
760
+ negative_prompt: { type: "string", description: "Negative prompt" },
761
+ input: { type: "string", description: "Model input object" },
762
+ version: { type: "string", description: "Model version" },
763
+ seed: { type: "number", description: "Random seed" },
764
+ num_outputs: {
765
+ type: "number",
766
+ min: 1,
767
+ description: "Number of outputs to generate"
768
+ },
769
+ num_inference_steps: {
770
+ type: "number",
771
+ min: 1,
772
+ description: "Number of inference steps"
773
+ },
774
+ guidance_scale: {
775
+ type: "number",
776
+ min: 0,
777
+ description: "Guidance scale"
778
+ },
779
+ image_size: { type: "string", description: "Output image size" },
780
+ aspect_ratio: { type: "string", description: "Output aspect ratio" },
781
+ output_format: { type: "string", description: "Output format" },
782
+ width: { type: "number", min: 1, description: "Image width" },
783
+ height: { type: "number", min: 1, description: "Image height" },
784
+ stream: { type: "boolean", description: "Request streaming output" },
785
+ webhook: { type: "string", description: "Webhook URL" },
786
+ webhook_events_filter: {
787
+ type: "string",
788
+ description: "Webhook events filter"
789
+ }
790
+ };
791
+ var PRODIA_PARAM_SPECS = {
792
+ model: { type: "string", description: "Model name" },
793
+ prompt: { type: "string", description: "Prompt" },
794
+ negative_prompt: { type: "string", description: "Negative prompt" },
795
+ style_preset: { type: "string", description: "Style preset" },
796
+ steps: { type: "number", min: 1, description: "Generation steps" },
797
+ cfg_scale: { type: "number", min: 0, description: "CFG scale" },
798
+ seed: { type: "number", description: "Random seed" },
799
+ upscale: { type: "boolean", description: "Enable 2x upscale" },
800
+ sampler: { type: "string", description: "Sampler" },
801
+ width: { type: "number", min: 1, max: 1024, description: "Image width" },
802
+ height: { type: "number", min: 1, max: 1024, description: "Image height" },
803
+ image_size: { type: "string", description: "Output image size" },
804
+ aspect_ratio: { type: "string", description: "Output aspect ratio" },
805
+ output_format: { type: "string", description: "Output format" },
806
+ type: { type: "string", description: "Prodia v2 job type" },
807
+ config: { type: "string", description: "Prodia v2 job config" },
808
+ price: { type: "boolean", description: "Include Prodia v2 job price" }
809
+ };
810
+ var LUMA_PARAM_SPECS = {
811
+ prompt: { type: "string", description: "Prompt" },
812
+ model: { type: "string", description: "Model name" },
813
+ aspect_ratio: { type: "string", description: "Output aspect ratio" },
814
+ keyframes: { type: "string", description: "Generation keyframes" },
815
+ loop: { type: "boolean", description: "Generate a looping video" },
816
+ duration: { type: "string", description: "Generation duration" },
817
+ type: { type: "string", description: "Generation type" },
818
+ image_ref: { type: "string", description: "Image reference" },
819
+ video: { type: "string", description: "Video options" },
820
+ source: { type: "string", description: "Source generation or media" }
821
+ };
457
822
  var GOOGLE_COMPATIBLE_PARAM_SPECS = {
458
823
  temperature: {
459
824
  type: "number",
@@ -522,6 +887,12 @@ var PARAM_SPECS = {
522
887
  default: 4096,
523
888
  description: "Maximum output tokens"
524
889
  },
890
+ max_completion_tokens: {
891
+ type: "number",
892
+ min: 1,
893
+ default: 4096,
894
+ description: "Maximum completion tokens (reasoning models)"
895
+ },
525
896
  top_p: {
526
897
  type: "number",
527
898
  min: 0,
@@ -549,7 +920,7 @@ var PARAM_SPECS = {
549
920
  stream: { type: "boolean", default: false, description: "Stream response" },
550
921
  reasoning_effort: {
551
922
  type: "string",
552
- values: ["none", "minimal", "low", "medium", "high", "xhigh"],
923
+ values: REASONING_EFFORT_VALUES,
553
924
  default: "medium",
554
925
  description: "Reasoning effort"
555
926
  }
@@ -586,8 +957,8 @@ var PARAM_SPECS = {
586
957
  stream: { type: "boolean", default: false, description: "Stream response" },
587
958
  effort: {
588
959
  type: "string",
589
- values: ["low", "medium", "high", "max"],
590
- default: "medium",
960
+ values: REASONING_EFFORT_VALUES,
961
+ default: "low",
591
962
  description: "Thinking effort"
592
963
  },
593
964
  cache_control: {
@@ -812,6 +1183,12 @@ var PARAM_SPECS = {
812
1183
  default: 4096,
813
1184
  description: "Maximum output tokens"
814
1185
  },
1186
+ max_completion_tokens: {
1187
+ type: "number",
1188
+ min: 1,
1189
+ default: 4096,
1190
+ description: "Maximum completion tokens (reasoning models)"
1191
+ },
815
1192
  top_p: {
816
1193
  type: "number",
817
1194
  min: 0,
@@ -845,10 +1222,11 @@ var PARAM_SPECS = {
845
1222
  stream: { type: "boolean", default: false, description: "Stream response" },
846
1223
  reasoning_effort: {
847
1224
  type: "string",
848
- values: ["none", "minimal", "low", "medium", "high", "xhigh"],
1225
+ values: REASONING_EFFORT_VALUES,
849
1226
  default: "medium",
850
1227
  description: "Reasoning effort"
851
- }
1228
+ },
1229
+ ...OPENROUTER_ROUTING_PARAM_SPECS
852
1230
  },
853
1231
  vercel: {
854
1232
  // Loose validation — proxies to many providers with varying ranges
@@ -865,6 +1243,12 @@ var PARAM_SPECS = {
865
1243
  default: 4096,
866
1244
  description: "Maximum output tokens"
867
1245
  },
1246
+ max_completion_tokens: {
1247
+ type: "number",
1248
+ min: 1,
1249
+ default: 4096,
1250
+ description: "Maximum completion tokens (reasoning models)"
1251
+ },
868
1252
  top_p: {
869
1253
  type: "number",
870
1254
  min: 0,
@@ -898,14 +1282,70 @@ var PARAM_SPECS = {
898
1282
  stream: { type: "boolean", default: false, description: "Stream response" },
899
1283
  reasoning_effort: {
900
1284
  type: "string",
901
- values: ["none", "minimal", "low", "medium", "high", "xhigh"],
1285
+ values: REASONING_EFFORT_VALUES,
902
1286
  default: "medium",
903
1287
  description: "Reasoning effort"
1288
+ },
1289
+ order: { type: "string", description: "Gateway provider order" },
1290
+ only: { type: "string", description: "Gateway provider allowlist" },
1291
+ models: { type: "string", description: "Gateway fallback models" },
1292
+ tags: { type: "string", description: "Gateway usage tags" },
1293
+ sort: {
1294
+ type: "string",
1295
+ values: ["cost", "ttft", "tps"],
1296
+ description: "Gateway provider sort strategy"
1297
+ },
1298
+ caching: {
1299
+ type: "string",
1300
+ values: ["auto"],
1301
+ description: "Gateway automatic caching strategy"
1302
+ },
1303
+ user: { type: "string", description: "Gateway usage user identifier" },
1304
+ byok: { type: "string", description: "Gateway BYOK credentials" },
1305
+ zero_data_retention: {
1306
+ type: "boolean",
1307
+ description: "Gateway zero data retention routing"
1308
+ },
1309
+ zeroDataRetention: {
1310
+ type: "boolean",
1311
+ description: "Gateway zero data retention routing"
1312
+ },
1313
+ disallow_prompt_training: {
1314
+ type: "boolean",
1315
+ description: "Gateway prompt training opt-out routing"
1316
+ },
1317
+ disallowPromptTraining: {
1318
+ type: "boolean",
1319
+ description: "Gateway prompt training opt-out routing"
1320
+ },
1321
+ hipaa_compliant: {
1322
+ type: "boolean",
1323
+ description: "Gateway HIPAA-compliant routing"
1324
+ },
1325
+ hipaaCompliant: {
1326
+ type: "boolean",
1327
+ description: "Gateway HIPAA-compliant routing"
1328
+ },
1329
+ quota_entity_id: {
1330
+ type: "string",
1331
+ description: "Gateway quota entity identifier"
1332
+ },
1333
+ quotaEntityId: {
1334
+ type: "string",
1335
+ description: "Gateway quota entity identifier"
1336
+ },
1337
+ provider_timeouts: {
1338
+ type: "string",
1339
+ description: "Gateway provider timeouts"
1340
+ },
1341
+ providerTimeouts: {
1342
+ type: "string",
1343
+ description: "Gateway provider timeouts"
904
1344
  }
905
1345
  },
906
1346
  xai: OPENAI_COMPATIBLE_PARAM_SPECS,
907
1347
  groq: OPENAI_COMPATIBLE_PARAM_SPECS,
908
- fal: {},
1348
+ fal: FAL_PARAM_SPECS,
909
1349
  deepinfra: OPENAI_COMPATIBLE_PARAM_SPECS,
910
1350
  "black-forest-labs": {},
911
1351
  together: OPENAI_COMPATIBLE_PARAM_SPECS,
@@ -915,9 +1355,9 @@ var PARAM_SPECS = {
915
1355
  perplexity: OPENAI_COMPATIBLE_PARAM_SPECS,
916
1356
  alibaba: OPENAI_COMPATIBLE_PARAM_SPECS,
917
1357
  cerebras: OPENAI_COMPATIBLE_PARAM_SPECS,
918
- replicate: {},
919
- prodia: {},
920
- luma: {},
1358
+ replicate: REPLICATE_PARAM_SPECS,
1359
+ prodia: PRODIA_PARAM_SPECS,
1360
+ luma: LUMA_PARAM_SPECS,
921
1361
  bytedance: {},
922
1362
  kling: {},
923
1363
  elevenlabs: {},
@@ -931,11 +1371,13 @@ var PARAM_SPECS = {
931
1371
  huggingface: OPENAI_COMPATIBLE_PARAM_SPECS
932
1372
  };
933
1373
  function isReasoningModel(model) {
934
- const name = model.includes("/") ? model.split("/").pop() : model;
935
- return /^o[134]/.test(name);
1374
+ const name = modelLeafName(model);
1375
+ const oSeries = name.match(/^o\d+/)?.[0];
1376
+ const gptSeries = name.match(/^gpt-[5-9]/)?.[0];
1377
+ return (oSeries ? modelMatchesFamily(name, oSeries) : false) || (gptSeries ? modelMatchesFamily(name, gptSeries) : false);
936
1378
  }
937
1379
  function canHostOpenAIModels(provider) {
938
- return provider === "openai" || provider === "openrouter" || provider === "vercel";
1380
+ return provider === "openai" || provider === "azure" || provider === "openrouter" || provider === "vercel";
939
1381
  }
940
1382
  function isGatewayProvider(provider) {
941
1383
  return provider === "openrouter" || provider === "vercel";
@@ -943,29 +1385,27 @@ function isGatewayProvider(provider) {
943
1385
  function detectGatewaySubProvider(model) {
944
1386
  const slash = model.indexOf("/");
945
1387
  if (slash < 1) return void 0;
946
- const prefix = model.slice(0, slash);
947
- const direct = [
948
- "openai",
949
- "anthropic",
950
- "google",
951
- "mistral",
952
- "cohere"
953
- ];
954
- return direct.find((p) => p === prefix);
1388
+ const prefix = normalizeModelForMatching(model.slice(0, slash));
1389
+ const direct = {
1390
+ openai: "openai",
1391
+ anthropic: "anthropic",
1392
+ google: "google",
1393
+ vertex: "google",
1394
+ "google-vertex": "google",
1395
+ mistral: "mistral",
1396
+ cohere: "cohere"
1397
+ };
1398
+ return direct[prefix];
955
1399
  }
956
1400
  var REASONING_MODEL_UNSUPPORTED = /* @__PURE__ */ new Set([
957
1401
  "temperature",
958
1402
  "top_p",
1403
+ "top_k",
959
1404
  "frequency_penalty",
960
1405
  "presence_penalty",
961
1406
  "n"
962
1407
  ]);
963
1408
  function detectBedrockModelFamily(model) {
964
- const parts = model.split(".");
965
- let prefix = parts[0];
966
- if (["us", "eu", "apac", "global"].includes(prefix) && parts.length > 1) {
967
- prefix = parts[1];
968
- }
969
1409
  const families = [
970
1410
  "anthropic",
971
1411
  "meta",
@@ -974,12 +1414,18 @@ function detectBedrockModelFamily(model) {
974
1414
  "cohere",
975
1415
  "ai21"
976
1416
  ];
977
- return families.find((f) => prefix === f);
1417
+ const parts = modelLeafName(model).split(".");
1418
+ return families.find((family) => parts.includes(family));
978
1419
  }
979
1420
  function bedrockSupportsCaching(model) {
980
1421
  const family = detectBedrockModelFamily(model);
981
1422
  if (family === "anthropic") return true;
982
- if (family === "amazon" && model.includes("nova")) return true;
1423
+ if (family === "amazon") {
1424
+ const parts = modelLeafName(model).split(".");
1425
+ const amazonIndex = parts.indexOf("amazon");
1426
+ const modelName = amazonIndex >= 0 ? parts[amazonIndex + 1] : void 0;
1427
+ return modelName ? modelMatchesFamily(modelName, "nova") : false;
1428
+ }
983
1429
  return false;
984
1430
  }
985
1431
  var CACHE_VALUES = {
@@ -1064,7 +1510,6 @@ var CACHE_TTLS = {
1064
1510
  baseten: void 0,
1065
1511
  huggingface: void 0
1066
1512
  };
1067
- var DURATION_RE = /^\d+[mh]$/;
1068
1513
 
1069
1514
  // src/provider-meta.ts
1070
1515
  var PROVIDER_META = [
@@ -1249,7 +1694,6 @@ var CANONICAL_PARAM_SPECS = deriveCanonicalParamSpecs();
1249
1694
  CACHE_TTLS,
1250
1695
  CACHE_VALUES,
1251
1696
  CANONICAL_PARAM_SPECS,
1252
- DURATION_RE,
1253
1697
  HOST_ALIASES,
1254
1698
  PARAM_SPECS,
1255
1699
  PROVIDER_META,
@@ -1262,6 +1706,7 @@ var CANONICAL_PARAM_SPECS = deriveCanonicalParamSpecs();
1262
1706
  detectProvider,
1263
1707
  isGatewayProvider,
1264
1708
  isReasoningModel,
1709
+ modelMatchesFamily,
1265
1710
  providerFromHostAlias,
1266
1711
  resolveHostAlias
1267
1712
  });