@x12i/ai-tools 2.0.1 → 2.0.2

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 (84) hide show
  1. package/dist/{AiModelsCatalogClient-B5FMI9gj.d.cts → AiModelsCatalogClient-C9ZJHhv3.d.ts} +4 -1
  2. package/dist/{AiModelsCatalogClient-CPPNI6Ry.d.ts → AiModelsCatalogClient-DgBdVFk-.d.cts} +4 -1
  3. package/dist/aliases/index.d.cts +3 -3
  4. package/dist/aliases/index.d.ts +3 -3
  5. package/dist/catalog/index.cjs +6 -5
  6. package/dist/catalog/index.cjs.map +1 -1
  7. package/dist/catalog/index.d.cts +4 -4
  8. package/dist/catalog/index.d.ts +4 -4
  9. package/dist/catalog/index.js +5 -4
  10. package/dist/{chunk-EYHMQVAL.js → chunk-54GKLIDW.js} +22 -10
  11. package/dist/chunk-54GKLIDW.js.map +1 -0
  12. package/dist/{chunk-XAWBTX3N.cjs → chunk-75ZVXZAV.cjs} +7 -7
  13. package/dist/{chunk-XAWBTX3N.cjs.map → chunk-75ZVXZAV.cjs.map} +1 -1
  14. package/dist/{chunk-YQDSN6R6.cjs → chunk-76FHWQH3.cjs} +3 -3
  15. package/dist/{chunk-YQDSN6R6.cjs.map → chunk-76FHWQH3.cjs.map} +1 -1
  16. package/dist/{chunk-EDMCKHO6.cjs → chunk-BCX5CLJJ.cjs} +15 -2
  17. package/dist/chunk-BCX5CLJJ.cjs.map +1 -0
  18. package/dist/{chunk-OPN6BGNH.js → chunk-D6OIUYNC.js} +117 -5
  19. package/dist/{chunk-OPN6BGNH.js.map → chunk-D6OIUYNC.js.map} +1 -1
  20. package/dist/{chunk-WOHMHXRZ.cjs → chunk-DDRWORUU.cjs} +30 -276
  21. package/dist/chunk-DDRWORUU.cjs.map +1 -0
  22. package/dist/{chunk-5XAAMBDO.cjs → chunk-HBNYVRLZ.cjs} +123 -11
  23. package/dist/chunk-HBNYVRLZ.cjs.map +1 -0
  24. package/dist/chunk-HEB73GKJ.js +263 -0
  25. package/dist/chunk-HEB73GKJ.js.map +1 -0
  26. package/dist/{chunk-VJHLO2R3.js → chunk-KSJSLKYI.js} +2 -2
  27. package/dist/{chunk-SIH4GPV4.js → chunk-MOLWV5LV.js} +2 -2
  28. package/dist/{chunk-CTM35DMA.js → chunk-PN4FF6YF.js} +10 -253
  29. package/dist/chunk-PN4FF6YF.js.map +1 -0
  30. package/dist/{chunk-DXZOL3VN.cjs → chunk-RSHI4OOY.cjs} +46 -34
  31. package/dist/chunk-RSHI4OOY.cjs.map +1 -0
  32. package/dist/{chunk-B3V2EHRY.js → chunk-SLSKQRMI.js} +15 -2
  33. package/dist/{chunk-B3V2EHRY.js.map → chunk-SLSKQRMI.js.map} +1 -1
  34. package/dist/{chunk-XOKUDUUI.cjs → chunk-TMA6QSNH.cjs} +3 -3
  35. package/dist/{chunk-XOKUDUUI.cjs.map → chunk-TMA6QSNH.cjs.map} +1 -1
  36. package/dist/{chunk-6BQBKROR.js → chunk-VBROBIVI.js} +3 -3
  37. package/dist/{chunk-6BQBKROR.js.map → chunk-VBROBIVI.js.map} +1 -1
  38. package/dist/chunk-WSUFQR3D.cjs +266 -0
  39. package/dist/chunk-WSUFQR3D.cjs.map +1 -0
  40. package/dist/{chunk-PRCICORG.cjs → chunk-X42KFOUO.cjs} +6 -6
  41. package/dist/{chunk-PRCICORG.cjs.map → chunk-X42KFOUO.cjs.map} +1 -1
  42. package/dist/{chunk-AB5GNXJ4.js → chunk-ZPUZ7DBO.js} +2 -2
  43. package/dist/cli/index.cjs +16 -15
  44. package/dist/cli/index.cjs.map +1 -1
  45. package/dist/cli/index.js +7 -6
  46. package/dist/cli/index.js.map +1 -1
  47. package/dist/cost/index.cjs +4 -3
  48. package/dist/cost/index.cjs.map +1 -1
  49. package/dist/cost/index.d.cts +4 -4
  50. package/dist/cost/index.d.ts +4 -4
  51. package/dist/cost/index.js +3 -2
  52. package/dist/index.cjs +12 -9
  53. package/dist/index.cjs.map +1 -1
  54. package/dist/index.d.cts +6 -6
  55. package/dist/index.d.ts +6 -6
  56. package/dist/index.js +11 -8
  57. package/dist/{modelCache-CJftI-Ko.d.cts → modelCache-sL3dBfRM.d.cts} +1 -1
  58. package/dist/{modelCache-BzRn6t_C.d.ts → modelCache-xzoTUue2.d.ts} +1 -1
  59. package/dist/{modelNameResolver-5XkBMctP.d.ts → modelNameResolver-2WroQlqt.d.ts} +2 -1
  60. package/dist/{modelNameResolver-C5CSTGFF.d.cts → modelNameResolver-Bxlehrbp.d.cts} +2 -1
  61. package/dist/models/index.cjs +7 -6
  62. package/dist/models/index.cjs.map +1 -1
  63. package/dist/models/index.d.cts +3 -3
  64. package/dist/models/index.d.ts +3 -3
  65. package/dist/models/index.js +6 -5
  66. package/dist/{resolveUsageModel-BFwf80Hz.d.ts → resolveUsageModel-DrFuiuIW.d.ts} +2 -2
  67. package/dist/{resolveUsageModel-C_YmGR1M.d.cts → resolveUsageModel-xKZ2QpHy.d.cts} +2 -2
  68. package/dist/sync/index.cjs +7 -5
  69. package/dist/sync/index.cjs.map +1 -1
  70. package/dist/sync/index.d.cts +3 -3
  71. package/dist/sync/index.d.ts +3 -3
  72. package/dist/sync/index.js +6 -4
  73. package/dist/{types-BrzJWsTU.d.ts → types-BZYGjN2O.d.cts} +21 -2
  74. package/dist/{types-BrzJWsTU.d.cts → types-BZYGjN2O.d.ts} +21 -2
  75. package/package.json +1 -1
  76. package/dist/chunk-5XAAMBDO.cjs.map +0 -1
  77. package/dist/chunk-CTM35DMA.js.map +0 -1
  78. package/dist/chunk-DXZOL3VN.cjs.map +0 -1
  79. package/dist/chunk-EDMCKHO6.cjs.map +0 -1
  80. package/dist/chunk-EYHMQVAL.js.map +0 -1
  81. package/dist/chunk-WOHMHXRZ.cjs.map +0 -1
  82. /package/dist/{chunk-VJHLO2R3.js.map → chunk-KSJSLKYI.js.map} +0 -0
  83. /package/dist/{chunk-SIH4GPV4.js.map → chunk-MOLWV5LV.js.map} +0 -0
  84. /package/dist/{chunk-AB5GNXJ4.js.map → chunk-ZPUZ7DBO.js.map} +0 -0
@@ -0,0 +1,263 @@
1
+ import {
2
+ LOCAL_PROVIDERS,
3
+ loadOpenRouterRoutingEnv,
4
+ normalizeProvider,
5
+ normalizeString,
6
+ shouldDefaultRouteViaOpenRouter,
7
+ stripModelVersionSuffix
8
+ } from "./chunk-SLSKQRMI.js";
9
+
10
+ // src/cost/costModelResolution.ts
11
+ function isOpenRouterProvider(provider) {
12
+ return normalizeProvider(provider) === "openrouter";
13
+ }
14
+ function isLocalProvider(provider) {
15
+ const p = normalizeProvider(provider) ?? normalizeString(provider ?? "");
16
+ return LOCAL_PROVIDERS.has(p);
17
+ }
18
+ function isLocalProviderResolution(resolved, inputProvider) {
19
+ if (!resolved?.found || resolved.record) return false;
20
+ if (resolved.resolvedVia.includes("local-provider-passthrough")) return true;
21
+ return isLocalProvider(inputProvider);
22
+ }
23
+ function underlyingProviderFromModel(model, providerHint) {
24
+ const normalized = normalizeString(model);
25
+ if (normalized.includes("/")) {
26
+ const prefix = normalized.split("/")[0];
27
+ if (!isOpenRouterProvider(prefix)) return prefix;
28
+ }
29
+ if (providerHint && !isOpenRouterProvider(providerHint)) {
30
+ return normalizeProvider(providerHint);
31
+ }
32
+ return void 0;
33
+ }
34
+ function providerHintForProfiles(model, provider) {
35
+ if (isOpenRouterProvider(provider)) {
36
+ return underlyingProviderFromModel(model, provider);
37
+ }
38
+ return normalizeProvider(provider);
39
+ }
40
+ function buildCatalogResolveAttempts(model, provider) {
41
+ const attempts = [];
42
+ const seen = /* @__PURE__ */ new Set();
43
+ const add = (m, p) => {
44
+ const key = `${p ?? ""}\0${normalizeString(m)}`;
45
+ if (seen.has(key)) return;
46
+ seen.add(key);
47
+ attempts.push({ model: m, provider: p });
48
+ };
49
+ add(model, provider);
50
+ const underlying = underlyingProviderFromModel(model, provider);
51
+ if (provider) add(model, void 0);
52
+ if (underlying) add(model, underlying);
53
+ if (!isOpenRouterProvider(provider)) {
54
+ add(model, "openrouter");
55
+ }
56
+ return attempts;
57
+ }
58
+ async function resolveFromCatalogAttempts(catalog, attempts, options) {
59
+ let last = null;
60
+ let localPassthrough = null;
61
+ for (const attempt of attempts) {
62
+ const result = await catalog.resolveModel(attempt, options);
63
+ last = result;
64
+ if (result.found && result.record) return result;
65
+ if (result.found && !result.record && isLocalProviderResolution(result, attempt.provider)) {
66
+ localPassthrough = result;
67
+ }
68
+ }
69
+ return localPassthrough ?? last;
70
+ }
71
+ function resolveRoutedViaOpenRouter(inputProvider, resolved, modelId, routingEnv) {
72
+ const env = routingEnv ?? loadOpenRouterRoutingEnv();
73
+ if (isOpenRouterProvider(inputProvider)) return true;
74
+ if (resolved?.found) {
75
+ return resolved.routedViaOpenRouter;
76
+ }
77
+ const vendor = underlyingProviderFromModel(
78
+ modelId ?? (resolved?.found ? resolved.modelId : "") ?? "",
79
+ inputProvider
80
+ );
81
+ if (vendor && shouldDefaultRouteViaOpenRouter(vendor, env)) {
82
+ return true;
83
+ }
84
+ return false;
85
+ }
86
+
87
+ // src/cost/aiProfilesMatch.ts
88
+ import { createRequire } from "module";
89
+ import { dirname, join } from "path";
90
+ import { AIProfilesError, resolveAIProfile } from "@x12i/ai-profiles";
91
+ var require2 = createRequire(import.meta.url);
92
+ function loadProfilesRegistry() {
93
+ const entry = dirname(require2.resolve("@x12i/ai-profiles"));
94
+ const loader = require2(join(entry, "loader/loadAIProfilesRegistry.js"));
95
+ return loader.loadAIProfilesRegistry({ source: "auto" });
96
+ }
97
+ function profileKey(value) {
98
+ return value.trim().toLowerCase();
99
+ }
100
+ function canonicalModelId(provider, modelId) {
101
+ const normalized = normalizeString(modelId);
102
+ if (normalized.includes("/")) return normalized;
103
+ const p = normalizeProvider(provider) ?? normalizeString(provider);
104
+ return `${p}/${normalized}`;
105
+ }
106
+ var cachedIndex = null;
107
+ function indexRegistry(registry) {
108
+ const byKey = /* @__PURE__ */ new Map();
109
+ const add = (key, entry) => {
110
+ const k = profileKey(key);
111
+ if (!k) return;
112
+ const list = byKey.get(k) ?? [];
113
+ if (list.some(
114
+ (e) => e.canonicalModelId === entry.canonicalModelId && e.choice === entry.choice && e.profile === entry.profile
115
+ )) {
116
+ return;
117
+ }
118
+ list.push(entry);
119
+ byKey.set(k, list);
120
+ };
121
+ for (const profile of Object.values(registry.profiles)) {
122
+ for (const [choiceKey, choice] of Object.entries(profile.choices)) {
123
+ const entry = choiceEntry(choice, profile.profile, choiceKey);
124
+ add(choice.modelId, entry);
125
+ add(canonicalModelId(choice.provider, choice.modelId), entry);
126
+ }
127
+ }
128
+ return byKey;
129
+ }
130
+ function choiceEntry(choice, profile, choiceKey) {
131
+ const canonical = canonicalModelId(choice.provider, choice.modelId);
132
+ return {
133
+ provider: normalizeProvider(choice.provider) ?? choice.provider,
134
+ modelId: normalizeString(choice.modelId),
135
+ canonicalModelId: canonical,
136
+ pricing: choice.pricing,
137
+ profile,
138
+ choice: choiceKey
139
+ };
140
+ }
141
+ async function getProfileIndex() {
142
+ const registry = await loadProfilesRegistry();
143
+ const cacheKey = `${registry.version}:${registry.generatedAt ?? ""}:${registry.source}`;
144
+ if (cachedIndex?.cacheKey === cacheKey) {
145
+ return cachedIndex.byKey;
146
+ }
147
+ const byKey = indexRegistry(registry);
148
+ cachedIndex = { cacheKey, byKey };
149
+ return byKey;
150
+ }
151
+ function scoreCandidate(entry, model, providerHint) {
152
+ const normalized = normalizeString(model);
153
+ let score = 0;
154
+ if (normalized === entry.canonicalModelId) score += 100;
155
+ if (normalized === entry.modelId) score += 80;
156
+ if (providerHint && entry.provider === providerHint) score += 50;
157
+ if (entry.pricing) score += 2;
158
+ return score;
159
+ }
160
+ function pickBest(candidates, model, providerHint) {
161
+ if (candidates.length === 0) return null;
162
+ if (candidates.length === 1) return candidates[0];
163
+ let best = candidates[0];
164
+ let bestScore = scoreCandidate(best, model, providerHint);
165
+ for (let i = 1; i < candidates.length; i++) {
166
+ const c = candidates[i];
167
+ const s = scoreCandidate(c, model, providerHint);
168
+ if (s > bestScore) {
169
+ best = c;
170
+ bestScore = s;
171
+ }
172
+ }
173
+ return best;
174
+ }
175
+ function resolvedToMatch(resolved) {
176
+ return {
177
+ provider: normalizeProvider(resolved.provider) ?? resolved.provider,
178
+ modelId: normalizeString(resolved.modelId),
179
+ canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),
180
+ pricing: resolved.pricing,
181
+ instructionTier: resolved.instructionTier,
182
+ backend: resolved.backend,
183
+ matchedVia: resolved.shortcut ? "shortcut" : "profile",
184
+ profile: resolved.profile,
185
+ choice: resolved.choice
186
+ };
187
+ }
188
+ async function fromIndexed(entry) {
189
+ const resolved = await resolveAIProfile(entry.profile, { choice: entry.choice });
190
+ return {
191
+ provider: normalizeProvider(resolved.provider) ?? resolved.provider,
192
+ modelId: normalizeString(resolved.modelId),
193
+ canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),
194
+ pricing: resolved.pricing ?? entry.pricing,
195
+ instructionTier: resolved.instructionTier,
196
+ backend: resolved.backend,
197
+ matchedVia: "model-id",
198
+ profile: resolved.profile,
199
+ choice: resolved.choice
200
+ };
201
+ }
202
+ async function lookupInIndex(index, model, provider) {
203
+ const providerHint = provider ? normalizeProvider(provider) : void 0;
204
+ const keys = [
205
+ profileKey(model),
206
+ profileKey(normalizeString(model))
207
+ ];
208
+ if (providerHint) {
209
+ keys.push(profileKey(canonicalModelId(providerHint, model)));
210
+ }
211
+ const pooled = [];
212
+ for (const key of keys) {
213
+ const hits = index.get(key);
214
+ if (hits) pooled.push(...hits);
215
+ }
216
+ const bare = normalizeString(model);
217
+ if (!bare.includes("/")) {
218
+ for (const list of index.values()) {
219
+ for (const entry of list) {
220
+ if (entry.modelId === bare) pooled.push(entry);
221
+ }
222
+ }
223
+ }
224
+ const unique = /* @__PURE__ */ new Map();
225
+ for (const e of pooled) {
226
+ unique.set(`${e.profile}:${e.choice}:${e.canonicalModelId}`, e);
227
+ }
228
+ const best = pickBest([...unique.values()], model, providerHint);
229
+ return best ? fromIndexed(best) : null;
230
+ }
231
+ async function matchModelInAiProfiles(model, provider) {
232
+ try {
233
+ const resolved = await resolveAIProfile(model);
234
+ return resolvedToMatch(resolved);
235
+ } catch (err) {
236
+ if (!(err instanceof AIProfilesError) || err.code !== "UNKNOWN_PROFILE") {
237
+ throw err;
238
+ }
239
+ }
240
+ const index = await getProfileIndex();
241
+ const hint = providerHintForProfiles(model, provider);
242
+ const direct = await lookupInIndex(index, model, hint);
243
+ if (direct) return direct;
244
+ const stripped = stripModelVersionSuffix(model);
245
+ if (stripped && stripped !== normalizeString(model)) {
246
+ return lookupInIndex(
247
+ index,
248
+ stripped,
249
+ providerHintForProfiles(stripped, provider)
250
+ );
251
+ }
252
+ return null;
253
+ }
254
+
255
+ export {
256
+ isLocalProvider,
257
+ isLocalProviderResolution,
258
+ buildCatalogResolveAttempts,
259
+ resolveFromCatalogAttempts,
260
+ resolveRoutedViaOpenRouter,
261
+ matchModelInAiProfiles
262
+ };
263
+ //# sourceMappingURL=chunk-HEB73GKJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cost/costModelResolution.ts","../src/cost/aiProfilesMatch.ts"],"sourcesContent":["import type { AiModelsCatalogClient } from \"../catalog/AiModelsCatalogClient.js\";\nimport { LOCAL_PROVIDERS } from \"../sync/modelNameResolver/constants.js\";\nimport {\n loadOpenRouterRoutingEnv,\n shouldDefaultRouteViaOpenRouter,\n} from \"../sync/openRouterRoutingEnv.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport type {\n ModelResolutionInput,\n ModelResolutionResult,\n ModelResolverOptions,\n} from \"../sync/modelNameResolver/types.js\";\nimport type { OpenRouterRoutingConfig } from \"../sync/openRouterRoutingEnv.js\";\n\nexport function isOpenRouterProvider(provider?: string): boolean {\n return normalizeProvider(provider) === \"openrouter\";\n}\n\nexport function isLocalProvider(provider?: string): boolean {\n const p = normalizeProvider(provider) ?? normalizeString(provider ?? \"\");\n return LOCAL_PROVIDERS.has(p);\n}\n\n/** Catalog resolver returned success without a priced record (Ollama, LM Studio, …). */\nexport function isLocalProviderResolution(\n resolved: ModelResolutionResult | null,\n inputProvider?: string,\n): boolean {\n if (!resolved?.found || resolved.record) return false;\n if (resolved.resolvedVia.includes(\"local-provider-passthrough\")) return true;\n return isLocalProvider(inputProvider);\n}\n\n/**\n * Vendor id for a model slug (`openai/gpt-4o` → `openai`).\n * Ignores `openrouter` as a provider hint — it is a routing layer, not the model owner.\n */\nexport function underlyingProviderFromModel(\n model: string,\n providerHint?: string,\n): string | undefined {\n const normalized = normalizeString(model);\n if (normalized.includes(\"/\")) {\n const prefix = normalized.split(\"/\")[0]!;\n if (!isOpenRouterProvider(prefix)) return prefix;\n }\n if (providerHint && !isOpenRouterProvider(providerHint)) {\n return normalizeProvider(providerHint);\n }\n return undefined;\n}\n\n/** Provider hint for ai-profiles index lookup (openrouter → underlying vendor). */\nexport function providerHintForProfiles(\n model: string,\n provider?: string,\n): string | undefined {\n if (isOpenRouterProvider(provider)) {\n return underlyingProviderFromModel(model, provider);\n }\n return normalizeProvider(provider);\n}\n\n/**\n * Catalog resolve attempts for direct API and OpenRouter usage.\n * Tries the caller hint, inferred vendor, no hint, and openrouter routing.\n */\nexport function buildCatalogResolveAttempts(\n model: string,\n provider?: string,\n): ModelResolutionInput[] {\n const attempts: ModelResolutionInput[] = [];\n const seen = new Set<string>();\n const add = (m: string, p?: string) => {\n const key = `${p ?? \"\"}\\0${normalizeString(m)}`;\n if (seen.has(key)) return;\n seen.add(key);\n attempts.push({ model: m, provider: p });\n };\n\n add(model, provider);\n\n const underlying = underlyingProviderFromModel(model, provider);\n if (provider) add(model, undefined);\n if (underlying) add(model, underlying);\n if (!isOpenRouterProvider(provider)) {\n add(model, \"openrouter\");\n }\n\n return attempts;\n}\n\nexport async function resolveFromCatalogAttempts(\n catalog: AiModelsCatalogClient,\n attempts: ModelResolutionInput[],\n options?: ModelResolverOptions,\n): Promise<ModelResolutionResult | null> {\n let last: ModelResolutionResult | null = null;\n let localPassthrough: ModelResolutionResult | null = null;\n\n for (const attempt of attempts) {\n const result = await catalog.resolveModel(attempt, options);\n last = result;\n if (result.found && result.record) return result;\n if (\n result.found &&\n !result.record &&\n isLocalProviderResolution(result, attempt.provider)\n ) {\n localPassthrough = result;\n }\n }\n\n return localPassthrough ?? last;\n}\n\nexport function resolveRoutedViaOpenRouter(\n inputProvider: string | undefined,\n resolved: ModelResolutionResult | null,\n modelId?: string,\n routingEnv?: OpenRouterRoutingConfig,\n): boolean {\n const env = routingEnv ?? loadOpenRouterRoutingEnv();\n\n if (isOpenRouterProvider(inputProvider)) return true;\n\n if (resolved?.found) {\n return resolved.routedViaOpenRouter;\n }\n\n const vendor = underlyingProviderFromModel(\n modelId ?? (resolved?.found ? resolved.modelId : \"\") ?? \"\",\n inputProvider,\n );\n if (vendor && shouldDefaultRouteViaOpenRouter(vendor, env)) {\n return true;\n }\n\n return false;\n}\n","import { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\nimport { AIProfilesError, resolveAIProfile } from \"@x12i/ai-profiles\";\nimport type {\n AIProfileBackend,\n AIProfileChoice,\n AIModelPricing,\n AIProfilesRegistry,\n InstructionTier,\n ResolvedAIProfile,\n} from \"@x12i/ai-profiles\";\nimport { providerHintForProfiles } from \"./costModelResolution.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport { stripModelVersionSuffix } from \"../sync/modelNameResolver/stripVersionSuffix.js\";\n\nconst require = createRequire(import.meta.url);\n\ntype LoadRegistryFn = (options?: {\n source?: \"auto\" | \"remote\" | \"bundled\";\n refresh?: boolean;\n}) => Promise<AIProfilesRegistry>;\n\nfunction loadProfilesRegistry(): Promise<AIProfilesRegistry> {\n const entry = dirname(require.resolve(\"@x12i/ai-profiles\"));\n const loader = require(join(entry, \"loader/loadAIProfilesRegistry.js\")) as {\n loadAIProfilesRegistry: LoadRegistryFn;\n };\n return loader.loadAIProfilesRegistry({ source: \"auto\" });\n}\n\nexport type AiProfilesModelMatch = {\n provider: string;\n modelId: string;\n canonicalModelId: string;\n pricing?: AIModelPricing;\n instructionTier: InstructionTier;\n backend: AIProfileBackend;\n matchedVia: \"profile\" | \"shortcut\" | \"profile-alias\" | \"model-id\";\n profile?: string;\n choice?: string;\n};\n\nfunction profileKey(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction canonicalModelId(provider: string, modelId: string): string {\n const normalized = normalizeString(modelId);\n if (normalized.includes(\"/\")) return normalized;\n const p = normalizeProvider(provider) ?? normalizeString(provider);\n return `${p}/${normalized}`;\n}\n\ntype IndexedChoice = {\n provider: string;\n modelId: string;\n canonicalModelId: string;\n pricing?: AIModelPricing;\n profile: string;\n choice: string;\n};\n\nlet cachedIndex: {\n cacheKey: string;\n byKey: Map<string, IndexedChoice[]>;\n} | null = null;\n\n/** Index bare model ids only — profile/shortcut names resolve via {@link resolveAIProfile}. */\nfunction indexRegistry(registry: AIProfilesRegistry): Map<string, IndexedChoice[]> {\n const byKey = new Map<string, IndexedChoice[]>();\n\n const add = (key: string, entry: IndexedChoice) => {\n const k = profileKey(key);\n if (!k) return;\n const list = byKey.get(k) ?? [];\n if (\n list.some(\n (e) =>\n e.canonicalModelId === entry.canonicalModelId &&\n e.choice === entry.choice &&\n e.profile === entry.profile,\n )\n ) {\n return;\n }\n list.push(entry);\n byKey.set(k, list);\n };\n\n for (const profile of Object.values(registry.profiles)) {\n for (const [choiceKey, choice] of Object.entries(profile.choices)) {\n const entry = choiceEntry(choice, profile.profile, choiceKey);\n add(choice.modelId, entry);\n add(canonicalModelId(choice.provider, choice.modelId), entry);\n }\n }\n\n return byKey;\n}\n\nfunction choiceEntry(\n choice: AIProfileChoice,\n profile: string,\n choiceKey: string,\n): IndexedChoice {\n const canonical = canonicalModelId(choice.provider, choice.modelId);\n return {\n provider: normalizeProvider(choice.provider) ?? choice.provider,\n modelId: normalizeString(choice.modelId),\n canonicalModelId: canonical,\n pricing: choice.pricing,\n profile,\n choice: choiceKey,\n };\n}\n\nasync function getProfileIndex(): Promise<Map<string, IndexedChoice[]>> {\n const registry = await loadProfilesRegistry();\n const cacheKey = `${registry.version}:${registry.generatedAt ?? \"\"}:${registry.source}`;\n if (cachedIndex?.cacheKey === cacheKey) {\n return cachedIndex.byKey;\n }\n const byKey = indexRegistry(registry);\n cachedIndex = { cacheKey, byKey };\n return byKey;\n}\n\nfunction scoreCandidate(\n entry: IndexedChoice,\n model: string,\n providerHint?: string,\n): number {\n const normalized = normalizeString(model);\n let score = 0;\n\n if (normalized === entry.canonicalModelId) score += 100;\n if (normalized === entry.modelId) score += 80;\n if (providerHint && entry.provider === providerHint) score += 50;\n if (entry.pricing) score += 2;\n\n return score;\n}\n\nfunction pickBest(\n candidates: IndexedChoice[],\n model: string,\n providerHint?: string,\n): IndexedChoice | null {\n if (candidates.length === 0) return null;\n if (candidates.length === 1) return candidates[0]!;\n\n let best = candidates[0]!;\n let bestScore = scoreCandidate(best, model, providerHint);\n for (let i = 1; i < candidates.length; i++) {\n const c = candidates[i]!;\n const s = scoreCandidate(c, model, providerHint);\n if (s > bestScore) {\n best = c;\n bestScore = s;\n }\n }\n return best;\n}\n\nfunction resolvedToMatch(resolved: ResolvedAIProfile): AiProfilesModelMatch {\n return {\n provider: normalizeProvider(resolved.provider) ?? resolved.provider,\n modelId: normalizeString(resolved.modelId),\n canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),\n pricing: resolved.pricing,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n matchedVia: resolved.shortcut ? \"shortcut\" : \"profile\",\n profile: resolved.profile,\n choice: resolved.choice,\n };\n}\n\nasync function fromIndexed(entry: IndexedChoice): Promise<AiProfilesModelMatch> {\n const resolved = await resolveAIProfile(entry.profile, { choice: entry.choice });\n return {\n provider: normalizeProvider(resolved.provider) ?? resolved.provider,\n modelId: normalizeString(resolved.modelId),\n canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),\n pricing: resolved.pricing ?? entry.pricing,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n matchedVia: \"model-id\",\n profile: resolved.profile,\n choice: resolved.choice,\n };\n}\n\nasync function lookupInIndex(\n index: Map<string, IndexedChoice[]>,\n model: string,\n provider?: string,\n): Promise<AiProfilesModelMatch | null> {\n const providerHint = provider ? normalizeProvider(provider) : undefined;\n const keys = [\n profileKey(model),\n profileKey(normalizeString(model)),\n ];\n if (providerHint) {\n keys.push(profileKey(canonicalModelId(providerHint, model)));\n }\n\n const pooled: IndexedChoice[] = [];\n for (const key of keys) {\n const hits = index.get(key);\n if (hits) pooled.push(...hits);\n }\n\n const bare = normalizeString(model);\n if (!bare.includes(\"/\")) {\n for (const list of index.values()) {\n for (const entry of list) {\n if (entry.modelId === bare) pooled.push(entry);\n }\n }\n }\n\n const unique = new Map<string, IndexedChoice>();\n for (const e of pooled) {\n unique.set(`${e.profile}:${e.choice}:${e.canonicalModelId}`, e);\n }\n\n const best = pickBest([...unique.values()], model, providerHint);\n return best ? fromIndexed(best) : null;\n}\n\n/**\n * Resolve a model string via @x12i/ai-profiles — profile/shortcut names, aliases,\n * or a concrete model id that appears on a profile choice.\n */\nexport async function matchModelInAiProfiles(\n model: string,\n provider?: string,\n): Promise<AiProfilesModelMatch | null> {\n try {\n const resolved = await resolveAIProfile(model);\n return resolvedToMatch(resolved);\n } catch (err) {\n if (!(err instanceof AIProfilesError) || err.code !== \"UNKNOWN_PROFILE\") {\n throw err;\n }\n }\n\n const index = await getProfileIndex();\n const hint = providerHintForProfiles(model, provider);\n const direct = await lookupInIndex(index, model, hint);\n if (direct) return direct;\n\n const stripped = stripModelVersionSuffix(model);\n if (stripped && stripped !== normalizeString(model)) {\n return lookupInIndex(\n index,\n stripped,\n providerHintForProfiles(stripped, provider),\n );\n }\n\n return null;\n}\n\n/** @internal Test-only — reset module cache between tests. */\nexport function resetAiProfilesMatchCacheForTests(): void {\n cachedIndex = null;\n}\n"],"mappings":"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","names":["require"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AiModelsCatalogClient
3
- } from "./chunk-OPN6BGNH.js";
3
+ } from "./chunk-D6OIUYNC.js";
4
4
 
5
5
  // src/models/filterModels.ts
6
6
  function matchesSearch(record, search) {
@@ -83,4 +83,4 @@ export {
83
83
  AiModelsService,
84
84
  getModelInfo
85
85
  };
86
- //# sourceMappingURL=chunk-VJHLO2R3.js.map
86
+ //# sourceMappingURL=chunk-KSJSLKYI.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  computeSupportsReasoning
3
- } from "./chunk-EYHMQVAL.js";
3
+ } from "./chunk-54GKLIDW.js";
4
4
 
5
5
  // src/models/normalizeOpenRouterModel.ts
6
6
  function parsePrice(value) {
@@ -99,4 +99,4 @@ export {
99
99
  extractProviderId,
100
100
  normalizeOpenRouterModel
101
101
  };
102
- //# sourceMappingURL=chunk-SIH4GPV4.js.map
102
+ //# sourceMappingURL=chunk-MOLWV5LV.js.map
@@ -1,11 +1,15 @@
1
1
  import {
2
- LOCAL_PROVIDERS,
3
- loadOpenRouterRoutingEnv,
4
- normalizeProvider,
2
+ buildCatalogResolveAttempts,
3
+ isLocalProvider,
4
+ isLocalProviderResolution,
5
+ matchModelInAiProfiles,
6
+ resolveFromCatalogAttempts,
7
+ resolveRoutedViaOpenRouter
8
+ } from "./chunk-HEB73GKJ.js";
9
+ import {
5
10
  normalizeString,
6
- shouldDefaultRouteViaOpenRouter,
7
11
  stripModelVersionSuffix
8
- } from "./chunk-B3V2EHRY.js";
12
+ } from "./chunk-SLSKQRMI.js";
9
13
  import {
10
14
  UnknownModelCostError
11
15
  } from "./chunk-2PTCWPHV.js";
@@ -359,253 +363,6 @@ function resolveUsageModel(input) {
359
363
  return value.trim();
360
364
  }
361
365
 
362
- // src/cost/aiProfilesMatch.ts
363
- import { createRequire } from "module";
364
- import { dirname, join } from "path";
365
- import { AIProfilesError, resolveAIProfile } from "@x12i/ai-profiles";
366
-
367
- // src/cost/costModelResolution.ts
368
- function isOpenRouterProvider(provider) {
369
- return normalizeProvider(provider) === "openrouter";
370
- }
371
- function isLocalProvider(provider) {
372
- const p = normalizeProvider(provider) ?? normalizeString(provider ?? "");
373
- return LOCAL_PROVIDERS.has(p);
374
- }
375
- function isLocalProviderResolution(resolved, inputProvider) {
376
- if (!resolved?.found || resolved.record) return false;
377
- if (resolved.resolvedVia.includes("local-provider-passthrough")) return true;
378
- return isLocalProvider(inputProvider);
379
- }
380
- function underlyingProviderFromModel(model, providerHint) {
381
- const normalized = normalizeString(model);
382
- if (normalized.includes("/")) {
383
- const prefix = normalized.split("/")[0];
384
- if (!isOpenRouterProvider(prefix)) return prefix;
385
- }
386
- if (providerHint && !isOpenRouterProvider(providerHint)) {
387
- return normalizeProvider(providerHint);
388
- }
389
- return void 0;
390
- }
391
- function providerHintForProfiles(model, provider) {
392
- if (isOpenRouterProvider(provider)) {
393
- return underlyingProviderFromModel(model, provider);
394
- }
395
- return normalizeProvider(provider);
396
- }
397
- function buildCatalogResolveAttempts(model, provider) {
398
- const attempts = [];
399
- const seen = /* @__PURE__ */ new Set();
400
- const add = (m, p) => {
401
- const key = `${p ?? ""}\0${normalizeString(m)}`;
402
- if (seen.has(key)) return;
403
- seen.add(key);
404
- attempts.push({ model: m, provider: p });
405
- };
406
- add(model, provider);
407
- const underlying = underlyingProviderFromModel(model, provider);
408
- if (provider) add(model, void 0);
409
- if (underlying) add(model, underlying);
410
- if (!isOpenRouterProvider(provider)) {
411
- add(model, "openrouter");
412
- }
413
- return attempts;
414
- }
415
- async function resolveFromCatalogAttempts(catalog, attempts, options) {
416
- let last = null;
417
- let localPassthrough = null;
418
- for (const attempt of attempts) {
419
- const result = await catalog.resolveModel(attempt, options);
420
- last = result;
421
- if (result.found && result.record) return result;
422
- if (result.found && !result.record && isLocalProviderResolution(result, attempt.provider)) {
423
- localPassthrough = result;
424
- }
425
- }
426
- return localPassthrough ?? last;
427
- }
428
- function resolveRoutedViaOpenRouter(inputProvider, resolved, modelId, routingEnv) {
429
- const env = routingEnv ?? loadOpenRouterRoutingEnv();
430
- if (isOpenRouterProvider(inputProvider)) return true;
431
- if (resolved?.found) {
432
- return resolved.routedViaOpenRouter;
433
- }
434
- const vendor = underlyingProviderFromModel(
435
- modelId ?? (resolved?.found ? resolved.modelId : "") ?? "",
436
- inputProvider
437
- );
438
- if (vendor && shouldDefaultRouteViaOpenRouter(vendor, env)) {
439
- return true;
440
- }
441
- return false;
442
- }
443
-
444
- // src/cost/aiProfilesMatch.ts
445
- var require2 = createRequire(import.meta.url);
446
- function loadProfilesRegistry() {
447
- const entry = dirname(require2.resolve("@x12i/ai-profiles"));
448
- const loader = require2(join(entry, "loader/loadAIProfilesRegistry.js"));
449
- return loader.loadAIProfilesRegistry({ source: "auto" });
450
- }
451
- function profileKey(value) {
452
- return value.trim().toLowerCase();
453
- }
454
- function canonicalModelId(provider, modelId) {
455
- const normalized = normalizeString(modelId);
456
- if (normalized.includes("/")) return normalized;
457
- const p = normalizeProvider(provider) ?? normalizeString(provider);
458
- return `${p}/${normalized}`;
459
- }
460
- var cachedIndex = null;
461
- function indexRegistry(registry) {
462
- const byKey = /* @__PURE__ */ new Map();
463
- const add = (key, entry) => {
464
- const k = profileKey(key);
465
- if (!k) return;
466
- const list = byKey.get(k) ?? [];
467
- if (list.some(
468
- (e) => e.canonicalModelId === entry.canonicalModelId && e.choice === entry.choice && e.profile === entry.profile
469
- )) {
470
- return;
471
- }
472
- list.push(entry);
473
- byKey.set(k, list);
474
- };
475
- for (const profile of Object.values(registry.profiles)) {
476
- for (const [choiceKey, choice] of Object.entries(profile.choices)) {
477
- const entry = choiceEntry(choice, profile.profile, choiceKey);
478
- add(choice.modelId, entry);
479
- add(canonicalModelId(choice.provider, choice.modelId), entry);
480
- }
481
- }
482
- return byKey;
483
- }
484
- function choiceEntry(choice, profile, choiceKey) {
485
- const canonical = canonicalModelId(choice.provider, choice.modelId);
486
- return {
487
- provider: normalizeProvider(choice.provider) ?? choice.provider,
488
- modelId: normalizeString(choice.modelId),
489
- canonicalModelId: canonical,
490
- pricing: choice.pricing,
491
- profile,
492
- choice: choiceKey
493
- };
494
- }
495
- async function getProfileIndex() {
496
- const registry = await loadProfilesRegistry();
497
- const cacheKey = `${registry.version}:${registry.generatedAt ?? ""}:${registry.source}`;
498
- if (cachedIndex?.cacheKey === cacheKey) {
499
- return cachedIndex.byKey;
500
- }
501
- const byKey = indexRegistry(registry);
502
- cachedIndex = { cacheKey, byKey };
503
- return byKey;
504
- }
505
- function scoreCandidate(entry, model, providerHint) {
506
- const normalized = normalizeString(model);
507
- let score = 0;
508
- if (normalized === entry.canonicalModelId) score += 100;
509
- if (normalized === entry.modelId) score += 80;
510
- if (providerHint && entry.provider === providerHint) score += 50;
511
- if (entry.pricing) score += 2;
512
- return score;
513
- }
514
- function pickBest(candidates, model, providerHint) {
515
- if (candidates.length === 0) return null;
516
- if (candidates.length === 1) return candidates[0];
517
- let best = candidates[0];
518
- let bestScore = scoreCandidate(best, model, providerHint);
519
- for (let i = 1; i < candidates.length; i++) {
520
- const c = candidates[i];
521
- const s = scoreCandidate(c, model, providerHint);
522
- if (s > bestScore) {
523
- best = c;
524
- bestScore = s;
525
- }
526
- }
527
- return best;
528
- }
529
- function resolvedToMatch(resolved) {
530
- return {
531
- provider: normalizeProvider(resolved.provider) ?? resolved.provider,
532
- modelId: normalizeString(resolved.modelId),
533
- canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),
534
- pricing: resolved.pricing,
535
- instructionTier: resolved.instructionTier,
536
- backend: resolved.backend,
537
- matchedVia: resolved.shortcut ? "shortcut" : "profile",
538
- profile: resolved.profile,
539
- choice: resolved.choice
540
- };
541
- }
542
- async function fromIndexed(entry) {
543
- const resolved = await resolveAIProfile(entry.profile, { choice: entry.choice });
544
- return {
545
- provider: normalizeProvider(resolved.provider) ?? resolved.provider,
546
- modelId: normalizeString(resolved.modelId),
547
- canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),
548
- pricing: resolved.pricing ?? entry.pricing,
549
- instructionTier: resolved.instructionTier,
550
- backend: resolved.backend,
551
- matchedVia: "model-id",
552
- profile: resolved.profile,
553
- choice: resolved.choice
554
- };
555
- }
556
- async function lookupInIndex(index, model, provider) {
557
- const providerHint = provider ? normalizeProvider(provider) : void 0;
558
- const keys = [
559
- profileKey(model),
560
- profileKey(normalizeString(model))
561
- ];
562
- if (providerHint) {
563
- keys.push(profileKey(canonicalModelId(providerHint, model)));
564
- }
565
- const pooled = [];
566
- for (const key of keys) {
567
- const hits = index.get(key);
568
- if (hits) pooled.push(...hits);
569
- }
570
- const bare = normalizeString(model);
571
- if (!bare.includes("/")) {
572
- for (const list of index.values()) {
573
- for (const entry of list) {
574
- if (entry.modelId === bare) pooled.push(entry);
575
- }
576
- }
577
- }
578
- const unique = /* @__PURE__ */ new Map();
579
- for (const e of pooled) {
580
- unique.set(`${e.profile}:${e.choice}:${e.canonicalModelId}`, e);
581
- }
582
- const best = pickBest([...unique.values()], model, providerHint);
583
- return best ? fromIndexed(best) : null;
584
- }
585
- async function matchModelInAiProfiles(model, provider) {
586
- try {
587
- const resolved = await resolveAIProfile(model);
588
- return resolvedToMatch(resolved);
589
- } catch (err) {
590
- if (!(err instanceof AIProfilesError) || err.code !== "UNKNOWN_PROFILE") {
591
- throw err;
592
- }
593
- }
594
- const index = await getProfileIndex();
595
- const hint = providerHintForProfiles(model, provider);
596
- const direct = await lookupInIndex(index, model, hint);
597
- if (direct) return direct;
598
- const stripped = stripModelVersionSuffix(model);
599
- if (stripped && stripped !== normalizeString(model)) {
600
- return lookupInIndex(
601
- index,
602
- stripped,
603
- providerHintForProfiles(stripped, provider)
604
- );
605
- }
606
- return null;
607
- }
608
-
609
366
  // src/cost/profilePricing.ts
610
367
  var TOKENS_PER_UNIT = 1e6;
611
368
  function usdPerToken(perMillion) {
@@ -945,4 +702,4 @@ export {
945
702
  resolveUsageModel,
946
703
  CostCalculator
947
704
  };
948
- //# sourceMappingURL=chunk-CTM35DMA.js.map
705
+ //# sourceMappingURL=chunk-PN4FF6YF.js.map