@x12i/ai-profiles 2.0.1 → 2.1.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 (79) hide show
  1. package/README.md +147 -44
  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 +9 -2
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +6 -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/profileChoiceKey.d.ts +35 -0
  38. package/dist/profileChoiceKey.d.ts.map +1 -0
  39. package/dist/profileChoiceKey.js +81 -0
  40. package/dist/profileChoiceKey.js.map +1 -0
  41. package/dist/profileDiscoveryMatch.d.ts +15 -0
  42. package/dist/profileDiscoveryMatch.d.ts.map +1 -0
  43. package/dist/profileDiscoveryMatch.js +17 -0
  44. package/dist/profileDiscoveryMatch.js.map +1 -0
  45. package/dist/resolveAIProfile.d.ts +4 -5
  46. package/dist/resolveAIProfile.d.ts.map +1 -1
  47. package/dist/resolveAIProfile.js +51 -81
  48. package/dist/resolveAIProfile.js.map +1 -1
  49. package/dist/resolveAIProfileByTags.d.ts +2 -2
  50. package/dist/resolveAIProfileByTags.d.ts.map +1 -1
  51. package/dist/resolveAIProfileByTags.js +28 -10
  52. package/dist/resolveAIProfileByTags.js.map +1 -1
  53. package/dist/resolveAIProfileWithCostAlternatives.d.ts +17 -0
  54. package/dist/resolveAIProfileWithCostAlternatives.d.ts.map +1 -0
  55. package/dist/resolveAIProfileWithCostAlternatives.js +129 -0
  56. package/dist/resolveAIProfileWithCostAlternatives.js.map +1 -0
  57. package/dist/resolveCatalogModel.d.ts +7 -0
  58. package/dist/resolveCatalogModel.d.ts.map +1 -0
  59. package/dist/resolveCatalogModel.js +34 -0
  60. package/dist/resolveCatalogModel.js.map +1 -0
  61. package/dist/resolveSecondaryModel.d.ts.map +1 -1
  62. package/dist/resolveSecondaryModel.js +17 -8
  63. package/dist/resolveSecondaryModel.js.map +1 -1
  64. package/dist/secondaryModel.d.ts +0 -5
  65. package/dist/secondaryModel.d.ts.map +1 -1
  66. package/dist/secondaryModel.js +1 -13
  67. package/dist/secondaryModel.js.map +1 -1
  68. package/dist/types.d.ts +87 -8
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/validateProfileCatalogLinkage.d.ts.map +1 -1
  71. package/dist/validateProfileCatalogLinkage.js +2 -1
  72. package/dist/validateProfileCatalogLinkage.js.map +1 -1
  73. package/dist/validation/validateModelsProfilesJson.d.ts.map +1 -1
  74. package/dist/validation/validateModelsProfilesJson.js +11 -7
  75. package/dist/validation/validateModelsProfilesJson.js.map +1 -1
  76. package/dist/vendorPolicy.d.ts.map +1 -1
  77. package/dist/vendorPolicy.js +1 -6
  78. package/dist/vendorPolicy.js.map +1 -1
  79. package/package.json +1 -1
@@ -1,11 +1,10 @@
1
1
  import type { ResolveAIProfileOptions, ResolvedAIProfile } from "./types.js";
2
2
  /**
3
- * Resolve a profile primary key, alias, or shortcut to a concrete model and runtime config.
3
+ * Resolve an explicit `profile/choice` key (or a shortcut that pins both) to a concrete model.
4
4
  *
5
- * `input` names **intent** (e.g. `balanced`, `cheapest`, `cost-sensitive`), not a vendor model id.
6
- * Use `options.choice` to pick an alternative within the profile (e.g. `cheap` + `anthropic_cheap`).
7
- *
8
- * @see README.md — “Why AI profiles”
5
+ * For discovery (tags, search, profile-level intent), use {@link listAIProfiles},
6
+ * {@link resolveAIProfileByTags}, or {@link resolveAIProfileWithCostAlternatives}.
7
+ * For raw model SKUs, use {@link resolveCatalogModel}.
9
8
  */
10
9
  export declare function resolveAIProfile(input: string, options: ResolveAIProfileOptions): Promise<ResolvedAIProfile>;
11
10
  //# sourceMappingURL=resolveAIProfile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolveAIProfile.d.ts","sourceRoot":"","sources":["../src/resolveAIProfile.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE7E;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CA8O5B"}
1
+ {"version":3,"file":"resolveAIProfile.d.ts","sourceRoot":"","sources":["../src/resolveAIProfile.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE7E;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAoM5B"}
@@ -2,20 +2,18 @@ import { buildResolvedProfile } from "./buildResolvedProfile.js";
2
2
  import { AIProfilesError } from "./errors.js";
3
3
  import { loadAIProfilesRegistryWithWarnings } from "./loader/loadAIProfilesRegistry.js";
4
4
  import { loadModelsCatalogWithWarnings } from "./loader/loadModelsCatalog.js";
5
- import { matchProfileInput } from "./profileInputMatch.js";
6
- import { buildResolvedModelInput, modelInputLogMeta, resolveModelFromInput, } from "./modelInputFallback.js";
5
+ import { formatProfileChoiceKey, matchStrictProfileInput, } from "./profileChoiceKey.js";
7
6
  import { pickProfileChoiceWithConstraints } from "./modalityPolicy.js";
8
7
  import { normalizeCostCap } from "./costPolicy.js";
9
- import { logxer } from "./logger.js";
8
+ import { resolveCostTierCap } from "./costTiers.js";
10
9
  import { assertOpenRouterCatalogCoverage, assertProfileCatalogLane, } from "./profileCatalogLane.js";
11
10
  import { attachSecondaryToResolved } from "./resolveSecondaryModel.js";
12
11
  /**
13
- * Resolve a profile primary key, alias, or shortcut to a concrete model and runtime config.
12
+ * Resolve an explicit `profile/choice` key (or a shortcut that pins both) to a concrete model.
14
13
  *
15
- * `input` names **intent** (e.g. `balanced`, `cheapest`, `cost-sensitive`), not a vendor model id.
16
- * Use `options.choice` to pick an alternative within the profile (e.g. `cheap` + `anthropic_cheap`).
17
- *
18
- * @see README.md — “Why AI profiles”
14
+ * For discovery (tags, search, profile-level intent), use {@link listAIProfiles},
15
+ * {@link resolveAIProfileByTags}, or {@link resolveAIProfileWithCostAlternatives}.
16
+ * For raw model SKUs, use {@link resolveCatalogModel}.
19
17
  */
20
18
  export async function resolveAIProfile(input, options) {
21
19
  if (!options.catalogLane) {
@@ -32,70 +30,39 @@ export async function resolveAIProfile(input, options) {
32
30
  }),
33
31
  ]);
34
32
  const loaderWarnings = [...warnings, ...catalogResult.warnings];
35
- const match = matchProfileInput(registry, input);
36
- const modelFallback = match
37
- ? undefined
38
- : resolveModelFromInput(input, catalogResult.catalog);
33
+ const match = matchStrictProfileInput(registry, input);
39
34
  if (!match) {
40
- if (modelFallback) {
41
- const meta = modelInputLogMeta(input, modelFallback);
42
- if (modelFallback.confidence === "low") {
43
- logxer.warn("Best-effort AI model fallback for model-like input", meta);
44
- }
45
- else {
46
- logxer.info("Resolved model-like input to catalog model", meta);
47
- }
48
- return buildResolvedModelInput({
49
- input,
50
- match: modelFallback,
51
- registry,
52
- loaderWarnings,
53
- useOpenRouter: options.useOpenRouter,
54
- });
55
- }
56
- throw new AIProfilesError("UNKNOWN_PROFILE", `Unknown AI profile, shortcut, or alias: ${input}`, { input });
35
+ throw new AIProfilesError("UNKNOWN_PROFILE_CHOICE", `Unknown profile/choice key: ${input}. Use "profile/choice" (e.g. "cheap/default") or a shortcut that pins both.`, { input });
57
36
  }
58
- let profileKey;
59
- let requestedChoiceKey;
60
- let matchedShortcut;
61
- switch (match.kind) {
62
- case "profile":
63
- profileKey = match.profileKey;
64
- requestedChoiceKey = options.choice;
65
- matchedShortcut = undefined;
66
- break;
67
- case "shortcut":
68
- profileKey = match.profileKey;
69
- requestedChoiceKey = options.choice ?? match.shortcut.choice;
70
- matchedShortcut = match.shortcut;
71
- break;
72
- case "alias":
73
- profileKey = match.profileKey;
74
- requestedChoiceKey = options.choice;
75
- matchedShortcut = undefined;
76
- break;
37
+ if (match.kind === "invalidChoice") {
38
+ throw new AIProfilesError("UNKNOWN_CHOICE", `Unknown choice '${match.choice}' for AI profile '${match.profile}'`, { input, profile: match.profile, choice: match.choice });
77
39
  }
40
+ const profileKey = match.profile;
41
+ const requestedChoiceKey = match.choice;
42
+ const matchedShortcut = match.kind === "shortcut"
43
+ ? registry.shortcuts[match.shortcutKey]
44
+ : undefined;
78
45
  const profile = registry.profiles[profileKey];
79
46
  if (!profile) {
80
47
  throw new AIProfilesError("UNKNOWN_PROFILE", `Unknown AI profile: ${profileKey}`, { input, profile: profileKey });
81
48
  }
82
- if (options.catalogLane) {
83
- try {
84
- assertProfileCatalogLane({
85
- profileKey,
86
- profile,
87
- requestedLane: options.catalogLane,
88
- });
89
- }
90
- catch (error) {
91
- const message = error instanceof Error ? error.message : String(error);
92
- throw new AIProfilesError("CATALOG_LANE_MISMATCH", message, {
93
- input,
94
- profile: profileKey,
95
- catalogLane: options.catalogLane,
96
- });
97
- }
49
+ try {
50
+ assertProfileCatalogLane({
51
+ profileKey,
52
+ profile,
53
+ requestedLane: options.catalogLane,
54
+ });
55
+ }
56
+ catch (error) {
57
+ const message = error instanceof Error ? error.message : String(error);
58
+ throw new AIProfilesError("CATALOG_LANE_MISMATCH", message, {
59
+ input,
60
+ profile: profileKey,
61
+ catalogLane: options.catalogLane,
62
+ });
98
63
  }
64
+ const costCapPer1M = options.costCapPer1M ??
65
+ resolveCostTierCap(options.costTier, options.costTiers);
99
66
  let finalChoiceKey;
100
67
  let choice;
101
68
  try {
@@ -103,11 +70,12 @@ export async function resolveAIProfile(input, options) {
103
70
  choiceKey: requestedChoiceKey,
104
71
  allowedProviders: options.allowedProviders,
105
72
  preferLeadingVendors: options.preferLeadingVendors ?? true,
106
- explicitChoiceRequested: options.choice !== undefined ||
107
- (match.kind === "shortcut" && match.shortcut.choice !== undefined),
73
+ explicitChoiceRequested: true,
108
74
  inputModalities: options.inputModalities,
109
75
  outputModalities: options.outputModalities,
110
- costCapPer1M: options.costCapPer1M,
76
+ costCapPer1M,
77
+ capabilityFilter: options.capabilityFilter,
78
+ focus: options.focus,
111
79
  catalog: catalogResult.catalog,
112
80
  });
113
81
  finalChoiceKey = picked.choiceKey;
@@ -119,10 +87,8 @@ export async function resolveAIProfile(input, options) {
119
87
  throw new AIProfilesError("NO_ALLOWED_VENDOR", message, {
120
88
  input,
121
89
  profile: profileKey,
90
+ choice: requestedChoiceKey,
122
91
  allowedProviders: options.allowedProviders,
123
- availableProviders: [
124
- ...new Set(Object.values(profile.choices).map((c) => c.provider)),
125
- ],
126
92
  });
127
93
  }
128
94
  if (message.includes("required modalities")) {
@@ -139,22 +105,26 @@ export async function resolveAIProfile(input, options) {
139
105
  input,
140
106
  profile: profileKey,
141
107
  choice: requestedChoiceKey,
142
- costCapPer1M: options.costCapPer1M,
108
+ costCapPer1M,
143
109
  });
144
110
  }
145
111
  if (message.startsWith("Unknown choice")) {
146
- if (options.allowFallbackToDefaultChoice) {
147
- return resolveAIProfile(profileKey, {
148
- ...options,
149
- choice: profile.defaultChoice,
150
- });
151
- }
152
- throw new AIProfilesError("UNKNOWN_CHOICE", message, { input, profile: profileKey, choice: requestedChoiceKey });
112
+ throw new AIProfilesError("UNKNOWN_CHOICE", message, {
113
+ input,
114
+ profile: profileKey,
115
+ choice: requestedChoiceKey,
116
+ });
153
117
  }
154
118
  throw error;
155
119
  }
156
- if (!profile.choices[finalChoiceKey]) {
157
- throw new AIProfilesError("UNKNOWN_CHOICE", `Unknown choice '${finalChoiceKey}' for AI profile '${profileKey}'`, { input, profile: profileKey, choice: finalChoiceKey });
120
+ if (finalChoiceKey !== requestedChoiceKey) {
121
+ throw new AIProfilesError("CHOICE_SUBSTITUTED", `Explicit choice '${requestedChoiceKey}' was replaced with '${finalChoiceKey}' for profile '${profileKey}'. Use a different profile/choice key or discovery APIs.`, {
122
+ input,
123
+ profile: profileKey,
124
+ choice: requestedChoiceKey,
125
+ resolvedChoice: finalChoiceKey,
126
+ expectedKey: formatProfileChoiceKey(profileKey, requestedChoiceKey),
127
+ });
158
128
  }
159
129
  const enforceOpenRouterCatalog = profileKey === "local"
160
130
  ? options.requireOpenRouterCatalog === true
@@ -190,7 +160,7 @@ export async function resolveAIProfile(input, options) {
190
160
  loaderWarnings,
191
161
  useOpenRouter: options.useOpenRouter,
192
162
  catalog: catalogResult.catalog,
193
- costCapApplied: normalizeCostCap(options.costCapPer1M),
163
+ costCapApplied: normalizeCostCap(costCapPer1M),
194
164
  });
195
165
  if (options.includeSecondary) {
196
166
  return attachSecondaryToResolved(resolved, registry, catalogResult.catalog, options.useOpenRouter);
@@ -1 +1 @@
1
- {"version":3,"file":"resolveAIProfile.js","sourceRoot":"","sources":["../src/resolveAIProfile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolveAIProfile.js","sourceRoot":"","sources":["../src/resolveAIProfile.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,8 @@ export interface ResolveAIProfileByTagsOptions extends ResolveAIProfileOptions {
4
4
  minScore?: number;
5
5
  }
6
6
  /**
7
- * Resolve the best-matching profile for a tag set (partial overlap OK).
8
- * Picks the profile with the most matching tags; see {@link pickBestProfileByTags}.
7
+ * Discovery: pick the best-matching profile by tags, auto-select a choice under constraints,
8
+ * then resolve the resulting `profile/choice` key.
9
9
  */
10
10
  export declare function resolveAIProfileByTags(tags: AIProfileTag[], options: ResolveAIProfileByTagsOptions): Promise<ResolvedAIProfile>;
11
11
  //# sourceMappingURL=resolveAIProfileByTags.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolveAIProfileByTags.d.ts","sourceRoot":"","sources":["../src/resolveAIProfileByTags.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE3F,MAAM,WAAW,6BAA8B,SAAQ,uBAAuB;IAC5E,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,YAAY,EAAE,EACpB,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,iBAAiB,CAAC,CA4C5B"}
1
+ {"version":3,"file":"resolveAIProfileByTags.d.ts","sourceRoot":"","sources":["../src/resolveAIProfileByTags.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE3F,MAAM,WAAW,6BAA8B,SAAQ,uBAAuB;IAC5E,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,YAAY,EAAE,EACpB,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,iBAAiB,CAAC,CA8D5B"}
@@ -1,11 +1,14 @@
1
1
  import { AIProfilesError } from "./errors.js";
2
2
  import { loadAIProfilesRegistryWithWarnings } from "./loader/loadAIProfilesRegistry.js";
3
+ import { loadModelsCatalogWithWarnings } from "./loader/loadModelsCatalog.js";
3
4
  import { profileMatchesCatalogLane } from "./profileCatalogLane.js";
4
5
  import { pickBestProfileByTags } from "./profileDiscovery.js";
6
+ import { formatProfileChoiceKey } from "./profileChoiceKey.js";
7
+ import { pickProfileChoiceWithConstraints } from "./modalityPolicy.js";
5
8
  import { resolveAIProfile } from "./resolveAIProfile.js";
6
9
  /**
7
- * Resolve the best-matching profile for a tag set (partial overlap OK).
8
- * Picks the profile with the most matching tags; see {@link pickBestProfileByTags}.
10
+ * Discovery: pick the best-matching profile by tags, auto-select a choice under constraints,
11
+ * then resolve the resulting `profile/choice` key.
9
12
  */
10
13
  export async function resolveAIProfileByTags(tags, options) {
11
14
  if (!options.catalogLane) {
@@ -15,19 +18,34 @@ export async function resolveAIProfileByTags(tags, options) {
15
18
  if (uniqueTags.length === 0) {
16
19
  throw new AIProfilesError("UNKNOWN_PROFILE", "resolveAIProfileByTags requires at least one tag", { tags });
17
20
  }
18
- const { registry } = await loadAIProfilesRegistryWithWarnings({
19
- source: options.source,
20
- refresh: options.refresh,
21
- });
21
+ const [{ registry }, catalogResult] = await Promise.all([
22
+ loadAIProfilesRegistryWithWarnings({
23
+ source: options.source,
24
+ refresh: options.refresh,
25
+ }),
26
+ loadModelsCatalogWithWarnings({
27
+ source: options.source,
28
+ refresh: options.refresh,
29
+ }),
30
+ ]);
22
31
  const minScore = options.minScore ?? 1;
23
- const pool = options.catalogLane
24
- ? Object.fromEntries(Object.entries(registry.profiles).filter(([, profile]) => profileMatchesCatalogLane(profile, options.catalogLane)))
25
- : registry.profiles;
32
+ const pool = Object.fromEntries(Object.entries(registry.profiles).filter(([, profile]) => profileMatchesCatalogLane(profile, options.catalogLane)));
26
33
  const best = pickBestProfileByTags(pool, uniqueTags);
27
34
  if (!best || best.score < minScore) {
28
35
  throw new AIProfilesError("UNKNOWN_PROFILE", `No profile matches tags: ${uniqueTags.join(", ")}`, { tags: uniqueTags, minScore });
29
36
  }
37
+ const profile = registry.profiles[best.profileKey];
38
+ const picked = pickProfileChoiceWithConstraints(best.profileKey, profile, {
39
+ allowedProviders: options.allowedProviders,
40
+ preferLeadingVendors: options.preferLeadingVendors ?? true,
41
+ explicitChoiceRequested: false,
42
+ inputModalities: options.inputModalities,
43
+ outputModalities: options.outputModalities,
44
+ capabilityFilter: options.capabilityFilter,
45
+ focus: options.focus,
46
+ catalog: catalogResult.catalog,
47
+ });
30
48
  const { minScore: _minScore, ...resolveOptions } = options;
31
- return resolveAIProfile(best.profileKey, resolveOptions);
49
+ return resolveAIProfile(formatProfileChoiceKey(best.profileKey, picked.choiceKey), resolveOptions);
32
50
  }
33
51
  //# sourceMappingURL=resolveAIProfileByTags.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolveAIProfileByTags.js","sourceRoot":"","sources":["../src/resolveAIProfileByTags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,kCAAkC,EAAE,MAAM,oCAAoC,CAAC;AACxF,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAQzD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAoB,EACpB,OAAsC;IAEtC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACzB,MAAM,IAAI,eAAe,CACvB,sBAAsB,EACtB,qDAAqD,EACrD,EAAE,IAAI,EAAE,CACT,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,eAAe,CACvB,iBAAiB,EACjB,kDAAkD,EAClD,EAAE,IAAI,EAAE,CACT,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,kCAAkC,CAAC;QAC5D,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW;QAC9B,CAAC,CAAC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,CACvD,yBAAyB,CAAC,OAAO,EAAE,OAAO,CAAC,WAAY,CAAC,CACzD,CACF;QACH,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAEtB,MAAM,IAAI,GAAG,qBAAqB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAErD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,GAAG,QAAQ,EAAE,CAAC;QACnC,MAAM,IAAI,eAAe,CACvB,iBAAiB,EACjB,4BAA4B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EACnD,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAC/B,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,cAAc,EAAE,GAAG,OAAO,CAAC;IAC3D,OAAO,gBAAgB,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;AAC3D,CAAC"}
1
+ {"version":3,"file":"resolveAIProfileByTags.js","sourceRoot":"","sources":["../src/resolveAIProfileByTags.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { CostTierSpec, ResolveAIProfileOptions, ResolvedAIProfile } from "./types.js";
2
+ export interface ResolveAIProfileWithCostAlternativesResult {
3
+ primary: ResolvedAIProfile;
4
+ alternativesByCostTier: Array<{
5
+ tier: string;
6
+ resolved: ResolvedAIProfile | null;
7
+ reason?: string;
8
+ }>;
9
+ }
10
+ /**
11
+ * Resolve a fixed `profile/choice` and scout alternate choices under other cost-tier caps.
12
+ */
13
+ export declare function resolveAIProfileWithCostAlternatives(input: string, options: ResolveAIProfileOptions & {
14
+ tiers?: CostTierSpec[];
15
+ includePrimaryTier?: boolean;
16
+ }): Promise<ResolveAIProfileWithCostAlternativesResult>;
17
+ //# sourceMappingURL=resolveAIProfileWithCostAlternatives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveAIProfileWithCostAlternatives.d.ts","sourceRoot":"","sources":["../src/resolveAIProfileWithCostAlternatives.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,YAAY,EACZ,uBAAuB,EACvB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,0CAA0C;IACzD,OAAO,EAAE,iBAAiB,CAAC;IAC3B,sBAAsB,EAAE,KAAK,CAAC;QAC5B,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;QACnC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAQD;;GAEG;AACH,wBAAsB,oCAAoC,CACxD,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,uBAAuB,GAAG;IACjC,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,GACA,OAAO,CAAC,0CAA0C,CAAC,CAwJrD"}
@@ -0,0 +1,129 @@
1
+ import { buildResolvedProfile } from "./buildResolvedProfile.js";
2
+ import { AIProfilesError } from "./errors.js";
3
+ import { loadAIProfilesRegistryWithWarnings } from "./loader/loadAIProfilesRegistry.js";
4
+ import { loadModelsCatalogWithWarnings } from "./loader/loadModelsCatalog.js";
5
+ import { formatProfileChoiceKey, matchStrictProfileInput, } from "./profileChoiceKey.js";
6
+ import { pickProfileChoiceWithConstraints } from "./modalityPolicy.js";
7
+ import { normalizeCostCap } from "./costPolicy.js";
8
+ import { DEFAULT_COST_TIERS, resolveCostTierCap } from "./costTiers.js";
9
+ import { assertOpenRouterCatalogCoverage, assertProfileCatalogLane, } from "./profileCatalogLane.js";
10
+ import { attachSecondaryToResolved } from "./resolveSecondaryModel.js";
11
+ function normalizeTiers(input) {
12
+ return (input?.length ? input : DEFAULT_COST_TIERS).filter((t) => typeof t?.key === "string" && t.key.trim() !== "");
13
+ }
14
+ /**
15
+ * Resolve a fixed `profile/choice` and scout alternate choices under other cost-tier caps.
16
+ */
17
+ export async function resolveAIProfileWithCostAlternatives(input, options) {
18
+ if (!options.catalogLane) {
19
+ throw new AIProfilesError("MISSING_CATALOG_LANE", "resolveAIProfileWithCostAlternatives requires options.catalogLane (e.g. \"text\", \"image\")", { input });
20
+ }
21
+ const [{ registry, warnings }, catalogResult] = await Promise.all([
22
+ loadAIProfilesRegistryWithWarnings({
23
+ source: options.source,
24
+ refresh: options.refresh,
25
+ }),
26
+ loadModelsCatalogWithWarnings({
27
+ source: options.source,
28
+ refresh: options.refresh,
29
+ }),
30
+ ]);
31
+ const loaderWarnings = [...warnings, ...catalogResult.warnings];
32
+ const match = matchStrictProfileInput(registry, input);
33
+ if (!match) {
34
+ throw new AIProfilesError("UNKNOWN_PROFILE_CHOICE", `Unknown profile/choice key: ${input}. Use "profile/choice" (e.g. "cheap/default").`, { input });
35
+ }
36
+ if (match.kind === "invalidChoice") {
37
+ throw new AIProfilesError("UNKNOWN_CHOICE", `Unknown choice '${match.choice}' for AI profile '${match.profile}'`, { input, profile: match.profile, choice: match.choice });
38
+ }
39
+ const profileKey = match.profile;
40
+ const requestedChoiceKey = match.choice;
41
+ const matchedShortcut = match.kind === "shortcut"
42
+ ? registry.shortcuts[match.shortcutKey]
43
+ : undefined;
44
+ const profile = registry.profiles[profileKey];
45
+ if (!profile) {
46
+ throw new AIProfilesError("UNKNOWN_PROFILE", `Unknown AI profile: ${profileKey}`, { input, profile: profileKey });
47
+ }
48
+ try {
49
+ assertProfileCatalogLane({
50
+ profileKey,
51
+ profile,
52
+ requestedLane: options.catalogLane,
53
+ });
54
+ }
55
+ catch (error) {
56
+ const message = error instanceof Error ? error.message : String(error);
57
+ throw new AIProfilesError("CATALOG_LANE_MISMATCH", message, {
58
+ input,
59
+ profile: profileKey,
60
+ catalogLane: options.catalogLane,
61
+ });
62
+ }
63
+ const baseCostCapPer1M = options.costCapPer1M ??
64
+ resolveCostTierCap(options.costTier, options.costTiers);
65
+ const pickAndResolve = (capOverride) => {
66
+ const picked = pickProfileChoiceWithConstraints(profileKey, profile, {
67
+ choiceKey: requestedChoiceKey,
68
+ allowedProviders: options.allowedProviders,
69
+ preferLeadingVendors: options.preferLeadingVendors ?? true,
70
+ explicitChoiceRequested: true,
71
+ inputModalities: options.inputModalities,
72
+ outputModalities: options.outputModalities,
73
+ costCapPer1M: capOverride ?? baseCostCapPer1M,
74
+ capabilityFilter: options.capabilityFilter,
75
+ focus: options.focus,
76
+ catalog: catalogResult.catalog,
77
+ });
78
+ if (picked.choiceKey !== requestedChoiceKey) {
79
+ throw new Error(`Choice '${requestedChoiceKey}' exceeds cost cap (${formatProfileChoiceKey(profileKey, requestedChoiceKey)})`);
80
+ }
81
+ const enforceOpenRouterCatalog = profileKey === "local"
82
+ ? options.requireOpenRouterCatalog === true
83
+ : options.requireOpenRouterCatalog !== false;
84
+ if (enforceOpenRouterCatalog) {
85
+ assertOpenRouterCatalogCoverage({
86
+ profileKey,
87
+ choiceKey: picked.choiceKey,
88
+ choice: picked.choice,
89
+ catalog: catalogResult.catalog,
90
+ });
91
+ }
92
+ const resolved = buildResolvedProfile({
93
+ input,
94
+ shortcutKey: match.kind === "shortcut" ? match.shortcutKey : undefined,
95
+ profile,
96
+ choice: picked.choice,
97
+ choiceKey: picked.choiceKey,
98
+ shortcut: matchedShortcut,
99
+ registry,
100
+ loaderWarnings,
101
+ useOpenRouter: options.useOpenRouter,
102
+ catalog: catalogResult.catalog,
103
+ costCapApplied: normalizeCostCap(capOverride ?? baseCostCapPer1M),
104
+ });
105
+ return options.includeSecondary
106
+ ? attachSecondaryToResolved(resolved, registry, catalogResult.catalog, options.useOpenRouter)
107
+ : resolved;
108
+ };
109
+ const primary = pickAndResolve(undefined);
110
+ const tiers = normalizeTiers(options.tiers ?? options.costTiers);
111
+ const includePrimaryTier = options.includePrimaryTier ?? false;
112
+ const alternativesByCostTier = tiers
113
+ .filter((t) => includePrimaryTier || t.key !== options.costTier)
114
+ .map((tier) => {
115
+ const cap = resolveCostTierCap(tier.key, tiers);
116
+ if (!cap) {
117
+ return { tier: tier.key, resolved: null, reason: "Unknown tier key." };
118
+ }
119
+ try {
120
+ return { tier: tier.key, resolved: pickAndResolve(cap) };
121
+ }
122
+ catch (error) {
123
+ const message = error instanceof Error ? error.message : String(error);
124
+ return { tier: tier.key, resolved: null, reason: message };
125
+ }
126
+ });
127
+ return { primary, alternativesByCostTier };
128
+ }
129
+ //# sourceMappingURL=resolveAIProfileWithCostAlternatives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveAIProfileWithCostAlternatives.js","sourceRoot":"","sources":["../src/resolveAIProfileWithCostAlternatives.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ResolveCatalogModelOptions, ResolvedAIProfile } from "./types.js";
2
+ /**
3
+ * Resolve a vendor or OpenRouter model id to catalog-backed runtime config.
4
+ * Use {@link resolveAIProfile} when you have an explicit `profile/choice` key.
5
+ */
6
+ export declare function resolveCatalogModel(input: string, options: ResolveCatalogModelOptions): Promise<ResolvedAIProfile>;
7
+ //# sourceMappingURL=resolveCatalogModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveCatalogModel.d.ts","sourceRoot":"","sources":["../src/resolveCatalogModel.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEhF;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,iBAAiB,CAAC,CA8B5B"}
@@ -0,0 +1,34 @@
1
+ import { AIProfilesError } from "./errors.js";
2
+ import { loadAIProfilesRegistryWithWarnings } from "./loader/loadAIProfilesRegistry.js";
3
+ import { loadModelsCatalogWithWarnings } from "./loader/loadModelsCatalog.js";
4
+ import { buildResolvedModelInput, modelInputLogMeta, resolveModelFromInput, } from "./modelInputFallback.js";
5
+ import { logxer } from "./logger.js";
6
+ /**
7
+ * Resolve a vendor or OpenRouter model id to catalog-backed runtime config.
8
+ * Use {@link resolveAIProfile} when you have an explicit `profile/choice` key.
9
+ */
10
+ export async function resolveCatalogModel(input, options) {
11
+ const [{ registry, warnings }, catalogResult] = await Promise.all([
12
+ loadAIProfilesRegistryWithWarnings({
13
+ source: options.source,
14
+ refresh: options.refresh,
15
+ }),
16
+ loadModelsCatalogWithWarnings({
17
+ source: options.source,
18
+ refresh: options.refresh,
19
+ }),
20
+ ]);
21
+ const match = resolveModelFromInput(input, catalogResult.catalog);
22
+ if (!match || match.confidence !== "exact" && match.confidence !== "high") {
23
+ throw new AIProfilesError("UNKNOWN_MODEL", `Unknown catalog model: ${input}`, { input });
24
+ }
25
+ logxer.info("Resolved catalog model input", modelInputLogMeta(input, match));
26
+ return buildResolvedModelInput({
27
+ input,
28
+ match,
29
+ registry,
30
+ loaderWarnings: [...warnings, ...catalogResult.warnings],
31
+ useOpenRouter: options.useOpenRouter,
32
+ });
33
+ }
34
+ //# sourceMappingURL=resolveCatalogModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveCatalogModel.js","sourceRoot":"","sources":["../src/resolveCatalogModel.ts"],"names":[],"mappings":"AAAA,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,EACL,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAa,EACb,OAAmC;IAEnC,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;IAEH,MAAM,KAAK,GAAG,qBAAqB,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAClE,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,KAAK,OAAO,IAAI,KAAK,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;QAC1E,MAAM,IAAI,eAAe,CACvB,eAAe,EACf,0BAA0B,KAAK,EAAE,EACjC,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAE7E,OAAO,uBAAuB,CAAC;QAC7B,KAAK;QACL,KAAK;QACL,QAAQ;QACR,cAAc,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC;QACxD,aAAa,EAAE,OAAO,CAAC,aAAa;KACrC,CAAC,CAAC;AACL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolveSecondaryModel.d.ts","sourceRoot":"","sources":["../src/resolveSecondaryModel.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,8BAA8B,EAG/B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EACV,4BAA4B,EAC5B,2BAA2B,EAC3B,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,2BAA2B,CAAC,CA8FtC;AAED,OAAO,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AAErE,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,UAAU,CAAC,OAAO,8BAA8B,CAAC,CAAC,CAAC,CAAC,EAC9D,OAAO,EAAE,UAAU,CAAC,OAAO,8BAA8B,CAAC,CAAC,CAAC,CAAC,EAC7D,aAAa,CAAC,EAAE,OAAO,GACtB,iBAAiB,CAKnB"}
1
+ {"version":3,"file":"resolveSecondaryModel.d.ts","sourceRoot":"","sources":["../src/resolveSecondaryModel.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,8BAA8B,EAE/B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EACV,4BAA4B,EAC5B,2BAA2B,EAC3B,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,2BAA2B,CAAC,CAoGtC;AAED,OAAO,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AAErE,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,UAAU,CAAC,OAAO,8BAA8B,CAAC,CAAC,CAAC,CAAC,EAC9D,OAAO,EAAE,UAAU,CAAC,OAAO,8BAA8B,CAAC,CAAC,CAAC,CAAC,EAC7D,aAAa,CAAC,EAAE,OAAO,GACtB,iBAAiB,CAKnB"}
@@ -1,9 +1,9 @@
1
1
  import { AIProfilesError } from "./errors.js";
2
2
  import { loadAIProfilesRegistryWithWarnings } from "./loader/loadAIProfilesRegistry.js";
3
3
  import { loadModelsCatalogWithWarnings } from "./loader/loadModelsCatalog.js";
4
- import { matchProfileInput } from "./profileInputMatch.js";
4
+ import { matchStrictProfileInput } from "./profileChoiceKey.js";
5
5
  import { pickProfileChoiceWithConstraints } from "./modalityPolicy.js";
6
- import { getSecondaryForResolvedProfile, resolveProfileMatchChoiceKeys, resolveSecondaryForChoice, } from "./secondaryModel.js";
6
+ import { getSecondaryForResolvedProfile, resolveSecondaryForChoice, } from "./secondaryModel.js";
7
7
  export async function resolveSecondaryModel(input, options) {
8
8
  if (!options.catalogLane) {
9
9
  throw new AIProfilesError("MISSING_CATALOG_LANE", "resolveSecondaryModel requires options.catalogLane (e.g. \"text\", \"image\")", { input });
@@ -18,11 +18,15 @@ export async function resolveSecondaryModel(input, options) {
18
18
  refresh: options.refresh,
19
19
  }),
20
20
  ]);
21
- const match = matchProfileInput(registry, input);
21
+ const match = matchStrictProfileInput(registry, input);
22
22
  if (!match) {
23
- throw new AIProfilesError("UNKNOWN_PROFILE", `Unknown AI profile, shortcut, or alias: ${input}`, { input });
23
+ throw new AIProfilesError("UNKNOWN_PROFILE_CHOICE", `Unknown profile/choice key: ${input}. Use "profile/choice" (e.g. "cheap/default").`, { input });
24
24
  }
25
- const { profileKey, requestedChoiceKey } = resolveProfileMatchChoiceKeys(match, options.choice);
25
+ if (match.kind === "invalidChoice") {
26
+ throw new AIProfilesError("UNKNOWN_CHOICE", `Unknown choice '${match.choice}' for AI profile '${match.profile}'`, { input, profile: match.profile, choice: match.choice });
27
+ }
28
+ const profileKey = match.profile;
29
+ const requestedChoiceKey = match.choice;
26
30
  const profile = registry.profiles[profileKey];
27
31
  if (!profile) {
28
32
  throw new AIProfilesError("UNKNOWN_PROFILE", `Unknown AI profile: ${profileKey}`, { input, profile: profileKey });
@@ -34,10 +38,11 @@ export async function resolveSecondaryModel(input, options) {
34
38
  choiceKey: requestedChoiceKey,
35
39
  allowedProviders: options.allowedProviders,
36
40
  preferLeadingVendors: options.preferLeadingVendors ?? true,
37
- explicitChoiceRequested: options.choice !== undefined ||
38
- (match.kind === "shortcut" && match.shortcut.choice !== undefined),
41
+ explicitChoiceRequested: true,
39
42
  inputModalities: options.inputModalities,
40
43
  outputModalities: options.outputModalities,
44
+ capabilityFilter: options.capabilityFilter,
45
+ focus: options.focus,
41
46
  catalog: catalogResult.catalog,
42
47
  });
43
48
  finalChoiceKey = picked.choiceKey;
@@ -46,7 +51,11 @@ export async function resolveSecondaryModel(input, options) {
46
51
  catch (error) {
47
52
  const message = error instanceof Error ? error.message : String(error);
48
53
  if (message.startsWith("Unknown choice")) {
49
- throw new AIProfilesError("UNKNOWN_CHOICE", message, { input, profile: profileKey, choice: requestedChoiceKey });
54
+ throw new AIProfilesError("UNKNOWN_CHOICE", message, {
55
+ input,
56
+ profile: profileKey,
57
+ choice: requestedChoiceKey,
58
+ });
50
59
  }
51
60
  throw error;
52
61
  }