llm-strings 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +339 -330
- package/dist/ai-sdk.cjs +1146 -116
- package/dist/ai-sdk.d.cts +1 -1
- package/dist/ai-sdk.d.ts +1 -1
- package/dist/ai-sdk.js +95 -57
- package/dist/{chunk-OBLFZFNR.js → chunk-4BE457QA.js} +16 -28
- package/dist/{chunk-5YTG2NRX.js → chunk-6HQOCOQI.js} +1 -1
- package/dist/{chunk-DPVT3FFP.js → chunk-7Z7DCLZN.js} +14 -2
- package/dist/{chunk-76EFNZCF.js → chunk-PCJDQTOV.js} +520 -75
- package/dist/index.cjs +542 -94
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/dist/normalize.cjs +1065 -62
- package/dist/normalize.d.cts +1 -1
- package/dist/normalize.d.ts +1 -1
- package/dist/normalize.js +2 -2
- package/dist/parse.cjs +1075 -0
- package/dist/parse.d.cts +4 -4
- package/dist/parse.d.ts +4 -4
- package/dist/parse.js +2 -2
- package/dist/{provider-core-B934MuhJ.d.cts → provider-core-B1GMszQP.d.cts} +2 -3
- package/dist/{provider-core-B934MuhJ.d.ts → provider-core-B1GMszQP.d.ts} +2 -3
- package/dist/providers.cjs +520 -75
- package/dist/providers.d.cts +2 -2
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +3 -3
- package/dist/validate.cjs +542 -94
- package/dist/validate.d.cts +1 -1
- package/dist/validate.d.ts +1 -1
- package/dist/validate.js +4 -4
- package/package.json +16 -2
package/README.md
CHANGED
|
@@ -8,25 +8,47 @@
|
|
|
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
|
+
|
|
13
|
+
**Parse, normalize, validate, and build portable `llm://` URLs across AI providers.**
|
|
14
|
+
|
|
15
|
+
[Install](#install) · [Quick Start](#quick-start) · [Examples](#examples) · [Supported Providers](#supported-providers) · [API](#api-reference)
|
|
11
16
|
|
|
12
17
|
</div>
|
|
13
18
|
|
|
14
19
|
---
|
|
15
20
|
|
|
16
|
-

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