llm-strings 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +117 -45
  2. package/dist/ai-sdk.cjs +831 -0
  3. package/dist/ai-sdk.cjs.map +1 -0
  4. package/dist/ai-sdk.d.cts +27 -0
  5. package/dist/ai-sdk.d.ts +27 -0
  6. package/dist/ai-sdk.js +465 -0
  7. package/dist/ai-sdk.js.map +1 -0
  8. package/dist/{chunk-MPIHGH6L.js → chunk-2ARD4TFU.js} +5 -4
  9. package/dist/chunk-2ARD4TFU.js.map +1 -0
  10. package/dist/{chunk-FCEV23OT.js → chunk-BCOUH7LH.js} +9 -3
  11. package/dist/chunk-BCOUH7LH.js.map +1 -0
  12. package/dist/{chunk-UYMVUTLV.js → chunk-RPXK2A7O.js} +5 -9
  13. package/dist/chunk-RPXK2A7O.js.map +1 -0
  14. package/dist/{chunk-XID353H7.js → chunk-W4NIQY7M.js} +412 -52
  15. package/dist/chunk-W4NIQY7M.js.map +1 -0
  16. package/dist/index.cjs +1032 -12
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +1 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.js +9 -4
  21. package/dist/normalize.cjs +370 -4
  22. package/dist/normalize.cjs.map +1 -1
  23. package/dist/normalize.d.cts +1 -1
  24. package/dist/normalize.d.ts +1 -1
  25. package/dist/normalize.js +2 -2
  26. package/dist/parse.cjs +129 -5
  27. package/dist/parse.cjs.map +1 -1
  28. package/dist/parse.d.cts +5 -1
  29. package/dist/parse.d.ts +5 -1
  30. package/dist/parse.js +2 -1
  31. package/dist/{provider-core-DinpG40u.d.ts → provider-core-BiAl8MCV.d.cts} +20 -1
  32. package/dist/{provider-core-DinpG40u.d.cts → provider-core-BiAl8MCV.d.ts} +20 -1
  33. package/dist/providers.cjs +1145 -90
  34. package/dist/providers.cjs.map +1 -1
  35. package/dist/providers.d.cts +2 -2
  36. package/dist/providers.d.ts +2 -2
  37. package/dist/providers.js +379 -60
  38. package/dist/providers.js.map +1 -1
  39. package/dist/validate.cjs +1017 -6
  40. package/dist/validate.cjs.map +1 -1
  41. package/dist/validate.js +4 -4
  42. package/package.json +13 -2
  43. package/dist/chunk-FCEV23OT.js.map +0 -1
  44. package/dist/chunk-MGWGNZDJ.cjs +0 -116
  45. package/dist/chunk-MGWGNZDJ.cjs.map +0 -1
  46. package/dist/chunk-MPIHGH6L.js.map +0 -1
  47. package/dist/chunk-N6NVBE43.cjs +0 -37
  48. package/dist/chunk-N6NVBE43.cjs.map +0 -1
  49. package/dist/chunk-NSCBY4VD.cjs +0 -370
  50. package/dist/chunk-NSCBY4VD.cjs.map +0 -1
  51. package/dist/chunk-RSUXM42X.cjs +0 -180
  52. package/dist/chunk-RSUXM42X.cjs.map +0 -1
  53. package/dist/chunk-UYMVUTLV.js.map +0 -1
  54. package/dist/chunk-XID353H7.js.map +0 -1
package/README.md CHANGED
@@ -19,10 +19,9 @@
19
19
  llm://api.openai.com/gpt-5.2?temp=0.7&max=2000
20
20
  llm://my-app:sk-key-123@api.anthropic.com/claude-sonnet-4-5?cache=5m
21
21
  llm://bedrock-runtime.us-east-1.amazonaws.com/anthropic.claude-sonnet-4-5-20250929-v1:0?temp=0.5
22
+ llm://openai/gpt-5.2?temp=0.7&max=2000
22
23
  ```
23
24
 
24
-
25
-
26
25
  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.
27
26
 
28
27
  **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.
@@ -53,7 +52,11 @@ const issues = validate("llm://api.openai.com/gpt-5.2?temp=3.0");
53
52
  // → [{ param: "temperature", message: '"temperature" must be <= 2, got 3', severity: "error" }]
54
53
 
55
54
  // Build a connection string from a config object
56
- const str = build({ host: "api.openai.com", model: "gpt-5.2", params: { temperature: "0.7" } });
55
+ const str = build({
56
+ host: "api.openai.com",
57
+ model: "gpt-5.2",
58
+ params: { temperature: "0.7" },
59
+ });
57
60
  // → "llm://api.openai.com/gpt-5.2?temperature=0.7"
58
61
  ```
59
62
 
@@ -89,6 +92,7 @@ Your code stays the same. `normalize()` handles the parameter translation.
89
92
  - **Zero dependencies** — Pure TypeScript. No runtime baggage.
90
93
  - **Portable config** — Fits in an env var, a CLI flag, a config file, or a database column.
91
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.
92
96
 
93
97
  ## Format
94
98
 
@@ -96,13 +100,13 @@ Your code stays the same. `normalize()` handles the parameter translation.
96
100
  llm://[label[:apiKey]@]host/model[?params]
97
101
  ```
98
102
 
99
- | Part | Required | Description | Example |
100
- | ---------- | -------- | ----------------------------------------- | ------------------------------ |
101
- | `label` | No | App name or identifier | `my-app` |
102
- | `apiKey` | No | API key (in the password position) | `sk-proj-abc123` |
103
- | `host` | Yes | Provider's API hostname | `api.openai.com` |
104
- | `model` | Yes | Model name or ID | `gpt-5.2` |
105
- | `params` | No | Key-value config (query string) | `temp=0.7&max=2000` |
103
+ | Part | Required | Description | Example |
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` |
106
110
 
107
111
  ## Examples
108
112
 
@@ -129,6 +133,30 @@ for (const str of strings) {
129
133
  // google: { temperature: "0.7", maxOutputTokens: "2000", topP: "0.9" }
130
134
  ```
131
135
 
136
+ ### Short host aliases
137
+
138
+ Provider IDs can be used as short hostnames:
139
+
140
+ ```ts
141
+ import { parse, normalize } from "llm-strings";
142
+
143
+ const { config, provider } = normalize(parse("llm://openai/gpt-5.2?temp=0.7"));
144
+
145
+ config.host; // "api.openai.com"
146
+ provider; // "openai"
147
+ ```
148
+
149
+ Built-in aliases: `openai`, `anthropic`, `google`, `mistral`, `cohere`, `bedrock`, `openrouter`, `vercel`.
150
+
151
+ Set env overrides to point an alias at a regional or private endpoint:
152
+
153
+ ```sh
154
+ LLM_STRINGS_OPENAI_HOST="regional.openai.example.com"
155
+ LLM_STRINGS_BEDROCK_HOST="bedrock-runtime.us-west-2.amazonaws.com"
156
+ ```
157
+
158
+ The alternate form `LLM_STRINGS_HOST_OPENAI` is also supported. Overrides may include a scheme or path; only the host portion is used.
159
+
132
160
  ### Validating before calling the API
133
161
 
134
162
  Catch bad config before it hits the network:
@@ -138,7 +166,7 @@ import { validate } from "llm-strings";
138
166
 
139
167
  // Anthropic doesn't allow temperature + top_p together
140
168
  const issues = validate(
141
- "llm://api.anthropic.com/claude-sonnet-4-5?temp=0.7&top_p=0.9"
169
+ "llm://api.anthropic.com/claude-sonnet-4-5?temp=0.7&top_p=0.9",
142
170
  );
143
171
 
144
172
  for (const issue of issues) {
@@ -173,12 +201,40 @@ const response = await fetch(`https://${config.host}/v1/chat/completions`, {
173
201
  model: config.model,
174
202
  messages: [{ role: "user", content: "Hello!" }],
175
203
  ...Object.fromEntries(
176
- Object.entries(config.params).map(([k, v]) => [k, isNaN(+v) ? v : +v])
204
+ Object.entries(config.params).map(([k, v]) => [k, isNaN(+v) ? v : +v]),
177
205
  ),
178
206
  }),
179
207
  });
180
208
  ```
181
209
 
210
+ ### AI SDK providerOptions
211
+
212
+ The AI SDK adapter is available as a separate subpath so you can load it only
213
+ where you need it:
214
+
215
+ ```ts
216
+ import { parse } from "llm-strings";
217
+
218
+ const { createAiSdkProviderOptions } = await import("llm-strings/ai-sdk");
219
+
220
+ const { providerOptions } = createAiSdkProviderOptions(
221
+ parse("llm://api.anthropic.com/claude-sonnet-4-5?cache=1h&effort=max"),
222
+ );
223
+
224
+ // {
225
+ // anthropic: {
226
+ // cacheControl: { type: "ephemeral", ttl: "1h" },
227
+ // effort: "max"
228
+ // }
229
+ // }
230
+ ```
231
+
232
+ Common generation settings like `temperature`, `topP`, and `maxOutputTokens`
233
+ belong on the AI SDK call itself, so this helper only emits provider-specific
234
+ configuration such as Anthropic cache control, Bedrock cache points, OpenAI
235
+ reasoning options, Mistral `safePrompt`, OpenRouter reasoning, and Vercel AI
236
+ Gateway routing options.
237
+
182
238
  ### Prompt caching (Anthropic & Bedrock)
183
239
 
184
240
  ```ts
@@ -186,21 +242,21 @@ import { parse, normalize } from "llm-strings";
186
242
 
187
243
  // cache=true → cache_control=ephemeral
188
244
  const { config } = normalize(
189
- parse("llm://api.anthropic.com/claude-sonnet-4-5?max=4096&cache=true")
245
+ parse("llm://api.anthropic.com/claude-sonnet-4-5?max=4096&cache=true"),
190
246
  );
191
247
  // → params: { max_tokens: "4096", cache_control: "ephemeral" }
192
248
 
193
249
  // cache=5m → cache_control=ephemeral + cache_ttl=5m
194
250
  const { config: withTtl } = normalize(
195
- parse("llm://api.anthropic.com/claude-sonnet-4-5?max=4096&cache=5m")
251
+ parse("llm://api.anthropic.com/claude-sonnet-4-5?max=4096&cache=5m"),
196
252
  );
197
253
  // → params: { max_tokens: "4096", cache_control: "ephemeral", cache_ttl: "5m" }
198
254
 
199
255
  // Works on Bedrock too (Claude and Nova models)
200
256
  const { config: bedrock } = normalize(
201
257
  parse(
202
- "llm://bedrock-runtime.us-east-1.amazonaws.com/anthropic.claude-sonnet-4-5-20250929-v1:0?cache=1h"
203
- )
258
+ "llm://bedrock-runtime.us-east-1.amazonaws.com/anthropic.claude-sonnet-4-5-20250929-v1:0?cache=1h",
259
+ ),
204
260
  );
205
261
  // → params: { cache_control: "ephemeral", cache_ttl: "1h" }
206
262
  ```
@@ -214,9 +270,9 @@ import { parse, normalize } from "llm-strings";
214
270
 
215
271
  const { changes } = normalize(
216
272
  parse(
217
- "llm://generativelanguage.googleapis.com/gemini-3-flash-preview?temp=0.7&max=2000&topp=0.9"
273
+ "llm://generativelanguage.googleapis.com/gemini-3-flash-preview?temp=0.7&max=2000&topp=0.9",
218
274
  ),
219
- { verbose: true }
275
+ { verbose: true },
220
276
  );
221
277
 
222
278
  for (const c of changes) {
@@ -251,7 +307,7 @@ import { parse, normalize } from "llm-strings";
251
307
  import { detectBedrockModelFamily } from "llm-strings/providers";
252
308
 
253
309
  const config = parse(
254
- "llm://bedrock-runtime.us-east-1.amazonaws.com/us.anthropic.claude-sonnet-4-5-20250929-v1:0?temp=0.5&max=4096"
310
+ "llm://bedrock-runtime.us-east-1.amazonaws.com/us.anthropic.claude-sonnet-4-5-20250929-v1:0?temp=0.5&max=4096",
255
311
  );
256
312
 
257
313
  detectBedrockModelFamily(config.model);
@@ -269,7 +325,7 @@ import { parse, normalize, validate } from "llm-strings";
269
325
 
270
326
  // OpenRouter proxies to any provider
271
327
  const { config } = normalize(
272
- parse("llm://openrouter.ai/anthropic/claude-sonnet-4-5?temp=0.7&max=2000")
328
+ parse("llm://openrouter.ai/anthropic/claude-sonnet-4-5?temp=0.7&max=2000"),
273
329
  );
274
330
  // → params: { temperature: "0.7", max_tokens: "2000" }
275
331
 
@@ -298,19 +354,19 @@ Gateways like OpenRouter and Vercel route to any upstream provider. Bedrock host
298
354
 
299
355
  Use these shortcuts in your connection strings — they expand automatically during normalization:
300
356
 
301
- | Shorthand | Canonical |
302
- | -------------------------------------------------------------------- | -------------------- |
303
- | `temp` | `temperature` |
304
- | `max`, `max_out`, `max_output`, `max_output_tokens`, `maxTokens`, `maxOutputTokens`, `max_completion_tokens` | `max_tokens` |
305
- | `topp`, `topP`, `nucleus` | `top_p` |
306
- | `topk`, `topK` | `top_k` |
307
- | `freq`, `freq_penalty`, `frequencyPenalty`, `repetition_penalty` | `frequency_penalty` |
308
- | `pres`, `pres_penalty`, `presencePenalty` | `presence_penalty` |
309
- | `stop_sequences`, `stopSequences`, `stop_sequence` | `stop` |
310
- | `random_seed`, `randomSeed` | `seed` |
311
- | `candidateCount`, `candidate_count`, `num_completions` | `n` |
312
- | `reasoning`, `reasoning_effort` | `effort` |
313
- | `cache_control`, `cacheControl`, `cachePoint`, `cache_point` | `cache` |
357
+ | Shorthand | Canonical |
358
+ | ------------------------------------------------------------------------------------------------------------ | ------------------- |
359
+ | `temp` | `temperature` |
360
+ | `max`, `max_out`, `max_output`, `max_output_tokens`, `maxTokens`, `maxOutputTokens`, `max_completion_tokens` | `max_tokens` |
361
+ | `topp`, `topP`, `nucleus` | `top_p` |
362
+ | `topk`, `topK` | `top_k` |
363
+ | `freq`, `freq_penalty`, `frequencyPenalty`, `repetition_penalty` | `frequency_penalty` |
364
+ | `pres`, `pres_penalty`, `presencePenalty` | `presence_penalty` |
365
+ | `stop_sequences`, `stopSequences`, `stop_sequence` | `stop` |
366
+ | `random_seed`, `randomSeed` | `seed` |
367
+ | `candidateCount`, `candidate_count`, `num_completions` | `n` |
368
+ | `reasoning`, `reasoning_effort` | `effort` |
369
+ | `cache_control`, `cacheControl`, `cachePoint`, `cache_point` | `cache` |
314
370
 
315
371
  ## Sub-path Imports
316
372
 
@@ -320,7 +376,14 @@ For smaller bundles, import only what you need:
320
376
  import { parse, build } from "llm-strings/parse";
321
377
  import { normalize } from "llm-strings/normalize";
322
378
  import { validate } from "llm-strings/validate";
323
- import { detectProvider, ALIASES, PROVIDER_PARAMS, PARAM_SPECS } from "llm-strings/providers";
379
+ import {
380
+ detectProvider,
381
+ resolveHostAlias,
382
+ ALIASES,
383
+ HOST_ALIASES,
384
+ PROVIDER_PARAMS,
385
+ PARAM_SPECS,
386
+ } from "llm-strings/providers";
324
387
  ```
325
388
 
326
389
  All sub-paths ship ESM + CJS with full type declarations.
@@ -367,6 +430,10 @@ validate("llm://custom-api.com/my-model?temp=0.5", { strict: true });
367
430
 
368
431
  Identifies the provider from a hostname string.
369
432
 
433
+ ### `resolveHostAlias(host): HostResolution`
434
+
435
+ 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.
436
+
370
437
  ### `detectBedrockModelFamily(model): BedrockModelFamily | undefined`
371
438
 
372
439
  Identifies the model family (anthropic, meta, amazon, mistral, cohere, ai21) from a Bedrock model ID. Handles cross-region (`us.`, `eu.`, `apac.`) and global inference profiles.
@@ -393,15 +460,16 @@ Returns `true` if the Bedrock model supports prompt caching (Claude and Nova mod
393
460
 
394
461
  ### Constants
395
462
 
396
- | Export | Description |
397
- | --- | --- |
398
- | `ALIASES` | Shorthand → canonical param name mapping |
399
- | `PROVIDER_PARAMS` | Canonical provider-specific param names, per provider |
400
- | `PARAM_SPECS` | Validation rules (type, min/max, enum) per provider, keyed by provider-specific param name |
401
- | `REASONING_MODEL_UNSUPPORTED` | Set of canonical params unsupported by reasoning models |
402
- | `PROVIDER_META` | Array of provider metadata (id, name, host, brand color) for UI integrations |
403
- | `MODELS` | Suggested model IDs per provider |
404
- | `CANONICAL_PARAM_SPECS` | Canonical param specs per provider with descriptions — useful for building UIs |
463
+ | Export | Description |
464
+ | ----------------------------- | ------------------------------------------------------------------------------------------ |
465
+ | `ALIASES` | Shorthand → canonical param name mapping |
466
+ | `HOST_ALIASES` | Short provider host aliases canonical API hosts |
467
+ | `PROVIDER_PARAMS` | Canonical provider-specific param names, per provider |
468
+ | `PARAM_SPECS` | Validation rules (type, min/max, enum) per provider, keyed by provider-specific param name |
469
+ | `REASONING_MODEL_UNSUPPORTED` | Set of canonical params unsupported by reasoning models |
470
+ | `PROVIDER_META` | Array of provider metadata (id, name, host, brand color) for UI integrations |
471
+ | `MODELS` | Suggested model IDs per provider |
472
+ | `CANONICAL_PARAM_SPECS` | Canonical param specs per provider with descriptions — useful for building UIs |
405
473
 
406
474
  ## TypeScript
407
475
 
@@ -433,7 +501,11 @@ import type {
433
501
  The library exports metadata useful for building UIs — provider names, brand colors, suggested models, and canonical parameter specs:
434
502
 
435
503
  ```ts
436
- import { PROVIDER_META, MODELS, CANONICAL_PARAM_SPECS } from "llm-strings/providers";
504
+ import {
505
+ PROVIDER_META,
506
+ MODELS,
507
+ CANONICAL_PARAM_SPECS,
508
+ } from "llm-strings/providers";
437
509
 
438
510
  // Provider display info
439
511
  PROVIDER_META.forEach((p) => console.log(`${p.name}: ${p.host} (${p.color})`));
@@ -442,7 +514,7 @@ PROVIDER_META.forEach((p) => console.log(`${p.name}: ${p.host} (${p.color})`));
442
514
  // ...
443
515
 
444
516
  // Suggested models per provider
445
- MODELS.openai; // → ["gpt-5.2", "gpt-5.2-pro", "gpt-4.1", "gpt-4.1-mini", ...]
517
+ MODELS.openai; // → ["gpt-5.2", "gpt-5.2-pro", "gpt-4.1", "gpt-4.1-mini", ...]
446
518
  MODELS.anthropic; // → ["claude-opus-4-6", "claude-sonnet-4-6", "claude-sonnet-4-5", ...]
447
519
 
448
520
  // Canonical param specs — useful for building config forms