@x12i/ai-tools 2.1.5 → 2.3.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 (93) hide show
  1. package/dist/{AiModelsCatalogClient-DgBdVFk-.d.cts → AiModelsCatalogClient-CQf-zHc6.d.cts} +1 -1
  2. package/dist/{AiModelsCatalogClient-C9ZJHhv3.d.ts → AiModelsCatalogClient-Cohl3zfe.d.ts} +1 -1
  3. package/dist/aliases/index.d.cts +4 -3
  4. package/dist/aliases/index.d.ts +4 -3
  5. package/dist/catalog/index.cjs +5 -4
  6. package/dist/catalog/index.cjs.map +1 -1
  7. package/dist/catalog/index.d.cts +5 -4
  8. package/dist/catalog/index.d.ts +5 -4
  9. package/dist/catalog/index.js +4 -3
  10. package/dist/{chunk-4ILJWO64.js → chunk-3CUSLNEV.js} +8 -1
  11. package/dist/chunk-3CUSLNEV.js.map +1 -0
  12. package/dist/{chunk-IYRZYLUP.cjs → chunk-3JDAPUZM.cjs} +14 -12
  13. package/dist/chunk-3JDAPUZM.cjs.map +1 -0
  14. package/dist/chunk-6T7QT6YH.cjs +7 -0
  15. package/dist/chunk-6T7QT6YH.cjs.map +1 -0
  16. package/dist/{chunk-OZHZUMNR.js → chunk-A7JKTDSD.js} +5 -3
  17. package/dist/{chunk-OZHZUMNR.js.map → chunk-A7JKTDSD.js.map} +1 -1
  18. package/dist/{chunk-4UA2V5R2.cjs → chunk-AGLZXZCH.cjs} +23 -21
  19. package/dist/chunk-AGLZXZCH.cjs.map +1 -0
  20. package/dist/{chunk-SYDW33AL.cjs → chunk-EDZOFPLV.cjs} +8 -1
  21. package/dist/chunk-EDZOFPLV.cjs.map +1 -0
  22. package/dist/{chunk-RK4QKTQ2.cjs → chunk-EE3Z75GO.cjs} +5 -5
  23. package/dist/{chunk-RK4QKTQ2.cjs.map → chunk-EE3Z75GO.cjs.map} +1 -1
  24. package/dist/{chunk-WJFOQS6I.js → chunk-FHJDIYPJ.js} +3 -3
  25. package/dist/{chunk-CM3GY62V.cjs → chunk-H7W5LMP6.cjs} +31 -15
  26. package/dist/chunk-H7W5LMP6.cjs.map +1 -0
  27. package/dist/{chunk-DIVRTJUA.js → chunk-LHJV2YLY.js} +13 -3
  28. package/dist/{chunk-DIVRTJUA.js.map → chunk-LHJV2YLY.js.map} +1 -1
  29. package/dist/chunk-OPKL4YNL.js +7 -0
  30. package/dist/chunk-OPKL4YNL.js.map +1 -0
  31. package/dist/{chunk-YQVY7CWT.js → chunk-U2LOUZP7.js} +3 -2
  32. package/dist/chunk-U2LOUZP7.js.map +1 -0
  33. package/dist/{chunk-MN6K2YHF.js → chunk-VR4P5QB2.js} +6 -4
  34. package/dist/{chunk-MN6K2YHF.js.map → chunk-VR4P5QB2.js.map} +1 -1
  35. package/dist/{chunk-YY2AGHRV.cjs → chunk-VVCG536Q.cjs} +7 -7
  36. package/dist/{chunk-YY2AGHRV.cjs.map → chunk-VVCG536Q.cjs.map} +1 -1
  37. package/dist/{chunk-DYVCBK2C.js → chunk-WVJZCVI7.js} +2 -2
  38. package/dist/{chunk-U3BAEJ2C.cjs → chunk-XKJFO6VG.cjs} +16 -6
  39. package/dist/chunk-XKJFO6VG.cjs.map +1 -0
  40. package/dist/{chunk-WBHH3JEK.js → chunk-YERYMWKM.js} +28 -12
  41. package/dist/chunk-YERYMWKM.js.map +1 -0
  42. package/dist/{chunk-5IZ7PLY2.cjs → chunk-YGOZDVK3.cjs} +4 -3
  43. package/dist/chunk-YGOZDVK3.cjs.map +1 -0
  44. package/dist/cli/index.cjs +17 -16
  45. package/dist/cli/index.cjs.map +1 -1
  46. package/dist/cli/index.js +8 -7
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/cost/index.cjs +6 -5
  49. package/dist/cost/index.cjs.map +1 -1
  50. package/dist/cost/index.d.cts +6 -5
  51. package/dist/cost/index.d.ts +6 -5
  52. package/dist/cost/index.js +5 -4
  53. package/dist/index.cjs +13 -9
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.d.cts +9 -9
  56. package/dist/index.d.ts +9 -9
  57. package/dist/index.js +12 -8
  58. package/dist/{modelCache-xzoTUue2.d.ts → modelCache-Bbw8Yc8Y.d.ts} +1 -1
  59. package/dist/{modelCache-sL3dBfRM.d.cts → modelCache-_mEwDBW7.d.cts} +1 -1
  60. package/dist/{modelNameResolver-2WroQlqt.d.ts → modelNameResolver-6k18Wvys.d.ts} +1 -1
  61. package/dist/{modelNameResolver-Bxlehrbp.d.cts → modelNameResolver-MoyOpdC3.d.cts} +1 -1
  62. package/dist/models/index.cjs +7 -6
  63. package/dist/models/index.cjs.map +1 -1
  64. package/dist/models/index.d.cts +5 -4
  65. package/dist/models/index.d.ts +5 -4
  66. package/dist/models/index.js +6 -5
  67. package/dist/profiles/index.cjs +6 -2
  68. package/dist/profiles/index.cjs.map +1 -1
  69. package/dist/profiles/index.d.cts +8 -3
  70. package/dist/profiles/index.d.ts +8 -3
  71. package/dist/profiles/index.js +5 -1
  72. package/dist/{resolveModelVendor-DQpJpk0w.d.ts → resolveModelVendor-Bb-TvXHF.d.ts} +3 -3
  73. package/dist/{resolveModelVendor-uphYBFMY.d.ts → resolveModelVendor-CF9l_SVN.d.ts} +1 -1
  74. package/dist/{resolveModelVendor-XvmXsVzo.d.cts → resolveModelVendor-CI64t5sk.d.cts} +3 -3
  75. package/dist/{resolveModelVendor-B0t5nq-v.d.cts → resolveModelVendor-Ck059GDf.d.cts} +1 -1
  76. package/dist/sync/index.cjs +2 -2
  77. package/dist/sync/index.d.cts +5 -4
  78. package/dist/sync/index.d.ts +5 -4
  79. package/dist/sync/index.js +1 -1
  80. package/dist/{types-BZYGjN2O.d.ts → types-CILRAzjr.d.cts} +4 -0
  81. package/dist/{types-BZYGjN2O.d.cts → types-CILRAzjr.d.ts} +4 -0
  82. package/package.json +2 -2
  83. package/dist/chunk-4ILJWO64.js.map +0 -1
  84. package/dist/chunk-4UA2V5R2.cjs.map +0 -1
  85. package/dist/chunk-5IZ7PLY2.cjs.map +0 -1
  86. package/dist/chunk-CM3GY62V.cjs.map +0 -1
  87. package/dist/chunk-IYRZYLUP.cjs.map +0 -1
  88. package/dist/chunk-SYDW33AL.cjs.map +0 -1
  89. package/dist/chunk-U3BAEJ2C.cjs.map +0 -1
  90. package/dist/chunk-WBHH3JEK.js.map +0 -1
  91. package/dist/chunk-YQVY7CWT.js.map +0 -1
  92. /package/dist/{chunk-WJFOQS6I.js.map → chunk-FHJDIYPJ.js.map} +0 -0
  93. /package/dist/{chunk-DYVCBK2C.js.map → chunk-WVJZCVI7.js.map} +0 -0
@@ -6,6 +6,9 @@ import {
6
6
  shouldDefaultRouteViaOpenRouter,
7
7
  stripModelVersionSuffix
8
8
  } from "./chunk-OB44D7RG.js";
9
+ import {
10
+ TEXT_CATALOG_LANE
11
+ } from "./chunk-OPKL4YNL.js";
9
12
 
10
13
  // src/cost/costModelResolution.ts
11
14
  function isOpenRouterProvider(provider) {
@@ -107,8 +110,12 @@ var registrySourceOverride;
107
110
  function registrySource(options) {
108
111
  return options?.source ?? registrySourceOverride ?? "auto";
109
112
  }
110
- function profileResolveOptions(source) {
111
- return source === "auto" ? { source } : { source, refresh: true };
113
+ function catalogLane(options) {
114
+ return options?.catalogLane ?? TEXT_CATALOG_LANE;
115
+ }
116
+ function profileResolveOptions(source, lane) {
117
+ const base = { source, catalogLane: lane };
118
+ return source === "auto" ? base : { ...base, refresh: true };
112
119
  }
113
120
  function indexRegistry(registry) {
114
121
  const byKey = /* @__PURE__ */ new Map();
@@ -147,7 +154,9 @@ function choiceEntry(choice, profile, choiceKey) {
147
154
  };
148
155
  }
149
156
  async function getProfileIndex(source) {
150
- const registry = await loadAIProfilesRegistry(profileResolveOptions(source));
157
+ const registry = await loadAIProfilesRegistry(
158
+ profileResolveOptions(source, TEXT_CATALOG_LANE)
159
+ );
151
160
  const cacheKey = `${source}:${registry.version}:${registry.generatedAt ?? ""}:${registry.source}`;
152
161
  if (cachedIndex?.cacheKey === cacheKey) {
153
162
  return cachedIndex.byKey;
@@ -180,6 +189,9 @@ function pickBest(candidates, model, providerHint) {
180
189
  }
181
190
  return best;
182
191
  }
192
+ function isLowConfidenceModelResolution(resolved) {
193
+ return resolved.resolutionKind === "model" && resolved.warnings?.some((w) => w.code === "MODEL_INPUT_FALLBACK_GUESS") === true;
194
+ }
183
195
  function resolvedToMatch(resolved) {
184
196
  const direct = resolved.invocation.direct;
185
197
  const canonical = resolved.invocation.openrouter?.modelId ?? buildOpenRouterModelId(direct.provider, direct.modelId);
@@ -190,15 +202,15 @@ function resolvedToMatch(resolved) {
190
202
  pricing: resolved.pricing,
191
203
  instructionTier: resolved.instructionTier,
192
204
  backend: resolved.backend,
193
- matchedVia: resolved.shortcut ? "shortcut" : "profile",
205
+ matchedVia: resolved.resolutionKind === "model" ? "model-id" : resolved.shortcut ? "shortcut" : "profile",
194
206
  profile: resolved.profile,
195
207
  choice: resolved.choice
196
208
  };
197
209
  }
198
- async function fromIndexed(entry, source) {
210
+ async function fromIndexed(entry, source, lane) {
199
211
  const resolved = await resolveAIProfile(entry.profile, {
200
212
  choice: entry.choice,
201
- ...profileResolveOptions(source)
213
+ ...profileResolveOptions(source, lane)
202
214
  });
203
215
  const direct = resolved.invocation.direct;
204
216
  return {
@@ -213,7 +225,7 @@ async function fromIndexed(entry, source) {
213
225
  choice: resolved.choice
214
226
  };
215
227
  }
216
- async function lookupInIndex(index, model, source, provider) {
228
+ async function lookupInIndex(index, model, source, lane, provider) {
217
229
  const providerHint = provider ? normalizeProvider(provider) : void 0;
218
230
  const keys = [
219
231
  profileKey(model),
@@ -240,14 +252,17 @@ async function lookupInIndex(index, model, source, provider) {
240
252
  unique.set(`${e.profile}:${e.choice}:${e.canonicalModelId}`, e);
241
253
  }
242
254
  const best = pickBest([...unique.values()], model, providerHint);
243
- return best ? fromIndexed(best, source) : null;
255
+ return best ? fromIndexed(best, source, lane) : null;
244
256
  }
245
257
  async function matchModelInAiProfiles(model, provider, options) {
246
258
  const source = registrySource(options);
247
- const resolveOpts = profileResolveOptions(source);
259
+ const lane = catalogLane(options);
260
+ const resolveOpts = profileResolveOptions(source, lane);
248
261
  try {
249
262
  const resolved = await resolveAIProfile(model, resolveOpts);
250
- return resolvedToMatch(resolved);
263
+ if (!isLowConfidenceModelResolution(resolved)) {
264
+ return resolvedToMatch(resolved);
265
+ }
251
266
  } catch (err) {
252
267
  if (!(err instanceof AIProfilesError) || err.code !== "UNKNOWN_PROFILE") {
253
268
  throw err;
@@ -255,7 +270,7 @@ async function matchModelInAiProfiles(model, provider, options) {
255
270
  }
256
271
  const index = await getProfileIndex(source);
257
272
  const hint = providerHintForProfiles(model, provider);
258
- const direct = await lookupInIndex(index, model, source, hint);
273
+ const direct = await lookupInIndex(index, model, source, lane, hint);
259
274
  if (direct) return direct;
260
275
  const stripped = stripModelVersionSuffix(model);
261
276
  if (stripped && stripped !== normalizeString(model)) {
@@ -263,6 +278,7 @@ async function matchModelInAiProfiles(model, provider, options) {
263
278
  index,
264
279
  stripped,
265
280
  source,
281
+ lane,
266
282
  providerHintForProfiles(stripped, provider)
267
283
  );
268
284
  }
@@ -277,4 +293,4 @@ export {
277
293
  resolveRoutedViaOpenRouter,
278
294
  matchModelInAiProfiles
279
295
  };
280
- //# sourceMappingURL=chunk-WBHH3JEK.js.map
296
+ //# sourceMappingURL=chunk-YERYMWKM.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 {\n AIProfilesError,\n buildOpenRouterModelId,\n getChoiceOpenRouterModelId,\n getChoicePricing,\n getChoiceVendorModelId,\n loadAIProfilesRegistry,\n resolveAIProfile,\n} from \"@x12i/ai-profiles\";\nimport type {\n AIProfileBackend,\n AIProfileChoice,\n AIModelPricing,\n AIProfilesRegistry,\n InstructionTier,\n ProfileCatalogLane,\n RegistrySourceMode,\n ResolvedAIProfile,\n} from \"@x12i/ai-profiles\";\nimport { TEXT_CATALOG_LANE } from \"../profiles/catalogLane.js\";\nimport { providerHintForProfiles } from \"./costModelResolution.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport { stripModelVersionSuffix } from \"../sync/modelNameResolver/stripVersionSuffix.js\";\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 return buildOpenRouterModelId(provider, 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\nexport type MatchModelInAiProfilesOptions = {\n source?: RegistrySourceMode;\n /** OpenRouter catalog lane (required by @x12i/ai-profiles 2.x). Defaults to {@link TEXT_CATALOG_LANE}. */\n catalogLane?: ProfileCatalogLane;\n};\n\n/** When set (tests), overrides default `auto` registry/catalog source. */\nlet registrySourceOverride: RegistrySourceMode | undefined;\n\nfunction registrySource(options?: MatchModelInAiProfilesOptions): RegistrySourceMode {\n return options?.source ?? registrySourceOverride ?? \"auto\";\n}\n\nfunction catalogLane(options?: MatchModelInAiProfilesOptions): ProfileCatalogLane {\n return options?.catalogLane ?? TEXT_CATALOG_LANE;\n}\n\n/** ai-profiles returns a valid in-memory cache before honoring `source`; refresh on explicit sources. */\nfunction profileResolveOptions(\n source: RegistrySourceMode,\n lane: ProfileCatalogLane,\n) {\n const base = { source, catalogLane: lane };\n return source === \"auto\" ? base : { ...base, refresh: true as const };\n}\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(getChoiceVendorModelId(choice), entry);\n add(canonicalModelId(choice.provider, getChoiceVendorModelId(choice)), entry);\n }\n }\n\n return byKey;\n}\n\nfunction choiceEntry(\n choice: AIProfileChoice,\n profile: string,\n choiceKey: string,\n): IndexedChoice {\n const vendorModelId = getChoiceVendorModelId(choice);\n const provider = normalizeProvider(choice.provider) ?? choice.provider;\n const canonical =\n getChoiceOpenRouterModelId(choice) ??\n canonicalModelId(choice.provider, vendorModelId);\n return {\n provider,\n modelId: normalizeString(vendorModelId),\n canonicalModelId: canonical,\n pricing: getChoicePricing(choice),\n profile,\n choice: choiceKey,\n };\n}\n\nasync function getProfileIndex(\n source: RegistrySourceMode,\n): Promise<Map<string, IndexedChoice[]>> {\n const registry = await loadAIProfilesRegistry(\n profileResolveOptions(source, TEXT_CATALOG_LANE),\n );\n const cacheKey = `${source}:${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 isLowConfidenceModelResolution(resolved: ResolvedAIProfile): boolean {\n return (\n resolved.resolutionKind === \"model\" &&\n resolved.warnings?.some((w) => w.code === \"MODEL_INPUT_FALLBACK_GUESS\") === true\n );\n}\n\nfunction resolvedToMatch(resolved: ResolvedAIProfile): AiProfilesModelMatch {\n const direct = resolved.invocation.direct;\n const canonical =\n resolved.invocation.openrouter?.modelId ??\n buildOpenRouterModelId(direct.provider, direct.modelId);\n return {\n provider: normalizeProvider(direct.provider) ?? direct.provider,\n modelId: normalizeString(direct.modelId),\n canonicalModelId: canonical,\n pricing: resolved.pricing,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n matchedVia:\n resolved.resolutionKind === \"model\"\n ? \"model-id\"\n : resolved.shortcut\n ? \"shortcut\"\n : \"profile\",\n profile: resolved.profile,\n choice: resolved.choice,\n };\n}\n\nasync function fromIndexed(\n entry: IndexedChoice,\n source: RegistrySourceMode,\n lane: ProfileCatalogLane,\n): Promise<AiProfilesModelMatch> {\n const resolved = await resolveAIProfile(entry.profile, {\n choice: entry.choice,\n ...profileResolveOptions(source, lane),\n });\n const direct = resolved.invocation.direct;\n return {\n provider: normalizeProvider(direct.provider) ?? direct.provider,\n modelId: normalizeString(direct.modelId),\n canonicalModelId:\n resolved.invocation.openrouter?.modelId ??\n buildOpenRouterModelId(direct.provider, direct.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 source: RegistrySourceMode,\n lane: ProfileCatalogLane,\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, source, lane) : 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 options?: MatchModelInAiProfilesOptions,\n): Promise<AiProfilesModelMatch | null> {\n const source = registrySource(options);\n const lane = catalogLane(options);\n const resolveOpts = profileResolveOptions(source, lane);\n\n try {\n const resolved = await resolveAIProfile(model, resolveOpts);\n if (!isLowConfidenceModelResolution(resolved)) {\n return resolvedToMatch(resolved);\n }\n } catch (err) {\n if (!(err instanceof AIProfilesError) || err.code !== \"UNKNOWN_PROFILE\") {\n throw err;\n }\n }\n\n const index = await getProfileIndex(source);\n const hint = providerHintForProfiles(model, provider);\n const direct = await lookupInIndex(index, model, source, lane, 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 source,\n lane,\n providerHintForProfiles(stripped, provider),\n );\n }\n\n return null;\n}\n\n/** @internal Test-only — reset module cache between tests. */\nexport function resetAiProfilesMatchCacheForTests(\n options?: { source?: RegistrySourceMode },\n): void {\n cachedIndex = null;\n registrySourceOverride = options?.source ?? \"bundled\";\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/profiles/resolveProfileForAsk.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/profiles/resolveProfileForAsk.ts
2
2
  var _aiprofiles = require('@x12i/ai-profiles');
3
3
  function profileConfigFromResolved(resolved) {
4
4
  return {
@@ -25,9 +25,10 @@ function profileConfigFromResolved(resolved) {
25
25
  }
26
26
  async function resolveProfileForAsk(input) {
27
27
  const resolved = await _aiprofiles.resolveAIProfile.call(void 0, input.profile, {
28
+ catalogLane: input.catalogLane,
28
29
  choice: input.choice,
29
30
  source: input.source,
30
- refresh: input.refresh
31
+ refresh: _nullishCoalesce(input.refresh, () => ( (input.source !== void 0 && input.source !== "auto" ? true : void 0)))
31
32
  });
32
33
  return profileConfigFromResolved(resolved);
33
34
  }
@@ -48,4 +49,4 @@ async function resolveProfileForAsk(input) {
48
49
 
49
50
 
50
51
  exports.profileConfigFromResolved = profileConfigFromResolved; exports.resolveProfileForAsk = resolveProfileForAsk; exports.resolveAIProfile = _aiprofiles.resolveAIProfile; exports.listAIProfiles = _aiprofiles.listAIProfiles; exports.listAIShortcuts = _aiprofiles.listAIShortcuts; exports.isKnownProfileOrShortcut = _aiprofiles.isKnownProfileOrShortcut;
51
- //# sourceMappingURL=chunk-5IZ7PLY2.cjs.map
52
+ //# sourceMappingURL=chunk-YGOZDVK3.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-YGOZDVK3.cjs","../src/profiles/resolveProfileForAsk.ts","../src/profiles/index.ts"],"names":[],"mappings":"AAAA;ACAA,+CAAiC;AAyC1B,SAAS,yBAAA,CACd,QAAA,EACuB;AACvB,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,QAAA,CAAS,QAAA;AAAA,IACnB,KAAA,EAAO,QAAA,CAAS,OAAA;AAAA,IAChB,eAAA,EAAiB,QAAA,CAAS,eAAA;AAAA,IAC1B,OAAA,EAAS,QAAA,CAAS,OAAA;AAAA,IAClB,OAAA,EAAS,QAAA,CAAS,OAAA;AAAA,IAClB,MAAA,EAAQ,QAAA,CAAS,MAAA;AAAA,IACjB,WAAA,EAAa,QAAA,CAAS,OAAA,CAAQ,WAAA;AAAA,IAC9B,UAAA,EAAY,QAAA,CAAS,OAAA,CAAQ,UAAA;AAAA,IAC7B,UAAA,EAAY,QAAA,CAAS,OAAA,CAAQ,UAAA;AAAA,IAC7B,eAAA,EAAiB,QAAA,CAAS,OAAA,CAAQ,eAAA;AAAA,IAClC,aAAA,EAAe,QAAA,CAAS,OAAA,CAAQ,aAAA;AAAA,IAChC,gBAAA,EAAkB,QAAA,CAAS,OAAA,CAAQ,gBAAA;AAAA,IACnC,QAAA,EAAU,QAAA,CAAS,OAAA,CAAQ,QAAA;AAAA,IAC3B,eAAA,EAAiB,QAAA,CAAS,OAAA,CAAQ,eAAA;AAAA,IAClC,kBAAA,EAAoB,QAAA,CAAS,OAAA,CAAQ,kBAAA;AAAA,IACrC,WAAA,EAAa,QAAA,CAAS,OAAA,CAAQ,WAAA;AAAA,IAC9B,GAAI,QAAA,CAAS,SAAA,IAAa,KAAA,EAAA,EAAY,EAAE,QAAA,EAAU,QAAA,CAAS,SAAS,EAAA,EAAI,CAAC,CAAA;AAAA,IACzE,GAAI,QAAA,CAAS,QAAA,IAAY,KAAA,EAAA,EAAY,EAAE,OAAA,EAAS,QAAA,CAAS,QAAQ,EAAA,EAAI,CAAC,CAAA;AAAA,IACtE;AAAA,EACF,CAAA;AACF;AAOA,MAAA,SAAsB,oBAAA,CACpB,KAAA,EACgC;AAChC,EAAA,MAAM,SAAA,EAAW,MAAM,0CAAA,KAAiB,CAAM,OAAA,EAAS;AAAA,IACrD,WAAA,EAAa,KAAA,CAAM,WAAA;AAAA,IACnB,MAAA,EAAQ,KAAA,CAAM,MAAA;AAAA,IACd,MAAA,EAAQ,KAAA,CAAM,MAAA;AAAA,IACd,OAAA,mBACE,KAAA,CAAM,OAAA,UAAA,CACL,KAAA,CAAM,OAAA,IAAW,KAAA,EAAA,GAAa,KAAA,CAAM,OAAA,IAAW,OAAA,EAAS,KAAA,EAAO,KAAA,CAAA;AAAA,EACpE,CAAC,CAAA;AACD,EAAA,OAAO,yBAAA,CAA0B,QAAQ,CAAA;AAC3C;ADlDA;AACA;AEbA;AACE;AACA;AACA;AACA;AAAA;AFgBF;AACA;AACE;AACA;AACA;AACA;AACA;AACA;AACF,iWAAC","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-YGOZDVK3.cjs","sourcesContent":[null,"import { resolveAIProfile } from \"@x12i/ai-profiles\";\nimport type {\n AIProfileBackend,\n InstructionTier,\n ProfileCatalogLane,\n RegistrySourceMode,\n ResolvedAIProfile,\n} from \"@x12i/ai-profiles\";\n\nexport type ResolveProfileForAskInput = {\n profile: string;\n /** OpenRouter catalog lane — must match the profile (e.g. `text`, `image`). */\n catalogLane: ProfileCatalogLane;\n choice?: string;\n source?: RegistrySourceMode;\n refresh?: boolean;\n};\n\n/** FuncX / ask-node model config derived from {@link ResolvedAIProfile}. */\nexport type AskProfileModelConfig = {\n provider: ResolvedAIProfile[\"provider\"];\n model: string;\n instructionTier: InstructionTier;\n backend: AIProfileBackend;\n profile: string;\n choice: string;\n temperature: number;\n outputMode: ResolvedAIProfile[\"runtime\"][\"outputMode\"];\n toolPolicy: ResolvedAIProfile[\"runtime\"][\"toolPolicy\"];\n reasoningEffort: ResolvedAIProfile[\"runtime\"][\"reasoningEffort\"];\n executionMode: ResolvedAIProfile[\"runtime\"][\"executionMode\"];\n requireCitations: boolean;\n allowWeb: boolean;\n allowFileSearch: boolean;\n allowCodeExecution: boolean;\n humanReview: ResolvedAIProfile[\"runtime\"][\"humanReview\"];\n metadata?: Record<string, unknown>;\n pricing?: ResolvedAIProfile[\"pricing\"];\n resolved: ResolvedAIProfile;\n};\n\nexport function profileConfigFromResolved(\n resolved: ResolvedAIProfile,\n): AskProfileModelConfig {\n return {\n provider: resolved.provider,\n model: resolved.modelId,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n profile: resolved.profile,\n choice: resolved.choice,\n temperature: resolved.runtime.temperature,\n outputMode: resolved.runtime.outputMode,\n toolPolicy: resolved.runtime.toolPolicy,\n reasoningEffort: resolved.runtime.reasoningEffort,\n executionMode: resolved.runtime.executionMode,\n requireCitations: resolved.runtime.requireCitations,\n allowWeb: resolved.runtime.allowWeb,\n allowFileSearch: resolved.runtime.allowFileSearch,\n allowCodeExecution: resolved.runtime.allowCodeExecution,\n humanReview: resolved.runtime.humanReview,\n ...(resolved.metadata !== undefined ? { metadata: resolved.metadata } : {}),\n ...(resolved.pricing !== undefined ? { pricing: resolved.pricing } : {}),\n resolved,\n };\n}\n\n/**\n * Resolve a profile (+ optional choice) into ask-node / FuncX model configuration.\n * Uses {@link ResolvedAIProfile.instructionTier} and {@link ResolvedAIProfile.backend}\n * from `@x12i/ai-profiles` — do not duplicate preset tables locally.\n */\nexport async function resolveProfileForAsk(\n input: ResolveProfileForAskInput,\n): Promise<AskProfileModelConfig> {\n const resolved = await resolveAIProfile(input.profile, {\n catalogLane: input.catalogLane,\n choice: input.choice,\n source: input.source,\n refresh:\n input.refresh ??\n (input.source !== undefined && input.source !== \"auto\" ? true : undefined),\n });\n return profileConfigFromResolved(resolved);\n}\n","export {\n resolveProfileForAsk,\n profileConfigFromResolved,\n} from \"./resolveProfileForAsk.js\";\nexport type {\n AskProfileModelConfig,\n ResolveProfileForAskInput,\n} from \"./resolveProfileForAsk.js\";\n\nexport type {\n ResolvedAIProfile,\n InstructionTier,\n AIProfileBackend,\n AIProfileSummary,\n AIShortcutSummary,\n ResolveAIProfileOptions,\n RegistrySourceMode,\n ProfileCatalogLane,\n} from \"@x12i/ai-profiles\";\n\nexport { TEXT_CATALOG_LANE } from \"./catalogLane.js\";\n\nexport {\n resolveAIProfile,\n listAIProfiles,\n listAIShortcuts,\n isKnownProfileOrShortcut,\n} from \"@x12i/ai-profiles\";\n"]}
@@ -1,28 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict"; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
3
3
 
4
- var _chunk4UA2V5R2cjs = require('../chunk-4UA2V5R2.cjs');
4
+ var _chunkAGLZXZCHcjs = require('../chunk-AGLZXZCH.cjs');
5
5
 
6
6
 
7
7
 
8
8
  var _chunkBAHBDADJcjs = require('../chunk-BAHBDADJ.cjs');
9
9
 
10
10
 
11
- var _chunkRK4QKTQ2cjs = require('../chunk-RK4QKTQ2.cjs');
12
- require('../chunk-IYRZYLUP.cjs');
13
- require('../chunk-SYDW33AL.cjs');
11
+ var _chunkEE3Z75GOcjs = require('../chunk-EE3Z75GO.cjs');
12
+ require('../chunk-3JDAPUZM.cjs');
13
+ require('../chunk-EDZOFPLV.cjs');
14
14
 
15
15
 
16
16
 
17
- var _chunkYY2AGHRVcjs = require('../chunk-YY2AGHRV.cjs');
17
+ var _chunkVVCG536Qcjs = require('../chunk-VVCG536Q.cjs');
18
18
 
19
19
 
20
20
 
21
- var _chunkU3BAEJ2Ccjs = require('../chunk-U3BAEJ2C.cjs');
22
- require('../chunk-CM3GY62V.cjs');
21
+ var _chunkXKJFO6VGcjs = require('../chunk-XKJFO6VG.cjs');
22
+ require('../chunk-H7W5LMP6.cjs');
23
23
  require('../chunk-2KPWVOOT.cjs');
24
24
  require('../chunk-OZE336BL.cjs');
25
25
  require('../chunk-PADNCGZB.cjs');
26
+ require('../chunk-6T7QT6YH.cjs');
26
27
 
27
28
 
28
29
  var _chunkGS7T56RPcjs = require('../chunk-GS7T56RP.cjs');
@@ -38,8 +39,8 @@ function registry(path) {
38
39
  function resolver(path) {
39
40
  return new (0, _chunkBAHBDADJcjs.AliasResolver)({
40
41
  registry: registry(path),
41
- catalogClient: new (0, _chunkU3BAEJ2Ccjs.AiModelsCatalogClient)({
42
- cacheTtlMs: _chunkU3BAEJ2Ccjs.resolveCatalogCacheTtlMs.call(void 0, )
42
+ catalogClient: new (0, _chunkXKJFO6VGcjs.AiModelsCatalogClient)({
43
+ cacheTtlMs: _chunkXKJFO6VGcjs.resolveCatalogCacheTtlMs.call(void 0, )
43
44
  })
44
45
  });
45
46
  }
@@ -164,7 +165,7 @@ function emitHuman(lines) {
164
165
  function registerCatalogCommand(program2) {
165
166
  const catalog = program2.command("catalog").description("Model catalog load and health commands");
166
167
  catalog.command("refresh").description("Fetch catalogs from open-assets.x12i.com and warm the cache").option("--bundled-only", "Use bundled src/data catalogs only (no HTTP)").option("--json", "Machine-readable JSON on stdout").action(async (opts) => {
167
- const result = await _chunkYY2AGHRVcjs.refreshAiModelsCatalog.call(void 0, { bundledOnly: opts.bundledOnly });
168
+ const result = await _chunkVVCG536Qcjs.refreshAiModelsCatalog.call(void 0, { bundledOnly: opts.bundledOnly });
168
169
  if (opts.json) {
169
170
  emitJson(result);
170
171
  } else {
@@ -176,7 +177,7 @@ function registerCatalogCommand(program2) {
176
177
  }
177
178
  });
178
179
  catalog.command("verify").description("Validate direct + OpenRouter catalogs load successfully").option("--bundled-only", "Use bundled src/data catalogs only (no HTTP)").option("--json", "Machine-readable JSON on stdout").action(async (opts) => {
179
- const report = await _chunkYY2AGHRVcjs.verifyAiModelsCatalog.call(void 0, { bundledOnly: opts.bundledOnly });
180
+ const report = await _chunkVVCG536Qcjs.verifyAiModelsCatalog.call(void 0, { bundledOnly: opts.bundledOnly });
180
181
  if (opts.json) {
181
182
  emitJson(report);
182
183
  } else {
@@ -204,11 +205,11 @@ function registerCostCommand(program2) {
204
205
  "Completion token count",
205
206
  (v) => Number.parseInt(v, 10)
206
207
  ).option("--cached-tokens <n>", "Cached token count", (v) => Number.parseInt(v, 10)).option("--reasoning-tokens <n>", "Reasoning token count", (v) => Number.parseInt(v, 10)).option("--provider <id>", "Provider for pricing selection", "openrouter").option("--json", "Output raw AiCostResult JSON").option("--bundled-only", "Use src/data catalogs only (no HTTP)").action(async (opts) => {
207
- const catalogClient = new (0, _chunkU3BAEJ2Ccjs.AiModelsCatalogClient)({
208
- cacheTtlMs: _chunkU3BAEJ2Ccjs.resolveCatalogCacheTtlMs.call(void 0, ),
208
+ const catalogClient = new (0, _chunkXKJFO6VGcjs.AiModelsCatalogClient)({
209
+ cacheTtlMs: _chunkXKJFO6VGcjs.resolveCatalogCacheTtlMs.call(void 0, ),
209
210
  bundledOnly: opts.bundledOnly
210
211
  });
211
- const calculator = new (0, _chunk4UA2V5R2cjs.CostCalculator)(catalogClient, {
212
+ const calculator = new (0, _chunkAGLZXZCHcjs.CostCalculator)(catalogClient, {
212
213
  aliasRegistry: new (0, _chunkBAHBDADJcjs.AliasRegistry)()
213
214
  });
214
215
  const result = await calculator.calculate({
@@ -250,8 +251,8 @@ function registerCostCommand(program2) {
250
251
 
251
252
  // src/cli/commands/models.ts
252
253
  function service(opts) {
253
- return new (0, _chunkRK4QKTQ2cjs.AiModelsService)({
254
- cacheTtlMs: _chunkU3BAEJ2Ccjs.resolveCatalogCacheTtlMs.call(void 0, ),
254
+ return new (0, _chunkEE3Z75GOcjs.AiModelsService)({
255
+ cacheTtlMs: _chunkXKJFO6VGcjs.resolveCatalogCacheTtlMs.call(void 0, ),
255
256
  bundledOnly: opts.bundledOnly
256
257
  });
257
258
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/cli/index.cjs","../../src/cli/index.ts","../../src/cli/commands/alias.ts","../../src/cli/report.ts","../../src/cli/commands/catalog.ts","../../src/cli/commands/cost.ts","../../src/cli/commands/models.ts"],"names":["program"],"mappings":"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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/cli/index.cjs","sourcesContent":[null,"#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { registerAliasCommand } from \"./commands/alias.js\";\nimport { registerCatalogCommand } from \"./commands/catalog.js\";\nimport { registerCostCommand } from \"./commands/cost.js\";\nimport { registerModelsCommand } from \"./commands/models.js\";\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\n\nconst pkg = JSON.parse(\n readFileSync(join(dirname(fileURLToPath(import.meta.url)), \"../../package.json\"), \"utf8\"),\n) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"ai-tools\")\n .description(\"@x12i/ai-tools — AI model catalog, cost calculation, and utilities\")\n .version(pkg.version);\n\nregisterCatalogCommand(program);\nregisterModelsCommand(program);\nregisterCostCommand(program);\nregisterAliasCommand(program);\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n});\n","import fs from \"node:fs\";\nimport type { Command } from \"commander\";\nimport { AliasRegistry } from \"../../aliases/AliasRegistry.js\";\nimport { AliasResolver } from \"../../aliases/AliasResolver.js\";\nimport { AiModelsCatalogClient } from \"../../catalog/AiModelsCatalogClient.js\";\nimport { resolveCatalogCacheTtlMs } from \"../../cache/modelCache.js\";\n\nfunction registry(path?: string) {\n return new AliasRegistry(path ? { aliasesPath: path } : {});\n}\n\nfunction resolver(path?: string) {\n return new AliasResolver({\n registry: registry(path),\n catalogClient: new AiModelsCatalogClient({\n cacheTtlMs: resolveCatalogCacheTtlMs(),\n }),\n });\n}\n\nexport function registerAliasCommand(program: Command): void {\n const alias = program.command(\"alias\").description(\"Manage project-local model aliases\");\n\n alias\n .command(\"init\")\n .description(\"Create an empty ai-tools/aliases.json\")\n .option(\"--path <path>\", \"Custom path\")\n .option(\"--force\", \"Overwrite if already exists\")\n .action((opts: { path?: string; force?: boolean }) => {\n const reg = registry(opts.path);\n if (reg.exists() && !opts.force) {\n console.log(`Aliases file already exists at ${reg.path}`);\n return;\n }\n if (opts.force && reg.exists()) {\n fs.unlinkSync(reg.path);\n }\n reg.init();\n console.log(`✔ Created ${reg.path}`);\n console.log(\n \" Tip: commit this file to your repository so aliases are consistent across environments.\",\n );\n });\n\n alias\n .command(\"set\")\n .description(\"Create or update an alias\")\n .argument(\"<name>\", \"Alias name\")\n .argument(\"<modelId>\", \"Model ID\")\n .option(\"--provider <p>\", \"Provider routing\", \"openrouter\")\n .option(\"--description <d>\", \"Human-readable note\")\n .option(\"--tag <t>\", \"Tag (repeatable)\", (v: string, prev: string[]) => [...prev, v], [] as string[])\n .option(\"--path <path>\", \"Custom aliases path\")\n .action(\n (\n name: string,\n modelId: string,\n opts: { provider: string; description?: string; tag: string[]; path?: string },\n ) => {\n const reg = registry(opts.path);\n if (!reg.exists()) reg.init();\n reg.set(name, {\n modelId,\n provider: opts.provider,\n description: opts.description,\n tags: opts.tag.length ? opts.tag : undefined,\n });\n console.log(`✔ alias \"${name}\" → ${modelId} (via ${opts.provider})`);\n console.log(` Updated ${reg.path}`);\n },\n );\n\n alias\n .command(\"get\")\n .description(\"Show one alias (with catalog resolution when available)\")\n .argument(\"<name>\", \"Alias name\")\n .option(\"--path <path>\", \"Custom aliases path\")\n .action(async (name: string, opts: { path?: string }) => {\n const ref = await resolver(opts.path).getModel(name);\n console.log(`Alias: ${ref.alias}`);\n console.log(`Model ID: ${ref.modelId}`);\n console.log(`Provider: ${ref.provider}`);\n if (ref.modelRecord) {\n console.log(`Name: ${ref.name}`);\n console.log(`Context: ${ref.modelRecord.contextLength.toLocaleString()} tokens`);\n console.log(`Status: ${ref.modelRecord.status} ✔`);\n } else {\n console.log(`Catalog: ✘ not found in ai-models catalog (local/custom model)`);\n }\n if (ref.entry.description) console.log(`Description: ${ref.entry.description}`);\n if (ref.entry.tags?.length) console.log(`Tags: ${ref.entry.tags.join(\", \")}`);\n });\n\n alias\n .command(\"list\")\n .description(\"List all aliases\")\n .option(\"--tag <t>\", \"Filter by tag\")\n .option(\"--json\", \"Output raw JSON\")\n .option(\"--check\", \"Validate each alias against the catalog\")\n .option(\"--path <path>\", \"Custom aliases path\")\n .action(async (opts: { tag?: string; json?: boolean; check?: boolean; path?: string }) => {\n const reg = registry(opts.path);\n const rows = reg.list(opts.tag ? { tag: opts.tag } : undefined);\n\n if (opts.json) {\n console.log(JSON.stringify(rows, null, 2));\n return;\n }\n\n if (opts.check) {\n const report = await resolver(opts.path).validate();\n console.log(\"NAME\".padEnd(14), \"MODEL ID\".padEnd(32), \"STATUS\");\n console.log(\"─\".repeat(60));\n for (const e of report.entries) {\n const status =\n e.status === \"ok\" ? \"✔ resolved\" : e.status === \"unknown\" ? \"✘ not in catalog\" : \"✗ broken\";\n console.log(e.name.padEnd(14), e.modelId.padEnd(32), status);\n }\n return;\n }\n\n console.log(\"NAME\".padEnd(14), \"MODEL ID\".padEnd(32), \"PROVIDER\".padEnd(12), \"DESCRIPTION\");\n console.log(\"─\".repeat(90));\n for (const row of rows) {\n console.log(\n row.name.padEnd(14),\n row.modelId.padEnd(32),\n row.provider.padEnd(12),\n (row.description ?? \"\").slice(0, 40),\n );\n }\n });\n\n alias\n .command(\"remove\")\n .description(\"Remove an alias\")\n .argument(\"<name>\", \"Alias name\")\n .option(\"--yes\", \"Skip confirmation\")\n .option(\"--path <path>\", \"Custom aliases path\")\n .action((name: string, opts: { yes?: boolean; path?: string }) => {\n if (!opts.yes) {\n console.log(`Remove alias \"${name}\"? Use --yes to confirm.`);\n process.exit(1);\n }\n const removed = registry(opts.path).remove(name);\n if (removed) console.log(`✔ Removed alias \"${name}\"`);\n else {\n console.error(`Alias not found: ${name}`);\n process.exit(1);\n }\n });\n\n alias\n .command(\"rename\")\n .description(\"Rename an alias\")\n .argument(\"<from>\", \"Current name\")\n .argument(\"<to>\", \"New name\")\n .option(\"--force\", \"Overwrite destination if it exists\")\n .option(\"--path <path>\", \"Custom aliases path\")\n .action((from: string, to: string, opts: { force?: boolean; path?: string }) => {\n registry(opts.path).rename(from, to, { force: opts.force });\n console.log(`✔ Renamed \"${from}\" → \"${to}\"`);\n });\n\n alias\n .command(\"check\")\n .description(\"Validate all aliases against the catalog (CI-friendly)\")\n .option(\"--path <path>\", \"Custom aliases path\")\n .action(async (opts: { path?: string }) => {\n const report = await resolver(opts.path).validate();\n console.log(`Checking ${report.total} aliases against ai-models catalog…\\n`);\n\n for (const e of report.entries) {\n const icon = e.status === \"ok\" ? \"✔\" : e.status === \"unknown\" ? \"⚠\" : \"✗\";\n const extra = e.resolvedName ? ` (${e.resolvedName})` : e.issue ? ` (${e.issue})` : \"\";\n console.log(` ${icon} ${e.name.padEnd(12)} → ${e.modelId.padEnd(28)}${extra}`);\n }\n\n console.log(\n `\\n${report.total} total · ${report.ok} ok · ${report.unknown} unknown · ${report.broken} broken`,\n );\n\n if (report.broken > 0) process.exit(1);\n });\n}\n","export function emitJson(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\nexport function emitHuman(lines: string[]): void {\n for (const line of lines) {\n console.log(line);\n }\n}\n","import type { Command } from \"commander\";\nimport { refreshAiModelsCatalog, verifyAiModelsCatalog } from \"../../catalog/index.js\";\nimport { emitHuman, emitJson } from \"../report.js\";\n\nexport function registerCatalogCommand(program: Command): void {\n const catalog = program.command(\"catalog\").description(\"Model catalog load and health commands\");\n\n catalog\n .command(\"refresh\")\n .description(\"Fetch catalogs from open-assets.x12i.com and warm the cache\")\n .option(\"--bundled-only\", \"Use bundled src/data catalogs only (no HTTP)\")\n .option(\"--json\", \"Machine-readable JSON on stdout\")\n .action(async (opts: { bundledOnly?: boolean; json?: boolean }) => {\n const result = await refreshAiModelsCatalog({ bundledOnly: opts.bundledOnly });\n if (opts.json) {\n emitJson(result);\n } else {\n emitHuman([\n \"✔ Catalog refresh complete\",\n ` Direct: ${result.directCount} (${result.directSource})`,\n ` OpenRouter: ${result.openRouterCount} (${result.openRouterSource})`,\n ]);\n }\n });\n\n catalog\n .command(\"verify\")\n .description(\"Validate direct + OpenRouter catalogs load successfully\")\n .option(\"--bundled-only\", \"Use bundled src/data catalogs only (no HTTP)\")\n .option(\"--json\", \"Machine-readable JSON on stdout\")\n .action(async (opts: { bundledOnly?: boolean; json?: boolean }) => {\n const report = await verifyAiModelsCatalog({ bundledOnly: opts.bundledOnly });\n\n if (opts.json) {\n emitJson(report);\n } else {\n emitHuman([\n report.ok ? \"✔ Catalog verification passed\" : \"✗ Catalog verification FAILED\",\n ` Direct models: ${report.directCount} (${report.directSource})`,\n ` OpenRouter models: ${report.openRouterCount} (${report.openRouterSource})`,\n ` Direct URL: ${report.directUrl}`,\n ` OpenRouter URL: ${report.openRouterUrl}`,\n ]);\n }\n\n if (!report.ok) {\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { AliasRegistry } from \"../../aliases/AliasRegistry.js\";\nimport { CostCalculator } from \"../../cost/CostCalculator.js\";\nimport { AiModelsCatalogClient } from \"../../catalog/AiModelsCatalogClient.js\";\nimport { resolveCatalogCacheTtlMs } from \"../../cache/modelCache.js\";\n\nfunction formatUsd(n: number): string {\n return `$${n.toFixed(6)}`;\n}\n\nexport function registerCostCommand(program: Command): void {\n program\n .command(\"cost\")\n .description(\"Estimate cost from catalog pricing\")\n .requiredOption(\"--model <id>\", \"Model ID or alias\")\n .requiredOption(\"--prompt-tokens <n>\", \"Prompt token count\", (v) => Number.parseInt(v, 10))\n .requiredOption(\n \"--completion-tokens <n>\",\n \"Completion token count\",\n (v) => Number.parseInt(v, 10),\n )\n .option(\"--cached-tokens <n>\", \"Cached token count\", (v) => Number.parseInt(v, 10))\n .option(\"--reasoning-tokens <n>\", \"Reasoning token count\", (v) => Number.parseInt(v, 10))\n .option(\"--provider <id>\", \"Provider for pricing selection\", \"openrouter\")\n .option(\"--json\", \"Output raw AiCostResult JSON\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (opts: {\n model: string;\n promptTokens: number;\n completionTokens: number;\n cachedTokens?: number;\n reasoningTokens?: number;\n provider: string;\n json?: boolean;\n bundledOnly?: boolean;\n }) => {\n const catalogClient = new AiModelsCatalogClient({\n cacheTtlMs: resolveCatalogCacheTtlMs(),\n bundledOnly: opts.bundledOnly,\n });\n\n const calculator = new CostCalculator(catalogClient, {\n aliasRegistry: new AliasRegistry(),\n });\n\n const result = await calculator.calculate({\n tokens: {\n prompt: opts.promptTokens,\n completion: opts.completionTokens,\n total: opts.promptTokens + opts.completionTokens,\n cached: opts.cachedTokens,\n reasoning: opts.reasoningTokens,\n },\n provider: opts.provider,\n modelUsed: opts.model,\n });\n\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n const b = result.breakdown;\n console.log(`Model: ${result.resolvedModelId}`);\n if (result.usedModel && result.usedModel !== result.resolvedModelId) {\n console.log(`Used model: ${result.usedModel}`);\n }\n console.log(\n `Prompt: ${opts.promptTokens.toLocaleString()} tokens → ${formatUsd(b?.promptCostUsd ?? 0)}`,\n );\n console.log(\n `Completion: ${opts.completionTokens.toLocaleString()} tokens → ${formatUsd(b?.completionCostUsd ?? 0)}`,\n );\n console.log(\n `Request fee: → ${formatUsd(b?.requestFlatCostUsd ?? 0)}`,\n );\n console.log(\"─\".repeat(38));\n console.log(`Total: → ${formatUsd(result.cost)}`);\n console.log(\n `Via OpenRouter: ${result.routedViaOpenRouter ? \"yes\" : \"no\"}`,\n );\n });\n}\n","import type { Command } from \"commander\";\nimport { AiModelsService } from \"../../models/AiModelsService.js\";\nimport { resolveCatalogCacheTtlMs } from \"../../cache/modelCache.js\";\n\nfunction service(opts: { bundledOnly?: boolean }) {\n return new AiModelsService({\n cacheTtlMs: resolveCatalogCacheTtlMs(),\n bundledOnly: opts.bundledOnly,\n });\n}\n\nexport function registerModelsCommand(program: Command): void {\n const models = program.command(\"models\").description(\"Inspect model catalogs\");\n\n models\n .command(\"list\")\n .description(\"List models with optional filters\")\n .option(\"--provider <id>\", \"Filter by providerId (e.g. openai, anthropic)\")\n .option(\"--output-modality <m>\", \"Filter by output modality (text, image, audio, …)\")\n .option(\"--input-modality <m>\", \"Filter by input modality\")\n .option(\"--parameter <p>\", \"Filter by supported parameter (e.g. tools)\")\n .option(\"--tools\", \"Only models that support tools\")\n .option(\"--reasoning\", \"Only reasoning / thinking models\")\n .option(\"--search <q>\", \"Search name, id, description\")\n .option(\"--json\", \"Output raw JSON\")\n .option(\"--limit <n>\", \"Max rows\", \"50\")\n .option(\"--offset <n>\", \"Skip rows\", \"0\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (opts: {\n provider?: string;\n outputModality?: string;\n inputModality?: string;\n parameter?: string;\n tools?: boolean;\n reasoning?: boolean;\n search?: string;\n json?: boolean;\n limit?: string;\n offset?: string;\n bundledOnly?: boolean;\n }) => {\n const { models: rows, total } = await service(opts).listModels({\n providerId: opts.provider,\n outputModality: opts.outputModality,\n inputModality: opts.inputModality,\n supportedParameter: opts.parameter,\n supportsTools: opts.tools ? true : undefined,\n supportsReasoning: opts.reasoning ? true : undefined,\n search: opts.search,\n limit: Number.parseInt(opts.limit ?? \"50\", 10),\n offset: Number.parseInt(opts.offset ?? \"0\", 10),\n });\n\n if (opts.json) {\n console.log(JSON.stringify({ total, models: rows }, null, 2));\n return;\n }\n\n console.log(\n \"MODEL ID\".padEnd(42),\n \"PROVIDER\".padEnd(14),\n \"OUTPUT\".padEnd(10),\n \"R\".padEnd(3),\n \"NAME\",\n );\n console.log(\"─\".repeat(104));\n for (const m of rows) {\n console.log(\n m.modelId.padEnd(42),\n m.providerId.padEnd(14),\n m.primaryOutputModality.padEnd(10),\n (m.supportsReasoning ? \"yes\" : \"no\").padEnd(3),\n m.name.slice(0, 40),\n );\n }\n console.log(`\\n${rows.length} shown · ${total} matching`);\n });\n\n models\n .command(\"get\")\n .description(\"Get full model record by ID or alias\")\n .argument(\"<modelId>\", \"Model ID or alias\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (modelId: string, opts: { bundledOnly?: boolean }) => {\n const model = await service(opts).getModelInfo(modelId);\n if (!model) {\n console.error(`Model not found: ${modelId}`);\n process.exit(1);\n }\n console.log(JSON.stringify(model, null, 2));\n });\n\n models\n .command(\"resolve\")\n .description(\"Resolve provider + model to canonical id\")\n .requiredOption(\"--model <m>\", \"Model string (required)\")\n .option(\"--provider <p>\", \"Provider hint (openrouter, openai, …)\")\n .option(\"--threshold <n>\", \"Confidence threshold 0–1\", \"0.6\")\n .option(\"--json\", \"Output raw ModelResolutionResult JSON\")\n .option(\"--verbose\", \"Show strategy trail\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (opts: {\n model: string;\n provider?: string;\n threshold?: string;\n json?: boolean;\n verbose?: boolean;\n bundledOnly?: boolean;\n }) => {\n const result = await service(opts).resolve(opts.model, opts.provider);\n\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n const providerLabel = opts.provider ?? \"unspecified\";\n console.log(`Input: provider=\"${providerLabel}\" model=\"${opts.model}\"`);\n\n if (opts.verbose && result.found) {\n console.log(`Normalised: model=\"${result.normalisedInput}\"`);\n console.log(\"\\nStrategy trail:\");\n for (const s of result.resolvedVia) {\n console.log(` • ${s}`);\n }\n console.log();\n }\n\n if (!result.found) {\n console.log(\"Result: NOT FOUND\");\n console.log(`Reason: ${result.reason}`);\n if (result.bestRejectedCandidate) {\n console.log(\n `Candidate: ${result.bestRejectedCandidate.modelId} (confidence ${result.bestRejectedCandidate.confidence.toFixed(2)})`,\n );\n }\n console.log('Tip: Run \"ai-tools catalog refresh\" or \"ai-tools alias set\".');\n process.exit(1);\n return;\n }\n\n console.log(`Resolved: ${result.modelId}`);\n console.log(`Name: ${result.record?.name ?? \"(no catalog record)\"}`);\n console.log(`Strategy: ${result.resolvedVia.join(\" → \")}`);\n console.log(`Confidence: ${result.confidence.toFixed(2)}`);\n console.log(`Via OR: ${result.routedViaOpenRouter ? \"yes\" : \"no\"}`);\n });\n\n models\n .command(\"vendor\")\n .description(\"Find model vendor from model name alone (best-effort)\")\n .requiredOption(\"--model <m>\", \"Model string (required)\")\n .option(\"--openrouter\", \"Return OpenRouter transport shape (provider openrouter, model vendor/slug)\")\n .option(\"--json\", \"Output raw JSON\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (opts: {\n model: string;\n openrouter?: boolean;\n json?: boolean;\n bundledOnly?: boolean;\n }) => {\n const ref = await service(opts).resolveVendor(opts.model, {\n asOpenRouter: opts.openrouter,\n });\n\n if (opts.json) {\n console.log(JSON.stringify(ref, null, 2));\n if (!ref) process.exit(1);\n return;\n }\n\n console.log(`Input: model=\"${opts.model}\"`);\n if (!ref) {\n console.log(\"Result: NOT FOUND\");\n process.exit(1);\n return;\n }\n\n console.log(`Vendor: ${ref.provider}`);\n console.log(`Model: ${ref.model}`);\n });\n\n models\n .command(\"count\")\n .description(\"Count models matching filters\")\n .option(\"--provider <id>\", \"Filter by providerId\")\n .option(\"--output-modality <m>\", \"Filter by output modality\")\n .option(\"--parameter <p>\", \"Filter by supported parameter\")\n .option(\"--tools\", \"Only models that support tools\")\n .option(\"--reasoning\", \"Only reasoning / thinking models\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (opts: {\n provider?: string;\n outputModality?: string;\n parameter?: string;\n tools?: boolean;\n reasoning?: boolean;\n bundledOnly?: boolean;\n }) => {\n const n = await service(opts).countModels({\n providerId: opts.provider,\n outputModality: opts.outputModality,\n supportedParameter: opts.parameter,\n supportsTools: opts.tools ? true : undefined,\n supportsReasoning: opts.reasoning ? true : undefined,\n });\n console.log(n);\n });\n}\n"]}
1
+ {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/cli/index.cjs","../../src/cli/index.ts","../../src/cli/commands/alias.ts","../../src/cli/report.ts","../../src/cli/commands/catalog.ts","../../src/cli/commands/cost.ts","../../src/cli/commands/models.ts"],"names":["program"],"mappings":"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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/cli/index.cjs","sourcesContent":[null,"#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { registerAliasCommand } from \"./commands/alias.js\";\nimport { registerCatalogCommand } from \"./commands/catalog.js\";\nimport { registerCostCommand } from \"./commands/cost.js\";\nimport { registerModelsCommand } from \"./commands/models.js\";\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\n\nconst pkg = JSON.parse(\n readFileSync(join(dirname(fileURLToPath(import.meta.url)), \"../../package.json\"), \"utf8\"),\n) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"ai-tools\")\n .description(\"@x12i/ai-tools — AI model catalog, cost calculation, and utilities\")\n .version(pkg.version);\n\nregisterCatalogCommand(program);\nregisterModelsCommand(program);\nregisterCostCommand(program);\nregisterAliasCommand(program);\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : error);\n process.exit(1);\n});\n","import fs from \"node:fs\";\nimport type { Command } from \"commander\";\nimport { AliasRegistry } from \"../../aliases/AliasRegistry.js\";\nimport { AliasResolver } from \"../../aliases/AliasResolver.js\";\nimport { AiModelsCatalogClient } from \"../../catalog/AiModelsCatalogClient.js\";\nimport { resolveCatalogCacheTtlMs } from \"../../cache/modelCache.js\";\n\nfunction registry(path?: string) {\n return new AliasRegistry(path ? { aliasesPath: path } : {});\n}\n\nfunction resolver(path?: string) {\n return new AliasResolver({\n registry: registry(path),\n catalogClient: new AiModelsCatalogClient({\n cacheTtlMs: resolveCatalogCacheTtlMs(),\n }),\n });\n}\n\nexport function registerAliasCommand(program: Command): void {\n const alias = program.command(\"alias\").description(\"Manage project-local model aliases\");\n\n alias\n .command(\"init\")\n .description(\"Create an empty ai-tools/aliases.json\")\n .option(\"--path <path>\", \"Custom path\")\n .option(\"--force\", \"Overwrite if already exists\")\n .action((opts: { path?: string; force?: boolean }) => {\n const reg = registry(opts.path);\n if (reg.exists() && !opts.force) {\n console.log(`Aliases file already exists at ${reg.path}`);\n return;\n }\n if (opts.force && reg.exists()) {\n fs.unlinkSync(reg.path);\n }\n reg.init();\n console.log(`✔ Created ${reg.path}`);\n console.log(\n \" Tip: commit this file to your repository so aliases are consistent across environments.\",\n );\n });\n\n alias\n .command(\"set\")\n .description(\"Create or update an alias\")\n .argument(\"<name>\", \"Alias name\")\n .argument(\"<modelId>\", \"Model ID\")\n .option(\"--provider <p>\", \"Provider routing\", \"openrouter\")\n .option(\"--description <d>\", \"Human-readable note\")\n .option(\"--tag <t>\", \"Tag (repeatable)\", (v: string, prev: string[]) => [...prev, v], [] as string[])\n .option(\"--path <path>\", \"Custom aliases path\")\n .action(\n (\n name: string,\n modelId: string,\n opts: { provider: string; description?: string; tag: string[]; path?: string },\n ) => {\n const reg = registry(opts.path);\n if (!reg.exists()) reg.init();\n reg.set(name, {\n modelId,\n provider: opts.provider,\n description: opts.description,\n tags: opts.tag.length ? opts.tag : undefined,\n });\n console.log(`✔ alias \"${name}\" → ${modelId} (via ${opts.provider})`);\n console.log(` Updated ${reg.path}`);\n },\n );\n\n alias\n .command(\"get\")\n .description(\"Show one alias (with catalog resolution when available)\")\n .argument(\"<name>\", \"Alias name\")\n .option(\"--path <path>\", \"Custom aliases path\")\n .action(async (name: string, opts: { path?: string }) => {\n const ref = await resolver(opts.path).getModel(name);\n console.log(`Alias: ${ref.alias}`);\n console.log(`Model ID: ${ref.modelId}`);\n console.log(`Provider: ${ref.provider}`);\n if (ref.modelRecord) {\n console.log(`Name: ${ref.name}`);\n console.log(`Context: ${ref.modelRecord.contextLength.toLocaleString()} tokens`);\n console.log(`Status: ${ref.modelRecord.status} ✔`);\n } else {\n console.log(`Catalog: ✘ not found in ai-models catalog (local/custom model)`);\n }\n if (ref.entry.description) console.log(`Description: ${ref.entry.description}`);\n if (ref.entry.tags?.length) console.log(`Tags: ${ref.entry.tags.join(\", \")}`);\n });\n\n alias\n .command(\"list\")\n .description(\"List all aliases\")\n .option(\"--tag <t>\", \"Filter by tag\")\n .option(\"--json\", \"Output raw JSON\")\n .option(\"--check\", \"Validate each alias against the catalog\")\n .option(\"--path <path>\", \"Custom aliases path\")\n .action(async (opts: { tag?: string; json?: boolean; check?: boolean; path?: string }) => {\n const reg = registry(opts.path);\n const rows = reg.list(opts.tag ? { tag: opts.tag } : undefined);\n\n if (opts.json) {\n console.log(JSON.stringify(rows, null, 2));\n return;\n }\n\n if (opts.check) {\n const report = await resolver(opts.path).validate();\n console.log(\"NAME\".padEnd(14), \"MODEL ID\".padEnd(32), \"STATUS\");\n console.log(\"─\".repeat(60));\n for (const e of report.entries) {\n const status =\n e.status === \"ok\" ? \"✔ resolved\" : e.status === \"unknown\" ? \"✘ not in catalog\" : \"✗ broken\";\n console.log(e.name.padEnd(14), e.modelId.padEnd(32), status);\n }\n return;\n }\n\n console.log(\"NAME\".padEnd(14), \"MODEL ID\".padEnd(32), \"PROVIDER\".padEnd(12), \"DESCRIPTION\");\n console.log(\"─\".repeat(90));\n for (const row of rows) {\n console.log(\n row.name.padEnd(14),\n row.modelId.padEnd(32),\n row.provider.padEnd(12),\n (row.description ?? \"\").slice(0, 40),\n );\n }\n });\n\n alias\n .command(\"remove\")\n .description(\"Remove an alias\")\n .argument(\"<name>\", \"Alias name\")\n .option(\"--yes\", \"Skip confirmation\")\n .option(\"--path <path>\", \"Custom aliases path\")\n .action((name: string, opts: { yes?: boolean; path?: string }) => {\n if (!opts.yes) {\n console.log(`Remove alias \"${name}\"? Use --yes to confirm.`);\n process.exit(1);\n }\n const removed = registry(opts.path).remove(name);\n if (removed) console.log(`✔ Removed alias \"${name}\"`);\n else {\n console.error(`Alias not found: ${name}`);\n process.exit(1);\n }\n });\n\n alias\n .command(\"rename\")\n .description(\"Rename an alias\")\n .argument(\"<from>\", \"Current name\")\n .argument(\"<to>\", \"New name\")\n .option(\"--force\", \"Overwrite destination if it exists\")\n .option(\"--path <path>\", \"Custom aliases path\")\n .action((from: string, to: string, opts: { force?: boolean; path?: string }) => {\n registry(opts.path).rename(from, to, { force: opts.force });\n console.log(`✔ Renamed \"${from}\" → \"${to}\"`);\n });\n\n alias\n .command(\"check\")\n .description(\"Validate all aliases against the catalog (CI-friendly)\")\n .option(\"--path <path>\", \"Custom aliases path\")\n .action(async (opts: { path?: string }) => {\n const report = await resolver(opts.path).validate();\n console.log(`Checking ${report.total} aliases against ai-models catalog…\\n`);\n\n for (const e of report.entries) {\n const icon = e.status === \"ok\" ? \"✔\" : e.status === \"unknown\" ? \"⚠\" : \"✗\";\n const extra = e.resolvedName ? ` (${e.resolvedName})` : e.issue ? ` (${e.issue})` : \"\";\n console.log(` ${icon} ${e.name.padEnd(12)} → ${e.modelId.padEnd(28)}${extra}`);\n }\n\n console.log(\n `\\n${report.total} total · ${report.ok} ok · ${report.unknown} unknown · ${report.broken} broken`,\n );\n\n if (report.broken > 0) process.exit(1);\n });\n}\n","export function emitJson(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\nexport function emitHuman(lines: string[]): void {\n for (const line of lines) {\n console.log(line);\n }\n}\n","import type { Command } from \"commander\";\nimport { refreshAiModelsCatalog, verifyAiModelsCatalog } from \"../../catalog/index.js\";\nimport { emitHuman, emitJson } from \"../report.js\";\n\nexport function registerCatalogCommand(program: Command): void {\n const catalog = program.command(\"catalog\").description(\"Model catalog load and health commands\");\n\n catalog\n .command(\"refresh\")\n .description(\"Fetch catalogs from open-assets.x12i.com and warm the cache\")\n .option(\"--bundled-only\", \"Use bundled src/data catalogs only (no HTTP)\")\n .option(\"--json\", \"Machine-readable JSON on stdout\")\n .action(async (opts: { bundledOnly?: boolean; json?: boolean }) => {\n const result = await refreshAiModelsCatalog({ bundledOnly: opts.bundledOnly });\n if (opts.json) {\n emitJson(result);\n } else {\n emitHuman([\n \"✔ Catalog refresh complete\",\n ` Direct: ${result.directCount} (${result.directSource})`,\n ` OpenRouter: ${result.openRouterCount} (${result.openRouterSource})`,\n ]);\n }\n });\n\n catalog\n .command(\"verify\")\n .description(\"Validate direct + OpenRouter catalogs load successfully\")\n .option(\"--bundled-only\", \"Use bundled src/data catalogs only (no HTTP)\")\n .option(\"--json\", \"Machine-readable JSON on stdout\")\n .action(async (opts: { bundledOnly?: boolean; json?: boolean }) => {\n const report = await verifyAiModelsCatalog({ bundledOnly: opts.bundledOnly });\n\n if (opts.json) {\n emitJson(report);\n } else {\n emitHuman([\n report.ok ? \"✔ Catalog verification passed\" : \"✗ Catalog verification FAILED\",\n ` Direct models: ${report.directCount} (${report.directSource})`,\n ` OpenRouter models: ${report.openRouterCount} (${report.openRouterSource})`,\n ` Direct URL: ${report.directUrl}`,\n ` OpenRouter URL: ${report.openRouterUrl}`,\n ]);\n }\n\n if (!report.ok) {\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { AliasRegistry } from \"../../aliases/AliasRegistry.js\";\nimport { CostCalculator } from \"../../cost/CostCalculator.js\";\nimport { AiModelsCatalogClient } from \"../../catalog/AiModelsCatalogClient.js\";\nimport { resolveCatalogCacheTtlMs } from \"../../cache/modelCache.js\";\n\nfunction formatUsd(n: number): string {\n return `$${n.toFixed(6)}`;\n}\n\nexport function registerCostCommand(program: Command): void {\n program\n .command(\"cost\")\n .description(\"Estimate cost from catalog pricing\")\n .requiredOption(\"--model <id>\", \"Model ID or alias\")\n .requiredOption(\"--prompt-tokens <n>\", \"Prompt token count\", (v) => Number.parseInt(v, 10))\n .requiredOption(\n \"--completion-tokens <n>\",\n \"Completion token count\",\n (v) => Number.parseInt(v, 10),\n )\n .option(\"--cached-tokens <n>\", \"Cached token count\", (v) => Number.parseInt(v, 10))\n .option(\"--reasoning-tokens <n>\", \"Reasoning token count\", (v) => Number.parseInt(v, 10))\n .option(\"--provider <id>\", \"Provider for pricing selection\", \"openrouter\")\n .option(\"--json\", \"Output raw AiCostResult JSON\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (opts: {\n model: string;\n promptTokens: number;\n completionTokens: number;\n cachedTokens?: number;\n reasoningTokens?: number;\n provider: string;\n json?: boolean;\n bundledOnly?: boolean;\n }) => {\n const catalogClient = new AiModelsCatalogClient({\n cacheTtlMs: resolveCatalogCacheTtlMs(),\n bundledOnly: opts.bundledOnly,\n });\n\n const calculator = new CostCalculator(catalogClient, {\n aliasRegistry: new AliasRegistry(),\n });\n\n const result = await calculator.calculate({\n tokens: {\n prompt: opts.promptTokens,\n completion: opts.completionTokens,\n total: opts.promptTokens + opts.completionTokens,\n cached: opts.cachedTokens,\n reasoning: opts.reasoningTokens,\n },\n provider: opts.provider,\n modelUsed: opts.model,\n });\n\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n const b = result.breakdown;\n console.log(`Model: ${result.resolvedModelId}`);\n if (result.usedModel && result.usedModel !== result.resolvedModelId) {\n console.log(`Used model: ${result.usedModel}`);\n }\n console.log(\n `Prompt: ${opts.promptTokens.toLocaleString()} tokens → ${formatUsd(b?.promptCostUsd ?? 0)}`,\n );\n console.log(\n `Completion: ${opts.completionTokens.toLocaleString()} tokens → ${formatUsd(b?.completionCostUsd ?? 0)}`,\n );\n console.log(\n `Request fee: → ${formatUsd(b?.requestFlatCostUsd ?? 0)}`,\n );\n console.log(\"─\".repeat(38));\n console.log(`Total: → ${formatUsd(result.cost)}`);\n console.log(\n `Via OpenRouter: ${result.routedViaOpenRouter ? \"yes\" : \"no\"}`,\n );\n });\n}\n","import type { Command } from \"commander\";\nimport { AiModelsService } from \"../../models/AiModelsService.js\";\nimport { resolveCatalogCacheTtlMs } from \"../../cache/modelCache.js\";\n\nfunction service(opts: { bundledOnly?: boolean }) {\n return new AiModelsService({\n cacheTtlMs: resolveCatalogCacheTtlMs(),\n bundledOnly: opts.bundledOnly,\n });\n}\n\nexport function registerModelsCommand(program: Command): void {\n const models = program.command(\"models\").description(\"Inspect model catalogs\");\n\n models\n .command(\"list\")\n .description(\"List models with optional filters\")\n .option(\"--provider <id>\", \"Filter by providerId (e.g. openai, anthropic)\")\n .option(\"--output-modality <m>\", \"Filter by output modality (text, image, audio, …)\")\n .option(\"--input-modality <m>\", \"Filter by input modality\")\n .option(\"--parameter <p>\", \"Filter by supported parameter (e.g. tools)\")\n .option(\"--tools\", \"Only models that support tools\")\n .option(\"--reasoning\", \"Only reasoning / thinking models\")\n .option(\"--search <q>\", \"Search name, id, description\")\n .option(\"--json\", \"Output raw JSON\")\n .option(\"--limit <n>\", \"Max rows\", \"50\")\n .option(\"--offset <n>\", \"Skip rows\", \"0\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (opts: {\n provider?: string;\n outputModality?: string;\n inputModality?: string;\n parameter?: string;\n tools?: boolean;\n reasoning?: boolean;\n search?: string;\n json?: boolean;\n limit?: string;\n offset?: string;\n bundledOnly?: boolean;\n }) => {\n const { models: rows, total } = await service(opts).listModels({\n providerId: opts.provider,\n outputModality: opts.outputModality,\n inputModality: opts.inputModality,\n supportedParameter: opts.parameter,\n supportsTools: opts.tools ? true : undefined,\n supportsReasoning: opts.reasoning ? true : undefined,\n search: opts.search,\n limit: Number.parseInt(opts.limit ?? \"50\", 10),\n offset: Number.parseInt(opts.offset ?? \"0\", 10),\n });\n\n if (opts.json) {\n console.log(JSON.stringify({ total, models: rows }, null, 2));\n return;\n }\n\n console.log(\n \"MODEL ID\".padEnd(42),\n \"PROVIDER\".padEnd(14),\n \"OUTPUT\".padEnd(10),\n \"R\".padEnd(3),\n \"NAME\",\n );\n console.log(\"─\".repeat(104));\n for (const m of rows) {\n console.log(\n m.modelId.padEnd(42),\n m.providerId.padEnd(14),\n m.primaryOutputModality.padEnd(10),\n (m.supportsReasoning ? \"yes\" : \"no\").padEnd(3),\n m.name.slice(0, 40),\n );\n }\n console.log(`\\n${rows.length} shown · ${total} matching`);\n });\n\n models\n .command(\"get\")\n .description(\"Get full model record by ID or alias\")\n .argument(\"<modelId>\", \"Model ID or alias\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (modelId: string, opts: { bundledOnly?: boolean }) => {\n const model = await service(opts).getModelInfo(modelId);\n if (!model) {\n console.error(`Model not found: ${modelId}`);\n process.exit(1);\n }\n console.log(JSON.stringify(model, null, 2));\n });\n\n models\n .command(\"resolve\")\n .description(\"Resolve provider + model to canonical id\")\n .requiredOption(\"--model <m>\", \"Model string (required)\")\n .option(\"--provider <p>\", \"Provider hint (openrouter, openai, …)\")\n .option(\"--threshold <n>\", \"Confidence threshold 0–1\", \"0.6\")\n .option(\"--json\", \"Output raw ModelResolutionResult JSON\")\n .option(\"--verbose\", \"Show strategy trail\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (opts: {\n model: string;\n provider?: string;\n threshold?: string;\n json?: boolean;\n verbose?: boolean;\n bundledOnly?: boolean;\n }) => {\n const result = await service(opts).resolve(opts.model, opts.provider);\n\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n const providerLabel = opts.provider ?? \"unspecified\";\n console.log(`Input: provider=\"${providerLabel}\" model=\"${opts.model}\"`);\n\n if (opts.verbose && result.found) {\n console.log(`Normalised: model=\"${result.normalisedInput}\"`);\n console.log(\"\\nStrategy trail:\");\n for (const s of result.resolvedVia) {\n console.log(` • ${s}`);\n }\n console.log();\n }\n\n if (!result.found) {\n console.log(\"Result: NOT FOUND\");\n console.log(`Reason: ${result.reason}`);\n if (result.bestRejectedCandidate) {\n console.log(\n `Candidate: ${result.bestRejectedCandidate.modelId} (confidence ${result.bestRejectedCandidate.confidence.toFixed(2)})`,\n );\n }\n console.log('Tip: Run \"ai-tools catalog refresh\" or \"ai-tools alias set\".');\n process.exit(1);\n return;\n }\n\n console.log(`Resolved: ${result.modelId}`);\n console.log(`Name: ${result.record?.name ?? \"(no catalog record)\"}`);\n console.log(`Strategy: ${result.resolvedVia.join(\" → \")}`);\n console.log(`Confidence: ${result.confidence.toFixed(2)}`);\n console.log(`Via OR: ${result.routedViaOpenRouter ? \"yes\" : \"no\"}`);\n });\n\n models\n .command(\"vendor\")\n .description(\"Find model vendor from model name alone (best-effort)\")\n .requiredOption(\"--model <m>\", \"Model string (required)\")\n .option(\"--openrouter\", \"Return OpenRouter transport shape (provider openrouter, model vendor/slug)\")\n .option(\"--json\", \"Output raw JSON\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (opts: {\n model: string;\n openrouter?: boolean;\n json?: boolean;\n bundledOnly?: boolean;\n }) => {\n const ref = await service(opts).resolveVendor(opts.model, {\n asOpenRouter: opts.openrouter,\n });\n\n if (opts.json) {\n console.log(JSON.stringify(ref, null, 2));\n if (!ref) process.exit(1);\n return;\n }\n\n console.log(`Input: model=\"${opts.model}\"`);\n if (!ref) {\n console.log(\"Result: NOT FOUND\");\n process.exit(1);\n return;\n }\n\n console.log(`Vendor: ${ref.provider}`);\n console.log(`Model: ${ref.model}`);\n });\n\n models\n .command(\"count\")\n .description(\"Count models matching filters\")\n .option(\"--provider <id>\", \"Filter by providerId\")\n .option(\"--output-modality <m>\", \"Filter by output modality\")\n .option(\"--parameter <p>\", \"Filter by supported parameter\")\n .option(\"--tools\", \"Only models that support tools\")\n .option(\"--reasoning\", \"Only reasoning / thinking models\")\n .option(\"--bundled-only\", \"Use src/data catalogs only (no HTTP)\")\n .action(async (opts: {\n provider?: string;\n outputModality?: string;\n parameter?: string;\n tools?: boolean;\n reasoning?: boolean;\n bundledOnly?: boolean;\n }) => {\n const n = await service(opts).countModels({\n providerId: opts.provider,\n outputModality: opts.outputModality,\n supportedParameter: opts.parameter,\n supportsTools: opts.tools ? true : undefined,\n supportsReasoning: opts.reasoning ? true : undefined,\n });\n console.log(n);\n });\n}\n"]}
package/dist/cli/index.js CHANGED
@@ -1,28 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CostCalculator
4
- } from "../chunk-OZHZUMNR.js";
4
+ } from "../chunk-A7JKTDSD.js";
5
5
  import {
6
6
  AliasRegistry,
7
7
  AliasResolver
8
8
  } from "../chunk-ANVONYJF.js";
9
9
  import {
10
10
  AiModelsService
11
- } from "../chunk-WJFOQS6I.js";
12
- import "../chunk-MN6K2YHF.js";
13
- import "../chunk-4ILJWO64.js";
11
+ } from "../chunk-FHJDIYPJ.js";
12
+ import "../chunk-VR4P5QB2.js";
13
+ import "../chunk-3CUSLNEV.js";
14
14
  import {
15
15
  refreshAiModelsCatalog,
16
16
  verifyAiModelsCatalog
17
- } from "../chunk-DYVCBK2C.js";
17
+ } from "../chunk-WVJZCVI7.js";
18
18
  import {
19
19
  AiModelsCatalogClient,
20
20
  resolveCatalogCacheTtlMs
21
- } from "../chunk-DIVRTJUA.js";
22
- import "../chunk-WBHH3JEK.js";
21
+ } from "../chunk-LHJV2YLY.js";
22
+ import "../chunk-YERYMWKM.js";
23
23
  import "../chunk-SQ6NOF4Z.js";
24
24
  import "../chunk-OB44D7RG.js";
25
25
  import "../chunk-2PTCWPHV.js";
26
+ import "../chunk-OPKL4YNL.js";
26
27
 
27
28
  // src/cli/index.ts
28
29
  import { Command } from "commander";