@x12i/ai-profiles 4.1.1 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -17
- package/dist/data/models-catalog.json +2183 -264
- package/dist/data/models-profiles.json +8 -63
- package/dist/data/models-registry.json +1 -1
- package/dist/deriveModelTags.d.ts +18 -0
- package/dist/deriveModelTags.d.ts.map +1 -0
- package/dist/deriveModelTags.js +148 -0
- package/dist/deriveModelTags.js.map +1 -0
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/isKnownProfileChoice.d.ts +21 -0
- package/dist/isKnownProfileChoice.d.ts.map +1 -1
- package/dist/isKnownProfileChoice.js +25 -0
- package/dist/isKnownProfileChoice.js.map +1 -1
- package/dist/listAICatalogModels.d.ts +45 -0
- package/dist/listAICatalogModels.d.ts.map +1 -0
- package/dist/listAICatalogModels.js +229 -0
- package/dist/listAICatalogModels.js.map +1 -0
- package/dist/listAIProfiles.d.ts.map +1 -1
- package/dist/listAIProfiles.js +8 -4
- package/dist/listAIProfiles.js.map +1 -1
- package/dist/modelsCatalog.d.ts.map +1 -1
- package/dist/modelsCatalog.js +5 -0
- package/dist/modelsCatalog.js.map +1 -1
- package/dist/profileDiscovery.d.ts +38 -6
- package/dist/profileDiscovery.d.ts.map +1 -1
- package/dist/profileDiscovery.js +70 -22
- package/dist/profileDiscovery.js.map +1 -1
- package/dist/profileTags.d.ts +5 -0
- package/dist/profileTags.d.ts.map +1 -1
- package/dist/profileTags.js +26 -0
- package/dist/profileTags.js.map +1 -1
- package/dist/resolveAIProfileByTags.d.ts +10 -2
- package/dist/resolveAIProfileByTags.d.ts.map +1 -1
- package/dist/resolveAIProfileByTags.js +21 -5
- package/dist/resolveAIProfileByTags.js.map +1 -1
- package/dist/resolveCatalogModelByTags.d.ts +39 -0
- package/dist/resolveCatalogModelByTags.d.ts.map +1 -0
- package/dist/resolveCatalogModelByTags.js +112 -0
- package/dist/resolveCatalogModelByTags.js.map +1 -0
- package/dist/resolveInput.d.ts +29 -0
- package/dist/resolveInput.d.ts.map +1 -0
- package/dist/resolveInput.js +41 -0
- package/dist/resolveInput.js.map +1 -0
- package/dist/resolveModelIdentity.d.ts +4 -0
- package/dist/resolveModelIdentity.d.ts.map +1 -1
- package/dist/resolveModelIdentity.js +8 -0
- package/dist/resolveModelIdentity.js.map +1 -1
- package/dist/types.d.ts +11 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/validation/validateModelsCatalog.d.ts.map +1 -1
- package/dist/validation/validateModelsCatalog.js +11 -0
- package/dist/validation/validateModelsCatalog.js.map +1 -1
- package/dist/validation/validateModelsProfilesJson.d.ts +5 -1
- package/dist/validation/validateModelsProfilesJson.d.ts.map +1 -1
- package/dist/validation/validateModelsProfilesJson.js +6 -13
- package/dist/validation/validateModelsProfilesJson.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ Graph JSON, studio defaults, and run overrides store **profile slot strings only
|
|
|
47
47
|
| `skillModel` | `balanced/default` | MAIN (skill gateway) |
|
|
48
48
|
| `postActionModel` | `cheap/default` | POST (xynthesis / wrap-up) |
|
|
49
49
|
|
|
50
|
-
Canonical storage form is **`profile/choice`** (separator `/`). Use **`formatProfileChoiceKey(profile, choice)`** when writing slots and **`
|
|
50
|
+
Canonical storage form is **`profile/choice`** (separator `/`). Use **`formatProfileChoiceKey(profile, choice)`** when writing slots and **`isKnownProfileInput(input)`** (or **`isKnownProfileChoice`** / **`matchStrictProfileInput`**) before persist or execute. Always include the choice segment — even for the profile default (`cheap/default`, not bare `cheap`).
|
|
51
51
|
|
|
52
52
|
```json
|
|
53
53
|
"modelConfig": {
|
|
@@ -249,10 +249,13 @@ npm install @x12i/ai-profiles
|
|
|
249
249
|
| `parseProfileChoiceKey(input)` | Yes | Parse `profile/choice` (accepts `\` as separator on input) |
|
|
250
250
|
| `matchStrictProfileInput(registry, input)` | Yes | Resolve input to profile+choice or `invalidChoice` |
|
|
251
251
|
| `isKnownProfileChoice(input)` | Yes (bundled only) | Whether input is a known valid `profile/choice` key |
|
|
252
|
+
| `isKnownProfileInput(input)` | Yes (bundled only) | Profile-intent gate: known `profile/choice` → `true`; concrete model ids → `false` |
|
|
253
|
+
| `isKnownProfileOrShortcut(input)` | Yes (bundled only) | Alias of `isKnownProfileInput` (shortcuts are not supported) |
|
|
252
254
|
| `isKnownProfileChoiceInput(registry, input)` | Yes | Same as above with an explicit registry |
|
|
253
255
|
| `getBundledRegistry()` | Yes | Sync bundled profiles registry (no network) |
|
|
254
256
|
| `resolveBundledAIProfile(input, options)` | Yes | Strict `profile/choice` → model, pricing, runtime (`source: "bundled"`) |
|
|
255
|
-
| `resolveBundledInput(input, options)` | Yes | Unified resolver: `profile/choice` → registry; vendor slug / gateway wire / `{ provider, modelId }` → catalog |
|
|
257
|
+
| `resolveBundledInput(input, options)` | Yes | Unified sync resolver: `profile/choice` → registry; vendor slug / gateway wire / `{ provider, modelId }` → catalog |
|
|
258
|
+
| `resolveInput(input, options)` | No (async) | Unified async resolver (same order as `resolveBundledInput`; `source: "auto" \| "remote" \| "bundled"`) |
|
|
256
259
|
| `resolveBundledCatalogModel(input, options?)` | Yes | Sync strict catalog resolution (exact/high confidence only) |
|
|
257
260
|
| `ensureConcreteModel(input, options?)` | Yes | String normalizer: `profile/choice` (strict) or concrete model (catalog best-effort) → invoke-time `{ provider, modelId }` |
|
|
258
261
|
| `normalizeInvokeModel(input, options?)` | Yes | Idempotent gateway invoke tuple: strips `openrouter/` display slugs; rejects unresolved `profile/choice` aliases |
|
|
@@ -271,8 +274,10 @@ npm install @x12i/ai-profiles
|
|
|
271
274
|
| `resolveSecondaryModel(input, options?)` | No (async) | Resolve primary choice + optional companion `secondary` from profile `secondary` refs |
|
|
272
275
|
| `getSecondaryForResolvedProfile(resolved, registry, catalog?)` | Yes | Secondary for an already-resolved primary (no extra I/O when catalog is passed) |
|
|
273
276
|
| `listProfileSecondaries(profileKey, registry)` | Yes | List per-choice `secondary` declarations on a profile |
|
|
274
|
-
| `resolveAIProfileByTags(tags, options?)` | No (async) | Pick best profile by
|
|
275
|
-
| `
|
|
277
|
+
| `resolveAIProfileByTags(tags, options?)` | No (async) | Pick best profile by weighted tags (`tagMatch`, excludes discovery by default), then resolve |
|
|
278
|
+
| `listAICatalogModels(options?)` | No (async) | Filter/rank catalog models by tags, provider, status, modalities, tools/reasoning; attaches intent `profileChoices` |
|
|
279
|
+
| `resolveCatalogModelByTags(tags, options?)` | No (async) | Best catalog model by weighted tags (+ optional profile branch map) |
|
|
280
|
+
| `scoreProfileTags` / `rankProfilesByTags` | Yes | Weighted tag scoring for discovery and custom UIs |
|
|
276
281
|
| `AIProfilesError` / `AIProfilesErrorCode` | — | Typed errors (`UNKNOWN_PROFILE`, `INVOKE_MODEL_ALIAS_AT_GATEWAY`, `INVOKE_MODEL_SHAPE_INVALID`, …) |
|
|
277
282
|
|
|
278
283
|
### Model identity (vendor + model strings)
|
|
@@ -282,7 +287,7 @@ Use these when callers pass **raw model ids or OpenRouter slugs**, not profile n
|
|
|
282
287
|
| Export | Sync? | Purpose |
|
|
283
288
|
|--------|-------|---------|
|
|
284
289
|
| `resolveCatalogModel(input, options?)` | No (async) | Resolve a model SKU or OpenRouter slug via `models-catalog.json` (strict; no profile intent) |
|
|
285
|
-
| `resolveModelIdentity(input, options?)` | Yes | Given a bare id or `vendor/slug`, return `{ provider, modelId, invocation? }` via bundled registry + catalog fallback |
|
|
290
|
+
| `resolveModelIdentity(input, options?)` | Yes | Given a bare id or `vendor/slug`, return `{ provider, modelId, invocation? }` via bundled registry + catalog fallback. Returns `null` for known `profile/choice` keys. |
|
|
286
291
|
| `buildModelInvocation(provider, modelId)` | Yes | `{ direct, openrouter }` endpoints for a provider hint + model string |
|
|
287
292
|
| `buildDirectInvocation(provider, modelId)` | Yes | Vendor-direct `{ provider, modelId }`; splits prefixed slugs for all vendors |
|
|
288
293
|
| `buildOpenRouterModelId(provider, modelId)` | Yes | Build an OpenRouter slug (`openai/gpt-5.4`) from registry fields |
|
|
@@ -327,7 +332,7 @@ For consumers that need **no network** and a single entry point:
|
|
|
327
332
|
```ts
|
|
328
333
|
import {
|
|
329
334
|
ensureConcreteModel,
|
|
330
|
-
|
|
335
|
+
isKnownProfileInput,
|
|
331
336
|
isReasoningModel,
|
|
332
337
|
resolveBundledInput,
|
|
333
338
|
resolveBundledAIProfile,
|
|
@@ -352,8 +357,9 @@ ensureConcreteModel("google/gemini-2.5-flash-lite");
|
|
|
352
357
|
ensureConcreteModel("openrouter/openai/gpt-5.5");
|
|
353
358
|
// → { provider: "openrouter", modelId: "openai/gpt-5.5" }
|
|
354
359
|
|
|
355
|
-
if (
|
|
360
|
+
if (isKnownProfileInput("cheap/default")) {
|
|
356
361
|
const resolved = resolveBundledInput("cheap/default", { catalogLane: "text" });
|
|
362
|
+
// resolved.provider is never "cheap"
|
|
357
363
|
}
|
|
358
364
|
|
|
359
365
|
const wire = normalizeGatewayWireId("openrouter/openai/gpt-5.5");
|
|
@@ -376,7 +382,16 @@ const routed = applyModelRouting(
|
|
|
376
382
|
);
|
|
377
383
|
```
|
|
378
384
|
|
|
379
|
-
|
|
385
|
+
For the same profile-first order with optional remote registry/catalog (`source: "auto"` / `"remote"` / `"bundled"`), use **`resolveInput`**:
|
|
386
|
+
|
|
387
|
+
```ts
|
|
388
|
+
import { resolveInput } from "@x12i/ai-profiles";
|
|
389
|
+
|
|
390
|
+
await resolveInput("cheap/default", { catalogLane: "text", source: "auto" });
|
|
391
|
+
await resolveInput("google/gemma-3-4b-it", { source: "bundled" });
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
`isKnownProfileInput` / `isKnownProfileChoice` return **false** for bare profiles (`cheap`), legacy shortcuts (`cheapest`), and concrete slugs (`google/gemini-2.5-flash-lite`).
|
|
380
395
|
|
|
381
396
|
## Basic usage
|
|
382
397
|
|
|
@@ -384,9 +399,10 @@ const routed = applyModelRouting(
|
|
|
384
399
|
import {
|
|
385
400
|
listAIProfiles,
|
|
386
401
|
listAIProfileChoices,
|
|
387
|
-
|
|
402
|
+
isKnownProfileInput,
|
|
388
403
|
resolveAIProfile,
|
|
389
404
|
resolveCatalogModel,
|
|
405
|
+
resolveInput,
|
|
390
406
|
} from "@x12i/ai-profiles";
|
|
391
407
|
|
|
392
408
|
const profiles = await listAIProfiles();
|
|
@@ -394,6 +410,7 @@ const choices = await listAIProfileChoices();
|
|
|
394
410
|
|
|
395
411
|
// Strict lookup key: profile/choice
|
|
396
412
|
const model = await resolveAIProfile("cheap/default", { catalogLane: "text" });
|
|
413
|
+
// Or unified async: await resolveInput("cheap/default", { catalogLane: "text" });
|
|
397
414
|
|
|
398
415
|
console.log(model.profile); // canonical primary key: cheap
|
|
399
416
|
console.log(model.provider); // "openrouter" by default for remote profiles
|
|
@@ -412,8 +429,8 @@ const sku = await resolveCatalogModel("google/gemini-2.5-flash-lite", {
|
|
|
412
429
|
preferOpenRouter: false,
|
|
413
430
|
});
|
|
414
431
|
|
|
415
|
-
console.log(
|
|
416
|
-
console.log(
|
|
432
|
+
console.log(isKnownProfileInput("cheap/default")); // true
|
|
433
|
+
console.log(isKnownProfileInput("cheap")); // false
|
|
417
434
|
```
|
|
418
435
|
|
|
419
436
|
## Registry statistics
|
|
@@ -455,7 +472,7 @@ Resolution accepts exactly **four** input forms:
|
|
|
455
472
|
|
|
456
473
|
**Not supported:** shortcuts (`cheapest`), bare profiles (`cheap`), aliases (`cost-sensitive`). Use discovery to pick a profile, then resolve an explicit `profile/choice`.
|
|
457
474
|
|
|
458
|
-
**Tags exist to filter.** Short codes on profiles (`cyb`, `eco`, `cod`, `oai`, …). Get the tag list, then filter
|
|
475
|
+
**Tags exist to filter.** Short codes on profiles and catalog models (`cyb`, `eco`, `cod`, `oai`, …). Get the tag list, then filter:
|
|
459
476
|
|
|
460
477
|
```ts
|
|
461
478
|
import {
|
|
@@ -463,6 +480,8 @@ import {
|
|
|
463
480
|
listUsedAIProfileTags, // tags present in the loaded registry
|
|
464
481
|
listAIProfiles, // filter profiles by tags
|
|
465
482
|
resolveAIProfileByTags, // pick best matching profile → resolve it
|
|
483
|
+
listAICatalogModels, // filter catalog models by tags
|
|
484
|
+
resolveCatalogModelByTags, // pick best matching model (+ optional profile branch)
|
|
466
485
|
} from "@x12i/ai-profiles";
|
|
467
486
|
|
|
468
487
|
listAIProfileTags(); // glossary for pickers
|
|
@@ -474,9 +493,21 @@ await listAIProfiles({ tags: ["cyb", "sec"], tagMatch: "all" }); // all of
|
|
|
474
493
|
|
|
475
494
|
// Filter + resolve in one step
|
|
476
495
|
await resolveAIProfileByTags(["cyb", "eco", "ds"], { catalogLane: "text" });
|
|
496
|
+
|
|
497
|
+
// Catalog models (tags are derived + inherited during registry:finish)
|
|
498
|
+
await listAICatalogModels({
|
|
499
|
+
tags: ["cod", "eco"],
|
|
500
|
+
tagMatch: "all",
|
|
501
|
+
provider: "google",
|
|
502
|
+
status: "active",
|
|
503
|
+
supportsTools: true,
|
|
504
|
+
});
|
|
505
|
+
await resolveCatalogModelByTags(["cod", "eco"], { catalogLane: "text" });
|
|
477
506
|
```
|
|
478
507
|
|
|
479
|
-
`tagMatch: "any"` (default) = match if any requested tag is present. `"all"` = every requested tag must be present. Results are ranked by
|
|
508
|
+
`tagMatch: "any"` (default) = match if any requested tag is present. `"all"` = every requested tag must be present. Results are ranked by **weighted** tag score (domain/task 3, capability 2, tier/vendor 1, `wf` 0.25), then coverage ratio, then fewer tags.
|
|
509
|
+
|
|
510
|
+
**Discovery exclusion:** by default, tag list/resolve pools skip `vendorFamily` and `category: "discovery"` profiles (`catalog`, `claude`, `grok`, …). Pass `includeDiscovery: true`, or include the `vnd` tag, to include them.
|
|
480
511
|
|
|
481
512
|
Input is normalized (trimmed, lowercased) before matching. Composite keys accept **`/` or `\`** as the separator (`cyber\default` → `cyber/default`). **Profile and choice segment names treat `-` and `_` as equivalent** (`cheap/google-floor` → `cheap/google_floor`).
|
|
482
513
|
|
|
@@ -563,12 +594,12 @@ resolveAndNormalizeBundledInvokeModel("cyber/deep_forensics", {
|
|
|
563
594
|
|
|
564
595
|
## Sync validation (bundled registry)
|
|
565
596
|
|
|
566
|
-
Use **`
|
|
597
|
+
Use **`isKnownProfileInput(input)`** (or **`isKnownProfileChoice`**) 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).
|
|
567
598
|
|
|
568
599
|
```ts
|
|
569
600
|
const canRun =
|
|
570
|
-
|
|
571
|
-
|
|
601
|
+
isKnownProfileInput(aiProfileKey) &&
|
|
602
|
+
isKnownProfileInput(fallbackKey);
|
|
572
603
|
```
|
|
573
604
|
|
|
574
605
|
Accepts **valid `profile/choice` keys only**. Unknown strings return `false`.
|
|
@@ -1014,7 +1045,7 @@ Workflow YAML is in [`docs/github-workflows/`](docs/github-workflows/). Copy int
|
|
|
1014
1045
|
Consumers install with:
|
|
1015
1046
|
|
|
1016
1047
|
```bash
|
|
1017
|
-
npm install @x12i/ai-profiles@^4.
|
|
1048
|
+
npm install @x12i/ai-profiles@^4.2.0
|
|
1018
1049
|
```
|
|
1019
1050
|
|
|
1020
1051
|
Peer dependency for downstream repos (graphs-studio, graph-engine, ai-tasks):
|