@x12i/ai-profiles 2.0.0 → 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 (89) hide show
  1. package/README.md +150 -44
  2. package/dist/buildCatalogFromOpenRouterApi.d.ts.map +1 -1
  3. package/dist/buildCatalogFromOpenRouterApi.js +2 -2
  4. package/dist/buildCatalogFromOpenRouterApi.js.map +1 -1
  5. package/dist/buildResolvedProfile.d.ts.map +1 -1
  6. package/dist/buildResolvedProfile.js +7 -0
  7. package/dist/buildResolvedProfile.js.map +1 -1
  8. package/dist/costTiers.d.ts +4 -0
  9. package/dist/costTiers.d.ts.map +1 -0
  10. package/dist/costTiers.js +20 -0
  11. package/dist/costTiers.js.map +1 -0
  12. package/dist/data/models-catalog.json +10 -10
  13. package/dist/data/models-profiles.bak.json +2336 -0
  14. package/dist/data/models-profiles.json +202 -18
  15. package/dist/data/models-profiles.schema.json +29 -0
  16. package/dist/data/profiles-shortcuts.json +86 -34
  17. package/dist/errors.d.ts +1 -1
  18. package/dist/errors.d.ts.map +1 -1
  19. package/dist/errors.js.map +1 -1
  20. package/dist/index.d.ts +11 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +8 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/isKnownProfileChoice.d.ts +6 -0
  25. package/dist/isKnownProfileChoice.d.ts.map +1 -0
  26. package/dist/isKnownProfileChoice.js +11 -0
  27. package/dist/isKnownProfileChoice.js.map +1 -0
  28. package/dist/listAIProfileChoices.d.ts +6 -0
  29. package/dist/listAIProfileChoices.d.ts.map +1 -0
  30. package/dist/listAIProfileChoices.js +50 -0
  31. package/dist/listAIProfileChoices.js.map +1 -0
  32. package/dist/listAIProfiles.d.ts.map +1 -1
  33. package/dist/listAIProfiles.js +23 -0
  34. package/dist/listAIProfiles.js.map +1 -1
  35. package/dist/modalityPolicy.d.ts +4 -1
  36. package/dist/modalityPolicy.d.ts.map +1 -1
  37. package/dist/modalityPolicy.js +82 -3
  38. package/dist/modalityPolicy.js.map +1 -1
  39. package/dist/modelInputFallback.d.ts.map +1 -1
  40. package/dist/modelInputFallback.js +12 -2
  41. package/dist/modelInputFallback.js.map +1 -1
  42. package/dist/modelsCatalog.d.ts +5 -0
  43. package/dist/modelsCatalog.d.ts.map +1 -1
  44. package/dist/modelsCatalog.js +32 -2
  45. package/dist/modelsCatalog.js.map +1 -1
  46. package/dist/profileChoiceKey.d.ts +35 -0
  47. package/dist/profileChoiceKey.d.ts.map +1 -0
  48. package/dist/profileChoiceKey.js +81 -0
  49. package/dist/profileChoiceKey.js.map +1 -0
  50. package/dist/profileDiscoveryMatch.d.ts +15 -0
  51. package/dist/profileDiscoveryMatch.d.ts.map +1 -0
  52. package/dist/profileDiscoveryMatch.js +17 -0
  53. package/dist/profileDiscoveryMatch.js.map +1 -0
  54. package/dist/resolveAIProfile.d.ts +4 -5
  55. package/dist/resolveAIProfile.d.ts.map +1 -1
  56. package/dist/resolveAIProfile.js +57 -82
  57. package/dist/resolveAIProfile.js.map +1 -1
  58. package/dist/resolveAIProfileByTags.d.ts +2 -2
  59. package/dist/resolveAIProfileByTags.d.ts.map +1 -1
  60. package/dist/resolveAIProfileByTags.js +28 -10
  61. package/dist/resolveAIProfileByTags.js.map +1 -1
  62. package/dist/resolveAIProfileWithCostAlternatives.d.ts +17 -0
  63. package/dist/resolveAIProfileWithCostAlternatives.d.ts.map +1 -0
  64. package/dist/resolveAIProfileWithCostAlternatives.js +129 -0
  65. package/dist/resolveAIProfileWithCostAlternatives.js.map +1 -0
  66. package/dist/resolveCatalogModel.d.ts +7 -0
  67. package/dist/resolveCatalogModel.d.ts.map +1 -0
  68. package/dist/resolveCatalogModel.js +34 -0
  69. package/dist/resolveCatalogModel.js.map +1 -0
  70. package/dist/resolveSecondaryModel.d.ts +6 -0
  71. package/dist/resolveSecondaryModel.d.ts.map +1 -0
  72. package/dist/resolveSecondaryModel.js +91 -0
  73. package/dist/resolveSecondaryModel.js.map +1 -0
  74. package/dist/secondaryModel.d.ts +37 -0
  75. package/dist/secondaryModel.d.ts.map +1 -0
  76. package/dist/secondaryModel.js +160 -0
  77. package/dist/secondaryModel.js.map +1 -0
  78. package/dist/types.d.ts +145 -8
  79. package/dist/types.d.ts.map +1 -1
  80. package/dist/validateProfileCatalogLinkage.d.ts.map +1 -1
  81. package/dist/validateProfileCatalogLinkage.js +2 -1
  82. package/dist/validateProfileCatalogLinkage.js.map +1 -1
  83. package/dist/validation/validateModelsProfilesJson.d.ts.map +1 -1
  84. package/dist/validation/validateModelsProfilesJson.js +73 -9
  85. package/dist/validation/validateModelsProfilesJson.js.map +1 -1
  86. package/dist/vendorPolicy.d.ts.map +1 -1
  87. package/dist/vendorPolicy.js +1 -6
  88. package/dist/vendorPolicy.js.map +1 -1
  89. package/package.json +1 -1
@@ -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"}
@@ -0,0 +1,6 @@
1
+ import { getSecondaryForResolvedProfile } from "./secondaryModel.js";
2
+ import type { ResolveSecondaryModelOptions, ResolveSecondaryModelResult, ResolvedAIProfile } from "./types.js";
3
+ export declare function resolveSecondaryModel(input: string, options: ResolveSecondaryModelOptions): Promise<ResolveSecondaryModelResult>;
4
+ export { getSecondaryForResolvedProfile } from "./secondaryModel.js";
5
+ export declare function attachSecondaryToResolved(resolved: ResolvedAIProfile, registry: Parameters<typeof getSecondaryForResolvedProfile>[1], catalog: Parameters<typeof getSecondaryForResolvedProfile>[2], useOpenRouter?: boolean): ResolvedAIProfile;
6
+ //# sourceMappingURL=resolveSecondaryModel.d.ts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,91 @@
1
+ import { AIProfilesError } from "./errors.js";
2
+ import { loadAIProfilesRegistryWithWarnings } from "./loader/loadAIProfilesRegistry.js";
3
+ import { loadModelsCatalogWithWarnings } from "./loader/loadModelsCatalog.js";
4
+ import { matchStrictProfileInput } from "./profileChoiceKey.js";
5
+ import { pickProfileChoiceWithConstraints } from "./modalityPolicy.js";
6
+ import { getSecondaryForResolvedProfile, resolveSecondaryForChoice, } from "./secondaryModel.js";
7
+ export async function resolveSecondaryModel(input, options) {
8
+ if (!options.catalogLane) {
9
+ throw new AIProfilesError("MISSING_CATALOG_LANE", "resolveSecondaryModel requires options.catalogLane (e.g. \"text\", \"image\")", { input });
10
+ }
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 = matchStrictProfileInput(registry, input);
22
+ if (!match) {
23
+ throw new AIProfilesError("UNKNOWN_PROFILE_CHOICE", `Unknown profile/choice key: ${input}. Use "profile/choice" (e.g. "cheap/default").`, { input });
24
+ }
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;
30
+ const profile = registry.profiles[profileKey];
31
+ if (!profile) {
32
+ throw new AIProfilesError("UNKNOWN_PROFILE", `Unknown AI profile: ${profileKey}`, { input, profile: profileKey });
33
+ }
34
+ let finalChoiceKey;
35
+ let primaryChoice;
36
+ try {
37
+ const picked = pickProfileChoiceWithConstraints(profileKey, profile, {
38
+ choiceKey: requestedChoiceKey,
39
+ allowedProviders: options.allowedProviders,
40
+ preferLeadingVendors: options.preferLeadingVendors ?? true,
41
+ explicitChoiceRequested: true,
42
+ inputModalities: options.inputModalities,
43
+ outputModalities: options.outputModalities,
44
+ capabilityFilter: options.capabilityFilter,
45
+ focus: options.focus,
46
+ catalog: catalogResult.catalog,
47
+ });
48
+ finalChoiceKey = picked.choiceKey;
49
+ primaryChoice = picked.choice;
50
+ }
51
+ catch (error) {
52
+ const message = error instanceof Error ? error.message : String(error);
53
+ if (message.startsWith("Unknown choice")) {
54
+ throw new AIProfilesError("UNKNOWN_CHOICE", message, {
55
+ input,
56
+ profile: profileKey,
57
+ choice: requestedChoiceKey,
58
+ });
59
+ }
60
+ throw error;
61
+ }
62
+ const secondary = resolveSecondaryForChoice({
63
+ profileKey,
64
+ profile,
65
+ primaryChoiceKey: finalChoiceKey,
66
+ primaryChoice,
67
+ registry,
68
+ catalog: catalogResult.catalog,
69
+ useOpenRouter: options.useOpenRouter,
70
+ loaderWarnings: warnings,
71
+ });
72
+ return {
73
+ primary: {
74
+ profile: profileKey,
75
+ choice: finalChoiceKey,
76
+ provider: primaryChoice.provider,
77
+ modelId: primaryChoice.modelId,
78
+ },
79
+ secondary,
80
+ source: registry.source,
81
+ loadedAt: registry.loadedAt,
82
+ };
83
+ }
84
+ export { getSecondaryForResolvedProfile } from "./secondaryModel.js";
85
+ export function attachSecondaryToResolved(resolved, registry, catalog, useOpenRouter) {
86
+ const secondary = getSecondaryForResolvedProfile(resolved, registry, catalog, {
87
+ useOpenRouter,
88
+ });
89
+ return { ...resolved, secondary };
90
+ }
91
+ //# sourceMappingURL=resolveSecondaryModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveSecondaryModel.js","sourceRoot":"","sources":["../src/resolveSecondaryModel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { AIProfileChoice, AIProfileDefinition, AIProfilesRegistry, ModelsCatalogJson, ResolvedAIProfile, ResolvedSecondaryModel, SecondaryRef } from "./types.js";
2
+ export declare function getSecondaryRef(profile: AIProfileDefinition, primaryChoiceKey: string): SecondaryRef | undefined;
3
+ export declare function secondaryRefToChoice(profileKey: string, profile: AIProfileDefinition, ref: SecondaryRef): {
4
+ choiceKey: string;
5
+ choice: AIProfileChoice;
6
+ };
7
+ export declare function assertNoSecondaryCycle(profileKey: string, profile: AIProfileDefinition, primaryChoiceKey: string, ref: SecondaryRef): void;
8
+ export declare function buildResolvedSecondaryModel(params: {
9
+ profileKey: string;
10
+ primaryChoiceKey: string;
11
+ profile: AIProfileDefinition;
12
+ choice: AIProfileChoice;
13
+ secondaryChoiceKey?: string;
14
+ registry: AIProfilesRegistry;
15
+ catalog?: ModelsCatalogJson;
16
+ useOpenRouter?: boolean;
17
+ loaderWarnings?: ResolvedAIProfile["warnings"];
18
+ reason?: string;
19
+ }): ResolvedSecondaryModel;
20
+ export declare function resolveSecondaryForChoice(params: {
21
+ profileKey: string;
22
+ profile: AIProfileDefinition;
23
+ primaryChoiceKey: string;
24
+ primaryChoice: AIProfileChoice;
25
+ registry: AIProfilesRegistry;
26
+ catalog?: ModelsCatalogJson;
27
+ useOpenRouter?: boolean;
28
+ loaderWarnings?: ResolvedAIProfile["warnings"];
29
+ }): ResolvedSecondaryModel | null;
30
+ export declare function getSecondaryForResolvedProfile(resolved: ResolvedAIProfile, registry: AIProfilesRegistry, catalog?: ModelsCatalogJson, options?: {
31
+ useOpenRouter?: boolean;
32
+ }): ResolvedSecondaryModel | null;
33
+ export declare function listProfileSecondaries(profileKey: string, registry: AIProfilesRegistry): Array<{
34
+ choice: string;
35
+ secondary: SecondaryRef;
36
+ }>;
37
+ //# sourceMappingURL=secondaryModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secondaryModel.d.ts","sourceRoot":"","sources":["../src/secondaryModel.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,wBAAgB,eAAe,CAC7B,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,EAAE,MAAM,GACvB,YAAY,GAAG,SAAS,CAe1B;AAED,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,mBAAmB,EAC5B,GAAG,EAAE,YAAY,GAChB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAyBhD;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,EAAE,MAAM,EACxB,GAAG,EAAE,YAAY,GAChB,IAAI,CAoCN;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,MAAM,EAAE,eAAe,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,sBAAsB,CA+BzB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,eAAe,CAAC;IAC/B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC;CAChD,GAAG,sBAAsB,GAAG,IAAI,CA4ChC;AAED,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,CAAC,EAAE,iBAAiB,EAC3B,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GACpC,sBAAsB,GAAG,IAAI,CAyB/B;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,kBAAkB,GAC3B,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC,CAepD"}
@@ -0,0 +1,160 @@
1
+ import { buildResolvedProfile } from "./buildResolvedProfile.js";
2
+ import { AIProfilesError } from "./errors.js";
3
+ import { fixVendorModelId } from "./profileRegistryV2.js";
4
+ export function getSecondaryRef(profile, primaryChoiceKey) {
5
+ const primary = profile.choices[primaryChoiceKey];
6
+ if (!primary) {
7
+ return undefined;
8
+ }
9
+ if (primary.secondary) {
10
+ return primary.secondary;
11
+ }
12
+ if (profile.defaultSecondaryChoice) {
13
+ return { kind: "choice", choice: profile.defaultSecondaryChoice };
14
+ }
15
+ return undefined;
16
+ }
17
+ export function secondaryRefToChoice(profileKey, profile, ref) {
18
+ if (ref.kind === "choice") {
19
+ const choice = profile.choices[ref.choice];
20
+ if (!choice) {
21
+ throw new AIProfilesError("UNKNOWN_SECONDARY_CHOICE", `Unknown secondary choice '${ref.choice}' for profile '${profileKey}'`, { profile: profileKey, choice: ref.choice });
22
+ }
23
+ return { choiceKey: ref.choice, choice };
24
+ }
25
+ const syntheticKey = `__secondary:${ref.provider}:${ref.modelId}`;
26
+ const choice = {
27
+ choice: syntheticKey,
28
+ displayName: "Secondary model",
29
+ description: ref.reason ?? "Explicit secondary model reference.",
30
+ provider: ref.provider,
31
+ modelId: fixVendorModelId(ref.modelId),
32
+ runtime: ref.runtime,
33
+ reason: ref.reason,
34
+ };
35
+ return { choiceKey: syntheticKey, choice };
36
+ }
37
+ export function assertNoSecondaryCycle(profileKey, profile, primaryChoiceKey, ref) {
38
+ if (ref.kind !== "choice") {
39
+ return;
40
+ }
41
+ const visited = new Set([primaryChoiceKey]);
42
+ let current = ref.choice;
43
+ while (current) {
44
+ if (visited.has(current)) {
45
+ throw new AIProfilesError("SECONDARY_CYCLE", `Secondary choice chain cycles on profile '${profileKey}' (involves '${current}')`, { profile: profileKey, choice: primaryChoiceKey, cycleAt: current });
46
+ }
47
+ visited.add(current);
48
+ const nextRef = profile.choices[current]?.secondary;
49
+ if (!nextRef) {
50
+ if (profile.defaultSecondaryChoice &&
51
+ profile.defaultSecondaryChoice !== current) {
52
+ current = profile.defaultSecondaryChoice;
53
+ continue;
54
+ }
55
+ break;
56
+ }
57
+ if (nextRef.kind !== "choice") {
58
+ break;
59
+ }
60
+ current = nextRef.choice;
61
+ }
62
+ }
63
+ export function buildResolvedSecondaryModel(params) {
64
+ const resolved = buildResolvedProfile({
65
+ input: `${params.profileKey}:${params.primaryChoiceKey}:secondary`,
66
+ profile: params.profile,
67
+ choice: params.choice,
68
+ choiceKey: params.secondaryChoiceKey ?? params.choice.choice,
69
+ registry: params.registry,
70
+ catalog: params.catalog,
71
+ useOpenRouter: params.useOpenRouter,
72
+ loaderWarnings: params.loaderWarnings,
73
+ });
74
+ return {
75
+ profile: params.profileKey,
76
+ primaryChoice: params.primaryChoiceKey,
77
+ ...(params.secondaryChoiceKey && !params.secondaryChoiceKey.startsWith("__secondary:")
78
+ ? { secondaryChoice: params.secondaryChoiceKey }
79
+ : {}),
80
+ provider: resolved.provider,
81
+ modelId: resolved.modelId,
82
+ routing: resolved.routing,
83
+ instructionTier: resolved.instructionTier,
84
+ backend: resolved.backend,
85
+ ...(resolved.pricing !== undefined ? { pricing: resolved.pricing } : {}),
86
+ modalities: resolved.modalities,
87
+ invocation: resolved.invocation,
88
+ reason: params.reason ?? resolved.reason,
89
+ runtime: resolved.runtime,
90
+ modelSignals: resolved.modelSignals,
91
+ ...(resolved.warnings?.length ? { warnings: resolved.warnings } : {}),
92
+ };
93
+ }
94
+ export function resolveSecondaryForChoice(params) {
95
+ const ref = getSecondaryRef(params.profile, params.primaryChoiceKey);
96
+ if (!ref) {
97
+ return null;
98
+ }
99
+ assertNoSecondaryCycle(params.profileKey, params.profile, params.primaryChoiceKey, ref);
100
+ const { choiceKey, choice } = secondaryRefToChoice(params.profileKey, params.profile, ref);
101
+ if (choice.provider === params.primaryChoice.provider &&
102
+ choice.modelId === params.primaryChoice.modelId) {
103
+ return buildResolvedSecondaryModel({
104
+ ...params,
105
+ choice,
106
+ secondaryChoiceKey: ref.kind === "choice" ? choiceKey : undefined,
107
+ reason: ref.reason,
108
+ loaderWarnings: [
109
+ ...(params.loaderWarnings ?? []),
110
+ {
111
+ code: "SECONDARY_SAME_AS_PRIMARY",
112
+ message: `Secondary resolves to the same SKU as primary (${choice.provider}/${choice.modelId}).`,
113
+ },
114
+ ],
115
+ });
116
+ }
117
+ return buildResolvedSecondaryModel({
118
+ ...params,
119
+ choice,
120
+ secondaryChoiceKey: ref.kind === "choice" ? choiceKey : undefined,
121
+ reason: ref.reason ?? choice.reason,
122
+ });
123
+ }
124
+ export function getSecondaryForResolvedProfile(resolved, registry, catalog, options) {
125
+ if (resolved.resolutionKind === "model") {
126
+ return null;
127
+ }
128
+ const profile = registry.profiles[resolved.profile];
129
+ if (!profile) {
130
+ return null;
131
+ }
132
+ const primaryChoice = profile.choices[resolved.choice];
133
+ if (!primaryChoice) {
134
+ return null;
135
+ }
136
+ return resolveSecondaryForChoice({
137
+ profileKey: resolved.profile,
138
+ profile,
139
+ primaryChoiceKey: resolved.choice,
140
+ primaryChoice,
141
+ registry,
142
+ catalog,
143
+ useOpenRouter: options?.useOpenRouter,
144
+ loaderWarnings: resolved.warnings,
145
+ });
146
+ }
147
+ export function listProfileSecondaries(profileKey, registry) {
148
+ const profile = registry.profiles[profileKey];
149
+ if (!profile) {
150
+ return [];
151
+ }
152
+ const out = [];
153
+ for (const [choiceKey, choice] of Object.entries(profile.choices)) {
154
+ if (choice.secondary) {
155
+ out.push({ choice: choiceKey, secondary: choice.secondary });
156
+ }
157
+ }
158
+ return out;
159
+ }
160
+ //# sourceMappingURL=secondaryModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secondaryModel.js","sourceRoot":"","sources":["../src/secondaryModel.ts"],"names":[],"mappings":"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"}