llm-strings 1.3.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.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +339 -339
  3. package/dist/ai-sdk.cjs +1146 -117
  4. package/dist/ai-sdk.d.cts +1 -1
  5. package/dist/ai-sdk.d.ts +1 -1
  6. package/dist/ai-sdk.js +95 -58
  7. package/dist/{chunk-7HE4RH6X.js → chunk-4BE457QA.js} +16 -29
  8. package/dist/{chunk-TQJ2ABCT.js → chunk-6HQOCOQI.js} +1 -2
  9. package/dist/{chunk-NZR5DUX5.js → chunk-7Z7DCLZN.js} +14 -3
  10. package/dist/{chunk-OCJX4QFJ.js → chunk-PCJDQTOV.js} +520 -76
  11. package/dist/index.cjs +542 -95
  12. package/dist/index.d.cts +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.js +4 -5
  15. package/dist/normalize.cjs +1065 -63
  16. package/dist/normalize.d.cts +1 -1
  17. package/dist/normalize.d.ts +1 -1
  18. package/dist/normalize.js +2 -3
  19. package/dist/parse.cjs +1075 -1
  20. package/dist/parse.d.cts +4 -4
  21. package/dist/parse.d.ts +4 -4
  22. package/dist/parse.js +2 -3
  23. package/dist/{provider-core-B934MuhJ.d.cts → provider-core-B1GMszQP.d.cts} +2 -3
  24. package/dist/{provider-core-B934MuhJ.d.ts → provider-core-B1GMszQP.d.ts} +2 -3
  25. package/dist/providers.cjs +542 -697
  26. package/dist/providers.d.cts +3 -8
  27. package/dist/providers.d.ts +3 -8
  28. package/dist/providers.js +25 -624
  29. package/dist/validate.cjs +542 -95
  30. package/dist/validate.d.cts +1 -1
  31. package/dist/validate.d.ts +1 -1
  32. package/dist/validate.js +4 -5
  33. package/package.json +16 -2
  34. package/dist/ai-sdk.cjs.map +0 -1
  35. package/dist/ai-sdk.js.map +0 -1
  36. package/dist/chunk-7HE4RH6X.js.map +0 -1
  37. package/dist/chunk-NZR5DUX5.js.map +0 -1
  38. package/dist/chunk-OCJX4QFJ.js.map +0 -1
  39. package/dist/chunk-TQJ2ABCT.js.map +0 -1
  40. package/dist/index.cjs.map +0 -1
  41. package/dist/index.js.map +0 -1
  42. package/dist/normalize.cjs.map +0 -1
  43. package/dist/normalize.js.map +0 -1
  44. package/dist/parse.cjs.map +0 -1
  45. package/dist/parse.js.map +0 -1
  46. package/dist/providers.cjs.map +0 -1
  47. package/dist/providers.js.map +0 -1
  48. package/dist/validate.cjs.map +0 -1
  49. package/dist/validate.js.map +0 -1
@@ -40,6 +40,17 @@ var HOST_ALIAS_PROVIDERS = {
40
40
  togetherai: "together",
41
41
  fireworksai: "fireworks"
42
42
  };
43
+ function normalizeHostValue(value) {
44
+ const trimmed = value.trim();
45
+ if (!trimmed) return trimmed;
46
+ try {
47
+ if (trimmed.includes("://")) {
48
+ return new URL(trimmed).host;
49
+ }
50
+ } catch {
51
+ }
52
+ return trimmed.replace(/^\/\//, "").split("/")[0] ?? trimmed;
53
+ }
43
54
  function providerFromHostAlias(alias) {
44
55
  const normalizedAlias = alias.toLowerCase();
45
56
  if (hasOwn(PROVIDER_PARAMS, normalizedAlias)) {
@@ -50,44 +61,92 @@ function providerFromHostAlias(alias) {
50
61
  }
51
62
  return void 0;
52
63
  }
64
+ function canonicalHostName(host) {
65
+ return normalizeHostValue(host).toLowerCase().split(":")[0] ?? host;
66
+ }
67
+ function hostMatches(host, ...domains) {
68
+ return domains.some((domain) => {
69
+ const normalizedDomain = domain.toLowerCase();
70
+ return host === normalizedDomain || host.endsWith(`.${normalizedDomain}`);
71
+ });
72
+ }
73
+ function hostHasLabel(host, ...labels) {
74
+ const hostLabels = host.split(".");
75
+ return labels.some((label) => hostLabels.includes(label.toLowerCase()));
76
+ }
77
+ function hostHasLabelPrefix(host, ...prefixes) {
78
+ const hostLabels = host.split(".");
79
+ return prefixes.some(
80
+ (prefix) => hostLabels.some((label) => label.startsWith(prefix.toLowerCase()))
81
+ );
82
+ }
83
+ var MODEL_FAMILY_DELIMITERS = /* @__PURE__ */ new Set(["-", "."]);
84
+ function normalizeModelForMatching(model) {
85
+ return model.trim().toLowerCase();
86
+ }
87
+ function modelLeafName(model) {
88
+ const normalized = normalizeModelForMatching(model);
89
+ const slash = normalized.lastIndexOf("/");
90
+ return slash >= 0 ? normalized.slice(slash + 1) : normalized;
91
+ }
92
+ function modelMatchesFamily(model, family) {
93
+ const name = modelLeafName(model);
94
+ const normalizedFamily = normalizeModelForMatching(family);
95
+ if (!name || !normalizedFamily) return false;
96
+ if (name === normalizedFamily) return true;
97
+ const delimiter = name[normalizedFamily.length];
98
+ return name.startsWith(normalizedFamily) && delimiter !== void 0 && MODEL_FAMILY_DELIMITERS.has(delimiter);
99
+ }
53
100
  function detectProvider(host) {
54
- host = host.toLowerCase();
55
- if (host.includes("openrouter")) return "openrouter";
56
- if (host.includes("gateway.ai.vercel")) return "vercel";
57
- if (host.includes("amazonaws") || host.includes("bedrock")) return "bedrock";
58
- if (host.includes("aiplatform.googleapis")) return "google-vertex";
59
- if (host.includes("api.x.ai")) return "xai";
60
- if (host.includes("groq")) return "groq";
61
- if (host.includes("fal.run") || host.includes("fal.ai")) return "fal";
62
- if (host.includes("deepinfra")) return "deepinfra";
63
- if (host.includes("bfl.ai")) return "black-forest-labs";
64
- if (host.includes("together")) return "together";
65
- if (host.includes("fireworks")) return "fireworks";
66
- if (host.includes("deepseek")) return "deepseek";
67
- if (host.includes("moonshot")) return "moonshotai";
68
- if (host.includes("perplexity")) return "perplexity";
69
- if (host.includes("dashscope") || host.includes("aliyuncs")) return "alibaba";
70
- if (host.includes("cerebras")) return "cerebras";
71
- if (host.includes("replicate")) return "replicate";
72
- if (host.includes("prodia")) return "prodia";
73
- if (host.includes("lumalabs") || host.includes("luma")) return "luma";
74
- if (host.includes("volces") || host.includes("bytedance")) return "bytedance";
75
- if (host.includes("kling")) return "kling";
76
- if (host.includes("elevenlabs")) return "elevenlabs";
77
- if (host.includes("assemblyai")) return "assemblyai";
78
- if (host.includes("deepgram")) return "deepgram";
79
- if (host.includes("gladia")) return "gladia";
80
- if (host.includes("lmnt")) return "lmnt";
81
- if (host.includes("hume")) return "hume";
82
- if (host.includes("rev.ai")) return "revai";
83
- if (host.includes("baseten")) return "baseten";
84
- if (host.includes("huggingface")) return "huggingface";
85
- if (host.includes("azure")) return "azure";
86
- if (host.includes("openai")) return "openai";
87
- if (host.includes("anthropic") || host.includes("claude")) return "anthropic";
88
- if (host.includes("googleapis") || host.includes("google")) return "google";
89
- if (host.includes("mistral")) return "mistral";
90
- if (host.includes("cohere")) return "cohere";
101
+ host = canonicalHostName(host);
102
+ if (hostMatches(host, "openrouter", "openrouter.ai")) return "openrouter";
103
+ if (hostMatches(host, "vercel", "gateway.ai.vercel.app", "gateway.ai.vercel.sh")) {
104
+ return "vercel";
105
+ }
106
+ if (hostMatches(host, "bedrock", "amazonaws.com") || hostHasLabelPrefix(host, "bedrock")) {
107
+ return "bedrock";
108
+ }
109
+ if (hostMatches(host, "aiplatform.googleapis.com")) return "google-vertex";
110
+ if (hostMatches(host, "xai", "x.ai", "api.x.ai")) return "xai";
111
+ if (hostMatches(host, "groq", "groq.com", "api.groq.com")) return "groq";
112
+ if (hostMatches(host, "fal", "fal.run", "fal.ai")) return "fal";
113
+ if (hostMatches(host, "deepinfra", "deepinfra.com")) return "deepinfra";
114
+ if (hostMatches(host, "bfl", "bfl.ai", "api.bfl.ai")) {
115
+ return "black-forest-labs";
116
+ }
117
+ if (hostMatches(host, "together", "together.xyz")) return "together";
118
+ if (hostMatches(host, "fireworks", "fireworks.ai")) return "fireworks";
119
+ if (hostMatches(host, "deepseek", "deepseek.com")) return "deepseek";
120
+ if (hostMatches(host, "moonshot", "moonshot.ai")) return "moonshotai";
121
+ if (hostMatches(host, "perplexity", "perplexity.ai")) return "perplexity";
122
+ if (hostMatches(host, "alibaba", "aliyuncs.com") || hostHasLabelPrefix(host, "dashscope")) {
123
+ return "alibaba";
124
+ }
125
+ if (hostMatches(host, "cerebras", "cerebras.ai")) return "cerebras";
126
+ if (hostMatches(host, "replicate", "replicate.com")) return "replicate";
127
+ if (hostMatches(host, "prodia", "prodia.com")) return "prodia";
128
+ if (hostMatches(host, "luma", "lumalabs.ai")) return "luma";
129
+ if (hostMatches(host, "bytedance", "volces.com") || hostHasLabel(host, "bytedance")) {
130
+ return "bytedance";
131
+ }
132
+ if (hostMatches(host, "kling", "klingai.com")) return "kling";
133
+ if (hostMatches(host, "elevenlabs", "elevenlabs.io")) return "elevenlabs";
134
+ if (hostMatches(host, "assemblyai", "assemblyai.com")) return "assemblyai";
135
+ if (hostMatches(host, "deepgram", "deepgram.com")) return "deepgram";
136
+ if (hostMatches(host, "gladia", "gladia.io")) return "gladia";
137
+ if (hostMatches(host, "lmnt", "lmnt.com")) return "lmnt";
138
+ if (hostMatches(host, "hume", "hume.ai")) return "hume";
139
+ if (hostMatches(host, "revai", "rev.ai")) return "revai";
140
+ if (hostMatches(host, "baseten", "baseten.co")) return "baseten";
141
+ if (hostMatches(host, "huggingface", "huggingface.co")) return "huggingface";
142
+ if (hostMatches(host, "azure", "azure.com")) return "azure";
143
+ if (hostMatches(host, "openai", "openai.com")) return "openai";
144
+ if (hostMatches(host, "anthropic", "anthropic.com", "claude.ai")) {
145
+ return "anthropic";
146
+ }
147
+ if (hostMatches(host, "google", "googleapis.com")) return "google";
148
+ if (hostMatches(host, "mistral", "mistral.ai")) return "mistral";
149
+ if (hostMatches(host, "cohere", "cohere.com")) return "cohere";
91
150
  return void 0;
92
151
  }
93
152
  var ALIASES = {
@@ -130,7 +189,10 @@ var ALIASES = {
130
189
  num_completions: "n",
131
190
  // effort / reasoning
132
191
  reasoning_effort: "effort",
192
+ reasoningEffort: "effort",
133
193
  reasoning: "effort",
194
+ thinking_effort: "effort",
195
+ thinkingEffort: "effort",
134
196
  // cache
135
197
  cache_control: "cache",
136
198
  cacheControl: "cache",
@@ -140,6 +202,7 @@ var ALIASES = {
140
202
  var OPENAI_COMPATIBLE_PARAMS = {
141
203
  temperature: "temperature",
142
204
  max_tokens: "max_tokens",
205
+ max_completion_tokens: "max_completion_tokens",
143
206
  top_p: "top_p",
144
207
  top_k: "top_k",
145
208
  frequency_penalty: "frequency_penalty",
@@ -150,6 +213,90 @@ var OPENAI_COMPATIBLE_PARAMS = {
150
213
  stream: "stream",
151
214
  effort: "reasoning_effort"
152
215
  };
216
+ var COMMON_IMAGE_PARAMS = {
217
+ prompt: "prompt",
218
+ negative_prompt: "negative_prompt",
219
+ seed: "seed",
220
+ image_size: "image_size",
221
+ aspect_ratio: "aspect_ratio",
222
+ output_format: "output_format",
223
+ width: "width",
224
+ height: "height"
225
+ };
226
+ var FAL_PARAMS = {
227
+ ...COMMON_IMAGE_PARAMS,
228
+ num_images: "num_images",
229
+ enable_safety_checker: "enable_safety_checker",
230
+ enable_safety_checks: "enable_safety_checks",
231
+ enable_prompt_expansion: "enable_prompt_expansion",
232
+ expand_prompt: "expand_prompt"
233
+ };
234
+ var REPLICATE_PARAMS = {
235
+ ...COMMON_IMAGE_PARAMS,
236
+ input: "input",
237
+ version: "version",
238
+ num_outputs: "num_outputs",
239
+ num_inference_steps: "num_inference_steps",
240
+ guidance_scale: "guidance_scale",
241
+ stream: "stream",
242
+ webhook: "webhook",
243
+ webhook_events_filter: "webhook_events_filter"
244
+ };
245
+ var PRODIA_PARAMS = {
246
+ ...COMMON_IMAGE_PARAMS,
247
+ model: "model",
248
+ style_preset: "style_preset",
249
+ steps: "steps",
250
+ cfg_scale: "cfg_scale",
251
+ upscale: "upscale",
252
+ sampler: "sampler",
253
+ type: "type",
254
+ config: "config",
255
+ price: "price"
256
+ };
257
+ var LUMA_PARAMS = {
258
+ prompt: "prompt",
259
+ model: "model",
260
+ aspect_ratio: "aspect_ratio",
261
+ keyframes: "keyframes",
262
+ loop: "loop",
263
+ duration: "duration",
264
+ type: "type",
265
+ image_ref: "image_ref",
266
+ video: "video",
267
+ source: "source"
268
+ };
269
+ var OPENROUTER_ROUTING_PARAMS = {
270
+ provider: "provider",
271
+ order: "order",
272
+ "provider.order": "provider.order",
273
+ only: "only",
274
+ "provider.only": "provider.only",
275
+ ignore: "ignore",
276
+ "provider.ignore": "provider.ignore",
277
+ allow_fallbacks: "allow_fallbacks",
278
+ "provider.allow_fallbacks": "provider.allow_fallbacks",
279
+ require_parameters: "require_parameters",
280
+ "provider.require_parameters": "provider.require_parameters",
281
+ data_collection: "data_collection",
282
+ "provider.data_collection": "provider.data_collection",
283
+ zdr: "zdr",
284
+ "provider.zdr": "provider.zdr",
285
+ enforce_distillable_text: "enforce_distillable_text",
286
+ "provider.enforce_distillable_text": "provider.enforce_distillable_text",
287
+ quantizations: "quantizations",
288
+ "provider.quantizations": "provider.quantizations",
289
+ sort: "sort",
290
+ "provider.sort": "provider.sort",
291
+ preferred_min_throughput: "preferred_min_throughput",
292
+ "provider.preferred_min_throughput": "provider.preferred_min_throughput",
293
+ preferred_max_latency: "preferred_max_latency",
294
+ "provider.preferred_max_latency": "provider.preferred_max_latency",
295
+ max_price: "max_price",
296
+ "provider.max_price": "provider.max_price",
297
+ transforms: "transforms",
298
+ plugins: "plugins"
299
+ };
153
300
  var GOOGLE_COMPATIBLE_PARAMS = {
154
301
  temperature: "temperature",
155
302
  max_tokens: "maxOutputTokens",
@@ -168,6 +315,7 @@ var PROVIDER_PARAMS = {
168
315
  openai: {
169
316
  temperature: "temperature",
170
317
  max_tokens: "max_tokens",
318
+ max_completion_tokens: "max_completion_tokens",
171
319
  top_p: "top_p",
172
320
  frequency_penalty: "frequency_penalty",
173
321
  presence_penalty: "presence_penalty",
@@ -244,6 +392,7 @@ var PROVIDER_PARAMS = {
244
392
  // OpenAI-compatible API with extra routing params
245
393
  temperature: "temperature",
246
394
  max_tokens: "max_tokens",
395
+ max_completion_tokens: "max_completion_tokens",
247
396
  top_p: "top_p",
248
397
  top_k: "top_k",
249
398
  frequency_penalty: "frequency_penalty",
@@ -252,12 +401,14 @@ var PROVIDER_PARAMS = {
252
401
  n: "n",
253
402
  seed: "seed",
254
403
  stream: "stream",
255
- effort: "reasoning_effort"
404
+ effort: "reasoning_effort",
405
+ ...OPENROUTER_ROUTING_PARAMS
256
406
  },
257
407
  vercel: {
258
408
  // OpenAI-compatible gateway
259
409
  temperature: "temperature",
260
410
  max_tokens: "max_tokens",
411
+ max_completion_tokens: "max_completion_tokens",
261
412
  top_p: "top_p",
262
413
  top_k: "top_k",
263
414
  frequency_penalty: "frequency_penalty",
@@ -270,7 +421,7 @@ var PROVIDER_PARAMS = {
270
421
  },
271
422
  xai: OPENAI_COMPATIBLE_PARAMS,
272
423
  groq: OPENAI_COMPATIBLE_PARAMS,
273
- fal: {},
424
+ fal: FAL_PARAMS,
274
425
  deepinfra: OPENAI_COMPATIBLE_PARAMS,
275
426
  "black-forest-labs": {},
276
427
  together: OPENAI_COMPATIBLE_PARAMS,
@@ -280,9 +431,9 @@ var PROVIDER_PARAMS = {
280
431
  perplexity: OPENAI_COMPATIBLE_PARAMS,
281
432
  alibaba: OPENAI_COMPATIBLE_PARAMS,
282
433
  cerebras: OPENAI_COMPATIBLE_PARAMS,
283
- replicate: {},
284
- prodia: {},
285
- luma: {},
434
+ replicate: REPLICATE_PARAMS,
435
+ prodia: PRODIA_PARAMS,
436
+ luma: LUMA_PARAMS,
286
437
  bytedance: {},
287
438
  kling: {},
288
439
  elevenlabs: {},
@@ -295,12 +446,842 @@ var PROVIDER_PARAMS = {
295
446
  baseten: OPENAI_COMPATIBLE_PARAMS,
296
447
  huggingface: OPENAI_COMPATIBLE_PARAMS
297
448
  };
449
+ var REASONING_EFFORT_VALUES = [
450
+ "none",
451
+ "minimal",
452
+ "low",
453
+ "medium",
454
+ "high",
455
+ "xhigh",
456
+ "max"
457
+ ];
458
+ var OPENAI_COMPATIBLE_PARAM_SPECS = {
459
+ temperature: {
460
+ type: "number",
461
+ min: 0,
462
+ max: 2,
463
+ default: 0.7,
464
+ description: "Controls randomness"
465
+ },
466
+ max_tokens: {
467
+ type: "number",
468
+ min: 1,
469
+ default: 4096,
470
+ description: "Maximum output tokens"
471
+ },
472
+ max_completion_tokens: {
473
+ type: "number",
474
+ min: 1,
475
+ default: 4096,
476
+ description: "Maximum completion tokens (reasoning models)"
477
+ },
478
+ top_p: {
479
+ type: "number",
480
+ min: 0,
481
+ max: 1,
482
+ default: 1,
483
+ description: "Nucleus sampling"
484
+ },
485
+ top_k: {
486
+ type: "number",
487
+ min: 0,
488
+ default: 40,
489
+ description: "Top-K sampling"
490
+ },
491
+ frequency_penalty: {
492
+ type: "number",
493
+ min: -2,
494
+ max: 2,
495
+ default: 0,
496
+ description: "Penalize frequent tokens"
497
+ },
498
+ presence_penalty: {
499
+ type: "number",
500
+ min: -2,
501
+ max: 2,
502
+ default: 0,
503
+ description: "Penalize repeated topics"
504
+ },
505
+ stop: { type: "string", description: "Stop sequences" },
506
+ n: { type: "number", min: 1, default: 1, description: "Completions count" },
507
+ seed: { type: "number", description: "Random seed" },
508
+ stream: { type: "boolean", default: false, description: "Stream response" },
509
+ reasoning_effort: {
510
+ type: "string",
511
+ values: REASONING_EFFORT_VALUES,
512
+ default: "medium",
513
+ description: "Reasoning effort"
514
+ }
515
+ };
516
+ var OPENROUTER_ROUTING_PARAM_SPECS = {
517
+ provider: { type: "string", description: "Provider routing preferences" },
518
+ order: { type: "string", description: "Provider order" },
519
+ "provider.order": { type: "string", description: "Provider order" },
520
+ only: { type: "string", description: "Provider allowlist" },
521
+ "provider.only": { type: "string", description: "Provider allowlist" },
522
+ ignore: { type: "string", description: "Provider blocklist" },
523
+ "provider.ignore": { type: "string", description: "Provider blocklist" },
524
+ allow_fallbacks: {
525
+ type: "boolean",
526
+ default: true,
527
+ description: "Allow fallback providers"
528
+ },
529
+ "provider.allow_fallbacks": {
530
+ type: "boolean",
531
+ default: true,
532
+ description: "Allow fallback providers"
533
+ },
534
+ require_parameters: {
535
+ type: "boolean",
536
+ default: false,
537
+ description: "Only route to providers that support all request params"
538
+ },
539
+ "provider.require_parameters": {
540
+ type: "boolean",
541
+ default: false,
542
+ description: "Only route to providers that support all request params"
543
+ },
544
+ data_collection: {
545
+ type: "string",
546
+ values: ["allow", "deny"],
547
+ default: "allow",
548
+ description: "Provider data collection policy"
549
+ },
550
+ "provider.data_collection": {
551
+ type: "string",
552
+ values: ["allow", "deny"],
553
+ default: "allow",
554
+ description: "Provider data collection policy"
555
+ },
556
+ zdr: {
557
+ type: "boolean",
558
+ description: "Require zero data retention providers"
559
+ },
560
+ "provider.zdr": {
561
+ type: "boolean",
562
+ description: "Require zero data retention providers"
563
+ },
564
+ enforce_distillable_text: {
565
+ type: "boolean",
566
+ description: "Require providers that allow text distillation"
567
+ },
568
+ "provider.enforce_distillable_text": {
569
+ type: "boolean",
570
+ description: "Require providers that allow text distillation"
571
+ },
572
+ quantizations: {
573
+ type: "string",
574
+ description: "Allowed provider quantization levels"
575
+ },
576
+ "provider.quantizations": {
577
+ type: "string",
578
+ description: "Allowed provider quantization levels"
579
+ },
580
+ sort: {
581
+ type: "string",
582
+ values: ["price", "throughput", "latency", "cost", "ttft", "tps"],
583
+ description: "Provider sort strategy"
584
+ },
585
+ "provider.sort": {
586
+ type: "string",
587
+ values: ["price", "throughput", "latency", "cost", "ttft", "tps"],
588
+ description: "Provider sort strategy"
589
+ },
590
+ preferred_min_throughput: {
591
+ type: "number",
592
+ min: 0,
593
+ description: "Preferred minimum provider throughput"
594
+ },
595
+ "provider.preferred_min_throughput": {
596
+ type: "number",
597
+ min: 0,
598
+ description: "Preferred minimum provider throughput"
599
+ },
600
+ preferred_max_latency: {
601
+ type: "number",
602
+ min: 0,
603
+ description: "Preferred maximum provider latency"
604
+ },
605
+ "provider.preferred_max_latency": {
606
+ type: "number",
607
+ min: 0,
608
+ description: "Preferred maximum provider latency"
609
+ },
610
+ max_price: {
611
+ type: "string",
612
+ description: "Maximum provider price filter"
613
+ },
614
+ "provider.max_price": {
615
+ type: "string",
616
+ description: "Maximum provider price filter"
617
+ },
618
+ transforms: {
619
+ type: "string",
620
+ description: "Legacy OpenRouter message transforms"
621
+ },
622
+ plugins: {
623
+ type: "string",
624
+ description: "OpenRouter request plugins"
625
+ }
626
+ };
627
+ var FAL_PARAM_SPECS = {
628
+ prompt: { type: "string", description: "Prompt" },
629
+ negative_prompt: { type: "string", description: "Negative prompt" },
630
+ seed: { type: "number", description: "Random seed" },
631
+ num_images: {
632
+ type: "number",
633
+ min: 1,
634
+ description: "Number of images to generate"
635
+ },
636
+ image_size: { type: "string", description: "Output image size" },
637
+ aspect_ratio: { type: "string", description: "Output aspect ratio" },
638
+ enable_safety_checker: {
639
+ type: "boolean",
640
+ description: "Enable safety checker"
641
+ },
642
+ enable_safety_checks: {
643
+ type: "boolean",
644
+ description: "Enable safety checker"
645
+ },
646
+ enable_prompt_expansion: {
647
+ type: "boolean",
648
+ description: "Enable prompt expansion"
649
+ },
650
+ expand_prompt: {
651
+ type: "boolean",
652
+ description: "Enable prompt expansion"
653
+ },
654
+ output_format: {
655
+ type: "string",
656
+ values: ["jpeg", "jpg", "png", "webp", "gif"],
657
+ description: "Output image format"
658
+ },
659
+ width: { type: "number", min: 1, description: "Image width" },
660
+ height: { type: "number", min: 1, description: "Image height" }
661
+ };
662
+ var REPLICATE_PARAM_SPECS = {
663
+ prompt: { type: "string", description: "Prompt" },
664
+ negative_prompt: { type: "string", description: "Negative prompt" },
665
+ input: { type: "string", description: "Model input object" },
666
+ version: { type: "string", description: "Model version" },
667
+ seed: { type: "number", description: "Random seed" },
668
+ num_outputs: {
669
+ type: "number",
670
+ min: 1,
671
+ description: "Number of outputs to generate"
672
+ },
673
+ num_inference_steps: {
674
+ type: "number",
675
+ min: 1,
676
+ description: "Number of inference steps"
677
+ },
678
+ guidance_scale: {
679
+ type: "number",
680
+ min: 0,
681
+ description: "Guidance scale"
682
+ },
683
+ image_size: { type: "string", description: "Output image size" },
684
+ aspect_ratio: { type: "string", description: "Output aspect ratio" },
685
+ output_format: { type: "string", description: "Output format" },
686
+ width: { type: "number", min: 1, description: "Image width" },
687
+ height: { type: "number", min: 1, description: "Image height" },
688
+ stream: { type: "boolean", description: "Request streaming output" },
689
+ webhook: { type: "string", description: "Webhook URL" },
690
+ webhook_events_filter: {
691
+ type: "string",
692
+ description: "Webhook events filter"
693
+ }
694
+ };
695
+ var PRODIA_PARAM_SPECS = {
696
+ model: { type: "string", description: "Model name" },
697
+ prompt: { type: "string", description: "Prompt" },
698
+ negative_prompt: { type: "string", description: "Negative prompt" },
699
+ style_preset: { type: "string", description: "Style preset" },
700
+ steps: { type: "number", min: 1, description: "Generation steps" },
701
+ cfg_scale: { type: "number", min: 0, description: "CFG scale" },
702
+ seed: { type: "number", description: "Random seed" },
703
+ upscale: { type: "boolean", description: "Enable 2x upscale" },
704
+ sampler: { type: "string", description: "Sampler" },
705
+ width: { type: "number", min: 1, max: 1024, description: "Image width" },
706
+ height: { type: "number", min: 1, max: 1024, description: "Image height" },
707
+ image_size: { type: "string", description: "Output image size" },
708
+ aspect_ratio: { type: "string", description: "Output aspect ratio" },
709
+ output_format: { type: "string", description: "Output format" },
710
+ type: { type: "string", description: "Prodia v2 job type" },
711
+ config: { type: "string", description: "Prodia v2 job config" },
712
+ price: { type: "boolean", description: "Include Prodia v2 job price" }
713
+ };
714
+ var LUMA_PARAM_SPECS = {
715
+ prompt: { type: "string", description: "Prompt" },
716
+ model: { type: "string", description: "Model name" },
717
+ aspect_ratio: { type: "string", description: "Output aspect ratio" },
718
+ keyframes: { type: "string", description: "Generation keyframes" },
719
+ loop: { type: "boolean", description: "Generate a looping video" },
720
+ duration: { type: "string", description: "Generation duration" },
721
+ type: { type: "string", description: "Generation type" },
722
+ image_ref: { type: "string", description: "Image reference" },
723
+ video: { type: "string", description: "Video options" },
724
+ source: { type: "string", description: "Source generation or media" }
725
+ };
726
+ var GOOGLE_COMPATIBLE_PARAM_SPECS = {
727
+ temperature: {
728
+ type: "number",
729
+ min: 0,
730
+ max: 2,
731
+ default: 0.7,
732
+ description: "Controls randomness"
733
+ },
734
+ maxOutputTokens: {
735
+ type: "number",
736
+ min: 1,
737
+ default: 4096,
738
+ description: "Maximum output tokens"
739
+ },
740
+ topP: {
741
+ type: "number",
742
+ min: 0,
743
+ max: 1,
744
+ default: 1,
745
+ description: "Nucleus sampling"
746
+ },
747
+ topK: {
748
+ type: "number",
749
+ min: 0,
750
+ default: 40,
751
+ description: "Top-K sampling"
752
+ },
753
+ frequencyPenalty: {
754
+ type: "number",
755
+ min: -2,
756
+ max: 2,
757
+ default: 0,
758
+ description: "Penalize frequent tokens"
759
+ },
760
+ presencePenalty: {
761
+ type: "number",
762
+ min: -2,
763
+ max: 2,
764
+ default: 0,
765
+ description: "Penalize repeated topics"
766
+ },
767
+ stopSequences: { type: "string", description: "Stop sequences" },
768
+ candidateCount: {
769
+ type: "number",
770
+ min: 1,
771
+ default: 1,
772
+ description: "Candidate count"
773
+ },
774
+ stream: { type: "boolean", default: false, description: "Stream response" },
775
+ seed: { type: "number", description: "Random seed" },
776
+ responseMimeType: { type: "string", description: "Response MIME type" },
777
+ responseSchema: { type: "string", description: "Response schema" }
778
+ };
779
+ var PARAM_SPECS = {
780
+ openai: {
781
+ temperature: {
782
+ type: "number",
783
+ min: 0,
784
+ max: 2,
785
+ default: 0.7,
786
+ description: "Controls randomness"
787
+ },
788
+ max_tokens: {
789
+ type: "number",
790
+ min: 1,
791
+ default: 4096,
792
+ description: "Maximum output tokens"
793
+ },
794
+ max_completion_tokens: {
795
+ type: "number",
796
+ min: 1,
797
+ default: 4096,
798
+ description: "Maximum completion tokens (reasoning models)"
799
+ },
800
+ top_p: {
801
+ type: "number",
802
+ min: 0,
803
+ max: 1,
804
+ default: 1,
805
+ description: "Nucleus sampling"
806
+ },
807
+ frequency_penalty: {
808
+ type: "number",
809
+ min: -2,
810
+ max: 2,
811
+ default: 0,
812
+ description: "Penalize frequent tokens"
813
+ },
814
+ presence_penalty: {
815
+ type: "number",
816
+ min: -2,
817
+ max: 2,
818
+ default: 0,
819
+ description: "Penalize repeated topics"
820
+ },
821
+ stop: { type: "string", description: "Stop sequences" },
822
+ n: { type: "number", min: 1, default: 1, description: "Completions count" },
823
+ seed: { type: "number", description: "Random seed" },
824
+ stream: { type: "boolean", default: false, description: "Stream response" },
825
+ reasoning_effort: {
826
+ type: "string",
827
+ values: REASONING_EFFORT_VALUES,
828
+ default: "medium",
829
+ description: "Reasoning effort"
830
+ }
831
+ },
832
+ azure: OPENAI_COMPATIBLE_PARAM_SPECS,
833
+ anthropic: {
834
+ temperature: {
835
+ type: "number",
836
+ min: 0,
837
+ max: 1,
838
+ default: 0.7,
839
+ description: "Controls randomness"
840
+ },
841
+ max_tokens: {
842
+ type: "number",
843
+ min: 1,
844
+ default: 4096,
845
+ description: "Maximum output tokens"
846
+ },
847
+ top_p: {
848
+ type: "number",
849
+ min: 0,
850
+ max: 1,
851
+ default: 1,
852
+ description: "Nucleus sampling"
853
+ },
854
+ top_k: {
855
+ type: "number",
856
+ min: 0,
857
+ default: 40,
858
+ description: "Top-K sampling"
859
+ },
860
+ stop_sequences: { type: "string", description: "Stop sequences" },
861
+ stream: { type: "boolean", default: false, description: "Stream response" },
862
+ effort: {
863
+ type: "string",
864
+ values: REASONING_EFFORT_VALUES,
865
+ default: "low",
866
+ description: "Thinking effort"
867
+ },
868
+ cache_control: {
869
+ type: "string",
870
+ values: ["ephemeral"],
871
+ default: "ephemeral",
872
+ description: "Cache control"
873
+ },
874
+ cache_ttl: {
875
+ type: "string",
876
+ values: ["5m", "1h"],
877
+ default: "5m",
878
+ description: "Cache TTL"
879
+ }
880
+ },
881
+ google: {
882
+ temperature: {
883
+ type: "number",
884
+ min: 0,
885
+ max: 2,
886
+ default: 0.7,
887
+ description: "Controls randomness"
888
+ },
889
+ maxOutputTokens: {
890
+ type: "number",
891
+ min: 1,
892
+ default: 4096,
893
+ description: "Maximum output tokens"
894
+ },
895
+ topP: {
896
+ type: "number",
897
+ min: 0,
898
+ max: 1,
899
+ default: 1,
900
+ description: "Nucleus sampling"
901
+ },
902
+ topK: {
903
+ type: "number",
904
+ min: 0,
905
+ default: 40,
906
+ description: "Top-K sampling"
907
+ },
908
+ frequencyPenalty: {
909
+ type: "number",
910
+ min: -2,
911
+ max: 2,
912
+ default: 0,
913
+ description: "Penalize frequent tokens"
914
+ },
915
+ presencePenalty: {
916
+ type: "number",
917
+ min: -2,
918
+ max: 2,
919
+ default: 0,
920
+ description: "Penalize repeated topics"
921
+ },
922
+ stopSequences: { type: "string", description: "Stop sequences" },
923
+ candidateCount: {
924
+ type: "number",
925
+ min: 1,
926
+ default: 1,
927
+ description: "Candidate count"
928
+ },
929
+ stream: { type: "boolean", default: false, description: "Stream response" },
930
+ seed: { type: "number", description: "Random seed" },
931
+ responseMimeType: { type: "string", description: "Response MIME type" },
932
+ responseSchema: { type: "string", description: "Response schema" }
933
+ },
934
+ "google-vertex": GOOGLE_COMPATIBLE_PARAM_SPECS,
935
+ mistral: {
936
+ temperature: {
937
+ type: "number",
938
+ min: 0,
939
+ max: 1,
940
+ default: 0.7,
941
+ description: "Controls randomness"
942
+ },
943
+ max_tokens: {
944
+ type: "number",
945
+ min: 1,
946
+ default: 4096,
947
+ description: "Maximum output tokens"
948
+ },
949
+ top_p: {
950
+ type: "number",
951
+ min: 0,
952
+ max: 1,
953
+ default: 1,
954
+ description: "Nucleus sampling"
955
+ },
956
+ frequency_penalty: {
957
+ type: "number",
958
+ min: -2,
959
+ max: 2,
960
+ default: 0,
961
+ description: "Penalize frequent tokens"
962
+ },
963
+ presence_penalty: {
964
+ type: "number",
965
+ min: -2,
966
+ max: 2,
967
+ default: 0,
968
+ description: "Penalize repeated topics"
969
+ },
970
+ stop: { type: "string", description: "Stop sequences" },
971
+ n: { type: "number", min: 1, default: 1, description: "Completions count" },
972
+ random_seed: { type: "number", description: "Random seed" },
973
+ stream: { type: "boolean", default: false, description: "Stream response" },
974
+ safe_prompt: {
975
+ type: "boolean",
976
+ default: false,
977
+ description: "Enable safe prompt"
978
+ },
979
+ min_tokens: {
980
+ type: "number",
981
+ min: 0,
982
+ default: 0,
983
+ description: "Minimum tokens"
984
+ }
985
+ },
986
+ cohere: {
987
+ temperature: {
988
+ type: "number",
989
+ min: 0,
990
+ max: 1,
991
+ default: 0.7,
992
+ description: "Controls randomness"
993
+ },
994
+ max_tokens: {
995
+ type: "number",
996
+ min: 1,
997
+ default: 4096,
998
+ description: "Maximum output tokens"
999
+ },
1000
+ p: {
1001
+ type: "number",
1002
+ min: 0,
1003
+ max: 1,
1004
+ default: 1,
1005
+ description: "Nucleus sampling (p)"
1006
+ },
1007
+ k: {
1008
+ type: "number",
1009
+ min: 0,
1010
+ max: 500,
1011
+ default: 40,
1012
+ description: "Top-K sampling (k)"
1013
+ },
1014
+ frequency_penalty: {
1015
+ type: "number",
1016
+ min: 0,
1017
+ max: 1,
1018
+ default: 0,
1019
+ description: "Penalize frequent tokens"
1020
+ },
1021
+ presence_penalty: {
1022
+ type: "number",
1023
+ min: 0,
1024
+ max: 1,
1025
+ default: 0,
1026
+ description: "Penalize repeated topics"
1027
+ },
1028
+ stop_sequences: { type: "string", description: "Stop sequences" },
1029
+ stream: { type: "boolean", default: false, description: "Stream response" },
1030
+ seed: { type: "number", description: "Random seed" }
1031
+ },
1032
+ bedrock: {
1033
+ // Converse API inferenceConfig params
1034
+ temperature: {
1035
+ type: "number",
1036
+ min: 0,
1037
+ max: 1,
1038
+ default: 0.7,
1039
+ description: "Controls randomness"
1040
+ },
1041
+ maxTokens: {
1042
+ type: "number",
1043
+ min: 1,
1044
+ default: 4096,
1045
+ description: "Maximum output tokens"
1046
+ },
1047
+ topP: {
1048
+ type: "number",
1049
+ min: 0,
1050
+ max: 1,
1051
+ default: 1,
1052
+ description: "Nucleus sampling"
1053
+ },
1054
+ topK: {
1055
+ type: "number",
1056
+ min: 0,
1057
+ default: 40,
1058
+ description: "Top-K sampling"
1059
+ },
1060
+ stopSequences: { type: "string", description: "Stop sequences" },
1061
+ stream: { type: "boolean", default: false, description: "Stream response" },
1062
+ cache_control: {
1063
+ type: "string",
1064
+ values: ["ephemeral"],
1065
+ default: "ephemeral",
1066
+ description: "Cache control"
1067
+ },
1068
+ cache_ttl: {
1069
+ type: "string",
1070
+ values: ["5m", "1h"],
1071
+ default: "5m",
1072
+ description: "Cache TTL"
1073
+ }
1074
+ },
1075
+ openrouter: {
1076
+ // Loose validation — proxies to many providers with varying ranges
1077
+ temperature: {
1078
+ type: "number",
1079
+ min: 0,
1080
+ max: 2,
1081
+ default: 0.7,
1082
+ description: "Controls randomness"
1083
+ },
1084
+ max_tokens: {
1085
+ type: "number",
1086
+ min: 1,
1087
+ default: 4096,
1088
+ description: "Maximum output tokens"
1089
+ },
1090
+ max_completion_tokens: {
1091
+ type: "number",
1092
+ min: 1,
1093
+ default: 4096,
1094
+ description: "Maximum completion tokens (reasoning models)"
1095
+ },
1096
+ top_p: {
1097
+ type: "number",
1098
+ min: 0,
1099
+ max: 1,
1100
+ default: 1,
1101
+ description: "Nucleus sampling"
1102
+ },
1103
+ top_k: {
1104
+ type: "number",
1105
+ min: 0,
1106
+ default: 40,
1107
+ description: "Top-K sampling"
1108
+ },
1109
+ frequency_penalty: {
1110
+ type: "number",
1111
+ min: -2,
1112
+ max: 2,
1113
+ default: 0,
1114
+ description: "Penalize frequent tokens"
1115
+ },
1116
+ presence_penalty: {
1117
+ type: "number",
1118
+ min: -2,
1119
+ max: 2,
1120
+ default: 0,
1121
+ description: "Penalize repeated topics"
1122
+ },
1123
+ stop: { type: "string", description: "Stop sequences" },
1124
+ n: { type: "number", min: 1, default: 1, description: "Completions count" },
1125
+ seed: { type: "number", description: "Random seed" },
1126
+ stream: { type: "boolean", default: false, description: "Stream response" },
1127
+ reasoning_effort: {
1128
+ type: "string",
1129
+ values: REASONING_EFFORT_VALUES,
1130
+ default: "medium",
1131
+ description: "Reasoning effort"
1132
+ },
1133
+ ...OPENROUTER_ROUTING_PARAM_SPECS
1134
+ },
1135
+ vercel: {
1136
+ // Loose validation — proxies to many providers with varying ranges
1137
+ temperature: {
1138
+ type: "number",
1139
+ min: 0,
1140
+ max: 2,
1141
+ default: 0.7,
1142
+ description: "Controls randomness"
1143
+ },
1144
+ max_tokens: {
1145
+ type: "number",
1146
+ min: 1,
1147
+ default: 4096,
1148
+ description: "Maximum output tokens"
1149
+ },
1150
+ max_completion_tokens: {
1151
+ type: "number",
1152
+ min: 1,
1153
+ default: 4096,
1154
+ description: "Maximum completion tokens (reasoning models)"
1155
+ },
1156
+ top_p: {
1157
+ type: "number",
1158
+ min: 0,
1159
+ max: 1,
1160
+ default: 1,
1161
+ description: "Nucleus sampling"
1162
+ },
1163
+ top_k: {
1164
+ type: "number",
1165
+ min: 0,
1166
+ default: 40,
1167
+ description: "Top-K sampling"
1168
+ },
1169
+ frequency_penalty: {
1170
+ type: "number",
1171
+ min: -2,
1172
+ max: 2,
1173
+ default: 0,
1174
+ description: "Penalize frequent tokens"
1175
+ },
1176
+ presence_penalty: {
1177
+ type: "number",
1178
+ min: -2,
1179
+ max: 2,
1180
+ default: 0,
1181
+ description: "Penalize repeated topics"
1182
+ },
1183
+ stop: { type: "string", description: "Stop sequences" },
1184
+ n: { type: "number", min: 1, default: 1, description: "Completions count" },
1185
+ seed: { type: "number", description: "Random seed" },
1186
+ stream: { type: "boolean", default: false, description: "Stream response" },
1187
+ reasoning_effort: {
1188
+ type: "string",
1189
+ values: REASONING_EFFORT_VALUES,
1190
+ default: "medium",
1191
+ description: "Reasoning effort"
1192
+ },
1193
+ order: { type: "string", description: "Gateway provider order" },
1194
+ only: { type: "string", description: "Gateway provider allowlist" },
1195
+ models: { type: "string", description: "Gateway fallback models" },
1196
+ tags: { type: "string", description: "Gateway usage tags" },
1197
+ sort: {
1198
+ type: "string",
1199
+ values: ["cost", "ttft", "tps"],
1200
+ description: "Gateway provider sort strategy"
1201
+ },
1202
+ caching: {
1203
+ type: "string",
1204
+ values: ["auto"],
1205
+ description: "Gateway automatic caching strategy"
1206
+ },
1207
+ user: { type: "string", description: "Gateway usage user identifier" },
1208
+ byok: { type: "string", description: "Gateway BYOK credentials" },
1209
+ zero_data_retention: {
1210
+ type: "boolean",
1211
+ description: "Gateway zero data retention routing"
1212
+ },
1213
+ zeroDataRetention: {
1214
+ type: "boolean",
1215
+ description: "Gateway zero data retention routing"
1216
+ },
1217
+ disallow_prompt_training: {
1218
+ type: "boolean",
1219
+ description: "Gateway prompt training opt-out routing"
1220
+ },
1221
+ disallowPromptTraining: {
1222
+ type: "boolean",
1223
+ description: "Gateway prompt training opt-out routing"
1224
+ },
1225
+ hipaa_compliant: {
1226
+ type: "boolean",
1227
+ description: "Gateway HIPAA-compliant routing"
1228
+ },
1229
+ hipaaCompliant: {
1230
+ type: "boolean",
1231
+ description: "Gateway HIPAA-compliant routing"
1232
+ },
1233
+ quota_entity_id: {
1234
+ type: "string",
1235
+ description: "Gateway quota entity identifier"
1236
+ },
1237
+ quotaEntityId: {
1238
+ type: "string",
1239
+ description: "Gateway quota entity identifier"
1240
+ },
1241
+ provider_timeouts: {
1242
+ type: "string",
1243
+ description: "Gateway provider timeouts"
1244
+ },
1245
+ providerTimeouts: {
1246
+ type: "string",
1247
+ description: "Gateway provider timeouts"
1248
+ }
1249
+ },
1250
+ xai: OPENAI_COMPATIBLE_PARAM_SPECS,
1251
+ groq: OPENAI_COMPATIBLE_PARAM_SPECS,
1252
+ fal: FAL_PARAM_SPECS,
1253
+ deepinfra: OPENAI_COMPATIBLE_PARAM_SPECS,
1254
+ "black-forest-labs": {},
1255
+ together: OPENAI_COMPATIBLE_PARAM_SPECS,
1256
+ fireworks: OPENAI_COMPATIBLE_PARAM_SPECS,
1257
+ deepseek: OPENAI_COMPATIBLE_PARAM_SPECS,
1258
+ moonshotai: OPENAI_COMPATIBLE_PARAM_SPECS,
1259
+ perplexity: OPENAI_COMPATIBLE_PARAM_SPECS,
1260
+ alibaba: OPENAI_COMPATIBLE_PARAM_SPECS,
1261
+ cerebras: OPENAI_COMPATIBLE_PARAM_SPECS,
1262
+ replicate: REPLICATE_PARAM_SPECS,
1263
+ prodia: PRODIA_PARAM_SPECS,
1264
+ luma: LUMA_PARAM_SPECS,
1265
+ bytedance: {},
1266
+ kling: {},
1267
+ elevenlabs: {},
1268
+ assemblyai: {},
1269
+ deepgram: {},
1270
+ gladia: {},
1271
+ lmnt: {},
1272
+ hume: {},
1273
+ revai: {},
1274
+ baseten: OPENAI_COMPATIBLE_PARAM_SPECS,
1275
+ huggingface: OPENAI_COMPATIBLE_PARAM_SPECS
1276
+ };
298
1277
  function isReasoningModel(model) {
299
- const name = model.includes("/") ? model.split("/").pop() : model;
300
- return /^o[134]/.test(name);
1278
+ const name = modelLeafName(model);
1279
+ const oSeries = name.match(/^o\d+/)?.[0];
1280
+ const gptSeries = name.match(/^gpt-[5-9]/)?.[0];
1281
+ return (oSeries ? modelMatchesFamily(name, oSeries) : false) || (gptSeries ? modelMatchesFamily(name, gptSeries) : false);
301
1282
  }
302
1283
  function canHostOpenAIModels(provider) {
303
- return provider === "openai" || provider === "openrouter" || provider === "vercel";
1284
+ return provider === "openai" || provider === "azure" || provider === "openrouter" || provider === "vercel";
304
1285
  }
305
1286
  function isGatewayProvider(provider) {
306
1287
  return provider === "openrouter" || provider === "vercel";
@@ -308,22 +1289,27 @@ function isGatewayProvider(provider) {
308
1289
  function detectGatewaySubProvider(model) {
309
1290
  const slash = model.indexOf("/");
310
1291
  if (slash < 1) return void 0;
311
- const prefix = model.slice(0, slash);
312
- const direct = [
313
- "openai",
314
- "anthropic",
315
- "google",
316
- "mistral",
317
- "cohere"
318
- ];
319
- return direct.find((p) => p === prefix);
1292
+ const prefix = normalizeModelForMatching(model.slice(0, slash));
1293
+ const direct = {
1294
+ openai: "openai",
1295
+ anthropic: "anthropic",
1296
+ google: "google",
1297
+ vertex: "google",
1298
+ "google-vertex": "google",
1299
+ mistral: "mistral",
1300
+ cohere: "cohere"
1301
+ };
1302
+ return direct[prefix];
320
1303
  }
1304
+ var REASONING_MODEL_UNSUPPORTED = /* @__PURE__ */ new Set([
1305
+ "temperature",
1306
+ "top_p",
1307
+ "top_k",
1308
+ "frequency_penalty",
1309
+ "presence_penalty",
1310
+ "n"
1311
+ ]);
321
1312
  function detectBedrockModelFamily(model) {
322
- const parts = model.split(".");
323
- let prefix = parts[0];
324
- if (["us", "eu", "apac", "global"].includes(prefix) && parts.length > 1) {
325
- prefix = parts[1];
326
- }
327
1313
  const families = [
328
1314
  "anthropic",
329
1315
  "meta",
@@ -332,12 +1318,18 @@ function detectBedrockModelFamily(model) {
332
1318
  "cohere",
333
1319
  "ai21"
334
1320
  ];
335
- return families.find((f) => prefix === f);
1321
+ const parts = modelLeafName(model).split(".");
1322
+ return families.find((family) => parts.includes(family));
336
1323
  }
337
1324
  function bedrockSupportsCaching(model) {
338
1325
  const family = detectBedrockModelFamily(model);
339
1326
  if (family === "anthropic") return true;
340
- if (family === "amazon" && model.includes("nova")) return true;
1327
+ if (family === "amazon") {
1328
+ const parts = modelLeafName(model).split(".");
1329
+ const amazonIndex = parts.indexOf("amazon");
1330
+ const modelName = amazonIndex >= 0 ? parts[amazonIndex + 1] : void 0;
1331
+ return modelName ? modelMatchesFamily(modelName, "nova") : false;
1332
+ }
341
1333
  return false;
342
1334
  }
343
1335
  var CACHE_VALUES = {
@@ -422,9 +1414,9 @@ var CACHE_TTLS = {
422
1414
  baseten: void 0,
423
1415
  huggingface: void 0
424
1416
  };
425
- var DURATION_RE = /^\d+[mh]$/;
426
1417
 
427
1418
  // src/normalize.ts
1419
+ var DURATION_RE = /^\d+[mh]$/;
428
1420
  function normalize(config, options = {}) {
429
1421
  const provider = (config.hostAlias ? providerFromHostAlias(config.hostAlias) : void 0) ?? detectProvider(config.host);
430
1422
  const subProvider = provider && isGatewayProvider(provider) ? detectGatewaySubProvider(config.model) : void 0;
@@ -512,6 +1504,17 @@ function normalize(config, options = {}) {
512
1504
  }
513
1505
  key = "max_completion_tokens";
514
1506
  }
1507
+ if (provider && canHostOpenAIModels(provider) && isReasoningModel(config.model) && REASONING_MODEL_UNSUPPORTED.has(key)) {
1508
+ if (options.verbose) {
1509
+ changes.push({
1510
+ from: key,
1511
+ to: "(dropped)",
1512
+ value,
1513
+ reason: `${provider} reasoning model "${config.model}" does not support "${key}"`
1514
+ });
1515
+ }
1516
+ continue;
1517
+ }
515
1518
  params[key] = value;
516
1519
  }
517
1520
  return {
@@ -525,4 +1528,3 @@ function normalize(config, options = {}) {
525
1528
  0 && (module.exports = {
526
1529
  normalize
527
1530
  });
528
- //# sourceMappingURL=normalize.cjs.map