@x12i/ai-tools 1.0.3 → 2.0.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 (153) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +146 -204
  3. package/dist/AiModelsCatalogClient-B5FMI9gj.d.cts +58 -0
  4. package/dist/AiModelsCatalogClient-CPPNI6Ry.d.ts +58 -0
  5. package/dist/aliases/index.cjs +4 -3
  6. package/dist/aliases/index.cjs.map +1 -1
  7. package/dist/aliases/index.d.cts +3 -5
  8. package/dist/aliases/index.d.ts +3 -5
  9. package/dist/aliases/index.js +2 -2
  10. package/dist/catalog/index.cjs +18 -9
  11. package/dist/catalog/index.cjs.map +1 -1
  12. package/dist/catalog/index.d.cts +13 -100
  13. package/dist/catalog/index.d.ts +13 -100
  14. package/dist/catalog/index.js +31 -23
  15. package/dist/{chunk-AJEKEWWB.js → chunk-2PTCWPHV.js} +17 -3
  16. package/dist/chunk-2PTCWPHV.js.map +1 -0
  17. package/dist/chunk-56R4XA2S.js +1 -0
  18. package/dist/chunk-5GUKLOEK.cjs +1 -0
  19. package/dist/chunk-5GUKLOEK.cjs.map +1 -0
  20. package/dist/chunk-5XAAMBDO.cjs +1988 -0
  21. package/dist/chunk-5XAAMBDO.cjs.map +1 -0
  22. package/dist/chunk-6BQBKROR.js +95 -0
  23. package/dist/chunk-6BQBKROR.js.map +1 -0
  24. package/dist/chunk-AB5GNXJ4.js +46 -0
  25. package/dist/chunk-AB5GNXJ4.js.map +1 -0
  26. package/dist/{chunk-O2A6OVEH.js → chunk-ANVONYJF.js} +2 -2
  27. package/dist/{chunk-O2A6OVEH.js.map → chunk-ANVONYJF.js.map} +1 -1
  28. package/dist/chunk-B3V2EHRY.js +225 -0
  29. package/dist/chunk-B3V2EHRY.js.map +1 -0
  30. package/dist/{chunk-QWAX7VQO.cjs → chunk-BAHBDADJ.cjs} +11 -11
  31. package/dist/{chunk-QWAX7VQO.cjs.map → chunk-BAHBDADJ.cjs.map} +1 -1
  32. package/dist/{chunk-TF4L2NEC.cjs → chunk-DXZOL3VN.cjs} +62 -313
  33. package/dist/chunk-DXZOL3VN.cjs.map +1 -0
  34. package/dist/chunk-EDMCKHO6.cjs +225 -0
  35. package/dist/chunk-EDMCKHO6.cjs.map +1 -0
  36. package/dist/{chunk-DJ5SWJDY.js → chunk-EYHMQVAL.js} +48 -299
  37. package/dist/chunk-EYHMQVAL.js.map +1 -0
  38. package/dist/chunk-GS7T56RP.cjs +8 -0
  39. package/dist/chunk-GS7T56RP.cjs.map +1 -0
  40. package/dist/chunk-NF2SKQR7.cjs +973 -0
  41. package/dist/chunk-NF2SKQR7.cjs.map +1 -0
  42. package/dist/chunk-OPN6BGNH.js +1985 -0
  43. package/dist/chunk-OPN6BGNH.js.map +1 -0
  44. package/dist/{chunk-7Q742NI3.cjs → chunk-PADNCGZB.cjs} +17 -3
  45. package/dist/chunk-PADNCGZB.cjs.map +1 -0
  46. package/dist/chunk-PRCICORG.cjs +95 -0
  47. package/dist/chunk-PRCICORG.cjs.map +1 -0
  48. package/dist/{chunk-6QGDZTGH.js → chunk-SIH4GPV4.js} +4 -29
  49. package/dist/chunk-SIH4GPV4.js.map +1 -0
  50. package/dist/chunk-U2YDDUVP.js +970 -0
  51. package/dist/chunk-U2YDDUVP.js.map +1 -0
  52. package/dist/{chunk-4NAY6HRP.js → chunk-VJHLO2R3.js} +7 -58
  53. package/dist/chunk-VJHLO2R3.js.map +1 -0
  54. package/dist/chunk-XAWBTX3N.cjs +46 -0
  55. package/dist/chunk-XAWBTX3N.cjs.map +1 -0
  56. package/dist/{chunk-AV6OE2YQ.cjs → chunk-XOKUDUUI.cjs} +14 -39
  57. package/dist/chunk-XOKUDUUI.cjs.map +1 -0
  58. package/dist/chunk-YQDSN6R6.cjs +86 -0
  59. package/dist/chunk-YQDSN6R6.cjs.map +1 -0
  60. package/dist/cli/index.cjs +59 -201
  61. package/dist/cli/index.cjs.map +1 -1
  62. package/dist/cli/index.js +53 -198
  63. package/dist/cli/index.js.map +1 -1
  64. package/dist/cost/index.cjs +19 -3
  65. package/dist/cost/index.cjs.map +1 -1
  66. package/dist/cost/index.d.cts +10 -50
  67. package/dist/cost/index.d.ts +10 -50
  68. package/dist/cost/index.js +18 -3
  69. package/dist/index.cjs +24 -16
  70. package/dist/index.cjs.map +1 -1
  71. package/dist/index.d.cts +13 -13
  72. package/dist/index.d.ts +13 -13
  73. package/dist/index.js +44 -37
  74. package/dist/modelCache-BzRn6t_C.d.ts +113 -0
  75. package/dist/modelCache-CJftI-Ko.d.cts +113 -0
  76. package/dist/{modelNameResolver-DqFt7g6W.d.ts → modelNameResolver-5XkBMctP.d.ts} +2 -6
  77. package/dist/{modelNameResolver-D9V_GfUK.d.cts → modelNameResolver-C5CSTGFF.d.cts} +2 -6
  78. package/dist/models/index.cjs +9 -6
  79. package/dist/models/index.cjs.map +1 -1
  80. package/dist/models/index.d.cts +9 -31
  81. package/dist/models/index.d.ts +9 -31
  82. package/dist/models/index.js +9 -7
  83. package/dist/resolveUsageModel-BFwf80Hz.d.ts +140 -0
  84. package/dist/resolveUsageModel-C_YmGR1M.d.cts +140 -0
  85. package/dist/sync/index.cjs +7 -9
  86. package/dist/sync/index.cjs.map +1 -1
  87. package/dist/sync/index.d.cts +3 -8
  88. package/dist/sync/index.d.ts +3 -8
  89. package/dist/sync/index.js +8 -11
  90. package/dist/toolbox/index.cjs +1 -0
  91. package/dist/toolbox/index.cjs.map +1 -1
  92. package/dist/types-BrzJWsTU.d.cts +277 -0
  93. package/dist/types-BrzJWsTU.d.ts +277 -0
  94. package/package.json +9 -20
  95. package/src/data/models-catalog.json +670 -0
  96. package/src/data/openrouter-models-catalog.json +857 -0
  97. package/dist/AiModelsCatalogClient-4RF5BCDL.cjs +0 -9
  98. package/dist/AiModelsCatalogClient-4RF5BCDL.cjs.map +0 -1
  99. package/dist/AiModelsCatalogClient-CNeqFiFs.d.cts +0 -30
  100. package/dist/AiModelsCatalogClient-NUF3CBLW.js +0 -9
  101. package/dist/AiModelsCatalogClient-nwFoEaqL.d.ts +0 -30
  102. package/dist/catalox/index.cjs +0 -21
  103. package/dist/catalox/index.cjs.map +0 -1
  104. package/dist/catalox/index.d.cts +0 -11
  105. package/dist/catalox/index.d.ts +0 -11
  106. package/dist/catalox/index.js +0 -21
  107. package/dist/catalox/index.js.map +0 -1
  108. package/dist/chunk-4NAY6HRP.js.map +0 -1
  109. package/dist/chunk-6QGDZTGH.js.map +0 -1
  110. package/dist/chunk-7Q742NI3.cjs.map +0 -1
  111. package/dist/chunk-AJEKEWWB.js.map +0 -1
  112. package/dist/chunk-AV6OE2YQ.cjs.map +0 -1
  113. package/dist/chunk-C3H7RTFR.cjs +0 -1
  114. package/dist/chunk-C3H7RTFR.cjs.map +0 -1
  115. package/dist/chunk-DJ5SWJDY.js.map +0 -1
  116. package/dist/chunk-DKHGWHXP.cjs +0 -169
  117. package/dist/chunk-DKHGWHXP.cjs.map +0 -1
  118. package/dist/chunk-F2F4UEFD.cjs +0 -75
  119. package/dist/chunk-F2F4UEFD.cjs.map +0 -1
  120. package/dist/chunk-FGP3QXWL.cjs +0 -163
  121. package/dist/chunk-FGP3QXWL.cjs.map +0 -1
  122. package/dist/chunk-G2G4KSC5.js +0 -30
  123. package/dist/chunk-G2G4KSC5.js.map +0 -1
  124. package/dist/chunk-HN6UAQAE.cjs +0 -83
  125. package/dist/chunk-HN6UAQAE.cjs.map +0 -1
  126. package/dist/chunk-HS74X2OJ.cjs +0 -172
  127. package/dist/chunk-HS74X2OJ.cjs.map +0 -1
  128. package/dist/chunk-HYGXZY25.js +0 -163
  129. package/dist/chunk-HYGXZY25.js.map +0 -1
  130. package/dist/chunk-KQOALKKX.js +0 -75
  131. package/dist/chunk-KQOALKKX.js.map +0 -1
  132. package/dist/chunk-LYOU7CA2.cjs +0 -30
  133. package/dist/chunk-LYOU7CA2.cjs.map +0 -1
  134. package/dist/chunk-M5TMA73F.js +0 -1
  135. package/dist/chunk-M5TMA73F.js.map +0 -1
  136. package/dist/chunk-MX3AMQFC.js +0 -172
  137. package/dist/chunk-MX3AMQFC.js.map +0 -1
  138. package/dist/chunk-QCRLKVB3.cjs +0 -137
  139. package/dist/chunk-QCRLKVB3.cjs.map +0 -1
  140. package/dist/chunk-TF4L2NEC.cjs.map +0 -1
  141. package/dist/chunk-VRFVF5RH.js +0 -169
  142. package/dist/chunk-VRFVF5RH.js.map +0 -1
  143. package/dist/chunk-YHO57D2V.js +0 -83
  144. package/dist/chunk-YHO57D2V.js.map +0 -1
  145. package/dist/syncAiModelsCatalog-CnXRLm2c.d.cts +0 -32
  146. package/dist/syncAiModelsCatalog-DpkN_w7S.d.ts +0 -32
  147. package/dist/types-BYXnCvKx.d.cts +0 -137
  148. package/dist/types-BYXnCvKx.d.ts +0 -137
  149. package/dist/types-CX6QFNNy.d.cts +0 -144
  150. package/dist/types-CuiPDcVs.d.ts +0 -144
  151. package/dist/upsertAiModelRecord-C831wOIF.d.ts +0 -35
  152. package/dist/upsertAiModelRecord-CjY-sny0.d.cts +0 -35
  153. /package/dist/{AiModelsCatalogClient-NUF3CBLW.js.map → chunk-56R4XA2S.js.map} +0 -0
package/dist/cli/index.js CHANGED
@@ -1,67 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CostCalculator
4
- } from "../chunk-YHO57D2V.js";
4
+ } from "../chunk-U2YDDUVP.js";
5
5
  import {
6
6
  AliasRegistry,
7
7
  AliasResolver
8
- } from "../chunk-O2A6OVEH.js";
8
+ } from "../chunk-ANVONYJF.js";
9
9
  import {
10
10
  AiModelsService
11
- } from "../chunk-4NAY6HRP.js";
11
+ } from "../chunk-VJHLO2R3.js";
12
12
  import {
13
- CatalogSyncJobError,
14
- runAiModelsCatalogSync,
13
+ refreshAiModelsCatalog,
15
14
  verifyAiModelsCatalog
16
- } from "../chunk-MX3AMQFC.js";
15
+ } from "../chunk-AB5GNXJ4.js";
17
16
  import {
18
- ensureAiModelsCatalog
19
- } from "../chunk-VRFVF5RH.js";
20
- import "../chunk-HYGXZY25.js";
21
- import "../chunk-6QGDZTGH.js";
22
- import {
23
- AiModelsCatalogClient
24
- } from "../chunk-KQOALKKX.js";
25
- import "../chunk-DJ5SWJDY.js";
26
- import "../chunk-AJEKEWWB.js";
17
+ AiModelsCatalogClient,
18
+ resolveCatalogCacheTtlMs
19
+ } from "../chunk-OPN6BGNH.js";
20
+ import "../chunk-EYHMQVAL.js";
21
+ import "../chunk-B3V2EHRY.js";
22
+ import "../chunk-2PTCWPHV.js";
27
23
 
28
24
  // src/cli/index.ts
29
25
  import { Command } from "commander";
30
26
 
31
27
  // src/cli/commands/alias.ts
32
28
  import fs from "fs";
33
-
34
- // src/cli/catalox.ts
35
- import { createCataloxFromEnv } from "@x12i/catalox/firebase";
36
- var cached = null;
37
- function getCataloxBundle() {
38
- if (!cached) {
39
- cached = createCataloxFromEnv();
40
- }
41
- return cached;
42
- }
43
- function getCatalox() {
44
- return getCataloxBundle().catalox;
45
- }
46
- function getFirestore() {
47
- return getCataloxBundle().firestore;
48
- }
49
-
50
- // src/cli/env.ts
51
- import { config } from "dotenv";
52
- config();
53
- function envAppId() {
54
- return process.env.AI_TOOLS_APP_ID ?? "ai-tools";
55
- }
56
- function envCatalogId() {
57
- return process.env.AI_TOOLS_CATALOG_ID ?? "ai-models";
58
- }
59
- function envCacheTtlMs() {
60
- const raw = process.env.AI_TOOLS_CACHE_TTL_MS;
61
- return raw ? Number.parseInt(raw, 10) : 60 * 60 * 1e3;
62
- }
63
-
64
- // src/cli/commands/alias.ts
65
29
  function registry(path) {
66
30
  return new AliasRegistry(path ? { aliasesPath: path } : {});
67
31
  }
@@ -69,10 +33,7 @@ function resolver(path) {
69
33
  return new AliasResolver({
70
34
  registry: registry(path),
71
35
  catalogClient: new AiModelsCatalogClient({
72
- catalox: getCatalox(),
73
- appId: envAppId(),
74
- catalogId: envCatalogId(),
75
- cacheTtlMs: envCacheTtlMs()
36
+ cacheTtlMs: resolveCatalogCacheTtlMs()
76
37
  })
77
38
  });
78
39
  }
@@ -192,78 +153,34 @@ function emitHuman(lines) {
192
153
  console.log(line);
193
154
  }
194
155
  }
195
- function formatSyncJobReport(result) {
196
- const lines = [
197
- "",
198
- result.ok ? "\u2714 Catalog sync job succeeded" : "\u2717 Catalog sync job failed",
199
- "",
200
- "Sync",
201
- ` Fetched: ${result.sync.fetched}`,
202
- ` Upserted: ${result.sync.upserted}`,
203
- ` Skipped: ${result.sync.skipped}`,
204
- ` Errors: ${result.sync.errors.length}`,
205
- ` Duration: ${result.sync.durationMs}ms`
206
- ];
207
- if (result.verify) {
208
- lines.push(
209
- "",
210
- "Verify",
211
- ` Status: ${result.verify.ok ? "ok" : "FAILED"}`,
212
- ` OpenRouter: ${result.verify.openRouterCount}`,
213
- ` Catalox: ${result.verify.cataloxCount}`,
214
- ` Missing: ${result.verify.missingInCatalox.length}`,
215
- ` Extra: ${result.verify.extraInCatalox.length}`,
216
- ` Duration: ${result.verify.durationMs}ms`
217
- );
218
- if (result.verify.missingInCatalox.length > 0) {
219
- lines.push(` Sample missing: ${result.verify.missingInCatalox.join(", ")}`);
220
- }
221
- if (result.verify.extraInCatalox.length > 0) {
222
- lines.push(` Sample extra: ${result.verify.extraInCatalox.join(", ")}`);
223
- }
224
- }
225
- if (result.prune) {
226
- lines.push("", "Prune", ` Scanned: ${result.prune.scanned}`, ` Removed: ${result.prune.pruned}`);
227
- }
228
- return lines;
229
- }
230
156
 
231
157
  // src/cli/commands/catalog.ts
232
158
  function registerCatalogCommand(program2) {
233
- const catalog = program2.command("catalog").description("Catalog bootstrap and health commands");
234
- catalog.command("ensure").description("Create catalog, descriptor, and app binding if missing").option("--app <appId>", "Override appId").option("--catalog <id>", "Override catalogId").option("--json", "Machine-readable JSON on stdout").action(async (opts) => {
235
- const appId = opts.app ?? envAppId();
236
- const catalogId = opts.catalog ?? envCatalogId();
237
- await ensureAiModelsCatalog(getCatalox(), { appId, catalogId });
159
+ const catalog = program2.command("catalog").description("Model catalog load and health commands");
160
+ 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) => {
161
+ const result = await refreshAiModelsCatalog({ bundledOnly: opts.bundledOnly });
238
162
  if (opts.json) {
239
- emitJson({ ok: true, appId, catalogId, action: "ensure" });
163
+ emitJson(result);
240
164
  } else {
241
- console.log("\u2714 ai-models catalog ensured");
165
+ emitHuman([
166
+ "\u2714 Catalog refresh complete",
167
+ ` Direct: ${result.directCount} (${result.directSource})`,
168
+ ` OpenRouter: ${result.openRouterCount} (${result.openRouterSource})`
169
+ ]);
242
170
  }
243
171
  });
244
- catalog.command("verify").description("Health check: compare Catalox ai-models against the live OpenRouter catalog").option("--app <appId>", "Override appId").option("--catalog <id>", "Override catalogId").option("--json", "Machine-readable JSON on stdout").action(async (opts) => {
245
- const report = await verifyAiModelsCatalog({
246
- catalox: getCatalox(),
247
- appId: opts.app ?? envAppId(),
248
- catalogId: opts.catalog ?? envCatalogId()
249
- });
172
+ 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) => {
173
+ const report = await verifyAiModelsCatalog({ bundledOnly: opts.bundledOnly });
250
174
  if (opts.json) {
251
175
  emitJson(report);
252
176
  } else {
253
177
  emitHuman([
254
178
  report.ok ? "\u2714 Catalog verification passed" : "\u2717 Catalog verification FAILED",
255
- ` OpenRouter models: ${report.openRouterCount}`,
256
- ` Catalox models: ${report.cataloxCount}`,
257
- ` Missing in Catalox: ${report.missingInCatalox.length}`,
258
- ` Extra in Catalox: ${report.extraInCatalox.length}`,
259
- ` Duration: ${report.durationMs}ms`
179
+ ` Direct models: ${report.directCount} (${report.directSource})`,
180
+ ` OpenRouter models: ${report.openRouterCount} (${report.openRouterSource})`,
181
+ ` Direct URL: ${report.directUrl}`,
182
+ ` OpenRouter URL: ${report.openRouterUrl}`
260
183
  ]);
261
- if (report.missingInCatalox.length > 0) {
262
- console.log(` Sample missing: ${report.missingInCatalox.join(", ")}`);
263
- }
264
- if (report.extraInCatalox.length > 0) {
265
- console.log(` Sample extra: ${report.extraInCatalox.join(", ")}`);
266
- }
267
184
  }
268
185
  if (!report.ok) {
269
186
  process.exit(1);
@@ -280,12 +197,10 @@ function registerCostCommand(program2) {
280
197
  "--completion-tokens <n>",
281
198
  "Completion token count",
282
199
  (v) => Number.parseInt(v, 10)
283
- ).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 OpenRouter delta logic", "openrouter").option("--json", "Output raw AiCostResult JSON").option("--app <appId>", "Override appId").option("--catalog <id>", "Override catalogId").action(async (opts) => {
200
+ ).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) => {
284
201
  const catalogClient = new AiModelsCatalogClient({
285
- catalox: getCatalox(),
286
- appId: opts.app ?? envAppId(),
287
- catalogId: opts.catalog ?? envCatalogId(),
288
- cacheTtlMs: envCacheTtlMs()
202
+ cacheTtlMs: resolveCatalogCacheTtlMs(),
203
+ bundledOnly: opts.bundledOnly
289
204
  });
290
205
  const calculator = new CostCalculator(catalogClient, {
291
206
  aliasRegistry: new AliasRegistry()
@@ -307,6 +222,9 @@ function registerCostCommand(program2) {
307
222
  }
308
223
  const b = result.breakdown;
309
224
  console.log(`Model: ${result.resolvedModelId}`);
225
+ if (result.usedModel && result.usedModel !== result.resolvedModelId) {
226
+ console.log(`Used model: ${result.usedModel}`);
227
+ }
310
228
  console.log(
311
229
  `Prompt: ${opts.promptTokens.toLocaleString()} tokens \u2192 ${formatUsd(b?.promptCostUsd ?? 0)}`
312
230
  );
@@ -327,15 +245,13 @@ function registerCostCommand(program2) {
327
245
  // src/cli/commands/models.ts
328
246
  function service(opts) {
329
247
  return new AiModelsService({
330
- catalox: getCatalox(),
331
- appId: opts.app ?? envAppId(),
332
- catalogId: opts.catalog ?? envCatalogId(),
333
- cacheTtlMs: envCacheTtlMs()
248
+ cacheTtlMs: resolveCatalogCacheTtlMs(),
249
+ bundledOnly: opts.bundledOnly
334
250
  });
335
251
  }
336
252
  function registerModelsCommand(program2) {
337
- const models = program2.command("models").description("Inspect ai-models catalog");
338
- models.command("list").description("List models with optional filters").option("--provider <id>", "Filter by providerId (e.g. openai, anthropic)").option("--output-modality <m>", "Filter by output modality (text, image, audio, \u2026)").option("--input-modality <m>", "Filter by input modality").option("--parameter <p>", "Filter by supported parameter (e.g. tools)").option("--tools", "Only models that support tools").option("--reasoning", "Only reasoning / thinking models").option("--search <q>", "Search name, id, description").option("--json", "Output raw JSON").option("--limit <n>", "Max rows", "50").option("--offset <n>", "Skip rows", "0").option("--app <appId>", "Override appId").option("--catalog <id>", "Override catalogId").action(async (opts) => {
253
+ const models = program2.command("models").description("Inspect model catalogs");
254
+ models.command("list").description("List models with optional filters").option("--provider <id>", "Filter by providerId (e.g. openai, anthropic)").option("--output-modality <m>", "Filter by output modality (text, image, audio, \u2026)").option("--input-modality <m>", "Filter by input modality").option("--parameter <p>", "Filter by supported parameter (e.g. tools)").option("--tools", "Only models that support tools").option("--reasoning", "Only reasoning / thinking models").option("--search <q>", "Search name, id, description").option("--json", "Output raw JSON").option("--limit <n>", "Max rows", "50").option("--offset <n>", "Skip rows", "0").option("--bundled-only", "Use src/data catalogs only (no HTTP)").action(async (opts) => {
339
255
  const { models: rows, total } = await service(opts).listModels({
340
256
  providerId: opts.provider,
341
257
  outputModality: opts.outputModality,
@@ -371,7 +287,7 @@ function registerModelsCommand(program2) {
371
287
  console.log(`
372
288
  ${rows.length} shown \xB7 ${total} matching`);
373
289
  });
374
- models.command("get").description("Get full model info (OpenRouter mirror) by ID or alias").argument("<modelId>", "Model ID or alias").option("--app <appId>", "Override appId").option("--catalog <id>", "Override catalogId").action(async (modelId, opts) => {
290
+ models.command("get").description("Get full model record by ID or alias").argument("<modelId>", "Model ID or alias").option("--bundled-only", "Use src/data catalogs only (no HTTP)").action(async (modelId, opts) => {
375
291
  const model = await service(opts).getModelInfo(modelId);
376
292
  if (!model) {
377
293
  console.error(`Model not found: ${modelId}`);
@@ -379,31 +295,18 @@ ${rows.length} shown \xB7 ${total} matching`);
379
295
  }
380
296
  console.log(JSON.stringify(model, null, 2));
381
297
  });
382
- models.command("resolve").description("Resolve provider + model to canonical id (smart resolver)").requiredOption("--model <m>", "Model string (required)").option("--provider <p>", "Provider hint (openrouter, openai, \u2026)").option("--threshold <n>", "Confidence threshold 0\u20131", "0.6").option("--json", "Output raw ModelResolutionResult JSON").option("--verbose", "Show strategy trail").option("--app <appId>", "Override appId").option("--catalog <id>", "Override catalogId").action(async (opts) => {
383
- const { AiModelsCatalogClient: AiModelsCatalogClient2 } = await import("../AiModelsCatalogClient-NUF3CBLW.js");
384
- const client = new AiModelsCatalogClient2({
385
- catalox: getCatalox(),
386
- appId: opts.app ?? envAppId(),
387
- catalogId: opts.catalog ?? envCatalogId(),
388
- cacheTtlMs: envCacheTtlMs()
389
- });
390
- const threshold = Number.parseFloat(opts.threshold ?? "0.6");
391
- const result = await client.resolveModel(
392
- { model: opts.model, provider: opts.provider },
393
- { confidenceThreshold: threshold }
394
- );
298
+ models.command("resolve").description("Resolve provider + model to canonical id").requiredOption("--model <m>", "Model string (required)").option("--provider <p>", "Provider hint (openrouter, openai, \u2026)").option("--threshold <n>", "Confidence threshold 0\u20131", "0.6").option("--json", "Output raw ModelResolutionResult JSON").option("--verbose", "Show strategy trail").option("--bundled-only", "Use src/data catalogs only (no HTTP)").action(async (opts) => {
299
+ const result = await service(opts).resolve(opts.model, opts.provider);
395
300
  if (opts.json) {
396
301
  console.log(JSON.stringify(result, null, 2));
397
- if (!result.found) process.exit(1);
398
302
  return;
399
303
  }
400
304
  const providerLabel = opts.provider ?? "unspecified";
401
305
  console.log(`Input: provider="${providerLabel}" model="${opts.model}"`);
402
- if (opts.verbose) {
403
- console.log(`Normalised: model="${result.found ? result.normalisedInput : opts.model}"`);
404
- const strategies = result.found ? result.resolvedVia : result.attemptedStrategies;
306
+ if (opts.verbose && result.found) {
307
+ console.log(`Normalised: model="${result.normalisedInput}"`);
405
308
  console.log("\nStrategy trail:");
406
- for (const s of strategies) {
309
+ for (const s of result.resolvedVia) {
407
310
  console.log(` \u2022 ${s}`);
408
311
  }
409
312
  console.log();
@@ -415,20 +318,18 @@ ${rows.length} shown \xB7 ${total} matching`);
415
318
  console.log(
416
319
  `Candidate: ${result.bestRejectedCandidate.modelId} (confidence ${result.bestRejectedCandidate.confidence.toFixed(2)})`
417
320
  );
418
- } else {
419
- console.log("Candidate: none");
420
321
  }
421
- console.log('Tip: Run "ai-tools sync" or add an alias with "ai-tools alias set".');
322
+ console.log('Tip: Run "ai-tools catalog refresh" or "ai-tools alias set".');
422
323
  process.exit(1);
423
324
  return;
424
325
  }
425
326
  console.log(`Resolved: ${result.modelId}`);
426
- console.log(`Name: ${result.record?.name ?? "(local / no catalog record)"}`);
327
+ console.log(`Name: ${result.record?.name ?? "(no catalog record)"}`);
427
328
  console.log(`Strategy: ${result.resolvedVia.join(" \u2192 ")}`);
428
329
  console.log(`Confidence: ${result.confidence.toFixed(2)}`);
429
330
  console.log(`Via OR: ${result.routedViaOpenRouter ? "yes" : "no"}`);
430
331
  });
431
- models.command("count").description("Count models matching filters").option("--provider <id>", "Filter by providerId").option("--output-modality <m>", "Filter by output modality").option("--parameter <p>", "Filter by supported parameter").option("--tools", "Only models that support tools").option("--reasoning", "Only reasoning / thinking models").option("--app <appId>", "Override appId").option("--catalog <id>", "Override catalogId").action(async (opts) => {
332
+ models.command("count").description("Count models matching filters").option("--provider <id>", "Filter by providerId").option("--output-modality <m>", "Filter by output modality").option("--parameter <p>", "Filter by supported parameter").option("--tools", "Only models that support tools").option("--reasoning", "Only reasoning / thinking models").option("--bundled-only", "Use src/data catalogs only (no HTTP)").action(async (opts) => {
432
333
  const n = await service(opts).countModels({
433
334
  providerId: opts.provider,
434
335
  outputModality: opts.outputModality,
@@ -440,61 +341,15 @@ ${rows.length} shown \xB7 ${total} matching`);
440
341
  });
441
342
  }
442
343
 
443
- // src/cli/commands/sync.ts
444
- function registerSyncCommand(program2) {
445
- program2.command("sync").description(
446
- "Production sync: fetch OpenRouter models, upsert into Catalox/Firestore, verify completeness"
447
- ).option("--dry-run", "Fetch and validate without writing to Firestore").option("--no-verify", "Skip post-sync verification (not recommended in production)").option("--prune-stale", "Remove catalog rows no longer on OpenRouter").option("--json", "Machine-readable JSON on stdout").option("--verbose", "Log fetch URL and upsert progress").option("--app <appId>", "Override appId").option("--catalog <id>", "Override catalogId").option("--force-cache", "Invalidate nx-cache before running").action(
448
- async (opts) => {
449
- const verifyAfter = opts.verify !== false;
450
- try {
451
- const result = await runAiModelsCatalogSync({
452
- catalox: getCatalox(),
453
- firestore: getFirestore(),
454
- openRouterApiKey: process.env.OPENROUTER_API_KEY,
455
- appId: opts.app ?? envAppId(),
456
- catalogId: opts.catalog ?? envCatalogId(),
457
- dryRun: opts.dryRun,
458
- verbose: opts.verbose,
459
- forceCache: opts.forceCache,
460
- verifyAfter,
461
- pruneStale: opts.pruneStale,
462
- onProgress: opts.verbose ? ({ completed, total, phase }) => {
463
- console.log(`[sync] ${phase} ${completed}/${total}`);
464
- } : void 0
465
- });
466
- if (opts.json) {
467
- emitJson(result);
468
- } else {
469
- emitHuman(formatSyncJobReport(result));
470
- }
471
- if (!result.ok) {
472
- process.exit(1);
473
- }
474
- } catch (error) {
475
- if (error instanceof CatalogSyncJobError) {
476
- const payload = {
477
- ok: false,
478
- sync: error.sync,
479
- verify: error.verify
480
- };
481
- if (opts.json) {
482
- emitJson(payload);
483
- } else {
484
- emitHuman(formatSyncJobReport(payload));
485
- }
486
- process.exit(1);
487
- }
488
- throw error;
489
- }
490
- }
491
- );
492
- }
493
-
494
344
  // src/cli/index.ts
345
+ import { readFileSync } from "fs";
346
+ import { fileURLToPath } from "url";
347
+ import { dirname, join } from "path";
348
+ var pkg = JSON.parse(
349
+ readFileSync(join(dirname(fileURLToPath(import.meta.url)), "../../package.json"), "utf8")
350
+ );
495
351
  var program = new Command();
496
- program.name("ai-tools").description("@x12i/ai-tools \u2014 AI model catalog, cost calculation, and utilities").version("1.0.0");
497
- registerSyncCommand(program);
352
+ program.name("ai-tools").description("@x12i/ai-tools \u2014 AI model catalog, cost calculation, and utilities").version(pkg.version);
498
353
  registerCatalogCommand(program);
499
354
  registerModelsCommand(program);
500
355
  registerCostCommand(program);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/alias.ts","../../src/cli/catalox.ts","../../src/cli/env.ts","../../src/cli/report.ts","../../src/cli/commands/catalog.ts","../../src/cli/commands/cost.ts","../../src/cli/commands/models.ts","../../src/cli/commands/sync.ts"],"sourcesContent":["#!/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 { registerSyncCommand } from \"./commands/sync.js\";\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(\"1.0.0\");\n\nregisterSyncCommand(program);\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 \"../../catalox/AiModelsCatalogClient.js\";\nimport { getCatalox } from \"../catalox.js\";\nimport { envAppId, envCacheTtlMs, envCatalogId } from \"../env.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 catalox: getCatalox(),\n appId: envAppId(),\n catalogId: envCatalogId(),\n cacheTtlMs: envCacheTtlMs(),\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","import { createCataloxFromEnv } from \"@x12i/catalox/firebase\";\nimport type { Catalox } from \"@x12i/catalox\";\nimport type { Firestore } from \"firebase-admin/firestore\";\n\ntype CataloxBundle = {\n catalox: Catalox;\n firestore: Firestore;\n};\n\nlet cached: CataloxBundle | null = null;\n\nexport function getCataloxBundle(): CataloxBundle {\n if (!cached) {\n cached = createCataloxFromEnv();\n }\n return cached;\n}\n\nexport function getCatalox(): Catalox {\n return getCataloxBundle().catalox;\n}\n\nexport function getFirestore(): Firestore {\n return getCataloxBundle().firestore;\n}\n","import { config } from \"dotenv\";\n\nconfig();\n\nexport function envAppId(): string {\n return process.env.AI_TOOLS_APP_ID ?? \"ai-tools\";\n}\n\nexport function envCatalogId(): string {\n return process.env.AI_TOOLS_CATALOG_ID ?? \"ai-models\";\n}\n\nexport function envCacheTtlMs(): number {\n const raw = process.env.AI_TOOLS_CACHE_TTL_MS;\n return raw ? Number.parseInt(raw, 10) : 60 * 60 * 1000;\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\nexport function formatSyncJobReport(result: {\n ok: boolean;\n sync: {\n fetched: number;\n upserted: number;\n skipped: number;\n errors: Array<{ modelId: string; error: string }>;\n durationMs: number;\n };\n verify?: {\n ok: boolean;\n openRouterCount: number;\n cataloxCount: number;\n missingInCatalox: string[];\n extraInCatalox: string[];\n durationMs: number;\n };\n prune?: { pruned: number; scanned: number };\n}): string[] {\n const lines = [\n \"\",\n result.ok ? \"✔ Catalog sync job succeeded\" : \"✗ Catalog sync job failed\",\n \"\",\n \"Sync\",\n ` Fetched: ${result.sync.fetched}`,\n ` Upserted: ${result.sync.upserted}`,\n ` Skipped: ${result.sync.skipped}`,\n ` Errors: ${result.sync.errors.length}`,\n ` Duration: ${result.sync.durationMs}ms`,\n ];\n\n if (result.verify) {\n lines.push(\n \"\",\n \"Verify\",\n ` Status: ${result.verify.ok ? \"ok\" : \"FAILED\"}`,\n ` OpenRouter: ${result.verify.openRouterCount}`,\n ` Catalox: ${result.verify.cataloxCount}`,\n ` Missing: ${result.verify.missingInCatalox.length}`,\n ` Extra: ${result.verify.extraInCatalox.length}`,\n ` Duration: ${result.verify.durationMs}ms`,\n );\n if (result.verify.missingInCatalox.length > 0) {\n lines.push(` Sample missing: ${result.verify.missingInCatalox.join(\", \")}`);\n }\n if (result.verify.extraInCatalox.length > 0) {\n lines.push(` Sample extra: ${result.verify.extraInCatalox.join(\", \")}`);\n }\n }\n\n if (result.prune) {\n lines.push(\"\", \"Prune\", ` Scanned: ${result.prune.scanned}`, ` Removed: ${result.prune.pruned}`);\n }\n\n return lines;\n}\n","import type { Command } from \"commander\";\nimport { ensureAiModelsCatalog } from \"../../catalog/ensureAiModelsCatalog.js\";\nimport { verifyAiModelsCatalog } from \"../../catalog/verifyAiModelsCatalog.js\";\nimport { getCatalox } from \"../catalox.js\";\nimport { envAppId, envCatalogId } from \"../env.js\";\nimport { emitHuman, emitJson } from \"../report.js\";\n\nexport function registerCatalogCommand(program: Command): void {\n const catalog = program.command(\"catalog\").description(\"Catalog bootstrap and health commands\");\n\n catalog\n .command(\"ensure\")\n .description(\"Create catalog, descriptor, and app binding if missing\")\n .option(\"--app <appId>\", \"Override appId\")\n .option(\"--catalog <id>\", \"Override catalogId\")\n .option(\"--json\", \"Machine-readable JSON on stdout\")\n .action(async (opts: { app?: string; catalog?: string; json?: boolean }) => {\n const appId = opts.app ?? envAppId();\n const catalogId = opts.catalog ?? envCatalogId();\n await ensureAiModelsCatalog(getCatalox(), { appId, catalogId });\n if (opts.json) {\n emitJson({ ok: true, appId, catalogId, action: \"ensure\" });\n } else {\n console.log(\"✔ ai-models catalog ensured\");\n }\n });\n\n catalog\n .command(\"verify\")\n .description(\"Health check: compare Catalox ai-models against the live OpenRouter catalog\")\n .option(\"--app <appId>\", \"Override appId\")\n .option(\"--catalog <id>\", \"Override catalogId\")\n .option(\"--json\", \"Machine-readable JSON on stdout\")\n .action(async (opts: { app?: string; catalog?: string; json?: boolean }) => {\n const report = await verifyAiModelsCatalog({\n catalox: getCatalox(),\n appId: opts.app ?? envAppId(),\n catalogId: opts.catalog ?? envCatalogId(),\n });\n\n if (opts.json) {\n emitJson(report);\n } else {\n emitHuman([\n report.ok ? \"✔ Catalog verification passed\" : \"✗ Catalog verification FAILED\",\n ` OpenRouter models: ${report.openRouterCount}`,\n ` Catalox models: ${report.cataloxCount}`,\n ` Missing in Catalox: ${report.missingInCatalox.length}`,\n ` Extra in Catalox: ${report.extraInCatalox.length}`,\n ` Duration: ${report.durationMs}ms`,\n ]);\n if (report.missingInCatalox.length > 0) {\n console.log(` Sample missing: ${report.missingInCatalox.join(\", \")}`);\n }\n if (report.extraInCatalox.length > 0) {\n console.log(` Sample extra: ${report.extraInCatalox.join(\", \")}`);\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 \"../../catalox/AiModelsCatalogClient.js\";\nimport { getCatalox } from \"../catalox.js\";\nimport { envAppId, envCacheTtlMs, envCatalogId } from \"../env.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 OpenRouter delta logic\", \"openrouter\")\n .option(\"--json\", \"Output raw AiCostResult JSON\")\n .option(\"--app <appId>\", \"Override appId\")\n .option(\"--catalog <id>\", \"Override catalogId\")\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 app?: string;\n catalog?: string;\n }) => {\n const catalogClient = new AiModelsCatalogClient({\n catalox: getCatalox(),\n appId: opts.app ?? envAppId(),\n catalogId: opts.catalog ?? envCatalogId(),\n cacheTtlMs: envCacheTtlMs(),\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 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 { getCatalox } from \"../catalox.js\";\nimport { envAppId, envCacheTtlMs, envCatalogId } from \"../env.js\";\n\nfunction service(opts: { app?: string; catalog?: string }) {\n return new AiModelsService({\n catalox: getCatalox(),\n appId: opts.app ?? envAppId(),\n catalogId: opts.catalog ?? envCatalogId(),\n cacheTtlMs: envCacheTtlMs(),\n });\n}\n\nexport function registerModelsCommand(program: Command): void {\n const models = program.command(\"models\").description(\"Inspect ai-models catalog\");\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(\"--app <appId>\", \"Override appId\")\n .option(\"--catalog <id>\", \"Override catalogId\")\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 app?: string;\n catalog?: string;\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 info (OpenRouter mirror) by ID or alias\")\n .argument(\"<modelId>\", \"Model ID or alias\")\n .option(\"--app <appId>\", \"Override appId\")\n .option(\"--catalog <id>\", \"Override catalogId\")\n .action(async (modelId: string, opts: { app?: string; catalog?: string }) => {\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 (smart resolver)\")\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(\"--app <appId>\", \"Override appId\")\n .option(\"--catalog <id>\", \"Override catalogId\")\n .action(async (opts: {\n model: string;\n provider?: string;\n threshold?: string;\n json?: boolean;\n verbose?: boolean;\n app?: string;\n catalog?: string;\n }) => {\n const { AiModelsCatalogClient } = await import(\"../../catalox/AiModelsCatalogClient.js\");\n const client = new AiModelsCatalogClient({\n catalox: getCatalox(),\n appId: opts.app ?? envAppId(),\n catalogId: opts.catalog ?? envCatalogId(),\n cacheTtlMs: envCacheTtlMs(),\n });\n const threshold = Number.parseFloat(opts.threshold ?? \"0.6\");\n const result = await client.resolveModel(\n { model: opts.model, provider: opts.provider },\n { confidenceThreshold: threshold },\n );\n\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n if (!result.found) process.exit(1);\n return;\n }\n\n const providerLabel = opts.provider ?? \"unspecified\";\n console.log(`Input: provider=\"${providerLabel}\" model=\"${opts.model}\"`);\n\n if (opts.verbose) {\n console.log(`Normalised: model=\"${result.found ? result.normalisedInput : opts.model}\"`);\n const strategies = result.found ? result.resolvedVia : result.attemptedStrategies;\n console.log(\"\\nStrategy trail:\");\n for (const s of strategies) {\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 } else {\n console.log(\"Candidate: none\");\n }\n console.log('Tip: Run \"ai-tools sync\" or add an alias with \"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 ?? \"(local / 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(\"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(\"--app <appId>\", \"Override appId\")\n .option(\"--catalog <id>\", \"Override catalogId\")\n .action(async (opts: {\n provider?: string;\n outputModality?: string;\n parameter?: string;\n tools?: boolean;\n reasoning?: boolean;\n app?: string;\n catalog?: string;\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","import type { Command } from \"commander\";\nimport { runAiModelsCatalogSync, CatalogSyncJobError } from \"../../catalog/runAiModelsCatalogSync.js\";\nimport { getCatalox, getFirestore } from \"../catalox.js\";\nimport { envAppId, envCatalogId } from \"../env.js\";\nimport { emitHuman, emitJson, formatSyncJobReport } from \"../report.js\";\n\nexport function registerSyncCommand(program: Command): void {\n program\n .command(\"sync\")\n .description(\n \"Production sync: fetch OpenRouter models, upsert into Catalox/Firestore, verify completeness\",\n )\n .option(\"--dry-run\", \"Fetch and validate without writing to Firestore\")\n .option(\"--no-verify\", \"Skip post-sync verification (not recommended in production)\")\n .option(\"--prune-stale\", \"Remove catalog rows no longer on OpenRouter\")\n .option(\"--json\", \"Machine-readable JSON on stdout\")\n .option(\"--verbose\", \"Log fetch URL and upsert progress\")\n .option(\"--app <appId>\", \"Override appId\")\n .option(\"--catalog <id>\", \"Override catalogId\")\n .option(\"--force-cache\", \"Invalidate nx-cache before running\")\n .action(\n async (opts: {\n dryRun?: boolean;\n verify?: boolean;\n pruneStale?: boolean;\n json?: boolean;\n verbose?: boolean;\n app?: string;\n catalog?: string;\n forceCache?: boolean;\n }) => {\n const verifyAfter = opts.verify !== false;\n\n try {\n const result = await runAiModelsCatalogSync({\n catalox: getCatalox(),\n firestore: getFirestore(),\n openRouterApiKey: process.env.OPENROUTER_API_KEY,\n appId: opts.app ?? envAppId(),\n catalogId: opts.catalog ?? envCatalogId(),\n dryRun: opts.dryRun,\n verbose: opts.verbose,\n forceCache: opts.forceCache,\n verifyAfter,\n pruneStale: opts.pruneStale,\n onProgress: opts.verbose\n ? ({ completed, total, phase }) => {\n console.log(`[sync] ${phase} ${completed}/${total}`);\n }\n : undefined,\n });\n\n if (opts.json) {\n emitJson(result);\n } else {\n emitHuman(formatSyncJobReport(result));\n }\n\n if (!result.ok) {\n process.exit(1);\n }\n } catch (error) {\n if (error instanceof CatalogSyncJobError) {\n const payload = {\n ok: false,\n sync: error.sync,\n verify: error.verify,\n };\n if (opts.json) {\n emitJson(payload);\n } else {\n emitHuman(formatSyncJobReport(payload));\n }\n process.exit(1);\n }\n throw error;\n }\n },\n );\n}\n"],"mappings":"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","names":["program","program","program","program","AiModelsCatalogClient","program"]}
1
+ {"version":3,"sources":["../../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"],"sourcesContent":["#!/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(\"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"],"mappings":"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","names":["program","program","program","program"]}
@@ -1,7 +1,23 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('../chunk-5GUKLOEK.cjs');
2
2
 
3
- var _chunkHN6UAQAEcjs = require('../chunk-HN6UAQAE.cjs');
4
3
 
5
4
 
6
- exports.CostCalculator = _chunkHN6UAQAEcjs.CostCalculator;
5
+
6
+
7
+
8
+
9
+
10
+ var _chunkNF2SKQR7cjs = require('../chunk-NF2SKQR7.cjs');
11
+ require('../chunk-EDMCKHO6.cjs');
12
+ require('../chunk-PADNCGZB.cjs');
13
+ require('../chunk-GS7T56RP.cjs');
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+ exports.CostCalculator = _chunkNF2SKQR7cjs.CostCalculator; exports.DEFAULT_OPENROUTER_MARKUP_RATE = _chunkNF2SKQR7cjs.DEFAULT_OPENROUTER_MARKUP_RATE; exports.MODEL_FIELD_PRIORITY = _chunkNF2SKQR7cjs.MODEL_FIELD_PRIORITY; exports.enrichCostResult = _chunkNF2SKQR7cjs.enrichCostResult; exports.extractUsageInput = _chunkNF2SKQR7cjs.extractUsageInput; exports.resolveUsageModel = _chunkNF2SKQR7cjs.resolveUsageModel; exports.toCostExtraction = _chunkNF2SKQR7cjs.toCostExtraction;
7
23
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/cost/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACF,yDAA8B;AAC9B;AACE;AACF,0DAAC","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/cost/index.cjs"}
1
+ {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/cost/index.cjs"],"names":[],"mappings":"AAAA,0GAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B,iCAA8B;AAC9B,iCAA8B;AAC9B,iCAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACF,4dAAC","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/cost/index.cjs"}