llm-strings 0.0.1 โ 1.0.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.
- package/README.md +38 -3
- package/dist/index.cjs +186 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -21
- package/dist/index.d.ts +9 -21
- package/dist/index.js +179 -5
- package/dist/index.js.map +1 -1
- package/dist/providers.cjs +561 -0
- package/dist/providers.cjs.map +1 -0
- package/dist/providers.d.cts +72 -0
- package/dist/providers.d.ts +72 -0
- package/dist/providers.js +522 -0
- package/dist/providers.js.map +1 -0
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -1,18 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ๐ llm-strings
|
|
2
4
|
|
|
3
5
|
**Connection strings for LLMs. Like database URLs, but for AI.**
|
|
4
6
|
|
|
7
|
+
[](https://www.npmjs.com/package/llm-strings)
|
|
8
|
+
[](https://github.com/justsml/llm-strings/blob/main/LICENSE)
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
[](https://www.npmjs.com/package/llm-strings)
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+

|
|
17
|
+
|
|
5
18
|
```ini
|
|
6
19
|
llm://api.openai.com/gpt-5.2?temp=0.7&max=2000
|
|
7
20
|
llm://my-app:sk-key-123@api.anthropic.com/claude-sonnet-4-5?cache=5m
|
|
8
21
|
llm://bedrock-runtime.us-east-1.amazonaws.com/anthropic.claude-sonnet-4-5-20250929-v1:0?temp=0.5
|
|
9
22
|
```
|
|
10
23
|
|
|
24
|
+
|
|
25
|
+
|
|
11
26
|
Every LLM provider invented their own parameter names. `max_tokens` vs `maxOutputTokens` vs `maxTokens`. `top_p` vs `topP` vs `p`. `stop` vs `stop_sequences` vs `stopSequences`. You write the config once, then rewrite it for every provider.
|
|
12
27
|
|
|
13
28
|
**llm-strings** gives you a single, portable format. Parse it, normalize it to any provider's API, and validate it โ all in one library with zero dependencies.
|
|
14
29
|
|
|
15
|
-
Based on the [LLM Connection Strings](https://danlevy.net/llm-connection-strings/)
|
|
30
|
+
Based on the [LLM Connection Strings](https://danlevy.net/llm-connection-strings/) article by Dan Levy. See [draft IETF RFC for `llm://`](https://datatracker.ietf.org/doc/html/draft-levy-llm-uri-scheme-00).
|
|
16
31
|
|
|
17
32
|
## Install
|
|
18
33
|
|
|
@@ -315,7 +330,7 @@ Normalizes parameters for the target provider:
|
|
|
315
330
|
|
|
316
331
|
Pass `{ verbose: true }` to get a detailed `changes` array documenting each transformation.
|
|
317
332
|
|
|
318
|
-
### `validate(connectionString): ValidationIssue[]`
|
|
333
|
+
### `validate(connectionString, options?): ValidationIssue[]`
|
|
319
334
|
|
|
320
335
|
Parses, normalizes, and validates a connection string against provider-specific rules. Returns `[]` if everything is valid. Checks:
|
|
321
336
|
|
|
@@ -325,6 +340,13 @@ Parses, normalizes, and validates a connection string against provider-specific
|
|
|
325
340
|
- Reasoning model restrictions (no `temperature` on o1/o3/o4)
|
|
326
341
|
- Bedrock model family constraints (`topK` only for Claude/Cohere/Mistral)
|
|
327
342
|
|
|
343
|
+
Pass `{ strict: true }` to promote warnings (unknown provider, unknown params) to errors:
|
|
344
|
+
|
|
345
|
+
```ts
|
|
346
|
+
validate("llm://custom-api.com/my-model?temp=0.5", { strict: true });
|
|
347
|
+
// โ [{ severity: "error", message: "Unknown provider โฆ" }]
|
|
348
|
+
```
|
|
349
|
+
|
|
328
350
|
### `detectProvider(host): Provider | undefined`
|
|
329
351
|
|
|
330
352
|
Identifies the provider from a hostname string.
|
|
@@ -343,12 +365,25 @@ import type {
|
|
|
343
365
|
NormalizeResult,
|
|
344
366
|
NormalizeChange,
|
|
345
367
|
NormalizeOptions,
|
|
368
|
+
ValidateOptions,
|
|
346
369
|
ValidationIssue,
|
|
347
370
|
Provider,
|
|
348
371
|
BedrockModelFamily,
|
|
349
372
|
} from "llm-strings";
|
|
350
373
|
```
|
|
351
374
|
|
|
375
|
+
## Contributing
|
|
376
|
+
|
|
377
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
378
|
+
|
|
352
379
|
## License
|
|
353
380
|
|
|
354
381
|
MIT
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
<div align="center">
|
|
386
|
+
|
|
387
|
+
**[๐ Read the spec](https://danlevy.net/llm-connection-strings/) ยท [๐ Report a bug](https://github.com/justsml/llm-strings/issues) ยท [๐ก Request a feature](https://github.com/justsml/llm-strings/issues)**
|
|
388
|
+
|
|
389
|
+
</div>
|
package/dist/index.cjs
CHANGED
|
@@ -21,10 +21,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
ALIASES: () => ALIASES,
|
|
24
|
+
CANONICAL_PARAM_SPECS: () => CANONICAL_PARAM_SPECS,
|
|
25
|
+
MODELS: () => MODELS,
|
|
26
|
+
PARAM_SPECS: () => PARAM_SPECS,
|
|
27
|
+
PROVIDER_META: () => PROVIDER_META,
|
|
24
28
|
PROVIDER_PARAMS: () => PROVIDER_PARAMS,
|
|
29
|
+
REASONING_MODEL_UNSUPPORTED: () => REASONING_MODEL_UNSUPPORTED,
|
|
25
30
|
build: () => build,
|
|
31
|
+
canHostOpenAIModels: () => canHostOpenAIModels,
|
|
26
32
|
detectBedrockModelFamily: () => detectBedrockModelFamily,
|
|
27
33
|
detectProvider: () => detectProvider,
|
|
34
|
+
isReasoningModel: () => isReasoningModel,
|
|
28
35
|
normalize: () => normalize,
|
|
29
36
|
parse: () => parse,
|
|
30
37
|
validate: () => validate
|
|
@@ -399,6 +406,174 @@ var CACHE_TTLS = {
|
|
|
399
406
|
vercel: void 0
|
|
400
407
|
};
|
|
401
408
|
var DURATION_RE = /^\d+[mh]$/;
|
|
409
|
+
var PROVIDER_META = [
|
|
410
|
+
{ id: "openai", name: "OpenAI", host: "api.openai.com", color: "#10a37f" },
|
|
411
|
+
{ id: "anthropic", name: "Anthropic", host: "api.anthropic.com", color: "#e8956a" },
|
|
412
|
+
{ id: "google", name: "Google", host: "generativelanguage.googleapis.com", color: "#4285f4" },
|
|
413
|
+
{ id: "mistral", name: "Mistral", host: "api.mistral.ai", color: "#ff7000" },
|
|
414
|
+
{ id: "cohere", name: "Cohere", host: "api.cohere.com", color: "#39594d" },
|
|
415
|
+
{ id: "bedrock", name: "Bedrock", host: "bedrock-runtime.us-east-1.amazonaws.com", color: "#ff9900" },
|
|
416
|
+
{ id: "openrouter", name: "OpenRouter", host: "openrouter.ai", color: "#818cf8" },
|
|
417
|
+
{ id: "vercel", name: "Vercel", host: "gateway.ai.vercel.app", color: "#ededed" }
|
|
418
|
+
];
|
|
419
|
+
var MODELS = {
|
|
420
|
+
openai: [
|
|
421
|
+
"gpt-5.2",
|
|
422
|
+
"gpt-5.2-pro",
|
|
423
|
+
"gpt-4.1",
|
|
424
|
+
"gpt-4.1-mini",
|
|
425
|
+
"gpt-4.1-nano",
|
|
426
|
+
"o3",
|
|
427
|
+
"o3-mini",
|
|
428
|
+
"o4-mini",
|
|
429
|
+
"o1-pro"
|
|
430
|
+
],
|
|
431
|
+
anthropic: [
|
|
432
|
+
"claude-opus-4-6",
|
|
433
|
+
"claude-sonnet-4-6",
|
|
434
|
+
"claude-sonnet-4-5",
|
|
435
|
+
"claude-haiku-4-5"
|
|
436
|
+
],
|
|
437
|
+
google: [
|
|
438
|
+
"gemini-3-pro-preview",
|
|
439
|
+
"gemini-3-flash-preview",
|
|
440
|
+
"gemini-2.5-pro",
|
|
441
|
+
"gemini-2.5-flash"
|
|
442
|
+
],
|
|
443
|
+
mistral: [
|
|
444
|
+
"mistral-large-latest",
|
|
445
|
+
"mistral-medium-latest",
|
|
446
|
+
"mistral-small-latest",
|
|
447
|
+
"codestral-latest",
|
|
448
|
+
"magistral-medium-latest"
|
|
449
|
+
],
|
|
450
|
+
cohere: [
|
|
451
|
+
"command-a-03-2025",
|
|
452
|
+
"command-r-plus-08-2024",
|
|
453
|
+
"command-r-08-2024",
|
|
454
|
+
"command-r7b-12-2024"
|
|
455
|
+
],
|
|
456
|
+
bedrock: [
|
|
457
|
+
"anthropic.claude-opus-4-6-v1",
|
|
458
|
+
"anthropic.claude-sonnet-4-6-v1",
|
|
459
|
+
"anthropic.claude-haiku-4-5-v1",
|
|
460
|
+
"amazon.nova-pro-v1",
|
|
461
|
+
"amazon.nova-lite-v1",
|
|
462
|
+
"meta.llama3-70b-instruct-v1:0"
|
|
463
|
+
],
|
|
464
|
+
openrouter: [
|
|
465
|
+
"openai/gpt-5.2",
|
|
466
|
+
"anthropic/claude-opus-4-6",
|
|
467
|
+
"google/gemini-2.5-pro",
|
|
468
|
+
"mistral/mistral-large-latest"
|
|
469
|
+
],
|
|
470
|
+
vercel: [
|
|
471
|
+
"openai/gpt-5.2",
|
|
472
|
+
"anthropic/claude-opus-4-6",
|
|
473
|
+
"google/gemini-2.5-pro",
|
|
474
|
+
"google/gemini-3-pro-preview",
|
|
475
|
+
"google/gemini-3-flash-preview",
|
|
476
|
+
"mistral/mistral-large-latest",
|
|
477
|
+
"qwen/qwen2.5-pro"
|
|
478
|
+
]
|
|
479
|
+
};
|
|
480
|
+
var CANONICAL_PARAM_SPECS = {
|
|
481
|
+
openai: {
|
|
482
|
+
temperature: { type: "number", min: 0, max: 2, default: 0.7, description: "Controls randomness" },
|
|
483
|
+
max_tokens: { type: "number", min: 1, default: 4096, description: "Maximum output tokens" },
|
|
484
|
+
top_p: { type: "number", min: 0, max: 1, default: 1, description: "Nucleus sampling" },
|
|
485
|
+
frequency_penalty: { type: "number", min: -2, max: 2, default: 0, description: "Penalize frequent tokens" },
|
|
486
|
+
presence_penalty: { type: "number", min: -2, max: 2, default: 0, description: "Penalize repeated topics" },
|
|
487
|
+
stop: { type: "string", default: "", description: "Stop sequences" },
|
|
488
|
+
n: { type: "number", min: 1, default: 1, description: "Completions count" },
|
|
489
|
+
seed: { type: "number", default: "", description: "Random seed" },
|
|
490
|
+
stream: { type: "boolean", default: false, description: "Stream response" },
|
|
491
|
+
effort: { type: "enum", values: ["none", "minimal", "low", "medium", "high", "xhigh"], default: "medium", description: "Reasoning effort" }
|
|
492
|
+
},
|
|
493
|
+
anthropic: {
|
|
494
|
+
temperature: { type: "number", min: 0, max: 1, default: 0.7, description: "Controls randomness" },
|
|
495
|
+
max_tokens: { type: "number", min: 1, default: 4096, description: "Maximum output tokens" },
|
|
496
|
+
top_p: { type: "number", min: 0, max: 1, default: 1, description: "Nucleus sampling" },
|
|
497
|
+
top_k: { type: "number", min: 0, default: 40, description: "Top-K sampling" },
|
|
498
|
+
stop: { type: "string", default: "", description: "Stop sequences" },
|
|
499
|
+
stream: { type: "boolean", default: false, description: "Stream response" },
|
|
500
|
+
effort: { type: "enum", values: ["low", "medium", "high", "max"], default: "medium", description: "Thinking effort" },
|
|
501
|
+
cache: { type: "enum", values: ["ephemeral"], default: "ephemeral", description: "Cache control" },
|
|
502
|
+
cache_ttl: { type: "enum", values: ["5m", "1h"], default: "5m", description: "Cache TTL" }
|
|
503
|
+
},
|
|
504
|
+
google: {
|
|
505
|
+
temperature: { type: "number", min: 0, max: 2, default: 0.7, description: "Controls randomness" },
|
|
506
|
+
max_tokens: { type: "number", min: 1, default: 4096, description: "Maximum output tokens" },
|
|
507
|
+
top_p: { type: "number", min: 0, max: 1, default: 1, description: "Nucleus sampling" },
|
|
508
|
+
top_k: { type: "number", min: 0, default: 40, description: "Top-K sampling" },
|
|
509
|
+
frequency_penalty: { type: "number", min: -2, max: 2, default: 0, description: "Penalize frequent tokens" },
|
|
510
|
+
presence_penalty: { type: "number", min: -2, max: 2, default: 0, description: "Penalize repeated topics" },
|
|
511
|
+
stop: { type: "string", default: "", description: "Stop sequences" },
|
|
512
|
+
n: { type: "number", min: 1, default: 1, description: "Candidate count" },
|
|
513
|
+
stream: { type: "boolean", default: false, description: "Stream response" },
|
|
514
|
+
seed: { type: "number", default: "", description: "Random seed" }
|
|
515
|
+
},
|
|
516
|
+
mistral: {
|
|
517
|
+
temperature: { type: "number", min: 0, max: 1, default: 0.7, description: "Controls randomness" },
|
|
518
|
+
max_tokens: { type: "number", min: 1, default: 4096, description: "Maximum output tokens" },
|
|
519
|
+
top_p: { type: "number", min: 0, max: 1, default: 1, description: "Nucleus sampling" },
|
|
520
|
+
frequency_penalty: { type: "number", min: -2, max: 2, default: 0, description: "Penalize frequent tokens" },
|
|
521
|
+
presence_penalty: { type: "number", min: -2, max: 2, default: 0, description: "Penalize repeated topics" },
|
|
522
|
+
stop: { type: "string", default: "", description: "Stop sequences" },
|
|
523
|
+
n: { type: "number", min: 1, default: 1, description: "Completions count" },
|
|
524
|
+
seed: { type: "number", default: "", description: "Random seed" },
|
|
525
|
+
stream: { type: "boolean", default: false, description: "Stream response" },
|
|
526
|
+
safe_prompt: { type: "boolean", default: false, description: "Enable safe prompt" },
|
|
527
|
+
min_tokens: { type: "number", min: 0, default: 0, description: "Minimum tokens" }
|
|
528
|
+
},
|
|
529
|
+
cohere: {
|
|
530
|
+
temperature: { type: "number", min: 0, max: 1, default: 0.7, description: "Controls randomness" },
|
|
531
|
+
max_tokens: { type: "number", min: 1, default: 4096, description: "Maximum output tokens" },
|
|
532
|
+
top_p: { type: "number", min: 0, max: 1, default: 1, description: "Nucleus sampling (p)" },
|
|
533
|
+
top_k: { type: "number", min: 0, max: 500, default: 40, description: "Top-K sampling (k)" },
|
|
534
|
+
frequency_penalty: { type: "number", min: 0, max: 1, default: 0, description: "Penalize frequent tokens" },
|
|
535
|
+
presence_penalty: { type: "number", min: 0, max: 1, default: 0, description: "Penalize repeated topics" },
|
|
536
|
+
stop: { type: "string", default: "", description: "Stop sequences" },
|
|
537
|
+
stream: { type: "boolean", default: false, description: "Stream response" },
|
|
538
|
+
seed: { type: "number", default: "", description: "Random seed" }
|
|
539
|
+
},
|
|
540
|
+
bedrock: {
|
|
541
|
+
temperature: { type: "number", min: 0, max: 1, default: 0.7, description: "Controls randomness" },
|
|
542
|
+
max_tokens: { type: "number", min: 1, default: 4096, description: "Maximum output tokens" },
|
|
543
|
+
top_p: { type: "number", min: 0, max: 1, default: 1, description: "Nucleus sampling" },
|
|
544
|
+
top_k: { type: "number", min: 0, default: 40, description: "Top-K sampling" },
|
|
545
|
+
stop: { type: "string", default: "", description: "Stop sequences" },
|
|
546
|
+
stream: { type: "boolean", default: false, description: "Stream response" },
|
|
547
|
+
cache: { type: "enum", values: ["ephemeral"], default: "ephemeral", description: "Cache control" },
|
|
548
|
+
cache_ttl: { type: "enum", values: ["5m", "1h"], default: "5m", description: "Cache TTL" }
|
|
549
|
+
},
|
|
550
|
+
openrouter: {
|
|
551
|
+
temperature: { type: "number", min: 0, max: 2, default: 0.7, description: "Controls randomness" },
|
|
552
|
+
max_tokens: { type: "number", min: 1, default: 4096, description: "Maximum output tokens" },
|
|
553
|
+
top_p: { type: "number", min: 0, max: 1, default: 1, description: "Nucleus sampling" },
|
|
554
|
+
top_k: { type: "number", min: 0, default: 40, description: "Top-K sampling" },
|
|
555
|
+
frequency_penalty: { type: "number", min: -2, max: 2, default: 0, description: "Penalize frequent tokens" },
|
|
556
|
+
presence_penalty: { type: "number", min: -2, max: 2, default: 0, description: "Penalize repeated topics" },
|
|
557
|
+
stop: { type: "string", default: "", description: "Stop sequences" },
|
|
558
|
+
n: { type: "number", min: 1, default: 1, description: "Completions count" },
|
|
559
|
+
seed: { type: "number", default: "", description: "Random seed" },
|
|
560
|
+
stream: { type: "boolean", default: false, description: "Stream response" },
|
|
561
|
+
effort: { type: "enum", values: ["none", "minimal", "low", "medium", "high", "xhigh"], default: "medium", description: "Reasoning effort" }
|
|
562
|
+
},
|
|
563
|
+
vercel: {
|
|
564
|
+
temperature: { type: "number", min: 0, max: 2, default: 0.7, description: "Controls randomness" },
|
|
565
|
+
max_tokens: { type: "number", min: 1, default: 4096, description: "Maximum output tokens" },
|
|
566
|
+
top_p: { type: "number", min: 0, max: 1, default: 1, description: "Nucleus sampling" },
|
|
567
|
+
top_k: { type: "number", min: 0, default: 40, description: "Top-K sampling" },
|
|
568
|
+
frequency_penalty: { type: "number", min: -2, max: 2, default: 0, description: "Penalize frequent tokens" },
|
|
569
|
+
presence_penalty: { type: "number", min: -2, max: 2, default: 0, description: "Penalize repeated topics" },
|
|
570
|
+
stop: { type: "string", default: "", description: "Stop sequences" },
|
|
571
|
+
n: { type: "number", min: 1, default: 1, description: "Completions count" },
|
|
572
|
+
seed: { type: "number", default: "", description: "Random seed" },
|
|
573
|
+
stream: { type: "boolean", default: false, description: "Stream response" },
|
|
574
|
+
effort: { type: "enum", values: ["none", "minimal", "low", "medium", "high", "xhigh"], default: "medium", description: "Reasoning effort" }
|
|
575
|
+
}
|
|
576
|
+
};
|
|
402
577
|
|
|
403
578
|
// src/normalize.ts
|
|
404
579
|
function normalize(config, options = {}) {
|
|
@@ -497,17 +672,16 @@ function normalize(config, options = {}) {
|
|
|
497
672
|
}
|
|
498
673
|
|
|
499
674
|
// src/validate.ts
|
|
500
|
-
function validate(connectionString) {
|
|
675
|
+
function validate(connectionString, options = {}) {
|
|
501
676
|
const parsed = parse(connectionString);
|
|
502
|
-
const { config } = normalize(parsed);
|
|
503
|
-
const provider = detectProvider(config.host);
|
|
677
|
+
const { config, provider } = normalize(parsed);
|
|
504
678
|
const issues = [];
|
|
505
679
|
if (!provider) {
|
|
506
680
|
issues.push({
|
|
507
681
|
param: "host",
|
|
508
682
|
value: config.host,
|
|
509
683
|
message: `Unknown provider for host "${config.host}". Validation skipped.`,
|
|
510
|
-
severity: "warning"
|
|
684
|
+
severity: options.strict ? "error" : "warning"
|
|
511
685
|
});
|
|
512
686
|
return issues;
|
|
513
687
|
}
|
|
@@ -549,7 +723,7 @@ function validate(connectionString) {
|
|
|
549
723
|
param: key,
|
|
550
724
|
value,
|
|
551
725
|
message: `Unknown param "${key}" for ${provider}.`,
|
|
552
|
-
severity: "warning"
|
|
726
|
+
severity: options.strict ? "error" : "warning"
|
|
553
727
|
});
|
|
554
728
|
continue;
|
|
555
729
|
}
|
|
@@ -620,10 +794,17 @@ function validate(connectionString) {
|
|
|
620
794
|
// Annotate the CommonJS export names for ESM import in node:
|
|
621
795
|
0 && (module.exports = {
|
|
622
796
|
ALIASES,
|
|
797
|
+
CANONICAL_PARAM_SPECS,
|
|
798
|
+
MODELS,
|
|
799
|
+
PARAM_SPECS,
|
|
800
|
+
PROVIDER_META,
|
|
623
801
|
PROVIDER_PARAMS,
|
|
802
|
+
REASONING_MODEL_UNSUPPORTED,
|
|
624
803
|
build,
|
|
804
|
+
canHostOpenAIModels,
|
|
625
805
|
detectBedrockModelFamily,
|
|
626
806
|
detectProvider,
|
|
807
|
+
isReasoningModel,
|
|
627
808
|
normalize,
|
|
628
809
|
parse,
|
|
629
810
|
validate
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/parse.ts","../src/providers.ts","../src/normalize.ts","../src/validate.ts"],"sourcesContent":["export { parse, build } from \"./parse.js\";\nexport type { LlmConnectionConfig } from \"./parse.js\";\n\nexport { normalize } from \"./normalize.js\";\nexport type { NormalizeChange, NormalizeOptions, NormalizeResult } from \"./normalize.js\";\n\nexport { validate } from \"./validate.js\";\nexport type { ValidationIssue } from \"./validate.js\";\n\nexport { detectProvider, detectBedrockModelFamily, ALIASES, PROVIDER_PARAMS } from \"./providers.js\";\nexport type { Provider, BedrockModelFamily } from \"./providers.js\";\n","export interface LlmConnectionConfig {\n /** The original connection string */\n raw: string;\n /** Provider's API base URL (e.g. \"api.openai.com\") */\n host: string;\n /** Model name (e.g. \"gpt-5.2\") */\n model: string;\n /** Optional label or app name */\n label?: string;\n /** Optional API key or password */\n apiKey?: string;\n /** Additional config parameters (temp, max_tokens, etc.) */\n params: Record<string, string>;\n}\n\n/**\n * Parse an LLM connection string into its component parts.\n *\n * Format: `llm://[label[:apiKey]@]host/model[?key=value&...]`\n *\n * @example\n * ```ts\n * parse(\"llm://api.openai.com/gpt-5.2?temp=0.7&max_tokens=1500\")\n * parse(\"llm://app-name:sk-proj-123456@api.openai.com/gpt-5.2?temp=0.7\")\n * ```\n */\nexport function parse(connectionString: string): LlmConnectionConfig {\n const url = new URL(connectionString);\n\n if (url.protocol !== \"llm:\") {\n throw new Error(\n `Invalid scheme: expected \"llm://\", got \"${url.protocol}//\"`,\n );\n }\n\n const host = url.hostname;\n const model = url.pathname.replace(/^\\//, \"\");\n const label = url.username || undefined;\n const apiKey = url.password || undefined;\n\n const params: Record<string, string> = {};\n for (const [key, value] of url.searchParams) {\n params[key] = value;\n }\n\n return {\n raw: connectionString,\n host,\n model,\n label,\n apiKey,\n params,\n };\n}\n\n/**\n * Build an LLM connection string from a config object.\n */\nexport function build(config: Omit<LlmConnectionConfig, \"raw\">): string {\n const auth =\n config.label || config.apiKey\n ? `${config.label ?? \"\"}${config.apiKey ? `:${config.apiKey}` : \"\"}@`\n : \"\";\n\n const query = new URLSearchParams(config.params).toString();\n const qs = query ? `?${query}` : \"\";\n\n return `llm://${auth}${config.host}/${config.model}${qs}`;\n}\n","export type Provider =\n | \"openai\"\n | \"anthropic\"\n | \"google\"\n | \"mistral\"\n | \"cohere\"\n | \"bedrock\"\n | \"openrouter\"\n | \"vercel\";\n\nexport function detectProvider(host: string): Provider | undefined {\n // Gateways and aggregators first โ they proxy to other providers\n if (host.includes(\"openrouter\")) return \"openrouter\";\n if (host.includes(\"gateway.ai.vercel\")) return \"vercel\";\n // Bedrock before native providers since it hosts models from multiple vendors\n if (host.includes(\"amazonaws\") || host.includes(\"bedrock\")) return \"bedrock\";\n if (host.includes(\"openai\")) return \"openai\";\n if (host.includes(\"anthropic\") || host.includes(\"claude\")) return \"anthropic\";\n if (host.includes(\"googleapis\") || host.includes(\"google\")) return \"google\";\n if (host.includes(\"mistral\")) return \"mistral\";\n if (host.includes(\"cohere\")) return \"cohere\";\n return undefined;\n}\n\n/**\n * Shorthand aliases โ canonical param name.\n * Canonical names use snake_case and follow OpenAI conventions where possible.\n */\nexport const ALIASES: Record<string, string> = {\n // temperature\n temp: \"temperature\",\n\n // max_tokens\n max: \"max_tokens\",\n max_out: \"max_tokens\",\n max_output: \"max_tokens\",\n max_output_tokens: \"max_tokens\",\n max_completion_tokens: \"max_tokens\",\n maxOutputTokens: \"max_tokens\",\n maxTokens: \"max_tokens\",\n\n // top_p\n topp: \"top_p\",\n topP: \"top_p\",\n nucleus: \"top_p\",\n\n // top_k\n topk: \"top_k\",\n topK: \"top_k\",\n\n // frequency_penalty\n freq: \"frequency_penalty\",\n freq_penalty: \"frequency_penalty\",\n frequencyPenalty: \"frequency_penalty\",\n repetition_penalty: \"frequency_penalty\",\n\n // presence_penalty\n pres: \"presence_penalty\",\n pres_penalty: \"presence_penalty\",\n presencePenalty: \"presence_penalty\",\n\n // stop\n stop_sequences: \"stop\",\n stopSequences: \"stop\",\n stop_sequence: \"stop\",\n\n // seed\n random_seed: \"seed\",\n randomSeed: \"seed\",\n\n // n (completions count)\n candidateCount: \"n\",\n candidate_count: \"n\",\n num_completions: \"n\",\n\n // effort / reasoning\n reasoning_effort: \"effort\",\n reasoning: \"effort\",\n\n // cache\n cache_control: \"cache\",\n cacheControl: \"cache\",\n cachePoint: \"cache\",\n cache_point: \"cache\",\n};\n\n/**\n * Canonical param name โ provider-specific API param name.\n * Only includes params the provider actually supports.\n */\nexport const PROVIDER_PARAMS: Record<Provider, Record<string, string>> = {\n openai: {\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"top_p\",\n frequency_penalty: \"frequency_penalty\",\n presence_penalty: \"presence_penalty\",\n stop: \"stop\",\n n: \"n\",\n seed: \"seed\",\n stream: \"stream\",\n effort: \"reasoning_effort\",\n },\n anthropic: {\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"top_p\",\n top_k: \"top_k\",\n stop: \"stop_sequences\",\n stream: \"stream\",\n effort: \"effort\",\n cache: \"cache_control\",\n cache_ttl: \"cache_ttl\",\n },\n google: {\n temperature: \"temperature\",\n max_tokens: \"maxOutputTokens\",\n top_p: \"topP\",\n top_k: \"topK\",\n frequency_penalty: \"frequencyPenalty\",\n presence_penalty: \"presencePenalty\",\n stop: \"stopSequences\",\n n: \"candidateCount\",\n stream: \"stream\",\n seed: \"seed\",\n responseMimeType: \"responseMimeType\",\n responseSchema: \"responseSchema\",\n },\n mistral: {\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"top_p\",\n frequency_penalty: \"frequency_penalty\",\n presence_penalty: \"presence_penalty\",\n stop: \"stop\",\n n: \"n\",\n seed: \"random_seed\",\n stream: \"stream\",\n safe_prompt: \"safe_prompt\",\n min_tokens: \"min_tokens\",\n },\n cohere: {\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"p\",\n top_k: \"k\",\n frequency_penalty: \"frequency_penalty\",\n presence_penalty: \"presence_penalty\",\n stop: \"stop_sequences\",\n stream: \"stream\",\n seed: \"seed\",\n },\n bedrock: {\n // Bedrock Converse API uses camelCase\n temperature: \"temperature\",\n max_tokens: \"maxTokens\",\n top_p: \"topP\",\n top_k: \"topK\", // Claude models via additionalModelRequestFields\n stop: \"stopSequences\",\n stream: \"stream\",\n cache: \"cache_control\",\n cache_ttl: \"cache_ttl\",\n },\n openrouter: {\n // OpenAI-compatible API with extra routing params\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"top_p\",\n top_k: \"top_k\",\n frequency_penalty: \"frequency_penalty\",\n presence_penalty: \"presence_penalty\",\n stop: \"stop\",\n n: \"n\",\n seed: \"seed\",\n stream: \"stream\",\n effort: \"reasoning_effort\",\n },\n vercel: {\n // OpenAI-compatible gateway\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"top_p\",\n top_k: \"top_k\",\n frequency_penalty: \"frequency_penalty\",\n presence_penalty: \"presence_penalty\",\n stop: \"stop\",\n n: \"n\",\n seed: \"seed\",\n stream: \"stream\",\n effort: \"reasoning_effort\",\n },\n};\n\n/**\n * Validation specs per provider, keyed by provider-specific param name.\n */\nexport interface ParamSpec {\n type: \"number\" | \"string\" | \"boolean\";\n min?: number;\n max?: number;\n values?: string[];\n}\n\nexport const PARAM_SPECS: Record<Provider, Record<string, ParamSpec>> = {\n openai: {\n temperature: { type: \"number\", min: 0, max: 2 },\n max_tokens: { type: \"number\", min: 1 },\n top_p: { type: \"number\", min: 0, max: 1 },\n frequency_penalty: { type: \"number\", min: -2, max: 2 },\n presence_penalty: { type: \"number\", min: -2, max: 2 },\n stop: { type: \"string\" },\n n: { type: \"number\", min: 1 },\n seed: { type: \"number\" },\n stream: { type: \"boolean\" },\n reasoning_effort: {\n type: \"string\",\n values: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"],\n },\n },\n anthropic: {\n temperature: { type: \"number\", min: 0, max: 1 },\n max_tokens: { type: \"number\", min: 1 },\n top_p: { type: \"number\", min: 0, max: 1 },\n top_k: { type: \"number\", min: 0 },\n stop_sequences: { type: \"string\" },\n stream: { type: \"boolean\" },\n effort: { type: \"string\", values: [\"low\", \"medium\", \"high\", \"max\"] },\n cache_control: { type: \"string\", values: [\"ephemeral\"] },\n cache_ttl: { type: \"string\", values: [\"5m\", \"1h\"] },\n },\n google: {\n temperature: { type: \"number\", min: 0, max: 2 },\n maxOutputTokens: { type: \"number\", min: 1 },\n topP: { type: \"number\", min: 0, max: 1 },\n topK: { type: \"number\", min: 0 },\n frequencyPenalty: { type: \"number\", min: -2, max: 2 },\n presencePenalty: { type: \"number\", min: -2, max: 2 },\n stopSequences: { type: \"string\" },\n candidateCount: { type: \"number\", min: 1 },\n stream: { type: \"boolean\" },\n seed: { type: \"number\" },\n responseMimeType: { type: \"string\" },\n responseSchema: { type: \"string\" },\n },\n mistral: {\n temperature: { type: \"number\", min: 0, max: 1 },\n max_tokens: { type: \"number\", min: 1 },\n top_p: { type: \"number\", min: 0, max: 1 },\n frequency_penalty: { type: \"number\", min: -2, max: 2 },\n presence_penalty: { type: \"number\", min: -2, max: 2 },\n stop: { type: \"string\" },\n n: { type: \"number\", min: 1 },\n random_seed: { type: \"number\" },\n stream: { type: \"boolean\" },\n safe_prompt: { type: \"boolean\" },\n min_tokens: { type: \"number\", min: 0 },\n },\n cohere: {\n temperature: { type: \"number\", min: 0, max: 1 },\n max_tokens: { type: \"number\", min: 1 },\n p: { type: \"number\", min: 0, max: 1 },\n k: { type: \"number\", min: 0, max: 500 },\n frequency_penalty: { type: \"number\", min: 0, max: 1 },\n presence_penalty: { type: \"number\", min: 0, max: 1 },\n stop_sequences: { type: \"string\" },\n stream: { type: \"boolean\" },\n seed: { type: \"number\" },\n },\n bedrock: {\n // Converse API inferenceConfig params\n temperature: { type: \"number\", min: 0, max: 1 },\n maxTokens: { type: \"number\", min: 1 },\n topP: { type: \"number\", min: 0, max: 1 },\n topK: { type: \"number\", min: 0 },\n stopSequences: { type: \"string\" },\n stream: { type: \"boolean\" },\n cache_control: { type: \"string\", values: [\"ephemeral\"] },\n cache_ttl: { type: \"string\", values: [\"5m\", \"1h\"] },\n },\n openrouter: {\n // Loose validation โ proxies to many providers with varying ranges\n temperature: { type: \"number\", min: 0, max: 2 },\n max_tokens: { type: \"number\", min: 1 },\n top_p: { type: \"number\", min: 0, max: 1 },\n top_k: { type: \"number\", min: 0 },\n frequency_penalty: { type: \"number\", min: -2, max: 2 },\n presence_penalty: { type: \"number\", min: -2, max: 2 },\n stop: { type: \"string\" },\n n: { type: \"number\", min: 1 },\n seed: { type: \"number\" },\n stream: { type: \"boolean\" },\n reasoning_effort: {\n type: \"string\",\n values: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"],\n },\n },\n vercel: {\n // Loose validation โ proxies to many providers with varying ranges\n temperature: { type: \"number\", min: 0, max: 2 },\n max_tokens: { type: \"number\", min: 1 },\n top_p: { type: \"number\", min: 0, max: 1 },\n top_k: { type: \"number\", min: 0 },\n frequency_penalty: { type: \"number\", min: -2, max: 2 },\n presence_penalty: { type: \"number\", min: -2, max: 2 },\n stop: { type: \"string\" },\n n: { type: \"number\", min: 1 },\n seed: { type: \"number\" },\n stream: { type: \"boolean\" },\n reasoning_effort: {\n type: \"string\",\n values: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"],\n },\n },\n};\n\n/** OpenAI reasoning models don't support standard sampling params. */\nexport function isReasoningModel(model: string): boolean {\n // Strip gateway prefix: \"openai/o3\" โ \"o3\"\n const name = model.includes(\"/\") ? model.split(\"/\").pop()! : model;\n return /^o[134]/.test(name);\n}\n\n/** Providers that can route to OpenAI models (and need reasoning-model checks). */\nexport function canHostOpenAIModels(provider: Provider): boolean {\n return provider === \"openai\" || provider === \"openrouter\" || provider === \"vercel\";\n}\n\nexport const REASONING_MODEL_UNSUPPORTED = new Set([\n \"temperature\",\n \"top_p\",\n \"frequency_penalty\",\n \"presence_penalty\",\n \"n\",\n]);\n\n/**\n * Bedrock model IDs are prefixed with the vendor name.\n * e.g. \"anthropic.claude-sonnet-4-5-20250929-v1:0\"\n */\nexport type BedrockModelFamily =\n | \"anthropic\"\n | \"meta\"\n | \"amazon\"\n | \"mistral\"\n | \"cohere\"\n | \"ai21\";\n\nexport function detectBedrockModelFamily(\n model: string,\n): BedrockModelFamily | undefined {\n // Handle cross-region inference profiles (e.g. \"us.anthropic.claude-sonnet-4-5...\")\n // and global inference profiles (e.g. \"global.anthropic.claude-sonnet-4-5...\")\n const parts = model.split(\".\");\n \n // If first part is a region prefix (us, eu, apac) or global, skip it\n let prefix = parts[0];\n if ([\"us\", \"eu\", \"apac\", \"global\"].includes(prefix) && parts.length > 1) {\n prefix = parts[1];\n }\n\n const families: BedrockModelFamily[] = [\n \"anthropic\",\n \"meta\",\n \"amazon\",\n \"mistral\",\n \"cohere\",\n \"ai21\",\n ];\n return families.find((f) => prefix === f);\n}\n\n/** Whether a Bedrock model supports prompt caching (Claude and Nova only). */\nexport function bedrockSupportsCaching(model: string): boolean {\n const family = detectBedrockModelFamily(model);\n if (family === \"anthropic\") return true;\n if (family === \"amazon\" && model.includes(\"nova\")) return true;\n return false;\n}\n\n/** Cache value normalization per provider. */\nexport const CACHE_VALUES: Record<Provider, string | undefined> = {\n openai: undefined, // OpenAI auto-caches; no explicit param\n anthropic: \"ephemeral\",\n google: undefined, // Google uses explicit caching API, not a param\n mistral: undefined,\n cohere: undefined,\n bedrock: \"ephemeral\", // Supported for Claude models on Bedrock\n openrouter: undefined, // Depends on underlying provider\n vercel: undefined, // Depends on underlying provider\n};\n\n/** Valid cache TTL values per provider. */\nexport const CACHE_TTLS: Record<Provider, string[] | undefined> = {\n openai: undefined,\n anthropic: [\"5m\", \"1h\"],\n google: undefined,\n mistral: undefined,\n cohere: undefined,\n bedrock: [\"5m\", \"1h\"], // Claude on Bedrock uses same TTLs as direct Anthropic\n openrouter: undefined,\n vercel: undefined,\n};\n\n/** Match a duration expression like \"5m\", \"1h\", \"30m\". */\nexport const DURATION_RE = /^\\d+[mh]$/;\n","import type { LlmConnectionConfig } from \"./parse.js\";\nimport {\n ALIASES,\n CACHE_TTLS,\n CACHE_VALUES,\n DURATION_RE,\n PROVIDER_PARAMS,\n bedrockSupportsCaching,\n canHostOpenAIModels,\n detectProvider,\n isReasoningModel,\n type Provider,\n} from \"./providers.js\";\n\nexport interface NormalizeChange {\n from: string;\n to: string;\n value: string;\n reason: string;\n}\n\nexport interface NormalizeResult {\n config: LlmConnectionConfig;\n provider: Provider | undefined;\n changes: NormalizeChange[];\n}\n\nexport interface NormalizeOptions {\n /** Include detailed change log in the result. */\n verbose?: boolean;\n}\n\n/**\n * Normalize an LLM connection config's params for its target provider.\n *\n * 1. Expands shorthand aliases (e.g. `temp` โ `temperature`)\n * 2. Maps canonical param names to provider-specific names\n * (e.g. `max_tokens` โ `maxOutputTokens` for Google)\n * 3. Normalizes special values (e.g. `cache=true` โ `cache_control=ephemeral` for Anthropic)\n * 4. For OpenAI reasoning models, remaps `max_tokens` โ `max_completion_tokens`\n * and warns about unsupported sampling params\n */\nexport function normalize(\n config: LlmConnectionConfig,\n options: NormalizeOptions = {},\n): NormalizeResult {\n const provider = detectProvider(config.host);\n const changes: NormalizeChange[] = [];\n const params: Record<string, string> = {};\n\n for (const [rawKey, value] of Object.entries(config.params)) {\n let key = rawKey;\n\n // Step 1: Expand aliases to canonical name\n if (ALIASES[key]) {\n const canonical = ALIASES[key];\n if (options.verbose) {\n changes.push({\n from: key,\n to: canonical,\n value,\n reason: `alias: \"${key}\" โ \"${canonical}\"`,\n });\n }\n key = canonical;\n }\n\n // Step 2: Handle special \"cache\" param\n if (key === \"cache\" && provider) {\n let cacheValue = CACHE_VALUES[provider];\n\n // Bedrock supports cache for Anthropic Claude and Amazon Nova models\n if (provider === \"bedrock\" && !bedrockSupportsCaching(config.model)) {\n cacheValue = undefined;\n }\n\n // Provider/model doesn't support cache โ drop it\n if (!cacheValue) {\n if (options.verbose) {\n changes.push({\n from: \"cache\",\n to: \"(dropped)\",\n value,\n reason: `${provider} does not use a cache param for this model (caching is automatic or unsupported)`,\n });\n }\n continue;\n }\n\n const isBool = value === \"true\" || value === \"1\" || value === \"yes\";\n const isDuration = DURATION_RE.test(value);\n\n if (isBool || isDuration) {\n const providerKey =\n PROVIDER_PARAMS[provider]?.[\"cache\"] ?? \"cache\";\n if (options.verbose) {\n changes.push({\n from: \"cache\",\n to: providerKey,\n value: cacheValue,\n reason: `cache=${value} โ ${providerKey}=${cacheValue} for ${provider}`,\n });\n }\n params[providerKey] = cacheValue;\n\n // Emit cache_ttl when a duration is specified\n if (isDuration && CACHE_TTLS[provider]) {\n if (options.verbose) {\n changes.push({\n from: \"cache\",\n to: \"cache_ttl\",\n value,\n reason: `cache=${value} โ cache_ttl=${value} for ${provider}`,\n });\n }\n params[\"cache_ttl\"] = value;\n }\n continue;\n }\n }\n\n // Step 3: Map canonical โ provider-specific param name\n if (provider && PROVIDER_PARAMS[provider]) {\n const providerKey = PROVIDER_PARAMS[provider][key];\n if (providerKey && providerKey !== key) {\n if (options.verbose) {\n changes.push({\n from: key,\n to: providerKey,\n value,\n reason: `${provider} uses \"${providerKey}\" instead of \"${key}\"`,\n });\n }\n key = providerKey;\n }\n }\n\n // Step 4: OpenAI reasoning model adjustments (direct or via gateway)\n if (\n provider &&\n canHostOpenAIModels(provider) &&\n isReasoningModel(config.model) &&\n key === \"max_tokens\"\n ) {\n if (options.verbose) {\n changes.push({\n from: \"max_tokens\",\n to: \"max_completion_tokens\",\n value,\n reason:\n \"OpenAI reasoning models use max_completion_tokens instead of max_tokens\",\n });\n }\n key = \"max_completion_tokens\";\n }\n\n params[key] = value;\n }\n\n return {\n config: { ...config, params },\n provider,\n changes,\n };\n}\n","import { parse } from \"./parse.js\";\nimport { normalize } from \"./normalize.js\";\nimport {\n PARAM_SPECS,\n PROVIDER_PARAMS,\n REASONING_MODEL_UNSUPPORTED,\n bedrockSupportsCaching,\n canHostOpenAIModels,\n detectBedrockModelFamily,\n detectProvider,\n isReasoningModel,\n} from \"./providers.js\";\n\nexport interface ValidationIssue {\n param: string;\n value: string;\n message: string;\n severity: \"error\" | \"warning\";\n}\n\n/**\n * Validate an LLM connection string.\n *\n * Parses and normalizes the string, then checks params against provider specs.\n * Returns a list of issues found. An empty array means all params look valid.\n */\nexport function validate(connectionString: string): ValidationIssue[] {\n const parsed = parse(connectionString);\n const { config } = normalize(parsed);\n const provider = detectProvider(config.host);\n const issues: ValidationIssue[] = [];\n\n if (!provider) {\n issues.push({\n param: \"host\",\n value: config.host,\n message: `Unknown provider for host \"${config.host}\". Validation skipped.`,\n severity: \"warning\",\n });\n return issues;\n }\n\n const specs = PARAM_SPECS[provider];\n const knownParams = new Set(Object.values(PROVIDER_PARAMS[provider]));\n\n for (const [key, value] of Object.entries(config.params)) {\n // Check for OpenAI reasoning model restrictions (direct or via gateway)\n if (\n canHostOpenAIModels(provider) &&\n isReasoningModel(config.model) &&\n REASONING_MODEL_UNSUPPORTED.has(key)\n ) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" is not supported by OpenAI reasoning model \"${config.model}\". Use \"reasoning_effort\" instead of temperature for controlling output.`,\n severity: \"error\",\n });\n continue;\n }\n\n // Bedrock model-family-specific checks\n if (provider === \"bedrock\") {\n const family = detectBedrockModelFamily(config.model);\n\n // topK is only supported by Claude, Cohere, and Mistral on Bedrock\n if (\n key === \"topK\" &&\n family &&\n family !== \"anthropic\" &&\n family !== \"cohere\" &&\n family !== \"mistral\"\n ) {\n issues.push({\n param: key,\n value,\n message: `\"topK\" is not supported by ${family} models on Bedrock.`,\n severity: \"error\",\n });\n continue;\n }\n\n // cache_control is only supported by Claude and Nova on Bedrock\n if (key === \"cache_control\" && !bedrockSupportsCaching(config.model)) {\n issues.push({\n param: key,\n value,\n message: `Prompt caching is only supported for Anthropic Claude and Amazon Nova models on Bedrock, not ${family ?? \"unknown\"} models.`,\n severity: \"error\",\n });\n continue;\n }\n }\n\n // Check if param is known for this provider\n if (!knownParams.has(key) && !specs[key]) {\n issues.push({\n param: key,\n value,\n message: `Unknown param \"${key}\" for ${provider}.`,\n severity: \"warning\",\n });\n continue;\n }\n\n // Validate against spec\n const spec = specs[key];\n if (!spec) continue;\n\n // Anthropic (and Bedrock Claude) mutual exclusion for temperature/top_p\n if (\n (provider === \"anthropic\" ||\n (provider === \"bedrock\" &&\n detectBedrockModelFamily(config.model) === \"anthropic\")) &&\n (key === \"temperature\" || key === \"top_p\" || key === \"topP\")\n ) {\n const otherKey =\n key === \"temperature\"\n ? provider === \"bedrock\"\n ? \"topP\"\n : \"top_p\"\n : \"temperature\";\n // Only report error once (on the temperature param) to avoid duplicate errors\n if (key === \"temperature\" && config.params[otherKey] !== undefined) {\n issues.push({\n param: key,\n value,\n message: `Cannot specify both \"temperature\" and \"${otherKey}\" for Anthropic models.`,\n severity: \"error\",\n });\n }\n }\n\n if (spec.type === \"number\") {\n const num = Number(value);\n if (isNaN(num)) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" should be a number, got \"${value}\".`,\n severity: \"error\",\n });\n continue;\n }\n if (spec.min !== undefined && num < spec.min) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" must be >= ${spec.min}, got ${num}.`,\n severity: \"error\",\n });\n }\n if (spec.max !== undefined && num > spec.max) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" must be <= ${spec.max}, got ${num}.`,\n severity: \"error\",\n });\n }\n }\n\n if (spec.type === \"boolean\") {\n if (![\"true\", \"false\", \"0\", \"1\"].includes(value)) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" should be a boolean (true/false), got \"${value}\".`,\n severity: \"error\",\n });\n }\n }\n\n if (spec.type === \"string\" && spec.values) {\n if (!spec.values.includes(value)) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" must be one of [${spec.values.join(\", \")}], got \"${value}\".`,\n severity: \"error\",\n });\n }\n }\n }\n\n return issues;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/parse.ts","../src/providers.ts","../src/normalize.ts","../src/validate.ts"],"sourcesContent":["export { parse, build } from \"./parse.js\";\nexport type { LlmConnectionConfig } from \"./parse.js\";\n\nexport { normalize } from \"./normalize.js\";\nexport type { NormalizeChange, NormalizeOptions, NormalizeResult } from \"./normalize.js\";\n\nexport { validate } from \"./validate.js\";\nexport type { ValidateOptions, ValidationIssue } from \"./validate.js\";\n\nexport {\n detectProvider,\n detectBedrockModelFamily,\n isReasoningModel,\n canHostOpenAIModels,\n ALIASES,\n PROVIDER_PARAMS,\n PARAM_SPECS,\n REASONING_MODEL_UNSUPPORTED,\n PROVIDER_META,\n MODELS,\n CANONICAL_PARAM_SPECS,\n} from \"./providers.js\";\nexport type {\n Provider,\n BedrockModelFamily,\n ParamSpec,\n ProviderMeta,\n CanonicalParamSpec,\n} from \"./providers.js\";\n","export interface LlmConnectionConfig {\n /** The original connection string */\n raw: string;\n /** Provider's API base URL (e.g. \"api.openai.com\") */\n host: string;\n /** Model name (e.g. \"gpt-5.2\") */\n model: string;\n /** Optional label or app name */\n label?: string;\n /** Optional API key or password */\n apiKey?: string;\n /** Additional config parameters (temp, max_tokens, etc.) */\n params: Record<string, string>;\n}\n\n/**\n * Parse an LLM connection string into its component parts.\n *\n * Format: `llm://[label[:apiKey]@]host/model[?key=value&...]`\n *\n * @example\n * ```ts\n * parse(\"llm://api.openai.com/gpt-5.2?temp=0.7&max_tokens=1500\")\n * parse(\"llm://app-name:sk-proj-123456@api.openai.com/gpt-5.2?temp=0.7\")\n * ```\n */\nexport function parse(connectionString: string): LlmConnectionConfig {\n const url = new URL(connectionString);\n\n if (url.protocol !== \"llm:\") {\n throw new Error(\n `Invalid scheme: expected \"llm://\", got \"${url.protocol}//\"`,\n );\n }\n\n const host = url.hostname;\n const model = url.pathname.replace(/^\\//, \"\");\n const label = url.username || undefined;\n const apiKey = url.password || undefined;\n\n const params: Record<string, string> = {};\n for (const [key, value] of url.searchParams) {\n params[key] = value;\n }\n\n return {\n raw: connectionString,\n host,\n model,\n label,\n apiKey,\n params,\n };\n}\n\n/**\n * Build an LLM connection string from a config object.\n */\nexport function build(config: Omit<LlmConnectionConfig, \"raw\">): string {\n const auth =\n config.label || config.apiKey\n ? `${config.label ?? \"\"}${config.apiKey ? `:${config.apiKey}` : \"\"}@`\n : \"\";\n\n const query = new URLSearchParams(config.params).toString();\n const qs = query ? `?${query}` : \"\";\n\n return `llm://${auth}${config.host}/${config.model}${qs}`;\n}\n","export type Provider =\n | \"openai\"\n | \"anthropic\"\n | \"google\"\n | \"mistral\"\n | \"cohere\"\n | \"bedrock\"\n | \"openrouter\"\n | \"vercel\";\n\nexport function detectProvider(host: string): Provider | undefined {\n // Gateways and aggregators first โ they proxy to other providers\n if (host.includes(\"openrouter\")) return \"openrouter\";\n if (host.includes(\"gateway.ai.vercel\")) return \"vercel\";\n // Bedrock before native providers since it hosts models from multiple vendors\n if (host.includes(\"amazonaws\") || host.includes(\"bedrock\")) return \"bedrock\";\n if (host.includes(\"openai\")) return \"openai\";\n if (host.includes(\"anthropic\") || host.includes(\"claude\")) return \"anthropic\";\n if (host.includes(\"googleapis\") || host.includes(\"google\")) return \"google\";\n if (host.includes(\"mistral\")) return \"mistral\";\n if (host.includes(\"cohere\")) return \"cohere\";\n return undefined;\n}\n\n/**\n * Shorthand aliases โ canonical param name.\n * Canonical names use snake_case and follow OpenAI conventions where possible.\n */\nexport const ALIASES: Record<string, string> = {\n // temperature\n temp: \"temperature\",\n\n // max_tokens\n max: \"max_tokens\",\n max_out: \"max_tokens\",\n max_output: \"max_tokens\",\n max_output_tokens: \"max_tokens\",\n max_completion_tokens: \"max_tokens\",\n maxOutputTokens: \"max_tokens\",\n maxTokens: \"max_tokens\",\n\n // top_p\n topp: \"top_p\",\n topP: \"top_p\",\n nucleus: \"top_p\",\n\n // top_k\n topk: \"top_k\",\n topK: \"top_k\",\n\n // frequency_penalty\n freq: \"frequency_penalty\",\n freq_penalty: \"frequency_penalty\",\n frequencyPenalty: \"frequency_penalty\",\n repetition_penalty: \"frequency_penalty\",\n\n // presence_penalty\n pres: \"presence_penalty\",\n pres_penalty: \"presence_penalty\",\n presencePenalty: \"presence_penalty\",\n\n // stop\n stop_sequences: \"stop\",\n stopSequences: \"stop\",\n stop_sequence: \"stop\",\n\n // seed\n random_seed: \"seed\",\n randomSeed: \"seed\",\n\n // n (completions count)\n candidateCount: \"n\",\n candidate_count: \"n\",\n num_completions: \"n\",\n\n // effort / reasoning\n reasoning_effort: \"effort\",\n reasoning: \"effort\",\n\n // cache\n cache_control: \"cache\",\n cacheControl: \"cache\",\n cachePoint: \"cache\",\n cache_point: \"cache\",\n};\n\n/**\n * Canonical param name โ provider-specific API param name.\n * Only includes params the provider actually supports.\n */\nexport const PROVIDER_PARAMS: Record<Provider, Record<string, string>> = {\n openai: {\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"top_p\",\n frequency_penalty: \"frequency_penalty\",\n presence_penalty: \"presence_penalty\",\n stop: \"stop\",\n n: \"n\",\n seed: \"seed\",\n stream: \"stream\",\n effort: \"reasoning_effort\",\n },\n anthropic: {\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"top_p\",\n top_k: \"top_k\",\n stop: \"stop_sequences\",\n stream: \"stream\",\n effort: \"effort\",\n cache: \"cache_control\",\n cache_ttl: \"cache_ttl\",\n },\n google: {\n temperature: \"temperature\",\n max_tokens: \"maxOutputTokens\",\n top_p: \"topP\",\n top_k: \"topK\",\n frequency_penalty: \"frequencyPenalty\",\n presence_penalty: \"presencePenalty\",\n stop: \"stopSequences\",\n n: \"candidateCount\",\n stream: \"stream\",\n seed: \"seed\",\n responseMimeType: \"responseMimeType\",\n responseSchema: \"responseSchema\",\n },\n mistral: {\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"top_p\",\n frequency_penalty: \"frequency_penalty\",\n presence_penalty: \"presence_penalty\",\n stop: \"stop\",\n n: \"n\",\n seed: \"random_seed\",\n stream: \"stream\",\n safe_prompt: \"safe_prompt\",\n min_tokens: \"min_tokens\",\n },\n cohere: {\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"p\",\n top_k: \"k\",\n frequency_penalty: \"frequency_penalty\",\n presence_penalty: \"presence_penalty\",\n stop: \"stop_sequences\",\n stream: \"stream\",\n seed: \"seed\",\n },\n bedrock: {\n // Bedrock Converse API uses camelCase\n temperature: \"temperature\",\n max_tokens: \"maxTokens\",\n top_p: \"topP\",\n top_k: \"topK\", // Claude models via additionalModelRequestFields\n stop: \"stopSequences\",\n stream: \"stream\",\n cache: \"cache_control\",\n cache_ttl: \"cache_ttl\",\n },\n openrouter: {\n // OpenAI-compatible API with extra routing params\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"top_p\",\n top_k: \"top_k\",\n frequency_penalty: \"frequency_penalty\",\n presence_penalty: \"presence_penalty\",\n stop: \"stop\",\n n: \"n\",\n seed: \"seed\",\n stream: \"stream\",\n effort: \"reasoning_effort\",\n },\n vercel: {\n // OpenAI-compatible gateway\n temperature: \"temperature\",\n max_tokens: \"max_tokens\",\n top_p: \"top_p\",\n top_k: \"top_k\",\n frequency_penalty: \"frequency_penalty\",\n presence_penalty: \"presence_penalty\",\n stop: \"stop\",\n n: \"n\",\n seed: \"seed\",\n stream: \"stream\",\n effort: \"reasoning_effort\",\n },\n};\n\n/**\n * Validation specs per provider, keyed by provider-specific param name.\n */\nexport interface ParamSpec {\n type: \"number\" | \"string\" | \"boolean\";\n min?: number;\n max?: number;\n values?: string[];\n}\n\nexport const PARAM_SPECS: Record<Provider, Record<string, ParamSpec>> = {\n openai: {\n temperature: { type: \"number\", min: 0, max: 2 },\n max_tokens: { type: \"number\", min: 1 },\n top_p: { type: \"number\", min: 0, max: 1 },\n frequency_penalty: { type: \"number\", min: -2, max: 2 },\n presence_penalty: { type: \"number\", min: -2, max: 2 },\n stop: { type: \"string\" },\n n: { type: \"number\", min: 1 },\n seed: { type: \"number\" },\n stream: { type: \"boolean\" },\n reasoning_effort: {\n type: \"string\",\n values: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"],\n },\n },\n anthropic: {\n temperature: { type: \"number\", min: 0, max: 1 },\n max_tokens: { type: \"number\", min: 1 },\n top_p: { type: \"number\", min: 0, max: 1 },\n top_k: { type: \"number\", min: 0 },\n stop_sequences: { type: \"string\" },\n stream: { type: \"boolean\" },\n effort: { type: \"string\", values: [\"low\", \"medium\", \"high\", \"max\"] },\n cache_control: { type: \"string\", values: [\"ephemeral\"] },\n cache_ttl: { type: \"string\", values: [\"5m\", \"1h\"] },\n },\n google: {\n temperature: { type: \"number\", min: 0, max: 2 },\n maxOutputTokens: { type: \"number\", min: 1 },\n topP: { type: \"number\", min: 0, max: 1 },\n topK: { type: \"number\", min: 0 },\n frequencyPenalty: { type: \"number\", min: -2, max: 2 },\n presencePenalty: { type: \"number\", min: -2, max: 2 },\n stopSequences: { type: \"string\" },\n candidateCount: { type: \"number\", min: 1 },\n stream: { type: \"boolean\" },\n seed: { type: \"number\" },\n responseMimeType: { type: \"string\" },\n responseSchema: { type: \"string\" },\n },\n mistral: {\n temperature: { type: \"number\", min: 0, max: 1 },\n max_tokens: { type: \"number\", min: 1 },\n top_p: { type: \"number\", min: 0, max: 1 },\n frequency_penalty: { type: \"number\", min: -2, max: 2 },\n presence_penalty: { type: \"number\", min: -2, max: 2 },\n stop: { type: \"string\" },\n n: { type: \"number\", min: 1 },\n random_seed: { type: \"number\" },\n stream: { type: \"boolean\" },\n safe_prompt: { type: \"boolean\" },\n min_tokens: { type: \"number\", min: 0 },\n },\n cohere: {\n temperature: { type: \"number\", min: 0, max: 1 },\n max_tokens: { type: \"number\", min: 1 },\n p: { type: \"number\", min: 0, max: 1 },\n k: { type: \"number\", min: 0, max: 500 },\n frequency_penalty: { type: \"number\", min: 0, max: 1 },\n presence_penalty: { type: \"number\", min: 0, max: 1 },\n stop_sequences: { type: \"string\" },\n stream: { type: \"boolean\" },\n seed: { type: \"number\" },\n },\n bedrock: {\n // Converse API inferenceConfig params\n temperature: { type: \"number\", min: 0, max: 1 },\n maxTokens: { type: \"number\", min: 1 },\n topP: { type: \"number\", min: 0, max: 1 },\n topK: { type: \"number\", min: 0 },\n stopSequences: { type: \"string\" },\n stream: { type: \"boolean\" },\n cache_control: { type: \"string\", values: [\"ephemeral\"] },\n cache_ttl: { type: \"string\", values: [\"5m\", \"1h\"] },\n },\n openrouter: {\n // Loose validation โ proxies to many providers with varying ranges\n temperature: { type: \"number\", min: 0, max: 2 },\n max_tokens: { type: \"number\", min: 1 },\n top_p: { type: \"number\", min: 0, max: 1 },\n top_k: { type: \"number\", min: 0 },\n frequency_penalty: { type: \"number\", min: -2, max: 2 },\n presence_penalty: { type: \"number\", min: -2, max: 2 },\n stop: { type: \"string\" },\n n: { type: \"number\", min: 1 },\n seed: { type: \"number\" },\n stream: { type: \"boolean\" },\n reasoning_effort: {\n type: \"string\",\n values: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"],\n },\n },\n vercel: {\n // Loose validation โ proxies to many providers with varying ranges\n temperature: { type: \"number\", min: 0, max: 2 },\n max_tokens: { type: \"number\", min: 1 },\n top_p: { type: \"number\", min: 0, max: 1 },\n top_k: { type: \"number\", min: 0 },\n frequency_penalty: { type: \"number\", min: -2, max: 2 },\n presence_penalty: { type: \"number\", min: -2, max: 2 },\n stop: { type: \"string\" },\n n: { type: \"number\", min: 1 },\n seed: { type: \"number\" },\n stream: { type: \"boolean\" },\n reasoning_effort: {\n type: \"string\",\n values: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"],\n },\n },\n};\n\n/** OpenAI reasoning models don't support standard sampling params. */\nexport function isReasoningModel(model: string): boolean {\n // Strip gateway prefix: \"openai/o3\" โ \"o3\"\n const name = model.includes(\"/\") ? model.split(\"/\").pop()! : model;\n return /^o[134]/.test(name);\n}\n\n/** Providers that can route to OpenAI models (and need reasoning-model checks). */\nexport function canHostOpenAIModels(provider: Provider): boolean {\n return provider === \"openai\" || provider === \"openrouter\" || provider === \"vercel\";\n}\n\nexport const REASONING_MODEL_UNSUPPORTED = new Set([\n \"temperature\",\n \"top_p\",\n \"frequency_penalty\",\n \"presence_penalty\",\n \"n\",\n]);\n\n/**\n * Bedrock model IDs are prefixed with the vendor name.\n * e.g. \"anthropic.claude-sonnet-4-5-20250929-v1:0\"\n */\nexport type BedrockModelFamily =\n | \"anthropic\"\n | \"meta\"\n | \"amazon\"\n | \"mistral\"\n | \"cohere\"\n | \"ai21\";\n\nexport function detectBedrockModelFamily(\n model: string,\n): BedrockModelFamily | undefined {\n // Handle cross-region inference profiles (e.g. \"us.anthropic.claude-sonnet-4-5...\")\n // and global inference profiles (e.g. \"global.anthropic.claude-sonnet-4-5...\")\n const parts = model.split(\".\");\n\n // If first part is a region prefix (us, eu, apac) or global, skip it\n let prefix = parts[0];\n if ([\"us\", \"eu\", \"apac\", \"global\"].includes(prefix) && parts.length > 1) {\n prefix = parts[1];\n }\n\n const families: BedrockModelFamily[] = [\n \"anthropic\",\n \"meta\",\n \"amazon\",\n \"mistral\",\n \"cohere\",\n \"ai21\",\n ];\n return families.find((f) => prefix === f);\n}\n\n/** Whether a Bedrock model supports prompt caching (Claude and Nova only). */\nexport function bedrockSupportsCaching(model: string): boolean {\n const family = detectBedrockModelFamily(model);\n if (family === \"anthropic\") return true;\n if (family === \"amazon\" && model.includes(\"nova\")) return true;\n return false;\n}\n\n/** Cache value normalization per provider. */\nexport const CACHE_VALUES: Record<Provider, string | undefined> = {\n openai: undefined, // OpenAI auto-caches; no explicit param\n anthropic: \"ephemeral\",\n google: undefined, // Google uses explicit caching API, not a param\n mistral: undefined,\n cohere: undefined,\n bedrock: \"ephemeral\", // Supported for Claude models on Bedrock\n openrouter: undefined, // Depends on underlying provider\n vercel: undefined, // Depends on underlying provider\n};\n\n/** Valid cache TTL values per provider. */\nexport const CACHE_TTLS: Record<Provider, string[] | undefined> = {\n openai: undefined,\n anthropic: [\"5m\", \"1h\"],\n google: undefined,\n mistral: undefined,\n cohere: undefined,\n bedrock: [\"5m\", \"1h\"], // Claude on Bedrock uses same TTLs as direct Anthropic\n openrouter: undefined,\n vercel: undefined,\n};\n\n/** Match a duration expression like \"5m\", \"1h\", \"30m\". */\nexport const DURATION_RE = /^\\d+[mh]$/;\n\n/* ------------------------------------------------------------------ */\n/* UI-consumable metadata for 3rd-party integrations */\n/* ------------------------------------------------------------------ */\n\nexport interface ProviderMeta {\n /** Provider identifier โ matches the Provider union type. */\n id: Provider;\n /** Human-readable display name. */\n name: string;\n /** Default / canonical API hostname. */\n host: string;\n /** Brand color as a CSS hex value. */\n color: string;\n}\n\nexport const PROVIDER_META: ProviderMeta[] = [\n { id: \"openai\", name: \"OpenAI\", host: \"api.openai.com\", color: \"#10a37f\" },\n { id: \"anthropic\", name: \"Anthropic\", host: \"api.anthropic.com\", color: \"#e8956a\" },\n { id: \"google\", name: \"Google\", host: \"generativelanguage.googleapis.com\", color: \"#4285f4\" },\n { id: \"mistral\", name: \"Mistral\", host: \"api.mistral.ai\", color: \"#ff7000\" },\n { id: \"cohere\", name: \"Cohere\", host: \"api.cohere.com\", color: \"#39594d\" },\n { id: \"bedrock\", name: \"Bedrock\", host: \"bedrock-runtime.us-east-1.amazonaws.com\", color: \"#ff9900\" },\n { id: \"openrouter\", name: \"OpenRouter\", host: \"openrouter.ai\", color: \"#818cf8\" },\n { id: \"vercel\", name: \"Vercel\", host: \"gateway.ai.vercel.app\", color: \"#ededed\" },\n];\n\n/**\n * Suggested / common model IDs per provider, ordered by recency.\n * Not exhaustive โ providers add models frequently.\n */\nexport const MODELS: Record<Provider, string[]> = {\n openai: [\n \"gpt-5.2\", \"gpt-5.2-pro\",\n \"gpt-4.1\", \"gpt-4.1-mini\", \"gpt-4.1-nano\",\n \"o3\", \"o3-mini\", \"o4-mini\", \"o1-pro\",\n ],\n anthropic: [\n \"claude-opus-4-6\", \"claude-sonnet-4-6\",\n \"claude-sonnet-4-5\", \"claude-haiku-4-5\",\n ],\n google: [\n \"gemini-3-pro-preview\", \"gemini-3-flash-preview\",\n \"gemini-2.5-pro\", \"gemini-2.5-flash\",\n ],\n mistral: [\n \"mistral-large-latest\", \"mistral-medium-latest\",\n \"mistral-small-latest\", \"codestral-latest\",\n \"magistral-medium-latest\",\n ],\n cohere: [\n \"command-a-03-2025\",\n \"command-r-plus-08-2024\", \"command-r-08-2024\",\n \"command-r7b-12-2024\",\n ],\n bedrock: [\n \"anthropic.claude-opus-4-6-v1\", \"anthropic.claude-sonnet-4-6-v1\",\n \"anthropic.claude-haiku-4-5-v1\",\n \"amazon.nova-pro-v1\", \"amazon.nova-lite-v1\",\n \"meta.llama3-70b-instruct-v1:0\",\n ],\n openrouter: [\n \"openai/gpt-5.2\", \"anthropic/claude-opus-4-6\",\n \"google/gemini-2.5-pro\", \"mistral/mistral-large-latest\",\n ],\n vercel: [\n \"openai/gpt-5.2\", \"anthropic/claude-opus-4-6\",\n \"google/gemini-2.5-pro\", \"google/gemini-3-pro-preview\",\n \"google/gemini-3-flash-preview\", \"mistral/mistral-large-latest\",\n \"qwen/qwen2.5-pro\",\n ],\n};\n\n/**\n * Canonical parameter spec โ keyed by canonical (snake_case) param names\n * with defaults and descriptions for UI consumption.\n */\nexport interface CanonicalParamSpec {\n type: \"number\" | \"string\" | \"boolean\" | \"enum\";\n min?: number;\n max?: number;\n values?: string[];\n default?: string | number | boolean;\n description?: string;\n}\n\nexport const CANONICAL_PARAM_SPECS: Record<Provider, Record<string, CanonicalParamSpec>> = {\n openai: {\n temperature: { type: \"number\", min: 0, max: 2, default: 0.7, description: \"Controls randomness\" },\n max_tokens: { type: \"number\", min: 1, default: 4096, description: \"Maximum output tokens\" },\n top_p: { type: \"number\", min: 0, max: 1, default: 1, description: \"Nucleus sampling\" },\n frequency_penalty: { type: \"number\", min: -2, max: 2, default: 0, description: \"Penalize frequent tokens\" },\n presence_penalty: { type: \"number\", min: -2, max: 2, default: 0, description: \"Penalize repeated topics\" },\n stop: { type: \"string\", default: \"\", description: \"Stop sequences\" },\n n: { type: \"number\", min: 1, default: 1, description: \"Completions count\" },\n seed: { type: \"number\", default: \"\", description: \"Random seed\" },\n stream: { type: \"boolean\", default: false, description: \"Stream response\" },\n effort: { type: \"enum\", values: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"], default: \"medium\", description: \"Reasoning effort\" },\n },\n anthropic: {\n temperature: { type: \"number\", min: 0, max: 1, default: 0.7, description: \"Controls randomness\" },\n max_tokens: { type: \"number\", min: 1, default: 4096, description: \"Maximum output tokens\" },\n top_p: { type: \"number\", min: 0, max: 1, default: 1, description: \"Nucleus sampling\" },\n top_k: { type: \"number\", min: 0, default: 40, description: \"Top-K sampling\" },\n stop: { type: \"string\", default: \"\", description: \"Stop sequences\" },\n stream: { type: \"boolean\", default: false, description: \"Stream response\" },\n effort: { type: \"enum\", values: [\"low\", \"medium\", \"high\", \"max\"], default: \"medium\", description: \"Thinking effort\" },\n cache: { type: \"enum\", values: [\"ephemeral\"], default: \"ephemeral\", description: \"Cache control\" },\n cache_ttl: { type: \"enum\", values: [\"5m\", \"1h\"], default: \"5m\", description: \"Cache TTL\" },\n },\n google: {\n temperature: { type: \"number\", min: 0, max: 2, default: 0.7, description: \"Controls randomness\" },\n max_tokens: { type: \"number\", min: 1, default: 4096, description: \"Maximum output tokens\" },\n top_p: { type: \"number\", min: 0, max: 1, default: 1, description: \"Nucleus sampling\" },\n top_k: { type: \"number\", min: 0, default: 40, description: \"Top-K sampling\" },\n frequency_penalty: { type: \"number\", min: -2, max: 2, default: 0, description: \"Penalize frequent tokens\" },\n presence_penalty: { type: \"number\", min: -2, max: 2, default: 0, description: \"Penalize repeated topics\" },\n stop: { type: \"string\", default: \"\", description: \"Stop sequences\" },\n n: { type: \"number\", min: 1, default: 1, description: \"Candidate count\" },\n stream: { type: \"boolean\", default: false, description: \"Stream response\" },\n seed: { type: \"number\", default: \"\", description: \"Random seed\" },\n },\n mistral: {\n temperature: { type: \"number\", min: 0, max: 1, default: 0.7, description: \"Controls randomness\" },\n max_tokens: { type: \"number\", min: 1, default: 4096, description: \"Maximum output tokens\" },\n top_p: { type: \"number\", min: 0, max: 1, default: 1, description: \"Nucleus sampling\" },\n frequency_penalty: { type: \"number\", min: -2, max: 2, default: 0, description: \"Penalize frequent tokens\" },\n presence_penalty: { type: \"number\", min: -2, max: 2, default: 0, description: \"Penalize repeated topics\" },\n stop: { type: \"string\", default: \"\", description: \"Stop sequences\" },\n n: { type: \"number\", min: 1, default: 1, description: \"Completions count\" },\n seed: { type: \"number\", default: \"\", description: \"Random seed\" },\n stream: { type: \"boolean\", default: false, description: \"Stream response\" },\n safe_prompt: { type: \"boolean\", default: false, description: \"Enable safe prompt\" },\n min_tokens: { type: \"number\", min: 0, default: 0, description: \"Minimum tokens\" },\n },\n cohere: {\n temperature: { type: \"number\", min: 0, max: 1, default: 0.7, description: \"Controls randomness\" },\n max_tokens: { type: \"number\", min: 1, default: 4096, description: \"Maximum output tokens\" },\n top_p: { type: \"number\", min: 0, max: 1, default: 1, description: \"Nucleus sampling (p)\" },\n top_k: { type: \"number\", min: 0, max: 500, default: 40, description: \"Top-K sampling (k)\" },\n frequency_penalty: { type: \"number\", min: 0, max: 1, default: 0, description: \"Penalize frequent tokens\" },\n presence_penalty: { type: \"number\", min: 0, max: 1, default: 0, description: \"Penalize repeated topics\" },\n stop: { type: \"string\", default: \"\", description: \"Stop sequences\" },\n stream: { type: \"boolean\", default: false, description: \"Stream response\" },\n seed: { type: \"number\", default: \"\", description: \"Random seed\" },\n },\n bedrock: {\n temperature: { type: \"number\", min: 0, max: 1, default: 0.7, description: \"Controls randomness\" },\n max_tokens: { type: \"number\", min: 1, default: 4096, description: \"Maximum output tokens\" },\n top_p: { type: \"number\", min: 0, max: 1, default: 1, description: \"Nucleus sampling\" },\n top_k: { type: \"number\", min: 0, default: 40, description: \"Top-K sampling\" },\n stop: { type: \"string\", default: \"\", description: \"Stop sequences\" },\n stream: { type: \"boolean\", default: false, description: \"Stream response\" },\n cache: { type: \"enum\", values: [\"ephemeral\"], default: \"ephemeral\", description: \"Cache control\" },\n cache_ttl: { type: \"enum\", values: [\"5m\", \"1h\"], default: \"5m\", description: \"Cache TTL\" },\n },\n openrouter: {\n temperature: { type: \"number\", min: 0, max: 2, default: 0.7, description: \"Controls randomness\" },\n max_tokens: { type: \"number\", min: 1, default: 4096, description: \"Maximum output tokens\" },\n top_p: { type: \"number\", min: 0, max: 1, default: 1, description: \"Nucleus sampling\" },\n top_k: { type: \"number\", min: 0, default: 40, description: \"Top-K sampling\" },\n frequency_penalty: { type: \"number\", min: -2, max: 2, default: 0, description: \"Penalize frequent tokens\" },\n presence_penalty: { type: \"number\", min: -2, max: 2, default: 0, description: \"Penalize repeated topics\" },\n stop: { type: \"string\", default: \"\", description: \"Stop sequences\" },\n n: { type: \"number\", min: 1, default: 1, description: \"Completions count\" },\n seed: { type: \"number\", default: \"\", description: \"Random seed\" },\n stream: { type: \"boolean\", default: false, description: \"Stream response\" },\n effort: { type: \"enum\", values: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"], default: \"medium\", description: \"Reasoning effort\" },\n },\n vercel: {\n temperature: { type: \"number\", min: 0, max: 2, default: 0.7, description: \"Controls randomness\" },\n max_tokens: { type: \"number\", min: 1, default: 4096, description: \"Maximum output tokens\" },\n top_p: { type: \"number\", min: 0, max: 1, default: 1, description: \"Nucleus sampling\" },\n top_k: { type: \"number\", min: 0, default: 40, description: \"Top-K sampling\" },\n frequency_penalty: { type: \"number\", min: -2, max: 2, default: 0, description: \"Penalize frequent tokens\" },\n presence_penalty: { type: \"number\", min: -2, max: 2, default: 0, description: \"Penalize repeated topics\" },\n stop: { type: \"string\", default: \"\", description: \"Stop sequences\" },\n n: { type: \"number\", min: 1, default: 1, description: \"Completions count\" },\n seed: { type: \"number\", default: \"\", description: \"Random seed\" },\n stream: { type: \"boolean\", default: false, description: \"Stream response\" },\n effort: { type: \"enum\", values: [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"], default: \"medium\", description: \"Reasoning effort\" },\n },\n};\n","import type { LlmConnectionConfig } from \"./parse.js\";\nimport {\n ALIASES,\n CACHE_TTLS,\n CACHE_VALUES,\n DURATION_RE,\n PROVIDER_PARAMS,\n bedrockSupportsCaching,\n canHostOpenAIModels,\n detectProvider,\n isReasoningModel,\n type Provider,\n} from \"./providers.js\";\n\nexport interface NormalizeChange {\n from: string;\n to: string;\n value: string;\n reason: string;\n}\n\nexport interface NormalizeResult {\n config: LlmConnectionConfig;\n provider: Provider | undefined;\n changes: NormalizeChange[];\n}\n\nexport interface NormalizeOptions {\n /** Include detailed change log in the result. */\n verbose?: boolean;\n}\n\n/**\n * Normalize an LLM connection config's params for its target provider.\n *\n * 1. Expands shorthand aliases (e.g. `temp` โ `temperature`)\n * 2. Maps canonical param names to provider-specific names\n * (e.g. `max_tokens` โ `maxOutputTokens` for Google)\n * 3. Normalizes special values (e.g. `cache=true` โ `cache_control=ephemeral` for Anthropic)\n * 4. For OpenAI reasoning models, remaps `max_tokens` โ `max_completion_tokens`\n * and warns about unsupported sampling params\n */\nexport function normalize(\n config: LlmConnectionConfig,\n options: NormalizeOptions = {},\n): NormalizeResult {\n const provider = detectProvider(config.host);\n const changes: NormalizeChange[] = [];\n const params: Record<string, string> = {};\n\n for (const [rawKey, value] of Object.entries(config.params)) {\n let key = rawKey;\n\n // Step 1: Expand aliases to canonical name\n if (ALIASES[key]) {\n const canonical = ALIASES[key];\n if (options.verbose) {\n changes.push({\n from: key,\n to: canonical,\n value,\n reason: `alias: \"${key}\" โ \"${canonical}\"`,\n });\n }\n key = canonical;\n }\n\n // Step 2: Handle special \"cache\" param\n if (key === \"cache\" && provider) {\n let cacheValue = CACHE_VALUES[provider];\n\n // Bedrock supports cache for Anthropic Claude and Amazon Nova models\n if (provider === \"bedrock\" && !bedrockSupportsCaching(config.model)) {\n cacheValue = undefined;\n }\n\n // Provider/model doesn't support cache โ drop it\n if (!cacheValue) {\n if (options.verbose) {\n changes.push({\n from: \"cache\",\n to: \"(dropped)\",\n value,\n reason: `${provider} does not use a cache param for this model (caching is automatic or unsupported)`,\n });\n }\n continue;\n }\n\n const isBool = value === \"true\" || value === \"1\" || value === \"yes\";\n const isDuration = DURATION_RE.test(value);\n\n if (isBool || isDuration) {\n const providerKey =\n PROVIDER_PARAMS[provider]?.[\"cache\"] ?? \"cache\";\n if (options.verbose) {\n changes.push({\n from: \"cache\",\n to: providerKey,\n value: cacheValue,\n reason: `cache=${value} โ ${providerKey}=${cacheValue} for ${provider}`,\n });\n }\n params[providerKey] = cacheValue;\n\n // Emit cache_ttl when a duration is specified\n if (isDuration && CACHE_TTLS[provider]) {\n if (options.verbose) {\n changes.push({\n from: \"cache\",\n to: \"cache_ttl\",\n value,\n reason: `cache=${value} โ cache_ttl=${value} for ${provider}`,\n });\n }\n params[\"cache_ttl\"] = value;\n }\n continue;\n }\n }\n\n // Step 3: Map canonical โ provider-specific param name\n if (provider && PROVIDER_PARAMS[provider]) {\n const providerKey = PROVIDER_PARAMS[provider][key];\n if (providerKey && providerKey !== key) {\n if (options.verbose) {\n changes.push({\n from: key,\n to: providerKey,\n value,\n reason: `${provider} uses \"${providerKey}\" instead of \"${key}\"`,\n });\n }\n key = providerKey;\n }\n }\n\n // Step 4: OpenAI reasoning model adjustments (direct or via gateway)\n if (\n provider &&\n canHostOpenAIModels(provider) &&\n isReasoningModel(config.model) &&\n key === \"max_tokens\"\n ) {\n if (options.verbose) {\n changes.push({\n from: \"max_tokens\",\n to: \"max_completion_tokens\",\n value,\n reason:\n \"OpenAI reasoning models use max_completion_tokens instead of max_tokens\",\n });\n }\n key = \"max_completion_tokens\";\n }\n\n params[key] = value;\n }\n\n return {\n config: { ...config, params },\n provider,\n changes,\n };\n}\n","import { parse } from \"./parse.js\";\nimport { normalize } from \"./normalize.js\";\nimport {\n PARAM_SPECS,\n PROVIDER_PARAMS,\n REASONING_MODEL_UNSUPPORTED,\n bedrockSupportsCaching,\n canHostOpenAIModels,\n detectBedrockModelFamily,\n isReasoningModel,\n} from \"./providers.js\";\n\nexport interface ValidationIssue {\n param: string;\n value: string;\n message: string;\n severity: \"error\" | \"warning\";\n}\n\nexport interface ValidateOptions {\n /** Promote warnings (unknown provider, unknown params) to errors. */\n strict?: boolean;\n}\n\n/**\n * Validate an LLM connection string.\n *\n * Parses and normalizes the string, then checks params against provider specs.\n * Returns a list of issues found. An empty array means all params look valid.\n */\nexport function validate(\n connectionString: string,\n options: ValidateOptions = {},\n): ValidationIssue[] {\n const parsed = parse(connectionString);\n const { config, provider } = normalize(parsed);\n const issues: ValidationIssue[] = [];\n\n if (!provider) {\n issues.push({\n param: \"host\",\n value: config.host,\n message: `Unknown provider for host \"${config.host}\". Validation skipped.`,\n severity: options.strict ? \"error\" : \"warning\",\n });\n return issues;\n }\n\n const specs = PARAM_SPECS[provider];\n const knownParams = new Set(Object.values(PROVIDER_PARAMS[provider]));\n\n for (const [key, value] of Object.entries(config.params)) {\n // Check for OpenAI reasoning model restrictions (direct or via gateway)\n if (\n canHostOpenAIModels(provider) &&\n isReasoningModel(config.model) &&\n REASONING_MODEL_UNSUPPORTED.has(key)\n ) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" is not supported by OpenAI reasoning model \"${config.model}\". Use \"reasoning_effort\" instead of temperature for controlling output.`,\n severity: \"error\",\n });\n continue;\n }\n\n // Bedrock model-family-specific checks\n if (provider === \"bedrock\") {\n const family = detectBedrockModelFamily(config.model);\n\n // topK is only supported by Claude, Cohere, and Mistral on Bedrock\n if (\n key === \"topK\" &&\n family &&\n family !== \"anthropic\" &&\n family !== \"cohere\" &&\n family !== \"mistral\"\n ) {\n issues.push({\n param: key,\n value,\n message: `\"topK\" is not supported by ${family} models on Bedrock.`,\n severity: \"error\",\n });\n continue;\n }\n\n // cache_control is only supported by Claude and Nova on Bedrock\n if (key === \"cache_control\" && !bedrockSupportsCaching(config.model)) {\n issues.push({\n param: key,\n value,\n message: `Prompt caching is only supported for Anthropic Claude and Amazon Nova models on Bedrock, not ${family ?? \"unknown\"} models.`,\n severity: \"error\",\n });\n continue;\n }\n }\n\n // Check if param is known for this provider\n if (!knownParams.has(key) && !specs[key]) {\n issues.push({\n param: key,\n value,\n message: `Unknown param \"${key}\" for ${provider}.`,\n severity: options.strict ? \"error\" : \"warning\",\n });\n continue;\n }\n\n // Validate against spec\n const spec = specs[key];\n if (!spec) continue;\n\n // Anthropic (and Bedrock Claude) mutual exclusion for temperature/top_p\n if (\n (provider === \"anthropic\" ||\n (provider === \"bedrock\" &&\n detectBedrockModelFamily(config.model) === \"anthropic\")) &&\n (key === \"temperature\" || key === \"top_p\" || key === \"topP\")\n ) {\n const otherKey =\n key === \"temperature\"\n ? provider === \"bedrock\"\n ? \"topP\"\n : \"top_p\"\n : \"temperature\";\n // Only report error once (on the temperature param) to avoid duplicate errors\n if (key === \"temperature\" && config.params[otherKey] !== undefined) {\n issues.push({\n param: key,\n value,\n message: `Cannot specify both \"temperature\" and \"${otherKey}\" for Anthropic models.`,\n severity: \"error\",\n });\n }\n }\n\n if (spec.type === \"number\") {\n const num = Number(value);\n if (isNaN(num)) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" should be a number, got \"${value}\".`,\n severity: \"error\",\n });\n continue;\n }\n if (spec.min !== undefined && num < spec.min) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" must be >= ${spec.min}, got ${num}.`,\n severity: \"error\",\n });\n }\n if (spec.max !== undefined && num > spec.max) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" must be <= ${spec.max}, got ${num}.`,\n severity: \"error\",\n });\n }\n }\n\n if (spec.type === \"boolean\") {\n if (![\"true\", \"false\", \"0\", \"1\"].includes(value)) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" should be a boolean (true/false), got \"${value}\".`,\n severity: \"error\",\n });\n }\n }\n\n if (spec.type === \"string\" && spec.values) {\n if (!spec.values.includes(value)) {\n issues.push({\n param: key,\n value,\n message: `\"${key}\" must be one of [${spec.values.join(\", \")}], got \"${value}\".`,\n severity: \"error\",\n });\n }\n }\n }\n\n return issues;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { Provider } from './providers.cjs';
|
|
2
|
+
export { ALIASES, BedrockModelFamily, CANONICAL_PARAM_SPECS, CanonicalParamSpec, MODELS, PARAM_SPECS, PROVIDER_META, PROVIDER_PARAMS, ParamSpec, ProviderMeta, REASONING_MODEL_UNSUPPORTED, canHostOpenAIModels, detectBedrockModelFamily, detectProvider, isReasoningModel } from './providers.cjs';
|
|
3
|
+
|
|
1
4
|
interface LlmConnectionConfig {
|
|
2
5
|
/** The original connection string */
|
|
3
6
|
raw: string;
|
|
@@ -29,25 +32,6 @@ declare function parse(connectionString: string): LlmConnectionConfig;
|
|
|
29
32
|
*/
|
|
30
33
|
declare function build(config: Omit<LlmConnectionConfig, "raw">): string;
|
|
31
34
|
|
|
32
|
-
type Provider = "openai" | "anthropic" | "google" | "mistral" | "cohere" | "bedrock" | "openrouter" | "vercel";
|
|
33
|
-
declare function detectProvider(host: string): Provider | undefined;
|
|
34
|
-
/**
|
|
35
|
-
* Shorthand aliases โ canonical param name.
|
|
36
|
-
* Canonical names use snake_case and follow OpenAI conventions where possible.
|
|
37
|
-
*/
|
|
38
|
-
declare const ALIASES: Record<string, string>;
|
|
39
|
-
/**
|
|
40
|
-
* Canonical param name โ provider-specific API param name.
|
|
41
|
-
* Only includes params the provider actually supports.
|
|
42
|
-
*/
|
|
43
|
-
declare const PROVIDER_PARAMS: Record<Provider, Record<string, string>>;
|
|
44
|
-
/**
|
|
45
|
-
* Bedrock model IDs are prefixed with the vendor name.
|
|
46
|
-
* e.g. "anthropic.claude-sonnet-4-5-20250929-v1:0"
|
|
47
|
-
*/
|
|
48
|
-
type BedrockModelFamily = "anthropic" | "meta" | "amazon" | "mistral" | "cohere" | "ai21";
|
|
49
|
-
declare function detectBedrockModelFamily(model: string): BedrockModelFamily | undefined;
|
|
50
|
-
|
|
51
35
|
interface NormalizeChange {
|
|
52
36
|
from: string;
|
|
53
37
|
to: string;
|
|
@@ -81,12 +65,16 @@ interface ValidationIssue {
|
|
|
81
65
|
message: string;
|
|
82
66
|
severity: "error" | "warning";
|
|
83
67
|
}
|
|
68
|
+
interface ValidateOptions {
|
|
69
|
+
/** Promote warnings (unknown provider, unknown params) to errors. */
|
|
70
|
+
strict?: boolean;
|
|
71
|
+
}
|
|
84
72
|
/**
|
|
85
73
|
* Validate an LLM connection string.
|
|
86
74
|
*
|
|
87
75
|
* Parses and normalizes the string, then checks params against provider specs.
|
|
88
76
|
* Returns a list of issues found. An empty array means all params look valid.
|
|
89
77
|
*/
|
|
90
|
-
declare function validate(connectionString: string): ValidationIssue[];
|
|
78
|
+
declare function validate(connectionString: string, options?: ValidateOptions): ValidationIssue[];
|
|
91
79
|
|
|
92
|
-
export {
|
|
80
|
+
export { type LlmConnectionConfig, type NormalizeChange, type NormalizeOptions, type NormalizeResult, Provider, type ValidateOptions, type ValidationIssue, build, normalize, parse, validate };
|