llm-strings 1.4.0 → 1.5.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/LICENSE +21 -0
- package/README.md +341 -330
- package/dist/ai-sdk.cjs +1 -1176
- package/dist/ai-sdk.d.cts +1 -1
- package/dist/ai-sdk.d.ts +1 -1
- package/dist/ai-sdk.js +1 -543
- package/dist/chunk-CT44CYBU.js +1 -0
- package/dist/chunk-JURQSYOT.js +1 -0
- package/dist/chunk-LIYUWJME.js +1 -0
- package/dist/chunk-M5ENVTNI.js +1 -0
- package/dist/index.cjs +1 -1351
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -22
- package/dist/normalize.cjs +1 -527
- package/dist/normalize.d.cts +1 -1
- package/dist/normalize.d.ts +1 -1
- package/dist/normalize.js +1 -7
- package/dist/parse.cjs +1 -159
- package/dist/parse.d.cts +4 -4
- package/dist/parse.d.ts +4 -4
- package/dist/parse.js +1 -9
- package/dist/{provider-core-B934MuhJ.d.cts → provider-core-CjpJ4qyF.d.cts} +35 -15
- package/dist/{provider-core-B934MuhJ.d.ts → provider-core-CjpJ4qyF.d.ts} +35 -15
- package/dist/providers.cjs +1 -1267
- package/dist/providers.d.cts +2 -2
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +1 -218
- package/dist/validate.cjs +1 -1334
- package/dist/validate.d.cts +1 -1
- package/dist/validate.d.ts +1 -1
- package/dist/validate.js +1 -9
- package/package.json +17 -2
- package/dist/chunk-5YTG2NRX.js +0 -42
- package/dist/chunk-76EFNZCF.js +0 -1043
- package/dist/chunk-DPVT3FFP.js +0 -116
- package/dist/chunk-OBLFZFNR.js +0 -175
package/README.md
CHANGED
|
@@ -8,25 +8,49 @@
|
|
|
8
8
|
[](https://github.com/justsml/llm-strings/blob/main/LICENSE)
|
|
9
9
|
[](https://www.typescriptlang.org/)
|
|
10
10
|
[](https://www.npmjs.com/package/llm-strings)
|
|
11
|
+
[](https://nodejs.org/)
|
|
12
|
+
[](https://bundlejs.com/?q=llm-strings)
|
|
13
|
+
[](https://bundlejs.com/?q=llm-strings&exports=parse)
|
|
14
|
+
|
|
15
|
+
**Parse, normalize, validate, and build portable `llm://` URLs across AI providers.**
|
|
16
|
+
|
|
17
|
+
[Install](#install) · [Quick Start](#quick-start) · [Examples](#examples) · [Supported Providers](#supported-providers) · [API](#api-reference)
|
|
11
18
|
|
|
12
19
|
</div>
|
|
13
20
|
|
|
14
21
|
---
|
|
15
22
|
|
|
16
|
-

|
|
17
24
|
|
|
18
25
|
```ini
|
|
19
|
-
llm://
|
|
20
|
-
llm://
|
|
21
|
-
llm://bedrock
|
|
22
|
-
llm://
|
|
26
|
+
llm://openai/gpt-5.5?effort=medium&maxTokens=2000
|
|
27
|
+
llm://anthropic/claude-opus-4-8?cache=5m&effort=max
|
|
28
|
+
llm://bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0?temp=0.5&max=4096
|
|
29
|
+
llm://openrouter/anthropic/claude-sonnet-4-5?temp=0.7&max=2000
|
|
23
30
|
```
|
|
24
31
|
|
|
25
|
-
Every LLM provider invented
|
|
32
|
+
Every LLM provider invented slightly different names for the same knobs:
|
|
33
|
+
`max_tokens` vs `maxOutputTokens` vs `maxTokens`, `top_p` vs `topP` vs `p`,
|
|
34
|
+
`stop` vs `stop_sequences` vs `stopSequences`.
|
|
35
|
+
|
|
36
|
+
**llm-strings** gives you one portable format for model configuration. Put the
|
|
37
|
+
whole config in an env var, normalize it to the provider's API shape, validate
|
|
38
|
+
it before you spend tokens, and build UI controls from the same metadata.
|
|
26
39
|
|
|
27
|
-
|
|
40
|
+
Based on the [LLM Connection Strings](https://danlevy.net/llm-connection-strings/)
|
|
41
|
+
proposal by Dan Levy. See the [draft IETF RFC for `llm://`](https://datatracker.ietf.org/doc/html/draft-levy-llm-uri-scheme-00).
|
|
28
42
|
|
|
29
|
-
|
|
43
|
+
## Why developers use it
|
|
44
|
+
|
|
45
|
+
- **One config string** for host, model, credentials, and generation params.
|
|
46
|
+
- **Provider-native output** from provider-agnostic input like `temp=0.7&max=2000`.
|
|
47
|
+
- **Early validation** for ranges, mutual exclusions, Bedrock model-family
|
|
48
|
+
rules, and OpenAI reasoning-family normalization.
|
|
49
|
+
- **Short aliases** like `openai`, `anthropic`, `google`, `bedrock`, `groq`, and
|
|
50
|
+
`openrouter`, with env overrides for private or regional endpoints.
|
|
51
|
+
- **AI SDK providerOptions** generation for provider-specific settings.
|
|
52
|
+
- **Zero runtime dependencies**, ESM + CJS, full TypeScript declarations, and
|
|
53
|
+
sub-path imports for smaller bundles.
|
|
30
54
|
|
|
31
55
|
## Install
|
|
32
56
|
|
|
@@ -34,164 +58,87 @@ Based on the [LLM Connection Strings](https://danlevy.net/llm-connection-strings
|
|
|
34
58
|
npm install llm-strings
|
|
35
59
|
```
|
|
36
60
|
|
|
37
|
-
## Quick Start
|
|
38
|
-
|
|
39
|
-
```ts
|
|
40
|
-
import { parse, normalize, validate, build } from "llm-strings";
|
|
41
|
-
|
|
42
|
-
// Parse a connection string into structured config
|
|
43
|
-
const config = parse("llm://api.openai.com/gpt-5.2?temp=0.7&max=2000");
|
|
44
|
-
// → { host: "api.openai.com", model: "gpt-5.2", params: { temp: "0.7", max: "2000" } }
|
|
45
|
-
|
|
46
|
-
// Normalize aliases and map to the provider's actual API param names
|
|
47
|
-
const { config: normalized, provider } = normalize(config);
|
|
48
|
-
// → params: { temperature: "0.7", max_tokens: "2000" }, provider: "openai"
|
|
49
|
-
|
|
50
|
-
// Validate against provider specs (returns [] if valid)
|
|
51
|
-
const issues = validate("llm://api.openai.com/gpt-5.2?temp=3.0");
|
|
52
|
-
// → [{ param: "temperature", message: '"temperature" must be <= 2, got 3', severity: "error" }]
|
|
53
|
-
|
|
54
|
-
// Build a connection string from a config object
|
|
55
|
-
const str = build({
|
|
56
|
-
host: "api.openai.com",
|
|
57
|
-
model: "gpt-5.2",
|
|
58
|
-
params: { temperature: "0.7" },
|
|
59
|
-
});
|
|
60
|
-
// → "llm://api.openai.com/gpt-5.2?temperature=0.7"
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Why Connection Strings?
|
|
64
|
-
|
|
65
|
-
You already use them for databases: `postgres://user:pass@host/db`. They're compact, portable, and easy to pass through environment variables. LLM configs deserve the same treatment.
|
|
66
|
-
|
|
67
|
-
**Store your entire model config in one env var:**
|
|
68
|
-
|
|
69
61
|
```bash
|
|
70
|
-
|
|
62
|
+
pnpm add llm-strings
|
|
71
63
|
```
|
|
72
64
|
|
|
73
|
-
**Switch providers by changing a string, not refactoring code:**
|
|
74
|
-
|
|
75
65
|
```bash
|
|
76
|
-
|
|
77
|
-
LLM_URL="llm://api.openai.com/gpt-5.2?temp=0.7&max=2000"
|
|
78
|
-
|
|
79
|
-
# Tuesday: Anthropic
|
|
80
|
-
LLM_URL="llm://api.anthropic.com/claude-sonnet-4-5?temp=0.7&max=2000"
|
|
81
|
-
|
|
82
|
-
# Wednesday: Bedrock in production
|
|
83
|
-
LLM_URL="llm://bedrock-runtime.us-east-1.amazonaws.com/anthropic.claude-sonnet-4-5-20250929-v1:0?temp=0.7&max=2000"
|
|
66
|
+
yarn add llm-strings
|
|
84
67
|
```
|
|
85
68
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
## Benefits
|
|
89
|
-
|
|
90
|
-
- **One format, every provider** — Write `temp=0.7&max=2000` once. Normalization maps it to `temperature`, `max_tokens`, `maxOutputTokens`, `maxTokens`, or whatever your provider calls it.
|
|
91
|
-
- **Catch mistakes early** — `validate()` checks types, ranges, and provider-specific rules before you burn tokens on a bad request.
|
|
92
|
-
- **Zero dependencies** — Pure TypeScript. No runtime baggage.
|
|
93
|
-
- **Portable config** — Fits in an env var, a CLI flag, a config file, or a database column.
|
|
94
|
-
- **Shorthand aliases** — Use `temp`, `max`, `topp`, `freq`, `pres` — they all expand to the right thing.
|
|
95
|
-
- **Short host aliases** — Use `llm://openai/...`, `llm://anthropic/...`, `llm://bedrock/...`, etc. Env overrides can redirect aliases to regional or private endpoints.
|
|
96
|
-
|
|
97
|
-
## Format
|
|
98
|
-
|
|
99
|
-
```ini
|
|
100
|
-
llm://[label[:apiKey]@]host/model[?params]
|
|
69
|
+
```bash
|
|
70
|
+
bun add llm-strings
|
|
101
71
|
```
|
|
102
72
|
|
|
103
|
-
|
|
104
|
-
| -------- | -------- | ---------------------------------- | -------------------------- |
|
|
105
|
-
| `label` | No | App name or identifier | `my-app` |
|
|
106
|
-
| `apiKey` | No | API key (in the password position) | `sk-proj-abc123` |
|
|
107
|
-
| `host` | Yes | Provider's API host or short alias | `api.openai.com`, `openai` |
|
|
108
|
-
| `model` | Yes | Model name or ID | `gpt-5.2` |
|
|
109
|
-
| `params` | No | Key-value config (query string) | `temp=0.7&max=2000` |
|
|
110
|
-
|
|
111
|
-
## Examples
|
|
112
|
-
|
|
113
|
-
### Switching between providers
|
|
114
|
-
|
|
115
|
-
Write portable params, let `normalize()` translate them:
|
|
73
|
+
## Quick Start
|
|
116
74
|
|
|
117
75
|
```ts
|
|
118
|
-
import {
|
|
119
|
-
|
|
120
|
-
// Same logical config, different providers
|
|
121
|
-
const strings = [
|
|
122
|
-
"llm://api.openai.com/gpt-5.2?temp=0.7&max=2000&top_p=0.9",
|
|
123
|
-
"llm://api.anthropic.com/claude-sonnet-4-5?temp=0.7&max=2000&top_p=0.9",
|
|
124
|
-
"llm://generativelanguage.googleapis.com/gemini-3-flash-preview?temp=0.7&max=2000&top_p=0.9",
|
|
125
|
-
];
|
|
126
|
-
|
|
127
|
-
for (const str of strings) {
|
|
128
|
-
const { config, provider } = normalize(parse(str));
|
|
129
|
-
console.log(`${provider}:`, config.params);
|
|
130
|
-
}
|
|
131
|
-
// openai: { temperature: "0.7", max_tokens: "2000", top_p: "0.9" }
|
|
132
|
-
// anthropic: { temperature: "0.7", max_tokens: "2000", top_p: "0.9" }
|
|
133
|
-
// google: { temperature: "0.7", maxOutputTokens: "2000", topP: "0.9" }
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Short host aliases
|
|
76
|
+
import { build, normalize, parse, validate } from "llm-strings";
|
|
137
77
|
|
|
138
|
-
|
|
78
|
+
const input = "llm://openai/gpt-4o?temp=0.7&max=2000&topp=0.9";
|
|
139
79
|
|
|
140
|
-
|
|
141
|
-
|
|
80
|
+
const parsed = parse(input);
|
|
81
|
+
// {
|
|
82
|
+
// raw: "llm://openai/gpt-4o?temp=0.7&max=2000&topp=0.9",
|
|
83
|
+
// host: "api.openai.com",
|
|
84
|
+
// hostAlias: "openai",
|
|
85
|
+
// model: "gpt-4o",
|
|
86
|
+
// params: { temp: "0.7", max: "2000", topp: "0.9" }
|
|
87
|
+
// }
|
|
142
88
|
|
|
143
|
-
const { config, provider } = normalize(
|
|
89
|
+
const { config, provider } = normalize(parsed);
|
|
90
|
+
// provider: "openai"
|
|
91
|
+
// config.params: { temperature: "0.7", max_tokens: "2000", top_p: "0.9" }
|
|
92
|
+
|
|
93
|
+
const issues = validate("llm://anthropic/claude-sonnet-4-5?temp=0.7&top_p=0.9");
|
|
94
|
+
// [
|
|
95
|
+
// {
|
|
96
|
+
// param: "temperature",
|
|
97
|
+
// value: "0.7",
|
|
98
|
+
// severity: "error",
|
|
99
|
+
// message: "Cannot specify both \"temperature\" and \"top_p\" for Anthropic models."
|
|
100
|
+
// }
|
|
101
|
+
// ]
|
|
144
102
|
|
|
145
|
-
|
|
146
|
-
|
|
103
|
+
const url = build({
|
|
104
|
+
host: "anthropic",
|
|
105
|
+
model: "claude-sonnet-4-5",
|
|
106
|
+
params: { temp: "0.7", max: "4096" },
|
|
107
|
+
});
|
|
108
|
+
// "llm://api.anthropic.com/claude-sonnet-4-5?temp=0.7&max=4096"
|
|
147
109
|
```
|
|
148
110
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
Set env overrides to point an alias at a regional or private endpoint:
|
|
111
|
+
## Format
|
|
152
112
|
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
LLM_STRINGS_BEDROCK_HOST="bedrock-runtime.us-west-2.amazonaws.com"
|
|
113
|
+
```ini
|
|
114
|
+
llm://[label[:apiKey]@]host/model[?params]
|
|
156
115
|
```
|
|
157
116
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
117
|
+
| Part | Required | Description | Example |
|
|
118
|
+
| -------- | -------- | --------------------------------- | -------------------------- |
|
|
119
|
+
| `label` | No | App name or environment label | `worker` |
|
|
120
|
+
| `apiKey` | No | API key in the password position | `sk-proj-abc123` |
|
|
121
|
+
| `host` | Yes | Provider host or short alias | `api.openai.com`, `openai` |
|
|
122
|
+
| `model` | Yes | Model name, route, or provider ID | `gpt-5.5` |
|
|
123
|
+
| `params` | No | Query-string generation settings | `effort=medium&max=2000` |
|
|
161
124
|
|
|
162
|
-
|
|
125
|
+
Connection strings can include secrets, so treat values containing `apiKey` like
|
|
126
|
+
credentials: store them in secret managers or env vars, and avoid logging them.
|
|
163
127
|
|
|
164
|
-
|
|
165
|
-
import { validate } from "llm-strings";
|
|
128
|
+
## Examples
|
|
166
129
|
|
|
167
|
-
|
|
168
|
-
const issues = validate(
|
|
169
|
-
"llm://api.anthropic.com/claude-sonnet-4-5?temp=0.7&top_p=0.9",
|
|
170
|
-
);
|
|
130
|
+
### One env var for your model config
|
|
171
131
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
// [error] temperature: Cannot specify both "temperature" and "top_p" for Anthropic models.
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
```ts
|
|
179
|
-
// OpenAI reasoning models have different rules
|
|
180
|
-
const issues = validate("llm://api.openai.com/o3?temp=0.7&max=2000");
|
|
181
|
-
// [error] temperature: "temperature" is not supported by OpenAI reasoning model "o3".
|
|
182
|
-
// Use "reasoning_effort" instead of temperature for controlling output.
|
|
132
|
+
```bash
|
|
133
|
+
LLM_URL="llm://worker:sk-proj-abc123@openai/gpt-4o?temp=0.7&max=2000"
|
|
183
134
|
```
|
|
184
135
|
|
|
185
|
-
### Environment-driven config
|
|
186
|
-
|
|
187
136
|
```ts
|
|
188
|
-
import {
|
|
137
|
+
import { normalize, parse } from "llm-strings";
|
|
189
138
|
|
|
190
|
-
// One env var holds the entire config
|
|
191
139
|
const { config, provider } = normalize(parse(process.env.LLM_URL!));
|
|
192
140
|
|
|
193
|
-
|
|
194
|
-
const response = await fetch(`https://${config.host}/v1/chat/completions`, {
|
|
141
|
+
await fetch(`https://${config.host}/v1/chat/completions`, {
|
|
195
142
|
method: "POST",
|
|
196
143
|
headers: {
|
|
197
144
|
Authorization: `Bearer ${config.apiKey}`,
|
|
@@ -201,156 +148,215 @@ const response = await fetch(`https://${config.host}/v1/chat/completions`, {
|
|
|
201
148
|
model: config.model,
|
|
202
149
|
messages: [{ role: "user", content: "Hello!" }],
|
|
203
150
|
...Object.fromEntries(
|
|
204
|
-
Object.entries(config.params).map(([
|
|
151
|
+
Object.entries(config.params).map(([key, value]) => [
|
|
152
|
+
key,
|
|
153
|
+
Number.isNaN(Number(value)) ? value : Number(value),
|
|
154
|
+
]),
|
|
205
155
|
),
|
|
206
156
|
}),
|
|
207
157
|
});
|
|
158
|
+
|
|
159
|
+
console.log(provider); // "openai"
|
|
208
160
|
```
|
|
209
161
|
|
|
210
|
-
###
|
|
162
|
+
### Switch providers without changing app code
|
|
211
163
|
|
|
212
|
-
|
|
213
|
-
|
|
164
|
+
```bash
|
|
165
|
+
# OpenAI
|
|
166
|
+
LLM_URL="llm://openai/gpt-4o?temp=0.7&max=2000"
|
|
214
167
|
|
|
215
|
-
|
|
216
|
-
|
|
168
|
+
# Anthropic
|
|
169
|
+
LLM_URL="llm://anthropic/claude-sonnet-4-5?temp=0.7&max=2000"
|
|
217
170
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
);
|
|
171
|
+
# Google
|
|
172
|
+
LLM_URL="llm://google/gemini-3.5-flash?temp=0.7&max=2000"
|
|
221
173
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
// cacheControl: { type: "ephemeral", ttl: "1h" },
|
|
225
|
-
// effort: "max"
|
|
226
|
-
// }
|
|
227
|
-
// }
|
|
174
|
+
# Bedrock
|
|
175
|
+
LLM_URL="llm://bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0?temp=0.7&max=2000"
|
|
228
176
|
```
|
|
229
177
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
178
|
+
```ts
|
|
179
|
+
import { normalize, parse } from "llm-strings";
|
|
180
|
+
|
|
181
|
+
for (const value of [
|
|
182
|
+
"llm://openai/gpt-4o?temp=0.7&max=2000",
|
|
183
|
+
"llm://anthropic/claude-sonnet-4-5?temp=0.7&max=2000",
|
|
184
|
+
"llm://google/gemini-3.5-flash?temp=0.7&max=2000",
|
|
185
|
+
]) {
|
|
186
|
+
const { config, provider } = normalize(parse(value));
|
|
187
|
+
console.log(provider, config.params);
|
|
188
|
+
}
|
|
235
189
|
|
|
236
|
-
|
|
190
|
+
// openai { temperature: "0.7", max_tokens: "2000" }
|
|
191
|
+
// anthropic { temperature: "0.7", max_tokens: "2000" }
|
|
192
|
+
// google { temperature: "0.7", maxOutputTokens: "2000" }
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Resolve short host aliases
|
|
237
196
|
|
|
238
197
|
```ts
|
|
239
|
-
import {
|
|
198
|
+
import { normalize, parse } from "llm-strings";
|
|
240
199
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
parse("llm://api.anthropic.com/claude-sonnet-4-5?max=4096&cache=true"),
|
|
200
|
+
const { config, provider } = normalize(
|
|
201
|
+
parse("llm://groq/llama-3.3-70b?max=1000"),
|
|
244
202
|
);
|
|
245
|
-
// → params: { max_tokens: "4096", cache_control: "ephemeral" }
|
|
246
203
|
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
);
|
|
251
|
-
// → params: { max_tokens: "4096", cache_control: "ephemeral", cache_ttl: "5m" }
|
|
204
|
+
config.host; // "api.groq.com"
|
|
205
|
+
provider; // "groq"
|
|
206
|
+
```
|
|
252
207
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
);
|
|
259
|
-
// → params: { cache_control: "ephemeral", cache_ttl: "1h" }
|
|
208
|
+
Override any alias at deploy time:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
LLM_STRINGS_OPENAI_HOST="regional.openai.example.com"
|
|
212
|
+
LLM_STRINGS_BEDROCK_HOST="https://bedrock-runtime.us-west-2.amazonaws.com/model"
|
|
260
213
|
```
|
|
261
214
|
|
|
262
|
-
|
|
215
|
+
The alternate form `LLM_STRINGS_HOST_OPENAI` is also supported. Overrides may
|
|
216
|
+
include a scheme or path; only the host portion is used.
|
|
263
217
|
|
|
264
|
-
|
|
218
|
+
### Validate before calling the provider
|
|
265
219
|
|
|
266
220
|
```ts
|
|
267
|
-
import {
|
|
221
|
+
import { validate } from "llm-strings";
|
|
268
222
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
"llm://generativelanguage.googleapis.com/gemini-3-flash-preview?temp=0.7&max=2000&topp=0.9",
|
|
272
|
-
),
|
|
273
|
-
{ verbose: true },
|
|
274
|
-
);
|
|
223
|
+
validate("llm://openai/gpt-4o?temp=3.0");
|
|
224
|
+
// [{ param: "temperature", message: "\"temperature\" must be <= 2, got 3", ... }]
|
|
275
225
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
// temp → temperature (alias: "temp" → "temperature")
|
|
280
|
-
// max → max_tokens (alias: "max" → "max_tokens")
|
|
281
|
-
// max_tokens → maxOutputTokens (google uses "maxOutputTokens" instead of "max_tokens")
|
|
282
|
-
// topp → top_p (alias: "topp" → "top_p")
|
|
283
|
-
// top_p → topP (google uses "topP" instead of "top_p")
|
|
284
|
-
```
|
|
226
|
+
validate("llm://openai/gpt-5.5?temp=0.7&max=2000");
|
|
227
|
+
// [] — temperature is a known unsupported reasoning-family param, so normalize() drops it
|
|
285
228
|
|
|
286
|
-
|
|
229
|
+
validate("llm://fal/fal-ai/flux-pro?future_model_param=1");
|
|
230
|
+
// [] — unknown params pass through by default for model-specific schemas
|
|
287
231
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const url = build({
|
|
292
|
-
host: "api.openai.com",
|
|
293
|
-
model: "gpt-5.2",
|
|
294
|
-
label: "my-app",
|
|
295
|
-
apiKey: "sk-proj-abc123",
|
|
296
|
-
params: { temperature: "0.7", max_tokens: "2000", stream: "true" },
|
|
297
|
-
});
|
|
298
|
-
// → "llm://my-app:sk-proj-abc123@api.openai.com/gpt-5.2?temperature=0.7&max_tokens=2000&stream=true"
|
|
232
|
+
validate("llm://fal/fal-ai/flux-pro?future_model_param=1", { strict: true });
|
|
233
|
+
// [{ param: "future_model_param", severity: "error", message: "Unknown param..." }]
|
|
299
234
|
```
|
|
300
235
|
|
|
301
|
-
###
|
|
236
|
+
### See exactly what changed
|
|
302
237
|
|
|
303
238
|
```ts
|
|
304
|
-
import {
|
|
305
|
-
import { detectBedrockModelFamily } from "llm-strings/providers";
|
|
239
|
+
import { normalize, parse } from "llm-strings";
|
|
306
240
|
|
|
307
|
-
const
|
|
308
|
-
"llm://
|
|
241
|
+
const { changes } = normalize(
|
|
242
|
+
parse("llm://google/gemini-3.5-flash?temp=0.7&max=2000&topp=0.9"),
|
|
243
|
+
{ verbose: true },
|
|
309
244
|
);
|
|
310
245
|
|
|
311
|
-
|
|
312
|
-
|
|
246
|
+
for (const change of changes) {
|
|
247
|
+
console.log(`${change.from} -> ${change.to} (${change.reason})`);
|
|
248
|
+
}
|
|
313
249
|
|
|
314
|
-
|
|
315
|
-
//
|
|
316
|
-
//
|
|
250
|
+
// temp -> temperature (alias: "temp" -> "temperature")
|
|
251
|
+
// max -> max_tokens (alias: "max" -> "max_tokens")
|
|
252
|
+
// max_tokens -> maxOutputTokens (google uses "maxOutputTokens" instead of "max_tokens")
|
|
253
|
+
// topp -> top_p (alias: "topp" -> "top_p")
|
|
254
|
+
// top_p -> topP (google uses "topP" instead of "top_p")
|
|
317
255
|
```
|
|
318
256
|
|
|
319
|
-
###
|
|
257
|
+
### Build AI SDK providerOptions
|
|
258
|
+
|
|
259
|
+
The AI SDK adapter lives on a separate sub-path so you only load it when you
|
|
260
|
+
need it:
|
|
320
261
|
|
|
321
262
|
```ts
|
|
322
|
-
|
|
263
|
+
const { createAiSdkProviderOptions } = await import("llm-strings/ai-sdk");
|
|
323
264
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
parse("llm://openrouter.ai/anthropic/claude-sonnet-4-5?temp=0.7&max=2000"),
|
|
265
|
+
const { providerOptions } = createAiSdkProviderOptions(
|
|
266
|
+
"llm://anthropic/claude-sonnet-4-5?cache=1h&effort=max",
|
|
327
267
|
);
|
|
328
|
-
// → params: { temperature: "0.7", max_tokens: "2000" }
|
|
329
268
|
|
|
330
|
-
//
|
|
331
|
-
|
|
332
|
-
//
|
|
333
|
-
//
|
|
269
|
+
// {
|
|
270
|
+
// anthropic: {
|
|
271
|
+
// cacheControl: { type: "ephemeral", ttl: "1h" },
|
|
272
|
+
// effort: "max"
|
|
273
|
+
// }
|
|
274
|
+
// }
|
|
334
275
|
```
|
|
335
276
|
|
|
336
|
-
|
|
277
|
+
Common generation settings like temperature, top-p, and max output tokens
|
|
278
|
+
belong on the AI SDK call itself. The helper emits provider-specific options
|
|
279
|
+
such as Anthropic cache control, Bedrock cache points, OpenAI reasoning options,
|
|
280
|
+
Mistral `safePrompt`, OpenRouter routing, and Vercel AI Gateway routing,
|
|
281
|
+
including options such as `order`, `sort=ttft`, and `caching=auto`.
|
|
337
282
|
|
|
338
|
-
|
|
339
|
-
| ----------- | ---------------------------------------- | ----------- |
|
|
340
|
-
| OpenAI | `api.openai.com` | snake_case |
|
|
341
|
-
| Anthropic | `api.anthropic.com` | snake_case |
|
|
342
|
-
| Google | `generativelanguage.googleapis.com` | camelCase |
|
|
343
|
-
| Mistral | `api.mistral.ai` | snake_case |
|
|
344
|
-
| Cohere | `api.cohere.com` | snake_case |
|
|
345
|
-
| AWS Bedrock | `bedrock-runtime.{region}.amazonaws.com` | camelCase |
|
|
346
|
-
| OpenRouter | `openrouter.ai` | snake_case |
|
|
347
|
-
| Vercel AI | `gateway.ai.vercel.app` | snake_case |
|
|
283
|
+
### Build provider-aware UIs
|
|
348
284
|
|
|
349
|
-
|
|
285
|
+
```ts
|
|
286
|
+
import { CANONICAL_PARAM_SPECS, PROVIDER_META } from "llm-strings/providers";
|
|
350
287
|
|
|
351
|
-
|
|
288
|
+
PROVIDER_META.map(({ id, name, host, color }) => ({ id, name, host, color }));
|
|
289
|
+
// [{ id: "openai", name: "OpenAI", host: "api.openai.com", color: "#10a37f" }, ...]
|
|
352
290
|
|
|
353
|
-
|
|
291
|
+
CANONICAL_PARAM_SPECS.anthropic.temperature;
|
|
292
|
+
// {
|
|
293
|
+
// type: "number",
|
|
294
|
+
// min: 0,
|
|
295
|
+
// max: 1,
|
|
296
|
+
// default: 0.7,
|
|
297
|
+
// description: "Controls randomness"
|
|
298
|
+
// }
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Supported Providers
|
|
302
|
+
|
|
303
|
+
`llm-strings` ships provider detection, host aliases, metadata, and parameter
|
|
304
|
+
normalization for the major LLM provider shapes. Chat-compatible providers get
|
|
305
|
+
canonical parameter mapping and validation; media and audio providers are
|
|
306
|
+
available for detection, metadata, aliases, and flexible AI SDK providerOptions.
|
|
307
|
+
|
|
308
|
+
| Category | Providers |
|
|
309
|
+
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
310
|
+
| Core chat + reasoning | OpenAI, Azure OpenAI, Anthropic, Google AI Studio, Google Vertex AI, Mistral, Cohere, AWS Bedrock, OpenRouter, Vercel AI Gateway |
|
|
311
|
+
| OpenAI-compatible APIs | xAI, Groq, DeepInfra, Together.ai, Fireworks, DeepSeek, Moonshot AI, Perplexity, Alibaba DashScope, Cerebras, Baseten, Hugging Face |
|
|
312
|
+
| Media, audio, and flexible | Fal, Black Forest Labs, Replicate, Prodia, Luma, ByteDance, Kling AI, ElevenLabs, AssemblyAI, Deepgram, Gladia, LMNT, Hume, Rev.ai |
|
|
313
|
+
| Extra aliases and endpoints | `aistudio`, `vertex`, `grok`, `bfl`, `dashscope`, `alibabacloud`, `togetherai`, `fireworksai`, `moonshot`, `wandb`, `weightsandbiases`, `baidu`, `qianfan`, `venice`, `parasail`, `novita`, `atlascloud`, `xiaomi`, `minimax` |
|
|
314
|
+
|
|
315
|
+
### Provider table
|
|
316
|
+
|
|
317
|
+
| Provider ID | Default host | Param style |
|
|
318
|
+
| ------------------- | ----------------------------------------- | ----------------- |
|
|
319
|
+
| `openai` | `api.openai.com` | snake_case |
|
|
320
|
+
| `azure` | `models.inference.ai.azure.com` | OpenAI-compatible |
|
|
321
|
+
| `anthropic` | `api.anthropic.com` | snake_case |
|
|
322
|
+
| `google` | `generativelanguage.googleapis.com` | camelCase |
|
|
323
|
+
| `google-vertex` | `aiplatform.googleapis.com` | camelCase |
|
|
324
|
+
| `mistral` | `api.mistral.ai` | snake_case |
|
|
325
|
+
| `cohere` | `api.cohere.com` | mixed |
|
|
326
|
+
| `bedrock` | `bedrock-runtime.us-east-1.amazonaws.com` | camelCase |
|
|
327
|
+
| `openrouter` | `openrouter.ai` | OpenAI-compatible |
|
|
328
|
+
| `vercel` | `gateway.ai.vercel.app` | OpenAI-compatible |
|
|
329
|
+
| `xai` | `api.x.ai` | OpenAI-compatible |
|
|
330
|
+
| `groq` | `api.groq.com` | OpenAI-compatible |
|
|
331
|
+
| `fal` | `fal.run` | flexible |
|
|
332
|
+
| `deepinfra` | `api.deepinfra.com` | OpenAI-compatible |
|
|
333
|
+
| `black-forest-labs` | `api.bfl.ai` | flexible |
|
|
334
|
+
| `together` | `api.together.xyz` | OpenAI-compatible |
|
|
335
|
+
| `fireworks` | `api.fireworks.ai` | OpenAI-compatible |
|
|
336
|
+
| `deepseek` | `api.deepseek.com` | OpenAI-compatible |
|
|
337
|
+
| `moonshotai` | `api.moonshot.ai` | OpenAI-compatible |
|
|
338
|
+
| `perplexity` | `api.perplexity.ai` | OpenAI-compatible |
|
|
339
|
+
| `alibaba` | `dashscope-intl.aliyuncs.com` | OpenAI-compatible |
|
|
340
|
+
| `cerebras` | `api.cerebras.ai` | OpenAI-compatible |
|
|
341
|
+
| `replicate` | `api.replicate.com` | flexible |
|
|
342
|
+
| `prodia` | `api.prodia.com` | flexible |
|
|
343
|
+
| `luma` | `api.lumalabs.ai` | flexible |
|
|
344
|
+
| `bytedance` | `ark.cn-beijing.volces.com` | flexible |
|
|
345
|
+
| `kling` | `api.klingai.com` | flexible |
|
|
346
|
+
| `elevenlabs` | `api.elevenlabs.io` | flexible |
|
|
347
|
+
| `assemblyai` | `api.assemblyai.com` | flexible |
|
|
348
|
+
| `deepgram` | `api.deepgram.com` | flexible |
|
|
349
|
+
| `gladia` | `api.gladia.io` | flexible |
|
|
350
|
+
| `lmnt` | `api.lmnt.com` | flexible |
|
|
351
|
+
| `hume` | `api.hume.ai` | flexible |
|
|
352
|
+
| `revai` | `api.rev.ai` | flexible |
|
|
353
|
+
| `baseten` | `api.baseten.co` | OpenAI-compatible |
|
|
354
|
+
| `huggingface` | `api-inference.huggingface.co` | OpenAI-compatible |
|
|
355
|
+
|
|
356
|
+
## Shorthand aliases
|
|
357
|
+
|
|
358
|
+
Use short, memorable query params. `normalize()` expands them first, then maps
|
|
359
|
+
them to provider-native names.
|
|
354
360
|
|
|
355
361
|
| Shorthand | Canonical |
|
|
356
362
|
| ------------------------------------------------------------------------------------------------------------ | ------------------- |
|
|
@@ -366,21 +372,48 @@ Use these shortcuts in your connection strings — they expand automatically dur
|
|
|
366
372
|
| `reasoning`, `reasoning_effort` | `effort` |
|
|
367
373
|
| `cache_control`, `cacheControl`, `cachePoint`, `cache_point` | `cache` |
|
|
368
374
|
|
|
369
|
-
##
|
|
375
|
+
## Prompt caching
|
|
376
|
+
|
|
377
|
+
```ts
|
|
378
|
+
import { normalize, parse } from "llm-strings";
|
|
379
|
+
|
|
380
|
+
normalize(parse("llm://anthropic/claude-sonnet-4-5?max=4096&cache=true")).config
|
|
381
|
+
.params;
|
|
382
|
+
// { max_tokens: "4096", cache_control: "ephemeral" }
|
|
383
|
+
|
|
384
|
+
normalize(parse("llm://anthropic/claude-sonnet-4-5?max=4096&cache=5m")).config
|
|
385
|
+
.params;
|
|
386
|
+
// { max_tokens: "4096", cache_control: "ephemeral", cache_ttl: "5m" }
|
|
370
387
|
|
|
371
|
-
|
|
388
|
+
normalize(
|
|
389
|
+
parse("llm://bedrock/anthropic.claude-sonnet-4-5-20250929-v1:0?cache=1h"),
|
|
390
|
+
).config.params;
|
|
391
|
+
// { cache_control: "ephemeral", cache_ttl: "1h" }
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Caching currently normalizes for Anthropic and supported Bedrock models. For
|
|
395
|
+
Anthropic, `cache=5m` and `cache=1h` are both supported. For Bedrock, support is
|
|
396
|
+
model-family specific and currently covers Claude and Amazon Nova models. For
|
|
397
|
+
providers where caching is automatic, unsupported, or provider-specific in a way
|
|
398
|
+
that should not be represented as a generation param, `cache` is dropped during
|
|
399
|
+
normalization.
|
|
400
|
+
|
|
401
|
+
## Sub-path imports
|
|
372
402
|
|
|
373
403
|
```ts
|
|
374
|
-
import {
|
|
404
|
+
import { build, parse } from "llm-strings/parse";
|
|
375
405
|
import { normalize } from "llm-strings/normalize";
|
|
376
406
|
import { validate } from "llm-strings/validate";
|
|
407
|
+
import { createAiSdkProviderOptions } from "llm-strings/ai-sdk";
|
|
377
408
|
import {
|
|
378
|
-
detectProvider,
|
|
379
|
-
resolveHostAlias,
|
|
380
409
|
ALIASES,
|
|
410
|
+
CANONICAL_PARAM_SPECS,
|
|
381
411
|
HOST_ALIASES,
|
|
382
|
-
PROVIDER_PARAMS,
|
|
383
412
|
PARAM_SPECS,
|
|
413
|
+
PROVIDER_META,
|
|
414
|
+
PROVIDER_PARAMS,
|
|
415
|
+
detectProvider,
|
|
416
|
+
resolveHostAlias,
|
|
384
417
|
} from "llm-strings/providers";
|
|
385
418
|
```
|
|
386
419
|
|
|
@@ -390,142 +423,120 @@ All sub-paths ship ESM + CJS with full type declarations.
|
|
|
390
423
|
|
|
391
424
|
### `parse(connectionString): LlmConnectionConfig`
|
|
392
425
|
|
|
393
|
-
Parses an `llm://` connection string into
|
|
426
|
+
Parses an `llm://` connection string into structured config. Throws when the
|
|
427
|
+
scheme is not `llm://`.
|
|
394
428
|
|
|
395
429
|
### `build(config): string`
|
|
396
430
|
|
|
397
|
-
|
|
431
|
+
Builds an `llm://` connection string from a config object. This is the inverse
|
|
432
|
+
of `parse()`.
|
|
398
433
|
|
|
399
434
|
### `normalize(config, options?): NormalizeResult`
|
|
400
435
|
|
|
401
|
-
Normalizes
|
|
436
|
+
Normalizes params for the detected provider:
|
|
402
437
|
|
|
403
|
-
1. Expands shorthand aliases
|
|
404
|
-
2. Maps to provider-specific
|
|
405
|
-
|
|
406
|
-
|
|
438
|
+
1. Expands shorthand aliases such as `temp` -> `temperature`.
|
|
439
|
+
2. Maps canonical names to provider-specific names such as `max_tokens` ->
|
|
440
|
+
`maxOutputTokens` for Google.
|
|
441
|
+
3. Normalizes cache values such as `cache=5m` -> `cache_control=ephemeral` and
|
|
442
|
+
`cache_ttl=5m`.
|
|
443
|
+
4. Adjusts OpenAI reasoning-family params such as `max_tokens` ->
|
|
444
|
+
`max_completion_tokens` and drops known unsupported sampling params.
|
|
407
445
|
|
|
408
|
-
Pass `{ verbose: true }` to get a
|
|
446
|
+
Pass `{ verbose: true }` to get a `changes` array that documents each
|
|
447
|
+
transformation.
|
|
409
448
|
|
|
410
449
|
### `validate(connectionString, options?): ValidationIssue[]`
|
|
411
450
|
|
|
412
|
-
Parses, normalizes, and validates a connection string
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
-
|
|
416
|
-
|
|
417
|
-
- Reasoning model restrictions (no `temperature` on o1/o3/o4)
|
|
418
|
-
- Bedrock model family constraints (`topK` only for Claude/Cohere/Mistral)
|
|
419
|
-
|
|
420
|
-
Pass `{ strict: true }` to promote warnings (unknown provider, unknown params) to errors:
|
|
421
|
-
|
|
422
|
-
```ts
|
|
423
|
-
validate("llm://custom-api.com/my-model?temp=0.5", { strict: true });
|
|
424
|
-
// → [{ severity: "error", message: "Unknown provider …" }]
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
### `detectProvider(host): Provider | undefined`
|
|
428
|
-
|
|
429
|
-
Identifies the provider from a hostname string.
|
|
430
|
-
|
|
431
|
-
### `resolveHostAlias(host): HostResolution`
|
|
432
|
-
|
|
433
|
-
Expands provider short host aliases such as `"openai"` to canonical hosts such as `"api.openai.com"`. Reads `LLM_STRINGS_<PROVIDER>_HOST` and `LLM_STRINGS_HOST_<PROVIDER>` env overrides when available.
|
|
434
|
-
|
|
435
|
-
### `detectBedrockModelFamily(model): BedrockModelFamily | undefined`
|
|
451
|
+
Parses, normalizes, and validates a connection string. Returns `[]` when the
|
|
452
|
+
config is valid. Checks include type correctness, numeric ranges, enum values,
|
|
453
|
+
unknown providers, Anthropic `temperature` + `top_p` mutual exclusion,
|
|
454
|
+
OpenAI reasoning-family normalization, and Bedrock model-family rules. Unknown
|
|
455
|
+
params are allowed by default so new model-specific schemas can pass through.
|
|
436
456
|
|
|
437
|
-
|
|
457
|
+
Pass `{ strict: true }` to report unknown providers or unknown params as
|
|
458
|
+
errors.
|
|
438
459
|
|
|
439
|
-
### `
|
|
460
|
+
### `createAiSdkProviderOptions(input, options?): AiSdkProviderOptionsResult`
|
|
440
461
|
|
|
441
|
-
|
|
462
|
+
Creates AI SDK `providerOptions` from a string, parsed config, or normalize
|
|
463
|
+
result. Import from `llm-strings/ai-sdk`.
|
|
442
464
|
|
|
443
|
-
###
|
|
465
|
+
### Provider helpers
|
|
444
466
|
|
|
445
|
-
|
|
467
|
+
Import from `llm-strings/providers`:
|
|
446
468
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
Returns `true` if the Bedrock model supports prompt caching (Claude and Nova models only).
|
|
469
|
+
| Export | Description |
|
|
470
|
+
| ------------------------------- | ------------------------------------------------------------------------------------- |
|
|
471
|
+
| `detectProvider(host)` | Detects provider from hostname. |
|
|
472
|
+
| `resolveHostAlias(host)` | Expands aliases and applies `LLM_STRINGS_*_HOST` overrides. |
|
|
473
|
+
| `detectBedrockModelFamily()` | Detects Anthropic, Meta, Amazon, Mistral, Cohere, or AI21 Bedrock families. |
|
|
474
|
+
| `detectGatewaySubProvider()` | Extracts provider prefix from gateway models like `anthropic/claude...`. |
|
|
475
|
+
| `isReasoningModel(model)` | Detects OpenAI GPT-5 and o-series reasoning models, including gateway-prefixed names. |
|
|
476
|
+
| `isGatewayProvider(provider)` | Returns true for `openrouter` and `vercel`. |
|
|
477
|
+
| `canHostOpenAIModels(provider)` | Returns true for providers that need OpenAI reasoning-model checks. |
|
|
478
|
+
| `bedrockSupportsCaching(model)` | Returns true for Bedrock Claude and Nova prompt caching support. |
|
|
458
479
|
|
|
459
480
|
### Constants
|
|
460
481
|
|
|
461
|
-
| Export | Description
|
|
462
|
-
| ----------------------------- |
|
|
463
|
-
| `ALIASES` | Shorthand
|
|
464
|
-
| `HOST_ALIASES` | Short provider host aliases
|
|
465
|
-
| `PROVIDER_PARAMS` | Canonical
|
|
466
|
-
| `PARAM_SPECS` | Validation rules
|
|
467
|
-
| `REASONING_MODEL_UNSUPPORTED` |
|
|
468
|
-
| `PROVIDER_META` |
|
|
469
|
-
| `CANONICAL_PARAM_SPECS` | Canonical param specs per provider
|
|
482
|
+
| Export | Description |
|
|
483
|
+
| ----------------------------- | ------------------------------------------------------------------------------- |
|
|
484
|
+
| `ALIASES` | Shorthand -> canonical param name mapping. |
|
|
485
|
+
| `HOST_ALIASES` | Short provider host aliases -> canonical API hosts. |
|
|
486
|
+
| `PROVIDER_PARAMS` | Canonical -> provider-specific param names, per provider. |
|
|
487
|
+
| `PARAM_SPECS` | Validation rules keyed by provider-specific param name. |
|
|
488
|
+
| `REASONING_MODEL_UNSUPPORTED` | Canonical params unsupported by OpenAI reasoning models. |
|
|
489
|
+
| `PROVIDER_META` | Provider metadata for UI integrations. |
|
|
490
|
+
| `CANONICAL_PARAM_SPECS` | Canonical param specs per provider, useful for building forms and settings UIs. |
|
|
470
491
|
|
|
471
492
|
## TypeScript
|
|
472
493
|
|
|
473
|
-
Full type definitions ship with the package:
|
|
474
|
-
|
|
475
494
|
```ts
|
|
476
|
-
// Core types from the main entry
|
|
477
495
|
import type {
|
|
478
496
|
LlmConnectionConfig,
|
|
479
|
-
NormalizeResult,
|
|
480
497
|
NormalizeChange,
|
|
481
498
|
NormalizeOptions,
|
|
499
|
+
NormalizeResult,
|
|
482
500
|
ValidateOptions,
|
|
483
501
|
ValidationIssue,
|
|
484
502
|
} from "llm-strings";
|
|
485
503
|
|
|
486
|
-
// Provider types from the providers sub-path
|
|
487
504
|
import type {
|
|
488
|
-
Provider,
|
|
489
505
|
BedrockModelFamily,
|
|
506
|
+
CanonicalParamSpec,
|
|
490
507
|
ParamSpec,
|
|
508
|
+
Provider,
|
|
491
509
|
ProviderMeta,
|
|
492
|
-
CanonicalParamSpec,
|
|
493
510
|
} from "llm-strings/providers";
|
|
494
511
|
```
|
|
495
512
|
|
|
496
|
-
##
|
|
497
|
-
|
|
498
|
-
The library exports metadata useful for building UIs — provider names, brand colors, and canonical parameter specs:
|
|
499
|
-
|
|
500
|
-
```ts
|
|
501
|
-
import { PROVIDER_META, CANONICAL_PARAM_SPECS } from "llm-strings/providers";
|
|
513
|
+
## Development
|
|
502
514
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
// Canonical param specs — useful for building config forms
|
|
510
|
-
CANONICAL_PARAM_SPECS.openai.temperature;
|
|
511
|
-
// → { type: "number", min: 0, max: 2, default: 0.7, description: "Controls randomness" }
|
|
512
|
-
|
|
513
|
-
CANONICAL_PARAM_SPECS.anthropic.effort;
|
|
514
|
-
// → { type: "enum", values: ["low", "medium", "high", "max"], default: "medium", description: "Thinking effort" }
|
|
515
|
+
```bash
|
|
516
|
+
pnpm install
|
|
517
|
+
pnpm test
|
|
518
|
+
pnpm run build
|
|
519
|
+
pnpm run lint
|
|
515
520
|
```
|
|
516
521
|
|
|
522
|
+
This package is intentionally small: pure TypeScript, zero runtime dependencies,
|
|
523
|
+
and focused tests for parsing, normalization, validation, provider metadata,
|
|
524
|
+
Bedrock behavior, gateway behavior, and AI SDK providerOptions.
|
|
525
|
+
|
|
517
526
|
## Contributing
|
|
518
527
|
|
|
519
|
-
|
|
528
|
+
Issues and pull requests are welcome. Good contributions include new provider
|
|
529
|
+
aliases, provider-specific validation rules, improved normalization mappings,
|
|
530
|
+
AI SDK providerOptions coverage, docs fixes, and real-world edge cases.
|
|
520
531
|
|
|
521
532
|
## License
|
|
522
533
|
|
|
523
|
-
MIT
|
|
534
|
+
MIT © Dan Levy
|
|
524
535
|
|
|
525
536
|
---
|
|
526
537
|
|
|
527
538
|
<div align="center">
|
|
528
539
|
|
|
529
|
-
**[
|
|
540
|
+
**[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)**
|
|
530
541
|
|
|
531
542
|
</div>
|