@x12i/ai-profiles 2.0.1 → 2.1.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.
Files changed (83) hide show
  1. package/README.md +148 -45
  2. package/dist/buildResolvedProfile.d.ts.map +1 -1
  3. package/dist/buildResolvedProfile.js +7 -0
  4. package/dist/buildResolvedProfile.js.map +1 -1
  5. package/dist/costTiers.d.ts +4 -0
  6. package/dist/costTiers.d.ts.map +1 -0
  7. package/dist/costTiers.js +20 -0
  8. package/dist/costTiers.js.map +1 -0
  9. package/dist/data/models-profiles.bak.json +2336 -0
  10. package/dist/data/models-profiles.json +166 -14
  11. package/dist/data/profiles-shortcuts.json +86 -34
  12. package/dist/errors.d.ts +1 -1
  13. package/dist/errors.d.ts.map +1 -1
  14. package/dist/errors.js.map +1 -1
  15. package/dist/index.d.ts +10 -2
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +7 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/isKnownProfileChoice.d.ts +6 -0
  20. package/dist/isKnownProfileChoice.d.ts.map +1 -0
  21. package/dist/isKnownProfileChoice.js +11 -0
  22. package/dist/isKnownProfileChoice.js.map +1 -0
  23. package/dist/listAIProfileChoices.d.ts +6 -0
  24. package/dist/listAIProfileChoices.d.ts.map +1 -0
  25. package/dist/listAIProfileChoices.js +50 -0
  26. package/dist/listAIProfileChoices.js.map +1 -0
  27. package/dist/listAIProfiles.d.ts.map +1 -1
  28. package/dist/listAIProfiles.js +23 -0
  29. package/dist/listAIProfiles.js.map +1 -1
  30. package/dist/modalityPolicy.d.ts +4 -1
  31. package/dist/modalityPolicy.d.ts.map +1 -1
  32. package/dist/modalityPolicy.js +82 -3
  33. package/dist/modalityPolicy.js.map +1 -1
  34. package/dist/modelInputFallback.d.ts.map +1 -1
  35. package/dist/modelInputFallback.js +12 -2
  36. package/dist/modelInputFallback.js.map +1 -1
  37. package/dist/normalizeKey.d.ts +6 -0
  38. package/dist/normalizeKey.d.ts.map +1 -1
  39. package/dist/normalizeKey.js +16 -0
  40. package/dist/normalizeKey.js.map +1 -1
  41. package/dist/profileChoiceKey.d.ts +37 -0
  42. package/dist/profileChoiceKey.d.ts.map +1 -0
  43. package/dist/profileChoiceKey.js +96 -0
  44. package/dist/profileChoiceKey.js.map +1 -0
  45. package/dist/profileDiscoveryMatch.d.ts +15 -0
  46. package/dist/profileDiscoveryMatch.d.ts.map +1 -0
  47. package/dist/profileDiscoveryMatch.js +18 -0
  48. package/dist/profileDiscoveryMatch.js.map +1 -0
  49. package/dist/resolveAIProfile.d.ts +4 -5
  50. package/dist/resolveAIProfile.d.ts.map +1 -1
  51. package/dist/resolveAIProfile.js +51 -81
  52. package/dist/resolveAIProfile.js.map +1 -1
  53. package/dist/resolveAIProfileByTags.d.ts +2 -2
  54. package/dist/resolveAIProfileByTags.d.ts.map +1 -1
  55. package/dist/resolveAIProfileByTags.js +28 -10
  56. package/dist/resolveAIProfileByTags.js.map +1 -1
  57. package/dist/resolveAIProfileWithCostAlternatives.d.ts +17 -0
  58. package/dist/resolveAIProfileWithCostAlternatives.d.ts.map +1 -0
  59. package/dist/resolveAIProfileWithCostAlternatives.js +129 -0
  60. package/dist/resolveAIProfileWithCostAlternatives.js.map +1 -0
  61. package/dist/resolveCatalogModel.d.ts +7 -0
  62. package/dist/resolveCatalogModel.d.ts.map +1 -0
  63. package/dist/resolveCatalogModel.js +34 -0
  64. package/dist/resolveCatalogModel.js.map +1 -0
  65. package/dist/resolveSecondaryModel.d.ts.map +1 -1
  66. package/dist/resolveSecondaryModel.js +17 -8
  67. package/dist/resolveSecondaryModel.js.map +1 -1
  68. package/dist/secondaryModel.d.ts +0 -5
  69. package/dist/secondaryModel.d.ts.map +1 -1
  70. package/dist/secondaryModel.js +1 -13
  71. package/dist/secondaryModel.js.map +1 -1
  72. package/dist/types.d.ts +87 -8
  73. package/dist/types.d.ts.map +1 -1
  74. package/dist/validateProfileCatalogLinkage.d.ts.map +1 -1
  75. package/dist/validateProfileCatalogLinkage.js +2 -1
  76. package/dist/validateProfileCatalogLinkage.js.map +1 -1
  77. package/dist/validation/validateModelsProfilesJson.d.ts.map +1 -1
  78. package/dist/validation/validateModelsProfilesJson.js +11 -7
  79. package/dist/validation/validateModelsProfilesJson.js.map +1 -1
  80. package/dist/vendorPolicy.d.ts.map +1 -1
  81. package/dist/vendorPolicy.js +1 -6
  82. package/dist/vendorPolicy.js.map +1 -1
  83. package/package.json +1 -1
package/README.md CHANGED
@@ -104,6 +104,94 @@ await resolveAIProfile("cyber", {
104
104
  await listAIProfiles({ catalogLane: "image" }); // → vision only
105
105
  ```
106
106
 
107
+ ### Cost tiers (optional)
108
+
109
+ If you want to restrict model selection by price, you can either set an explicit `costCapPer1M`, or use a named `costTier`.
110
+
111
+ ```ts
112
+ import { resolveAIProfile } from "@x12i/ai-profiles";
113
+
114
+ // Tier-based (default tiers: tier1=$0.5/1M output, tier2=$3, tier3=$10, tier4=$30)
115
+ const cheapTier1 = await resolveAIProfile("balanced", {
116
+ catalogLane: "text",
117
+ costTier: "tier1",
118
+ });
119
+
120
+ // Override tiers (per-tier caps can be maxOutput/maxInput/maxBlended)
121
+ const customTier = await resolveAIProfile("balanced", {
122
+ catalogLane: "text",
123
+ costTier: "budget",
124
+ costTiers: [{ key: "budget", cap: { maxOutput: 0.5 } }],
125
+ });
126
+
127
+ // Explicit caps always win if both are provided
128
+ const explicitCap = await resolveAIProfile("balanced", {
129
+ catalogLane: "text",
130
+ costTier: "tier1",
131
+ costCapPer1M: { maxBlended: 2 },
132
+ });
133
+ ```
134
+
135
+ ### Alternatives by cost tier
136
+
137
+ When you want a profile’s “same intent, different price points”, use:
138
+
139
+ ```ts
140
+ import { resolveAIProfileWithCostAlternatives } from "@x12i/ai-profiles";
141
+
142
+ const { primary, alternativesByCostTier } =
143
+ await resolveAIProfileWithCostAlternatives("deep", {
144
+ catalogLane: "text",
145
+ tiers: [
146
+ { key: "tier1", cap: { maxOutput: 0.5 } },
147
+ { key: "tier2", cap: { maxOutput: 3 } },
148
+ { key: "tier3", cap: { maxOutput: 10 } },
149
+ ],
150
+ });
151
+
152
+ // alternativesByCostTier: [{ tier, resolved|null, reason? }, ...]
153
+ ```
154
+
155
+ ### Focus filters (catalog-derived)
156
+
157
+ You can filter choices (and optionally profile listings) by catalog-derived capabilities.
158
+
159
+ ```ts
160
+ import { listAIProfiles, resolveAIProfile } from "@x12i/ai-profiles";
161
+
162
+ // Preset focus filter
163
+ const reasoningModel = await resolveAIProfile("deep", {
164
+ catalogLane: "text",
165
+ focus: "reasoning",
166
+ });
167
+
168
+ // Explicit capability filter
169
+ const structured = await resolveAIProfile("json", {
170
+ catalogLane: "text",
171
+ capabilityFilter: { structuredOutput: true },
172
+ });
173
+
174
+ // Filter profile discovery to profiles with at least one matching choice
175
+ const reasoningProfiles = await listAIProfiles({
176
+ source: "bundled",
177
+ focus: "reasoning",
178
+ });
179
+ ```
180
+
181
+ ### Reasoning model flag (always communicated)
182
+
183
+ Every resolved primary and secondary includes a stable boolean:
184
+
185
+ ```ts
186
+ const resolved = await resolveAIProfile("cheap", {
187
+ catalogLane: "text",
188
+ includeSecondary: true,
189
+ });
190
+
191
+ resolved.modelSignals.isReasoningModel; // boolean
192
+ resolved.secondary?.modelSignals.isReasoningModel; // boolean
193
+ ```
194
+
107
195
  Registry fields on each choice—`runtime` (`reasoningEffort`, `toolPolicy`, `outputMode`, `instructionTier`, `backend`), `modelStatus` (`verified` | `predicted`), `api` (vendor + OpenRouter slugs), and `reason`—document *why* that model backs the choice. **Pricing and capabilities** come from `models-catalog.json` at resolve time. Profile-level `requiredCapabilities` describes intent for future dynamic selection (Optimixer). Consumers use `resolveAIProfile` to materialize the merged result.
108
196
 
109
197
  ## Install
@@ -126,13 +214,14 @@ npm install @x12i/ai-profiles
126
214
  | `loadModelsCatalog(options?)` | No (async) | Unified models catalog (`auto` / `remote` / `bundled`, same cache pattern as profiles) |
127
215
  | `loadBundledModelsCatalog()` | Yes | Package-shipped `models-catalog.json` only |
128
216
  | `loadBundledModelsRegistry()` | Yes | Package-shipped `models-registry.json` (linkage index) |
129
- | `listAIShortcuts()` | Yes | Shortcut table: `{ key, profile, choice?, description? }[]` |
130
- | `resolveAIProfile(input, options?)` | No (async) | Resolve profile/shortcut/alias → model, pricing, runtime, canonical `profile` key. Pass `includeSecondary: true` to attach `secondary`. |
217
+ | `listAIProfileChoices(options?)` | No (async) | List explicit `profile/choice` keys for strict pickers and stored config |
218
+ | `listAIShortcuts()` | Yes | Shortcut table: `{ key, profile, choice, description? }[]` |
219
+ | `isKnownProfileChoice(input)` | Yes (bundled only) | Whether input is a known `profile/choice` key or shortcut |
220
+ | `resolveAIProfile(input, options?)` | No (async) | Resolve an explicit `profile/choice` key (or shortcut) → model, pricing, runtime. Pass `includeSecondary: true` to attach `secondary`. |
131
221
  | `resolveSecondaryModel(input, options?)` | No (async) | Resolve primary choice + optional companion `secondary` from profile `secondary` refs |
132
222
  | `getSecondaryForResolvedProfile(resolved, registry, catalog?)` | Yes | Secondary for an already-resolved primary (no extra I/O when catalog is passed) |
133
223
  | `listProfileSecondaries(profileKey, registry)` | Yes | List per-choice `secondary` declarations on a profile |
134
224
  | `resolveAIProfileByTags(tags, options?)` | No (async) | Pick best profile by tag overlap (partial match OK), then resolve |
135
- | `isKnownProfileOrShortcut(input)` | Yes (bundled only) | Whether input is a known primary key, shortcut, or alias |
136
225
  | `scoreProfileTags` / `rankProfilesByTags` | Yes | Tag overlap scoring for discovery and custom UIs |
137
226
  | `AIProfilesError` | — | Typed errors (`UNKNOWN_PROFILE`, …) |
138
227
 
@@ -142,6 +231,7 @@ Use these when callers pass **raw model ids or OpenRouter slugs**, not profile n
142
231
 
143
232
  | Export | Sync? | Purpose |
144
233
  |--------|-------|---------|
234
+ | `resolveCatalogModel(input, options?)` | No (async) | Resolve a model SKU or OpenRouter slug via `models-catalog.json` (strict; no profile intent) |
145
235
  | `resolveModelIdentity(input, options?)` | Yes | Given a bare id or `vendor/slug`, return `{ provider, modelId, invocation? }` via bundled registry + catalog fallback |
146
236
  | `buildModelInvocation(provider, modelId)` | Yes | `{ direct, openrouter }` endpoints for a provider hint + model string |
147
237
  | `buildDirectInvocation(provider, modelId)` | Yes | Vendor-direct `{ provider, modelId }`; splits prefixed slugs for all vendors |
@@ -183,14 +273,19 @@ Validate with `src/data/models-profiles.schema.json`. Maintainer scripts: `npm r
183
273
 
184
274
  ```ts
185
275
  import {
186
- isKnownProfileOrShortcut,
187
276
  listAIProfiles,
277
+ listAIProfileChoices,
188
278
  listAIShortcuts,
279
+ isKnownProfileChoice,
189
280
  resolveAIProfile,
281
+ resolveCatalogModel,
190
282
  } from "@x12i/ai-profiles";
191
283
 
192
284
  const profiles = await listAIProfiles();
193
- const model = await resolveAIProfile("cheap");
285
+ const choices = await listAIProfileChoices();
286
+
287
+ // Strict lookup key: profile/choice
288
+ const model = await resolveAIProfile("cheap/default", { catalogLane: "text" });
194
289
 
195
290
  console.log(model.profile); // canonical primary key: cheap
196
291
  console.log(model.provider); // "openrouter" by default for remote profiles
@@ -202,6 +297,15 @@ console.log(model.requiredCapabilities); // profile intent
202
297
  console.log(model.capabilities); // contextWindow, supportsTools, …
203
298
  console.log(model.instructionTier);
204
299
  console.log(model.backend);
300
+
301
+ // SKU lookup (catalog), not a profile
302
+ const sku = await resolveCatalogModel("google/gemini-2.5-flash-lite", {
303
+ source: "bundled",
304
+ useOpenRouter: false,
305
+ });
306
+
307
+ console.log(isKnownProfileChoice("cheap/default")); // true
308
+ console.log(isKnownProfileChoice("cheap")); // false
205
309
  ```
206
310
 
207
311
  ## Registry statistics
@@ -236,60 +340,54 @@ Each **profile** has exactly one **short primary key** (e.g. `balanced`, `cyber`
236
340
 
237
341
  **Tags** are short (2–4 chars), many per profile (`cyb`, `eco`, `ds`, …). Each profile has a **unique tag set**. Use `listAIProfiles({ tags })` (sorted by best match) or `resolveAIProfileByTags(['cyb', 'eco'])` — partial overlap is OK; the profile with the most matching tags wins.
238
342
 
239
- **Shortcuts** (`profiles-shortcuts.json`) are a second registry of intent names. A shortcut points at a profile and may pin a **choice** (e.g. `cheapest` → `cheap` + `google_floor`, `final-answer` → `vol` + `final`).
343
+ **Shortcuts** (`profiles-shortcuts.json`) are a second registry of intent names. A shortcut is a **named binding** to a specific `profile/choice` (e.g. `cheapest` → `cheap/google_floor`, `final-answer` → `vol/final`).
240
344
 
241
- Model SKU strings (e.g. `deepseek-v4-flash`, `google/gemini-2.5-flash-lite`) are **not** profiles, aliases, or shortcuts — they resolve via catalog fallback to `resolutionKind: "model"`.
345
+ Model SKU strings (e.g. `deepseek-v4-flash`, `google/gemini-2.5-flash-lite`) are **not** profiles or shortcuts — resolve them via `resolveCatalogModel(...)`.
242
346
 
243
347
  The same string can appear as both an alias and a shortcut. That is intentional.
244
348
 
245
- ### Resolution order
349
+ ### Resolution behavior (strict)
246
350
 
247
- For `resolveAIProfile(input)` and `isKnownProfileOrShortcut(input)` (bundled path uses the same rules):
351
+ `resolveAIProfile(input)` accepts only:
248
352
 
249
- 1. **Primary key** — input matches a profile id → that profile, default choice (unless `options.choice` is set).
250
- 2. **Shortcut** — input matches a shortcut key → shortcut’s profile and choice (shortcut overrides alias when both exist).
251
- 3. **Alias** — input matches an entry in some profile’s `aliases` → that profile, default choice.
353
+ 1. **Composite key** — `profile/choice` (e.g. `cheap/default`)
354
+ 2. **Shortcut** — a shortcut key that pins a choice (all bundled shortcuts do)
252
355
 
253
- Input is normalized (trimmed, lowercased) before matching.
356
+ Profile-only inputs and profile aliases are **discovery-only**; they are not valid for `resolveAIProfile`.
357
+
358
+ Input is normalized (trimmed, lowercased) before matching. Composite keys accept **`/` or `\`** as the separator on input (`cyber\default` → `cyber/default`); listed and resolved keys always use `/`. **Profile, choice, and shortcut segment names treat `-` and `_` as equivalent** (`cheap/google-floor` → `cheap/google_floor`).
254
359
 
255
360
  ### Examples
256
361
 
257
362
  ```ts
258
- // Primary key
259
- await resolveAIProfile("balanced"); // profile: balanced
260
-
261
- // Alias only (on cheap in bundled data)
262
- await resolveAIProfile("cost-sensitive"); // profile: cheap, choice: default
263
-
264
- // Alias shared with shortcut — shortcut wins if it pins a choice
265
- await resolveAIProfile("default"); // profile: balanced (via default shortcut)
363
+ // Composite key
364
+ await resolveAIProfile("balanced/default", { catalogLane: "text" });
266
365
 
267
366
  // Shortcut with explicit choice
268
- await resolveAIProfile("cheapest"); // profile: cheap, choice: google_floor
367
+ await resolveAIProfile("cheapest", { catalogLane: "text" }); // cheap/google_floor
269
368
 
270
369
  // Tag-based pick (partial overlap OK)
271
- await resolveAIProfileByTags(["cyb", "eco", "ds"]); // profile: cyber
370
+ await resolveAIProfileByTags(["cyb", "eco", "ds"], { catalogLane: "text" }); // cyber/<auto>
272
371
 
273
372
  // Model SKU → catalog, not a profile
274
- await resolveAIProfile("deepseek-v4-flash", { catalogLane: "text" }); // resolutionKind: "model"
373
+ await resolveCatalogModel("deepseek-v4-flash", { source: "bundled" }); // resolutionKind: "model"
275
374
  ```
276
375
 
277
376
  `listAIProfiles()` returns each profile’s `aliases` so UIs can show friendly labels. `listAIShortcuts()` lists shortcut keys separately (not duplicated inside `listAIProfiles()`).
278
377
 
279
378
  ## Sync validation (bundled registry)
280
379
 
281
- Use **`isKnownProfileOrShortcut(input)`** before run/execute or on first paint when the remote registry may not be loaded yet. It reads the **bundled** JSON only (no network, no in-memory cache race).
380
+ Use **`isKnownProfileChoice(input)`** before run/execute or on first paint when the remote registry may not be loaded yet. It reads the **bundled** JSON only (no network, no in-memory cache race).
282
381
 
283
382
  ```ts
284
383
  const canRun =
285
- isKnownProfileOrShortcut(aiProfile) &&
286
- isKnownProfileOrShortcut(choiceProfile) &&
287
- isKnownProfileOrShortcut(fallbackProfile);
384
+ isKnownProfileChoice(aiProfileKey) &&
385
+ isKnownProfileChoice(fallbackKey);
288
386
  ```
289
387
 
290
- Accepts **primary keys**, **shortcuts**, and **profile aliases**. Unknown strings return `false`.
388
+ Accepts **`profile/choice` keys** and **shortcuts**. Unknown strings return `false`.
291
389
 
292
- After validation, call `resolveAIProfile` (usually `source: "auto"` or `"bundled"`) to get the canonical `resolved.profile` primary key and model details.
390
+ After validation, call `resolveAIProfile` (usually `source: "auto"` or `"bundled"`) to get the canonical `resolved.profile` and the concrete model details.
293
391
 
294
392
  ### UI guidance
295
393
 
@@ -297,11 +395,11 @@ After validation, call `resolveAIProfile` (usually `source: "auto"` or `"bundled
297
395
  - **Shortcut picker** (optional): `listAIShortcuts()` → use `key` as the value.
298
396
  - **Stored config**: any accepted name (primary, alias, or shortcut) is valid; prefer primary keys for new data if you want one canonical form in your own schema.
299
397
 
300
- ## Force a choice
398
+ ## Pick a specific model implementation (choice)
301
399
 
302
400
  ```ts
303
- const model = await resolveAIProfile("cheap", {
304
- choice: "anthropic_cheap",
401
+ const model = await resolveAIProfile("cheap/anthropic_cheap", {
402
+ catalogLane: "text",
305
403
  });
306
404
  ```
307
405
 
@@ -320,9 +418,9 @@ Supported today: **OpenRouter** and **vendor-direct**. Azure and AWS routing are
320
418
  ### OpenRouter (default)
321
419
 
322
420
  ```ts
323
- const resolved = await resolveAIProfile("cheap");
421
+ const resolved = await resolveAIProfile("cheap/default", { catalogLane: "text" });
324
422
  // or explicitly:
325
- await resolveAIProfile("cheap", { useOpenRouter: true });
423
+ await resolveAIProfile("cheap/default", { catalogLane: "text", useOpenRouter: true });
326
424
 
327
425
  // resolved.provider === "openrouter"
328
426
  // resolved.modelId === "google/gemini-3.1-flash-lite"
@@ -340,7 +438,7 @@ Do **not** copy OpenRouter slugs into app config (`preActionModel`, env vars, et
340
438
 
341
439
  ```ts
342
440
  // Good — profile pointer + resolver
343
- const pre = await resolveAIProfile("cheap");
441
+ const pre = await resolveAIProfile("cheap/default", { catalogLane: "text" });
344
442
  preActionModel: pre.modelId; // "google/gemini-2.5-flash-lite"
345
443
 
346
444
  // Bad — stale transport slug from an old catalog page or doc
@@ -352,7 +450,10 @@ Use `assertStableOpenRouterSlug(slug)` before outbound OpenRouter calls when you
352
450
  ### Vendor-direct
353
451
 
354
452
  ```ts
355
- const resolved = await resolveAIProfile("cheap", { useOpenRouter: false });
453
+ const resolved = await resolveAIProfile("cheap/default", {
454
+ catalogLane: "text",
455
+ useOpenRouter: false,
456
+ });
356
457
 
357
458
  // resolved.provider === "google"
358
459
  // resolved.modelId === "gemini-2.5-flash-lite"
@@ -375,9 +476,9 @@ When `useOpenRouter` is omitted from `resolveAIProfile`, the env value is used.
375
476
 
376
477
  ```ts
377
478
  process.env.USE_OPENROUTER = "0";
378
- await resolveAIProfile("cheap"); // vendor-direct
479
+ await resolveAIProfile("cheap/default", { catalogLane: "text" }); // vendor-direct
379
480
 
380
- await resolveAIProfile("cheap", { useOpenRouter: true }); // still OpenRouter
481
+ await resolveAIProfile("cheap/default", { catalogLane: "text", useOpenRouter: true }); // still OpenRouter
381
482
  ```
382
483
 
383
484
  Helper exports:
@@ -523,7 +624,8 @@ Top-level `provider` / `modelId` / `routing` remain the **active** path selected
523
624
  Restrict resolution to specific vendors (auto-picks within the profile when the default is outside the set). **Leading vendors** (`openai`, `anthropic`, `google`, `deepseek`, `minimax`, `xai`) are **preferred** during auto-pick, not forced — explicit `choice` still honors `together` and other providers.
524
625
 
525
626
  ```ts
526
- await resolveAIProfile("balanced", {
627
+ await resolveAIProfile("balanced/default", {
628
+ catalogLane: "text",
527
629
  allowedProviders: ["google", "openai"],
528
630
  preferLeadingVendors: true, // default
529
631
  });
@@ -541,11 +643,12 @@ Supported values: `text`, `image`, `audio`, `video`, `file` (aligned with `model
541
643
  During resolution, choices whose catalog modalities do not satisfy the contract are **excluded**. A text-only model cannot be picked for `vision`; a vision-capable model can still serve text profiles.
542
644
 
543
645
  ```ts
544
- const resolved = await resolveAIProfile("vision");
646
+ const resolved = await resolveAIProfile("vision/default", { catalogLane: "image" });
545
647
  // resolved.requiredModalities.input includes "image"
546
648
  // resolved.modalities reflects the picked model from catalog
547
649
 
548
- await resolveAIProfile("cheap", {
650
+ await resolveAIProfile("cheap/default", {
651
+ catalogLane: "text",
549
652
  inputModalities: ["text", "image"], // override for this call
550
653
  outputModalities: ["text"],
551
654
  });
@@ -569,12 +672,12 @@ Restrict auto-pick to choices whose catalog pricing stays under a USD-per-1M-tok
569
672
 
570
673
  ```ts
571
674
  // Both input and output rates must be <= $0.20 / 1M tokens
572
- await resolveAIProfile("balanced", { costCapPer1M: 0.2 });
675
+ await resolveAIProfile("balanced/default", { catalogLane: "text", costCapPer1M: 0.2 });
573
676
 
574
677
  // Finer control
575
- await resolveAIProfile("cheap", {
678
+ await resolveAIProfile("cheap/minimax_cheap", {
679
+ catalogLane: "text",
576
680
  costCapPer1M: { maxInput: 0.2, maxOutput: 2 },
577
- choice: "minimax_cheap",
578
681
  });
579
682
  ```
580
683
 
@@ -1 +1 @@
1
- {"version":3,"file":"buildResolvedProfile.d.ts","sourceRoot":"","sources":["../src/buildResolvedProfile.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EAEZ,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,UAAU,yBAAyB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,cAAc,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,cAAc,CAAC,EAAE,YAAY,CAAC;CAC/B;AA8CD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,yBAAyB,GAChC,iBAAiB,CA2LnB"}
1
+ {"version":3,"file":"buildResolvedProfile.d.ts","sourceRoot":"","sources":["../src/buildResolvedProfile.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EAEZ,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,UAAU,yBAAyB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,cAAc,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,cAAc,CAAC,EAAE,YAAY,CAAC;CAC/B;AA8CD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,yBAAyB,GAChC,iBAAiB,CAmMnB"}
@@ -134,6 +134,12 @@ export function buildResolvedProfile(params) {
134
134
  maxOutputTokens: limits.maxOutputTokens,
135
135
  }
136
136
  : undefined;
137
+ const modelSignals = {
138
+ isReasoningModel: Boolean(capabilities?.supportsReasoning),
139
+ supportsStructuredOutput: capabilities?.supportsJsonSchema,
140
+ supportsTools: capabilities?.supportsTools,
141
+ contextWindow: capabilities?.contextWindow ?? limits?.contextWindow,
142
+ };
137
143
  const requiredModalities = resolveRequiredModalities(profile.profile, profile);
138
144
  const modalities = getChoiceModalities(choice, catalog);
139
145
  const resolved = {
@@ -156,6 +162,7 @@ export function buildResolvedProfile(params) {
156
162
  ...(choice.modelStatus !== undefined ? { modelStatus: choice.modelStatus } : {}),
157
163
  ...(limits !== undefined ? { limits } : {}),
158
164
  ...(capabilities !== undefined ? { capabilities } : {}),
165
+ modelSignals,
159
166
  ...(profile.requiredCapabilities !== undefined
160
167
  ? { requiredCapabilities: profile.requiredCapabilities }
161
168
  : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"buildResolvedProfile.js","sourceRoot":"","sources":["../src/buildResolvedProfile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"buildResolvedProfile.js","sourceRoot":"","sources":["../src/buildResolvedProfile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { CostCapPer1M, CostTierSpec } from "./types.js";
2
+ export declare const DEFAULT_COST_TIERS: CostTierSpec[];
3
+ export declare function resolveCostTierCap(costTier: string | undefined, overrideTiers?: CostTierSpec[]): CostCapPer1M | undefined;
4
+ //# sourceMappingURL=costTiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"costTiers.d.ts","sourceRoot":"","sources":["../src/costTiers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE7D,eAAO,MAAM,kBAAkB,EAAE,YAAY,EAK5C,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,aAAa,CAAC,EAAE,YAAY,EAAE,GAC7B,YAAY,GAAG,SAAS,CAkB1B"}
@@ -0,0 +1,20 @@
1
+ import { normalizeCostCap } from "./costPolicy.js";
2
+ export const DEFAULT_COST_TIERS = [
3
+ { key: "tier1", label: "Ultra low", cap: { maxOutput: 0.5 } },
4
+ { key: "tier2", label: "Low", cap: { maxOutput: 3 } },
5
+ { key: "tier3", label: "Medium", cap: { maxOutput: 10 } },
6
+ { key: "tier4", label: "High", cap: { maxOutput: 30 } },
7
+ ];
8
+ export function resolveCostTierCap(costTier, overrideTiers) {
9
+ if (!costTier) {
10
+ return undefined;
11
+ }
12
+ const tiers = (overrideTiers?.length ? overrideTiers : DEFAULT_COST_TIERS).filter((t) => typeof t?.key === "string" && t.key.trim() !== "");
13
+ const match = tiers.find((t) => t.key.trim().toLowerCase() === costTier.trim().toLowerCase());
14
+ if (!match) {
15
+ return undefined;
16
+ }
17
+ // Normalize ensures we only keep defined cap fields.
18
+ return normalizeCostCap(match.cap);
19
+ }
20
+ //# sourceMappingURL=costTiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"costTiers.js","sourceRoot":"","sources":["../src/costTiers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD,MAAM,CAAC,MAAM,kBAAkB,GAAmB;IAChD,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE;IAC7D,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE;IACrD,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE;IACzD,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE;CACxD,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAChC,QAA4B,EAC5B,aAA8B;IAE9B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAC/E,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CACzD,CAAC;IAEF,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CACpE,CAAC;IACF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,qDAAqD;IACrD,OAAO,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC"}