@x12i/ai-profiles 1.2.7 → 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/README.md +278 -18
- package/dist/buildCatalogFromOpenRouterApi.d.ts +29 -0
- package/dist/buildCatalogFromOpenRouterApi.d.ts.map +1 -0
- package/dist/buildCatalogFromOpenRouterApi.js +113 -0
- package/dist/buildCatalogFromOpenRouterApi.js.map +1 -0
- package/dist/buildModelsRegistry.d.ts +25 -0
- package/dist/buildModelsRegistry.d.ts.map +1 -0
- package/dist/buildModelsRegistry.js +190 -0
- package/dist/buildModelsRegistry.js.map +1 -0
- package/dist/buildResolvedProfile.d.ts +4 -1
- package/dist/buildResolvedProfile.d.ts.map +1 -1
- package/dist/buildResolvedProfile.js +102 -15
- package/dist/buildResolvedProfile.js.map +1 -1
- package/dist/catalogEnrichment.d.ts +19 -0
- package/dist/catalogEnrichment.d.ts.map +1 -0
- package/dist/catalogEnrichment.js +87 -0
- package/dist/catalogEnrichment.js.map +1 -0
- package/dist/computeRegistryStatistics.d.ts +15 -0
- package/dist/computeRegistryStatistics.d.ts.map +1 -0
- package/dist/computeRegistryStatistics.js +168 -0
- package/dist/computeRegistryStatistics.js.map +1 -0
- package/dist/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +10 -0
- package/dist/constants.js.map +1 -1
- package/dist/data/models-catalog.json +2219 -0
- package/dist/data/models-profiles.json +1361 -193
- package/dist/data/models-profiles.schema.json +130 -0
- package/dist/data/models-registry.json +1606 -0
- package/dist/data/openrouter-models-catalog.json +857 -0
- package/dist/data/profiles-shortcuts.json +101 -2
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/formatRegistryStatistics.d.ts +4 -0
- package/dist/formatRegistryStatistics.d.ts.map +1 -0
- package/dist/formatRegistryStatistics.js +34 -0
- package/dist/formatRegistryStatistics.js.map +1 -0
- package/dist/getAIRegistryStatistics.d.ts +11 -0
- package/dist/getAIRegistryStatistics.d.ts.map +1 -0
- package/dist/getAIRegistryStatistics.js +52 -0
- package/dist/getAIRegistryStatistics.js.map +1 -0
- package/dist/index.d.ts +24 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/listAIProfiles.d.ts +6 -0
- package/dist/listAIProfiles.d.ts.map +1 -1
- package/dist/listAIProfiles.js +6 -0
- package/dist/listAIProfiles.js.map +1 -1
- package/dist/loadModelsRegistry.d.ts +6 -0
- package/dist/loadModelsRegistry.d.ts.map +1 -0
- package/dist/loadModelsRegistry.js +43 -0
- package/dist/loadModelsRegistry.js.map +1 -0
- package/dist/loader/catalogMemoryCache.d.ts +12 -0
- package/dist/loader/catalogMemoryCache.d.ts.map +1 -0
- package/dist/loader/catalogMemoryCache.js +14 -0
- package/dist/loader/catalogMemoryCache.js.map +1 -0
- package/dist/loader/loadBundledModelsCatalog.d.ts +3 -0
- package/dist/loader/loadBundledModelsCatalog.d.ts.map +1 -0
- package/dist/loader/loadBundledModelsCatalog.js +20 -0
- package/dist/loader/loadBundledModelsCatalog.js.map +1 -0
- package/dist/loader/loadBundledModelsProfiles.d.ts +4 -0
- package/dist/loader/loadBundledModelsProfiles.d.ts.map +1 -0
- package/dist/loader/loadBundledModelsProfiles.js +14 -0
- package/dist/loader/loadBundledModelsProfiles.js.map +1 -0
- package/dist/loader/loadBundledRegistry.d.ts.map +1 -1
- package/dist/loader/loadBundledRegistry.js +2 -1
- package/dist/loader/loadBundledRegistry.js.map +1 -1
- package/dist/loader/loadModelsCatalog.d.ts +9 -0
- package/dist/loader/loadModelsCatalog.d.ts.map +1 -0
- package/dist/loader/loadModelsCatalog.js +72 -0
- package/dist/loader/loadModelsCatalog.js.map +1 -0
- package/dist/loader/loadModelsProfilesJson.d.ts +3 -0
- package/dist/loader/loadModelsProfilesJson.d.ts.map +1 -0
- package/dist/loader/loadModelsProfilesJson.js +18 -0
- package/dist/loader/loadModelsProfilesJson.js.map +1 -0
- package/dist/loader/loadRemoteModelsCatalog.d.ts +3 -0
- package/dist/loader/loadRemoteModelsCatalog.d.ts.map +1 -0
- package/dist/loader/loadRemoteModelsCatalog.js +23 -0
- package/dist/loader/loadRemoteModelsCatalog.js.map +1 -0
- package/dist/loader/loadRemoteModelsProfiles.d.ts +3 -0
- package/dist/loader/loadRemoteModelsProfiles.d.ts.map +1 -0
- package/dist/loader/loadRemoteModelsProfiles.js +21 -0
- package/dist/loader/loadRemoteModelsProfiles.js.map +1 -0
- package/dist/loader/loadRemoteRegistry.d.ts.map +1 -1
- package/dist/loader/loadRemoteRegistry.js +2 -1
- package/dist/loader/loadRemoteRegistry.js.map +1 -1
- package/dist/mergeCatalogSupplement.d.ts +4 -0
- package/dist/mergeCatalogSupplement.d.ts.map +1 -0
- package/dist/mergeCatalogSupplement.js +26 -0
- package/dist/mergeCatalogSupplement.js.map +1 -0
- package/dist/modelIdentity.d.ts +33 -0
- package/dist/modelIdentity.d.ts.map +1 -0
- package/dist/modelIdentity.js +150 -0
- package/dist/modelIdentity.js.map +1 -0
- package/dist/modelsCatalog.d.ts +21 -0
- package/dist/modelsCatalog.d.ts.map +1 -0
- package/dist/modelsCatalog.js +187 -0
- package/dist/modelsCatalog.js.map +1 -0
- package/dist/profileCatalogSupplement.d.ts +7 -0
- package/dist/profileCatalogSupplement.d.ts.map +1 -0
- package/dist/profileCatalogSupplement.js +292 -0
- package/dist/profileCatalogSupplement.js.map +1 -0
- package/dist/profileRegistryV2.d.ts +19 -0
- package/dist/profileRegistryV2.d.ts.map +1 -0
- package/dist/profileRegistryV2.js +257 -0
- package/dist/profileRegistryV2.js.map +1 -0
- package/dist/profileRegistryV3.d.ts +11 -0
- package/dist/profileRegistryV3.d.ts.map +1 -0
- package/dist/profileRegistryV3.js +526 -0
- package/dist/profileRegistryV3.js.map +1 -0
- package/dist/resolveAIProfile.d.ts +8 -0
- package/dist/resolveAIProfile.d.ts.map +1 -1
- package/dist/resolveAIProfile.js +63 -18
- package/dist/resolveAIProfile.js.map +1 -1
- package/dist/resolveModelRouting.d.ts +20 -0
- package/dist/resolveModelRouting.d.ts.map +1 -0
- package/dist/resolveModelRouting.js +70 -0
- package/dist/resolveModelRouting.js.map +1 -0
- package/dist/types.d.ts +348 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -1
- package/dist/validateProfileVendorCoverage.d.ts +12 -0
- package/dist/validateProfileVendorCoverage.d.ts.map +1 -0
- package/dist/validateProfileVendorCoverage.js +58 -0
- package/dist/validateProfileVendorCoverage.js.map +1 -0
- package/dist/validation/openRouterAlignment.d.ts +6 -15
- package/dist/validation/openRouterAlignment.d.ts.map +1 -1
- package/dist/validation/openRouterAlignment.js +9 -57
- package/dist/validation/openRouterAlignment.js.map +1 -1
- package/dist/validation/validateModelsCatalog.d.ts +3 -0
- package/dist/validation/validateModelsCatalog.d.ts.map +1 -0
- package/dist/validation/validateModelsCatalog.js +42 -0
- package/dist/validation/validateModelsCatalog.js.map +1 -0
- package/dist/validation/validateModelsProfilesJson.d.ts.map +1 -1
- package/dist/validation/validateModelsProfilesJson.js +38 -2
- package/dist/validation/validateModelsProfilesJson.js.map +1 -1
- package/dist/vendorPolicy.d.ts +20 -0
- package/dist/vendorPolicy.d.ts.map +1 -0
- package/dist/vendorPolicy.js +71 -0
- package/dist/vendorPolicy.js.map +1 -0
- package/package.json +15 -2
package/dist/resolveAIProfile.js
CHANGED
|
@@ -1,35 +1,50 @@
|
|
|
1
1
|
import { buildResolvedProfile } from "./buildResolvedProfile.js";
|
|
2
2
|
import { AIProfilesError } from "./errors.js";
|
|
3
3
|
import { loadAIProfilesRegistryWithWarnings } from "./loader/loadAIProfilesRegistry.js";
|
|
4
|
+
import { loadModelsCatalogWithWarnings } from "./loader/loadModelsCatalog.js";
|
|
4
5
|
import { matchProfileInput } from "./profileInputMatch.js";
|
|
6
|
+
import { pickProfileChoice } from "./vendorPolicy.js";
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a profile primary key, alias, or shortcut to a concrete model and runtime config.
|
|
9
|
+
*
|
|
10
|
+
* `input` names **intent** (e.g. `balanced`, `cheapest`, `cost-sensitive`), not a vendor model id.
|
|
11
|
+
* Use `options.choice` to pick an alternative within the profile (e.g. `cheap` + `safer_provider`).
|
|
12
|
+
*
|
|
13
|
+
* @see README.md — “Why AI profiles”
|
|
14
|
+
*/
|
|
5
15
|
export async function resolveAIProfile(input, options = {}) {
|
|
6
|
-
const { registry, warnings } = await
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
16
|
+
const [{ registry, warnings }, catalogResult] = await Promise.all([
|
|
17
|
+
loadAIProfilesRegistryWithWarnings({
|
|
18
|
+
source: options.source,
|
|
19
|
+
refresh: options.refresh,
|
|
20
|
+
}),
|
|
21
|
+
loadModelsCatalogWithWarnings({
|
|
22
|
+
source: options.source,
|
|
23
|
+
refresh: options.refresh,
|
|
24
|
+
}),
|
|
25
|
+
]);
|
|
26
|
+
const loaderWarnings = [...warnings, ...catalogResult.warnings];
|
|
10
27
|
const match = matchProfileInput(registry, input);
|
|
11
28
|
if (!match) {
|
|
12
29
|
throw new AIProfilesError("UNKNOWN_PROFILE", `Unknown AI profile, shortcut, or alias: ${input}`, { input });
|
|
13
30
|
}
|
|
14
31
|
let profileKey;
|
|
15
|
-
let
|
|
32
|
+
let requestedChoiceKey;
|
|
16
33
|
let matchedShortcut;
|
|
17
34
|
switch (match.kind) {
|
|
18
35
|
case "profile":
|
|
19
36
|
profileKey = match.profileKey;
|
|
20
|
-
|
|
21
|
-
options.choice ?? registry.profiles[profileKey].defaultChoice;
|
|
37
|
+
requestedChoiceKey = options.choice;
|
|
22
38
|
matchedShortcut = undefined;
|
|
23
39
|
break;
|
|
24
40
|
case "shortcut":
|
|
25
41
|
profileKey = match.profileKey;
|
|
26
|
-
|
|
42
|
+
requestedChoiceKey = options.choice ?? match.shortcut.choice;
|
|
27
43
|
matchedShortcut = match.shortcut;
|
|
28
44
|
break;
|
|
29
45
|
case "alias":
|
|
30
46
|
profileKey = match.profileKey;
|
|
31
|
-
|
|
32
|
-
options.choice ?? registry.profiles[profileKey].defaultChoice;
|
|
47
|
+
requestedChoiceKey = options.choice;
|
|
33
48
|
matchedShortcut = undefined;
|
|
34
49
|
break;
|
|
35
50
|
}
|
|
@@ -37,15 +52,42 @@ export async function resolveAIProfile(input, options = {}) {
|
|
|
37
52
|
if (!profile) {
|
|
38
53
|
throw new AIProfilesError("UNKNOWN_PROFILE", `Unknown AI profile: ${profileKey}`, { input, profile: profileKey });
|
|
39
54
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
55
|
+
let finalChoiceKey;
|
|
56
|
+
let choice;
|
|
57
|
+
try {
|
|
58
|
+
const picked = pickProfileChoice(profile, {
|
|
59
|
+
choiceKey: requestedChoiceKey,
|
|
60
|
+
allowedProviders: options.allowedProviders,
|
|
61
|
+
preferLeadingVendors: options.preferLeadingVendors ?? true,
|
|
62
|
+
explicitChoiceRequested: options.choice !== undefined,
|
|
63
|
+
});
|
|
64
|
+
finalChoiceKey = picked.choiceKey;
|
|
65
|
+
choice = picked.choice;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
69
|
+
if (message.includes("allowedProviders")) {
|
|
70
|
+
throw new AIProfilesError("NO_ALLOWED_VENDOR", message, {
|
|
71
|
+
input,
|
|
72
|
+
profile: profileKey,
|
|
73
|
+
allowedProviders: options.allowedProviders,
|
|
74
|
+
availableProviders: [
|
|
75
|
+
...new Set(Object.values(profile.choices).map((c) => c.provider)),
|
|
76
|
+
],
|
|
47
77
|
});
|
|
48
78
|
}
|
|
79
|
+
if (message.startsWith("Unknown choice")) {
|
|
80
|
+
if (options.allowFallbackToDefaultChoice) {
|
|
81
|
+
return resolveAIProfile(profileKey, {
|
|
82
|
+
...options,
|
|
83
|
+
choice: profile.defaultChoice,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
throw new AIProfilesError("UNKNOWN_CHOICE", message, { input, profile: profileKey, choice: requestedChoiceKey });
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
if (!profile.choices[finalChoiceKey]) {
|
|
49
91
|
throw new AIProfilesError("UNKNOWN_CHOICE", `Unknown choice '${finalChoiceKey}' for AI profile '${profileKey}'`, { input, profile: profileKey, choice: finalChoiceKey });
|
|
50
92
|
}
|
|
51
93
|
return buildResolvedProfile({
|
|
@@ -53,9 +95,12 @@ export async function resolveAIProfile(input, options = {}) {
|
|
|
53
95
|
shortcutKey: match.kind === "shortcut" ? match.shortcutKey : undefined,
|
|
54
96
|
profile,
|
|
55
97
|
choice,
|
|
98
|
+
choiceKey: finalChoiceKey,
|
|
56
99
|
shortcut: matchedShortcut,
|
|
57
100
|
registry,
|
|
58
|
-
loaderWarnings
|
|
101
|
+
loaderWarnings,
|
|
102
|
+
useOpenRouter: options.useOpenRouter,
|
|
103
|
+
catalog: catalogResult.catalog,
|
|
59
104
|
});
|
|
60
105
|
}
|
|
61
106
|
//# sourceMappingURL=resolveAIProfile.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveAIProfile.js","sourceRoot":"","sources":["../src/resolveAIProfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,kCAAkC,EAAE,MAAM,oCAAoC,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"resolveAIProfile.js","sourceRoot":"","sources":["../src/resolveAIProfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,kCAAkC,EAAE,MAAM,oCAAoC,CAAC;AACxF,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAa,EACb,UAAmC,EAAE;IAErC,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAChE,kCAAkC,CAAC;YACjC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;QACF,6BAA6B,CAAC;YAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAC;KACH,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,CAAC,GAAG,QAAQ,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEhE,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAEjD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,eAAe,CACvB,iBAAiB,EACjB,2CAA2C,KAAK,EAAE,EAClD,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,IAAI,UAAkB,CAAC;IACvB,IAAI,kBAAsC,CAAC;IAC3C,IAAI,eAAgE,CAAC;IAErE,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,SAAS;YACZ,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;YAC9B,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC;YACpC,eAAe,GAAG,SAAS,CAAC;YAC5B,MAAM;QACR,KAAK,UAAU;YACb,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;YAC9B,kBAAkB,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC7D,eAAe,GAAG,KAAK,CAAC,QAAQ,CAAC;YACjC,MAAM;QACR,KAAK,OAAO;YACV,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;YAC9B,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC;YACpC,eAAe,GAAG,SAAS,CAAC;YAC5B,MAAM;IACV,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAE9C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,eAAe,CACvB,iBAAiB,EACjB,uBAAuB,UAAU,EAAE,EACnC,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAC/B,CAAC;IACJ,CAAC;IAED,IAAI,cAAsB,CAAC;IAC3B,IAAI,MAAM,CAAC;IAEX,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE;YACxC,SAAS,EAAE,kBAAkB;YAC7B,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;YAC1C,oBAAoB,EAAE,OAAO,CAAC,oBAAoB,IAAI,IAAI;YAC1D,uBAAuB,EAAE,OAAO,CAAC,MAAM,KAAK,SAAS;SACtD,CAAC,CAAC;QACH,cAAc,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEvE,IAAI,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,eAAe,CACvB,mBAAmB,EACnB,OAAO,EACP;gBACE,KAAK;gBACL,OAAO,EAAE,UAAU;gBACnB,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;gBAC1C,kBAAkB,EAAE;oBAClB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;iBAClE;aACF,CACF,CAAC;QACJ,CAAC;QAED,IAAI,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACzC,IAAI,OAAO,CAAC,4BAA4B,EAAE,CAAC;gBACzC,OAAO,gBAAgB,CAAC,UAAU,EAAE;oBAClC,GAAG,OAAO;oBACV,MAAM,EAAE,OAAO,CAAC,aAAa;iBAC9B,CAAC,CAAC;YACL,CAAC;YAED,MAAM,IAAI,eAAe,CACvB,gBAAgB,EAChB,OAAO,EACP,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAC3D,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,eAAe,CACvB,gBAAgB,EAChB,mBAAmB,cAAc,qBAAqB,UAAU,GAAG,EACnE,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,CACvD,CAAC;IACJ,CAAC;IAED,OAAO,oBAAoB,CAAC;QAC1B,KAAK;QACL,WAAW,EAAE,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;QACtE,OAAO;QACP,MAAM;QACN,SAAS,EAAE,cAAc;QACzB,QAAQ,EAAE,eAAe;QACzB,QAAQ;QACR,cAAc;QACd,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,OAAO,EAAE,aAAa,CAAC,OAAO;KAC/B,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AIProfileBackend, AIProfileChoice, AIProvider } from "./types.js";
|
|
2
|
+
import { buildOpenRouterModelId } from "./modelIdentity.js";
|
|
3
|
+
export type AIModelRoutingMode = "openrouter" | "direct";
|
|
4
|
+
/** Reads `USE_OPENROUTER` from process env (loading `.env` once when unset). */
|
|
5
|
+
export declare function readUseOpenRouterFromEnv(): boolean | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Resolves whether to route via OpenRouter.
|
|
8
|
+
* Explicit option wins, then `USE_OPENROUTER` env, then default `true`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveUseOpenRouter(explicit?: boolean): boolean;
|
|
11
|
+
export declare function isRemoteProfileChoice(choice: AIProfileChoice): boolean;
|
|
12
|
+
export { buildOpenRouterModelId };
|
|
13
|
+
export interface AppliedModelRouting {
|
|
14
|
+
provider: AIProvider;
|
|
15
|
+
modelId: string;
|
|
16
|
+
backend: AIProfileBackend;
|
|
17
|
+
routing: AIModelRoutingMode;
|
|
18
|
+
}
|
|
19
|
+
export declare function applyModelRouting(choice: AIProfileChoice, backend: AIProfileBackend, useOpenRouter: boolean): AppliedModelRouting;
|
|
20
|
+
//# sourceMappingURL=resolveModelRouting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveModelRouting.d.ts","sourceRoot":"","sources":["../src/resolveModelRouting.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAO5D,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,QAAQ,CAAC;AAyBzD,gFAAgF;AAChF,wBAAgB,wBAAwB,IAAI,OAAO,GAAG,SAAS,CAU9D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAMhE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAUtE;AAED,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAElC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,UAAU,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,gBAAgB,EACzB,aAAa,EAAE,OAAO,GACrB,mBAAmB,CAuBrB"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { loadDotenv } from "@x12i/env";
|
|
2
|
+
import { buildOpenRouterModelId } from "./modelIdentity.js";
|
|
3
|
+
import { buildModelInvocationFromChoice, getChoiceOpenRouterModelId, getChoiceVendorModelId, } from "./profileRegistryV2.js";
|
|
4
|
+
let dotenvLoaded = false;
|
|
5
|
+
function ensureDotenvLoaded() {
|
|
6
|
+
if (!dotenvLoaded) {
|
|
7
|
+
loadDotenv();
|
|
8
|
+
dotenvLoaded = true;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function parseBooleanEnv(value) {
|
|
12
|
+
const normalized = value.trim().toLowerCase();
|
|
13
|
+
if (["1", "true", "yes", "on"].includes(normalized)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
if (["0", "false", "no", "off"].includes(normalized)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
/** Reads `USE_OPENROUTER` from process env (loading `.env` once when unset). */
|
|
22
|
+
export function readUseOpenRouterFromEnv() {
|
|
23
|
+
ensureDotenvLoaded();
|
|
24
|
+
const raw = process.env.USE_OPENROUTER;
|
|
25
|
+
if (raw === undefined || raw.trim() === "") {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
return parseBooleanEnv(raw);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolves whether to route via OpenRouter.
|
|
32
|
+
* Explicit option wins, then `USE_OPENROUTER` env, then default `true`.
|
|
33
|
+
*/
|
|
34
|
+
export function resolveUseOpenRouter(explicit) {
|
|
35
|
+
if (explicit !== undefined) {
|
|
36
|
+
return explicit;
|
|
37
|
+
}
|
|
38
|
+
return readUseOpenRouterFromEnv() ?? true;
|
|
39
|
+
}
|
|
40
|
+
export function isRemoteProfileChoice(choice) {
|
|
41
|
+
if (choice.provider === "local") {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (choice.modelId.startsWith("funcx:") || choice.modelId.startsWith("Xenova/")) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
export { buildOpenRouterModelId };
|
|
50
|
+
export function applyModelRouting(choice, backend, useOpenRouter) {
|
|
51
|
+
const vendorModelId = getChoiceVendorModelId(choice);
|
|
52
|
+
if (!isRemoteProfileChoice(choice) || !useOpenRouter) {
|
|
53
|
+
return {
|
|
54
|
+
provider: choice.provider,
|
|
55
|
+
modelId: vendorModelId,
|
|
56
|
+
backend: useOpenRouter ? backend : backend === "openrouter" ? "custom" : backend,
|
|
57
|
+
routing: "direct",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const openRouterModelId = getChoiceOpenRouterModelId(choice) ??
|
|
61
|
+
buildModelInvocationFromChoice(choice).openrouter?.modelId ??
|
|
62
|
+
buildOpenRouterModelId(choice.provider, vendorModelId);
|
|
63
|
+
return {
|
|
64
|
+
provider: "openrouter",
|
|
65
|
+
modelId: openRouterModelId,
|
|
66
|
+
backend: "openrouter",
|
|
67
|
+
routing: "openrouter",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=resolveModelRouting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveModelRouting.js","sourceRoot":"","sources":["../src/resolveModelRouting.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Registry types for {@link https://github.com/x12i/ai-profiles | @x12i/ai-profiles}.
|
|
3
|
+
*
|
|
4
|
+
* An **AI profile** is a capability contract (e.g. `cheap`, `deep`, `json`) — what kind of
|
|
5
|
+
* work is needed — not a specific model. Each profile has a **default choice** and optional
|
|
6
|
+
* **choices** (alternatives) that map intent to `provider`, `modelId`, pricing, and runtime
|
|
7
|
+
* defaults. Tasks should reference profiles (and optional choices), not vendor model names.
|
|
8
|
+
*
|
|
9
|
+
* @see README.md — “Why AI profiles” for the full design rationale.
|
|
10
|
+
*/
|
|
11
|
+
export type AIProvider = "openai" | "anthropic" | "google" | "deepseek" | "mistral" | "groq" | "together" | "xai" | "local" | "custom" | "openrouter";
|
|
2
12
|
export type InstructionTier = "default" | "cpu" | "reasoning";
|
|
3
13
|
export type AIProfileBackend = "openrouter" | "llama-cpp" | "transformersjs" | "custom";
|
|
4
14
|
export interface AIModelPricing {
|
|
@@ -31,27 +41,121 @@ export interface AIRuntimeDefaults {
|
|
|
31
41
|
instructionTier?: InstructionTier;
|
|
32
42
|
backend?: AIProfileBackend;
|
|
33
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* One implementation option within a profile (e.g. `default`, `cost_floor`, `openai_deep`).
|
|
46
|
+
* Choices let the same profile intent use different providers, cost/quality trade-offs, or
|
|
47
|
+
* capabilities (long context, batch execution) without changing caller code.
|
|
48
|
+
*/
|
|
49
|
+
export interface ProfileChoiceApi {
|
|
50
|
+
defaultTransport: "openrouter" | "direct";
|
|
51
|
+
vendorModelId: string;
|
|
52
|
+
openRouterModelId?: string | null;
|
|
53
|
+
}
|
|
54
|
+
export interface ProfileChoicePricingV2 {
|
|
55
|
+
billingModel: "token" | "self_hosted";
|
|
56
|
+
currency: "USD";
|
|
57
|
+
unit: "1M_tokens";
|
|
58
|
+
priceStatus?: "standard" | "promotional" | "estimated";
|
|
59
|
+
notes?: string;
|
|
60
|
+
standard?: {
|
|
61
|
+
input?: number;
|
|
62
|
+
output?: number;
|
|
63
|
+
cachedInput?: number;
|
|
64
|
+
};
|
|
65
|
+
batch?: {
|
|
66
|
+
input?: number;
|
|
67
|
+
output?: number;
|
|
68
|
+
};
|
|
69
|
+
cache?: {
|
|
70
|
+
write5m?: number;
|
|
71
|
+
write1h?: number;
|
|
72
|
+
hit?: number;
|
|
73
|
+
write?: number;
|
|
74
|
+
};
|
|
75
|
+
futureStandard?: {
|
|
76
|
+
input?: number;
|
|
77
|
+
output?: number;
|
|
78
|
+
validUntil?: string;
|
|
79
|
+
notes?: string;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export interface ProfileChoiceVerification {
|
|
83
|
+
lastVerifiedAt?: string;
|
|
84
|
+
sourceRefs?: string[];
|
|
85
|
+
}
|
|
86
|
+
export interface ProfileChoiceLimits {
|
|
87
|
+
contextWindow?: number;
|
|
88
|
+
maxOutputTokens?: number;
|
|
89
|
+
}
|
|
90
|
+
export type ModelAvailabilityStatus = "verified" | "predicted";
|
|
91
|
+
export type DeploymentType = "proprietary" | "openWeightsHosted" | "selfHosted";
|
|
92
|
+
export interface ProfileRequiredCapabilities {
|
|
93
|
+
reasoning?: "minimal" | "low" | "medium" | "high" | "max";
|
|
94
|
+
coding?: boolean;
|
|
95
|
+
context?: "standard" | "large" | "xlarge";
|
|
96
|
+
cost?: "low" | "medium" | "high";
|
|
97
|
+
speed?: "high";
|
|
98
|
+
latency?: "low";
|
|
99
|
+
quality?: "high" | "premium";
|
|
100
|
+
structuredOutput?: boolean;
|
|
101
|
+
supportsJsonSchema?: boolean;
|
|
102
|
+
supportsVision?: boolean;
|
|
103
|
+
supportsTools?: boolean;
|
|
104
|
+
}
|
|
105
|
+
export interface ModelCapabilitiesSnapshot {
|
|
106
|
+
contextWindow?: number;
|
|
107
|
+
maxOutputTokens?: number;
|
|
108
|
+
supportsVision?: boolean;
|
|
109
|
+
supportsTools?: boolean;
|
|
110
|
+
supportsReasoning?: boolean;
|
|
111
|
+
supportsJsonSchema?: boolean;
|
|
112
|
+
supportsCaching?: boolean;
|
|
113
|
+
supportsBatch?: boolean;
|
|
114
|
+
supportsStreaming?: boolean;
|
|
115
|
+
}
|
|
34
116
|
export interface AIProfileChoice {
|
|
35
117
|
choice: string;
|
|
36
118
|
displayName: string;
|
|
37
119
|
description: string;
|
|
120
|
+
/** Canonical vendor-native model identifier. */
|
|
38
121
|
provider: AIProvider;
|
|
39
122
|
modelId: string;
|
|
40
|
-
|
|
123
|
+
/** Whether the SKU is production-stable or a forward-looking placeholder. */
|
|
124
|
+
modelStatus?: ModelAvailabilityStatus;
|
|
125
|
+
/** How the model is operated when not a proprietary vendor API. */
|
|
126
|
+
deploymentType?: DeploymentType;
|
|
127
|
+
/** Transport mapping (v2 registry). */
|
|
128
|
+
api?: ProfileChoiceApi;
|
|
129
|
+
/** Legacy flat pricing and/or v2 nested pricing blocks. */
|
|
130
|
+
pricing?: AIModelPricing | ProfileChoicePricingV2;
|
|
41
131
|
runtime?: AIRuntimeDefaults;
|
|
42
132
|
reason?: string;
|
|
43
133
|
status?: "active" | "experimental" | "deprecated";
|
|
134
|
+
verification?: ProfileChoiceVerification;
|
|
135
|
+
limits?: ProfileChoiceLimits;
|
|
44
136
|
metadata?: Record<string, unknown>;
|
|
45
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Capability contract for a class of AI work (cost, speed, reasoning, structured output,
|
|
140
|
+
* agentic tools, research, local inference). Resolved via {@link resolveAIProfile}.
|
|
141
|
+
*/
|
|
46
142
|
export interface AIProfileDefinition {
|
|
47
143
|
profile: string;
|
|
48
144
|
displayName: string;
|
|
49
145
|
description: string;
|
|
146
|
+
/** Grouping for filtering (`cost`, `speed`, `standard`, `reasoning`, `output`, `agentic`, `research`, `local`). */
|
|
50
147
|
category: string;
|
|
51
148
|
/** Many alternate names for this profile (see `matchProfileInput`). */
|
|
52
149
|
aliases?: string[];
|
|
53
150
|
defaultChoice: string;
|
|
54
151
|
choices: Record<string, AIProfileChoice>;
|
|
152
|
+
/** Intent contract for dynamic model selection (Optimixer). */
|
|
153
|
+
requiredCapabilities?: ProfileRequiredCapabilities;
|
|
154
|
+
/** Profile-level deployment strategy (e.g. open weights). */
|
|
155
|
+
deploymentType?: DeploymentType;
|
|
156
|
+
/** Deterministic failover order when trimming vendors or choices. */
|
|
157
|
+
fallbackChoiceOrder?: string[];
|
|
158
|
+
intendedUseCases?: string[];
|
|
55
159
|
status?: "active" | "experimental" | "deprecated";
|
|
56
160
|
runtime?: AIRuntimeDefaults;
|
|
57
161
|
metadata?: Record<string, unknown>;
|
|
@@ -61,11 +165,25 @@ export interface AIProfileShortcut {
|
|
|
61
165
|
choice?: string;
|
|
62
166
|
description?: string;
|
|
63
167
|
}
|
|
168
|
+
export type ModelsProfilesSchemaId = "x12i.ai-profiles.models-profiles" | "x12i.ai-profiles.model-registry.v2" | "x12i.ai-profiles.model-registry.v3";
|
|
64
169
|
export interface ModelsProfilesJson {
|
|
65
|
-
schema:
|
|
170
|
+
schema: ModelsProfilesSchemaId;
|
|
171
|
+
registryId?: string;
|
|
66
172
|
/** Optional label in source JSON; not used for compatibility or selection logic. */
|
|
67
173
|
version?: string;
|
|
68
174
|
generatedAt?: string;
|
|
175
|
+
lastVerifiedAt?: string;
|
|
176
|
+
namingConvention?: string;
|
|
177
|
+
semantics?: Record<string, string>;
|
|
178
|
+
sourceCatalog?: {
|
|
179
|
+
providers: Array<{
|
|
180
|
+
id: string;
|
|
181
|
+
docsUrl?: string;
|
|
182
|
+
}>;
|
|
183
|
+
modelsCatalogUrl?: string;
|
|
184
|
+
/** @deprecated Use modelsCatalogUrl */
|
|
185
|
+
openRouterCatalogUrl?: string;
|
|
186
|
+
};
|
|
69
187
|
currency: "USD";
|
|
70
188
|
pricingUnit: "1M_tokens";
|
|
71
189
|
profiles: Record<string, AIProfileDefinition>;
|
|
@@ -111,9 +229,149 @@ export interface AIShortcutSummary {
|
|
|
111
229
|
description?: string;
|
|
112
230
|
}
|
|
113
231
|
export interface AIProfileWarning {
|
|
114
|
-
code: "USING_BUNDLED_FALLBACK" | "PROFILE_DEPRECATED" | "CHOICE_DEPRECATED" | "PRICING_MISSING" | "REMOTE_REFRESH_FAILED_USING_CACHE";
|
|
232
|
+
code: "USING_BUNDLED_FALLBACK" | "PROFILE_DEPRECATED" | "CHOICE_DEPRECATED" | "PRICING_MISSING" | "MODEL_PREDICTED" | "PRICING_FROM_CATALOG" | "REMOTE_REFRESH_FAILED_USING_CACHE" | "OPENROUTER_UNAVAILABLE";
|
|
115
233
|
message: string;
|
|
116
234
|
}
|
|
235
|
+
export interface ModelInvocationEndpoint {
|
|
236
|
+
provider: AIProvider;
|
|
237
|
+
modelId: string;
|
|
238
|
+
}
|
|
239
|
+
export interface ModelInvocation {
|
|
240
|
+
direct: ModelInvocationEndpoint;
|
|
241
|
+
openrouter: ModelInvocationEndpoint | null;
|
|
242
|
+
}
|
|
243
|
+
export type ModelRegistryKind = "linked" | "openrouter-only" | "local-only" | "faulty";
|
|
244
|
+
export type ModelLinkageStatus = "matched" | "faulty" | "skipped" | "catalog-miss";
|
|
245
|
+
export interface ModelRegistryLinkage {
|
|
246
|
+
status: ModelLinkageStatus;
|
|
247
|
+
openRouterCatalogId?: string;
|
|
248
|
+
canonicalSlug?: string;
|
|
249
|
+
matchMethod?: string;
|
|
250
|
+
exemptReason?: string;
|
|
251
|
+
}
|
|
252
|
+
export interface ModelRegistryEntry {
|
|
253
|
+
registryKey: string;
|
|
254
|
+
kind: ModelRegistryKind;
|
|
255
|
+
vendor: ModelInvocationEndpoint;
|
|
256
|
+
invocation: ModelInvocation;
|
|
257
|
+
linkage: ModelRegistryLinkage;
|
|
258
|
+
usage: {
|
|
259
|
+
profileChoices: Array<{
|
|
260
|
+
profile: string;
|
|
261
|
+
choice: string;
|
|
262
|
+
}>;
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
export interface ModelsRegistryJson {
|
|
266
|
+
schema: "x12i.ai-profiles.models-registry";
|
|
267
|
+
version?: string;
|
|
268
|
+
generatedAt?: string;
|
|
269
|
+
inputs?: {
|
|
270
|
+
openRouterCatalog?: {
|
|
271
|
+
schema?: string;
|
|
272
|
+
version?: string;
|
|
273
|
+
generatedAt?: string;
|
|
274
|
+
modelCount?: number;
|
|
275
|
+
};
|
|
276
|
+
modelsProfiles?: {
|
|
277
|
+
version?: string;
|
|
278
|
+
generatedAt?: string;
|
|
279
|
+
choiceCount?: number;
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
models: Record<string, ModelRegistryEntry>;
|
|
283
|
+
}
|
|
284
|
+
export interface CatalogOpenRouterPricing {
|
|
285
|
+
input?: number;
|
|
286
|
+
output?: number;
|
|
287
|
+
cachedInput?: number;
|
|
288
|
+
cacheWrite?: number;
|
|
289
|
+
batchInput?: number;
|
|
290
|
+
batchOutput?: number;
|
|
291
|
+
imageInput?: number;
|
|
292
|
+
audioInput?: number;
|
|
293
|
+
internalReasoning?: number;
|
|
294
|
+
webSearchPerRequest?: number;
|
|
295
|
+
}
|
|
296
|
+
export interface CatalogOpenRouterCapabilities {
|
|
297
|
+
reasoning?: boolean;
|
|
298
|
+
toolCalling?: boolean;
|
|
299
|
+
structuredOutputs?: boolean;
|
|
300
|
+
imageGeneration?: boolean;
|
|
301
|
+
}
|
|
302
|
+
export interface CatalogDirectSlice {
|
|
303
|
+
provider: AIProvider;
|
|
304
|
+
modelId: string;
|
|
305
|
+
/**
|
|
306
|
+
* OpenRouter slug prefix when `provider` is `custom` (e.g. `qwen` for `qwen/qwen3.7-max`).
|
|
307
|
+
* Not used for API calls — documents the upstream vendor namespace.
|
|
308
|
+
*/
|
|
309
|
+
vendorNamespace?: string;
|
|
310
|
+
}
|
|
311
|
+
export interface CatalogOpenRouterSlice {
|
|
312
|
+
provider: "openrouter";
|
|
313
|
+
modelId: string;
|
|
314
|
+
canonicalSlug?: string;
|
|
315
|
+
status?: string;
|
|
316
|
+
modalities?: {
|
|
317
|
+
input?: string[];
|
|
318
|
+
output?: string[];
|
|
319
|
+
};
|
|
320
|
+
contextWindow?: number;
|
|
321
|
+
maxCompletionTokens?: number;
|
|
322
|
+
knowledgeCutoff?: string;
|
|
323
|
+
pricing?: CatalogOpenRouterPricing;
|
|
324
|
+
capabilities?: CatalogOpenRouterCapabilities;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Unified catalog model: two explicit call shapes (never conflate them).
|
|
328
|
+
* - `direct` — vendor-native / direct API identity
|
|
329
|
+
* - `openrouter` — OpenRouter transport (`provider` is always `openrouter`)
|
|
330
|
+
*/
|
|
331
|
+
export interface CatalogModelEntry {
|
|
332
|
+
direct: CatalogDirectSlice;
|
|
333
|
+
openrouter: CatalogOpenRouterSlice;
|
|
334
|
+
displayName?: string;
|
|
335
|
+
family?: string;
|
|
336
|
+
status?: string;
|
|
337
|
+
modalities?: CatalogOpenRouterSlice["modalities"];
|
|
338
|
+
contextWindow?: number;
|
|
339
|
+
maxCompletionTokens?: number;
|
|
340
|
+
knowledgeCutoff?: string;
|
|
341
|
+
}
|
|
342
|
+
export interface ModelsCatalogJson {
|
|
343
|
+
schema: "x12i.ai-profiles.models-catalog";
|
|
344
|
+
version?: string;
|
|
345
|
+
generatedAt?: string;
|
|
346
|
+
currency: "USD";
|
|
347
|
+
pricingUnit: "1M_tokens";
|
|
348
|
+
sources: {
|
|
349
|
+
openrouter: {
|
|
350
|
+
catalogUrl: string;
|
|
351
|
+
pricingUrl?: string;
|
|
352
|
+
verifiedAt?: string;
|
|
353
|
+
normalization?: string;
|
|
354
|
+
};
|
|
355
|
+
};
|
|
356
|
+
notes?: string[];
|
|
357
|
+
models: CatalogModelEntry[];
|
|
358
|
+
}
|
|
359
|
+
/** @deprecated Use {@link ModelsCatalogJson} */
|
|
360
|
+
export type OpenRouterModelsCatalogJson = ModelsCatalogJson;
|
|
361
|
+
export interface ProfileVendorCoverageResult {
|
|
362
|
+
profile: string;
|
|
363
|
+
leadingVendorsPresent: AIProvider[];
|
|
364
|
+
leadingVendorsMissing: AIProvider[];
|
|
365
|
+
nonLeadingChoices: Array<{
|
|
366
|
+
choice: string;
|
|
367
|
+
provider: AIProvider;
|
|
368
|
+
}>;
|
|
369
|
+
}
|
|
370
|
+
export interface ValidateProfileVendorCoverageResult {
|
|
371
|
+
ok: boolean;
|
|
372
|
+
profiles: ProfileVendorCoverageResult[];
|
|
373
|
+
}
|
|
374
|
+
/** Materialized profile + choice: model, pricing, runtime, and routing after registry resolution. */
|
|
117
375
|
export interface ResolvedAIProfile {
|
|
118
376
|
input: string;
|
|
119
377
|
profile: string;
|
|
@@ -125,12 +383,20 @@ export interface ResolvedAIProfile {
|
|
|
125
383
|
choiceDescription: string;
|
|
126
384
|
provider: AIProvider;
|
|
127
385
|
modelId: string;
|
|
386
|
+
/** How the resolved provider/model were routed (`openrouter` vs vendor-direct). */
|
|
387
|
+
routing: "openrouter" | "direct";
|
|
128
388
|
instructionTier: InstructionTier;
|
|
129
389
|
backend: AIProfileBackend;
|
|
130
390
|
pricing?: AIModelPricing & {
|
|
131
391
|
currency: "USD";
|
|
132
392
|
unit: "1M_tokens";
|
|
133
393
|
};
|
|
394
|
+
/** Echo of choice modelStatus when present. */
|
|
395
|
+
modelStatus?: ModelAvailabilityStatus;
|
|
396
|
+
limits?: ProfileChoiceLimits;
|
|
397
|
+
capabilities?: ModelCapabilitiesSnapshot;
|
|
398
|
+
/** Profile intent contract (from registry definition). */
|
|
399
|
+
requiredCapabilities?: ProfileRequiredCapabilities;
|
|
134
400
|
runtime: Required<AIRuntimeDefaults>;
|
|
135
401
|
metadata?: Record<string, unknown>;
|
|
136
402
|
reason?: string;
|
|
@@ -144,6 +410,8 @@ export interface ResolvedAIProfile {
|
|
|
144
410
|
profile: string;
|
|
145
411
|
choice?: string;
|
|
146
412
|
};
|
|
413
|
+
/** Direct and OpenRouter call shapes for the resolved choice. */
|
|
414
|
+
invocation: ModelInvocation;
|
|
147
415
|
warnings?: AIProfileWarning[];
|
|
148
416
|
}
|
|
149
417
|
export interface ListAIProfilesOptions {
|
|
@@ -159,6 +427,17 @@ export interface ResolveAIProfileOptions {
|
|
|
159
427
|
refresh?: boolean;
|
|
160
428
|
allowFallbackToDefaultChoice?: boolean;
|
|
161
429
|
strict?: boolean;
|
|
430
|
+
/**
|
|
431
|
+
* When true (default), remote models resolve via OpenRouter (`provider: "openrouter"`,
|
|
432
|
+
* `modelId: "{vendor}/{model}"`). When false, use the choice's vendor provider and model id.
|
|
433
|
+
* Falls back to `USE_OPENROUTER` in `.env` when omitted (`1`/`true` → OpenRouter,
|
|
434
|
+
* `0`/`false` → direct). Azure and AWS routing are not supported yet.
|
|
435
|
+
*/
|
|
436
|
+
useOpenRouter?: boolean;
|
|
437
|
+
/** Restrict resolution to these vendors; auto-picks when default is outside the set. */
|
|
438
|
+
allowedProviders?: AIProvider[];
|
|
439
|
+
/** When auto-picking, rank {@link LEADING_VENDORS} ahead of other providers (default true). */
|
|
440
|
+
preferLeadingVendors?: boolean;
|
|
162
441
|
}
|
|
163
442
|
export interface LoadRegistryOptions {
|
|
164
443
|
source?: RegistrySourceMode;
|
|
@@ -168,4 +447,69 @@ export interface LoadRegistryResult {
|
|
|
168
447
|
registry: AIProfilesRegistry;
|
|
169
448
|
warnings: AIProfileWarning[];
|
|
170
449
|
}
|
|
450
|
+
export interface ProfileStatisticsFilter {
|
|
451
|
+
includeDeprecated?: boolean;
|
|
452
|
+
includeExperimental?: boolean;
|
|
453
|
+
category?: string;
|
|
454
|
+
}
|
|
455
|
+
export interface GetAIRegistryStatisticsOptions extends LoadRegistryOptions {
|
|
456
|
+
/** Include models catalog counts (default true). */
|
|
457
|
+
includeCatalog?: boolean;
|
|
458
|
+
/** Include profile↔catalog linkage counts (default true). */
|
|
459
|
+
includeLinkage?: boolean;
|
|
460
|
+
includeDeprecated?: boolean;
|
|
461
|
+
includeExperimental?: boolean;
|
|
462
|
+
category?: string;
|
|
463
|
+
}
|
|
464
|
+
export interface AIRegistryStatistics {
|
|
465
|
+
schema: "x12i.ai-profiles.registry-statistics";
|
|
466
|
+
generatedAt: string;
|
|
467
|
+
sources: {
|
|
468
|
+
profiles: "remote" | "bundled";
|
|
469
|
+
catalog?: "remote" | "bundled";
|
|
470
|
+
};
|
|
471
|
+
registry: {
|
|
472
|
+
version?: string;
|
|
473
|
+
loadedAt: string;
|
|
474
|
+
currency: "USD";
|
|
475
|
+
pricingUnit: "1M_tokens";
|
|
476
|
+
};
|
|
477
|
+
profiles: {
|
|
478
|
+
total: number;
|
|
479
|
+
choices: number;
|
|
480
|
+
aliases: number;
|
|
481
|
+
uniqueProviders: number;
|
|
482
|
+
providers: AIProvider[];
|
|
483
|
+
uniqueModelKeys: number;
|
|
484
|
+
uniqueVendorModelIds: number;
|
|
485
|
+
byStatus: Record<string, number>;
|
|
486
|
+
byCategory: Record<string, number>;
|
|
487
|
+
categories: string[];
|
|
488
|
+
averageChoicesPerProfile: number;
|
|
489
|
+
};
|
|
490
|
+
shortcuts: {
|
|
491
|
+
total: number;
|
|
492
|
+
};
|
|
493
|
+
catalog?: {
|
|
494
|
+
totalModels: number;
|
|
495
|
+
uniqueDirectProviders: number;
|
|
496
|
+
directProviders: string[];
|
|
497
|
+
active: number;
|
|
498
|
+
deprecated: number;
|
|
499
|
+
withPricing: number;
|
|
500
|
+
withReasoningCapability: number;
|
|
501
|
+
catalogVersion?: string;
|
|
502
|
+
generatedAt?: string;
|
|
503
|
+
};
|
|
504
|
+
linkage?: {
|
|
505
|
+
registryEntries: number;
|
|
506
|
+
profileChoiceReferences: number;
|
|
507
|
+
byLinkageStatus: Record<string, number>;
|
|
508
|
+
byKind: Record<string, number>;
|
|
509
|
+
matched: number;
|
|
510
|
+
faulty: number;
|
|
511
|
+
catalogMiss: number;
|
|
512
|
+
skipped: number;
|
|
513
|
+
};
|
|
514
|
+
}
|
|
171
515
|
//# sourceMappingURL=types.d.ts.map
|