@x12i/ai-tools 1.0.4 → 2.0.1

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 (162) 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-5IZ7PLY2.cjs +51 -0
  21. package/dist/chunk-5IZ7PLY2.cjs.map +1 -0
  22. package/dist/chunk-5XAAMBDO.cjs +1988 -0
  23. package/dist/chunk-5XAAMBDO.cjs.map +1 -0
  24. package/dist/chunk-6BQBKROR.js +95 -0
  25. package/dist/chunk-6BQBKROR.js.map +1 -0
  26. package/dist/chunk-AB5GNXJ4.js +46 -0
  27. package/dist/chunk-AB5GNXJ4.js.map +1 -0
  28. package/dist/{chunk-O2A6OVEH.js → chunk-ANVONYJF.js} +2 -2
  29. package/dist/{chunk-O2A6OVEH.js.map → chunk-ANVONYJF.js.map} +1 -1
  30. package/dist/chunk-B3V2EHRY.js +225 -0
  31. package/dist/chunk-B3V2EHRY.js.map +1 -0
  32. package/dist/{chunk-QWAX7VQO.cjs → chunk-BAHBDADJ.cjs} +11 -11
  33. package/dist/{chunk-QWAX7VQO.cjs.map → chunk-BAHBDADJ.cjs.map} +1 -1
  34. package/dist/chunk-CTM35DMA.js +948 -0
  35. package/dist/chunk-CTM35DMA.js.map +1 -0
  36. package/dist/{chunk-TF4L2NEC.cjs → chunk-DXZOL3VN.cjs} +62 -313
  37. package/dist/chunk-DXZOL3VN.cjs.map +1 -0
  38. package/dist/chunk-EDMCKHO6.cjs +225 -0
  39. package/dist/chunk-EDMCKHO6.cjs.map +1 -0
  40. package/dist/{chunk-DJ5SWJDY.js → chunk-EYHMQVAL.js} +48 -299
  41. package/dist/chunk-EYHMQVAL.js.map +1 -0
  42. package/dist/chunk-GS7T56RP.cjs +8 -0
  43. package/dist/chunk-GS7T56RP.cjs.map +1 -0
  44. package/dist/chunk-OPN6BGNH.js +1985 -0
  45. package/dist/chunk-OPN6BGNH.js.map +1 -0
  46. package/dist/{chunk-7Q742NI3.cjs → chunk-PADNCGZB.cjs} +17 -3
  47. package/dist/chunk-PADNCGZB.cjs.map +1 -0
  48. package/dist/chunk-PRCICORG.cjs +95 -0
  49. package/dist/chunk-PRCICORG.cjs.map +1 -0
  50. package/dist/{chunk-6QGDZTGH.js → chunk-SIH4GPV4.js} +4 -29
  51. package/dist/chunk-SIH4GPV4.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-WOHMHXRZ.cjs +951 -0
  55. package/dist/chunk-WOHMHXRZ.cjs.map +1 -0
  56. package/dist/chunk-XAWBTX3N.cjs +46 -0
  57. package/dist/chunk-XAWBTX3N.cjs.map +1 -0
  58. package/dist/{chunk-AV6OE2YQ.cjs → chunk-XOKUDUUI.cjs} +14 -39
  59. package/dist/chunk-XOKUDUUI.cjs.map +1 -0
  60. package/dist/chunk-YQDSN6R6.cjs +86 -0
  61. package/dist/chunk-YQDSN6R6.cjs.map +1 -0
  62. package/dist/chunk-YQVY7CWT.js +51 -0
  63. package/dist/chunk-YQVY7CWT.js.map +1 -0
  64. package/dist/cli/index.cjs +59 -201
  65. package/dist/cli/index.cjs.map +1 -1
  66. package/dist/cli/index.js +53 -198
  67. package/dist/cli/index.js.map +1 -1
  68. package/dist/cost/index.cjs +19 -3
  69. package/dist/cost/index.cjs.map +1 -1
  70. package/dist/cost/index.d.cts +10 -50
  71. package/dist/cost/index.d.ts +10 -50
  72. package/dist/cost/index.js +18 -3
  73. package/dist/index.cjs +36 -14
  74. package/dist/index.cjs.map +1 -1
  75. package/dist/index.d.cts +15 -13
  76. package/dist/index.d.ts +15 -13
  77. package/dist/index.js +56 -35
  78. package/dist/modelCache-BzRn6t_C.d.ts +113 -0
  79. package/dist/modelCache-CJftI-Ko.d.cts +113 -0
  80. package/dist/{modelNameResolver-DqFt7g6W.d.ts → modelNameResolver-5XkBMctP.d.ts} +2 -6
  81. package/dist/{modelNameResolver-D9V_GfUK.d.cts → modelNameResolver-C5CSTGFF.d.cts} +2 -6
  82. package/dist/models/index.cjs +9 -6
  83. package/dist/models/index.cjs.map +1 -1
  84. package/dist/models/index.d.cts +9 -31
  85. package/dist/models/index.d.ts +9 -31
  86. package/dist/models/index.js +9 -7
  87. package/dist/profiles/index.cjs +18 -0
  88. package/dist/profiles/index.cjs.map +1 -0
  89. package/dist/profiles/index.d.cts +40 -0
  90. package/dist/profiles/index.d.ts +40 -0
  91. package/dist/profiles/index.js +17 -0
  92. package/dist/resolveUsageModel-BFwf80Hz.d.ts +140 -0
  93. package/dist/resolveUsageModel-C_YmGR1M.d.cts +140 -0
  94. package/dist/sync/index.cjs +7 -9
  95. package/dist/sync/index.cjs.map +1 -1
  96. package/dist/sync/index.d.cts +3 -8
  97. package/dist/sync/index.d.ts +3 -8
  98. package/dist/sync/index.js +8 -11
  99. package/dist/toolbox/index.cjs +1 -0
  100. package/dist/toolbox/index.cjs.map +1 -1
  101. package/dist/types-BrzJWsTU.d.cts +277 -0
  102. package/dist/types-BrzJWsTU.d.ts +277 -0
  103. package/package.json +14 -20
  104. package/src/data/models-catalog.json +670 -0
  105. package/src/data/openrouter-models-catalog.json +857 -0
  106. package/dist/AiModelsCatalogClient-4RF5BCDL.cjs +0 -9
  107. package/dist/AiModelsCatalogClient-4RF5BCDL.cjs.map +0 -1
  108. package/dist/AiModelsCatalogClient-CNeqFiFs.d.cts +0 -30
  109. package/dist/AiModelsCatalogClient-NUF3CBLW.js +0 -9
  110. package/dist/AiModelsCatalogClient-nwFoEaqL.d.ts +0 -30
  111. package/dist/catalox/index.cjs +0 -21
  112. package/dist/catalox/index.cjs.map +0 -1
  113. package/dist/catalox/index.d.cts +0 -11
  114. package/dist/catalox/index.d.ts +0 -11
  115. package/dist/catalox/index.js +0 -21
  116. package/dist/chunk-4NAY6HRP.js.map +0 -1
  117. package/dist/chunk-6QGDZTGH.js.map +0 -1
  118. package/dist/chunk-7Q742NI3.cjs.map +0 -1
  119. package/dist/chunk-AJEKEWWB.js.map +0 -1
  120. package/dist/chunk-AV6OE2YQ.cjs.map +0 -1
  121. package/dist/chunk-C3H7RTFR.cjs +0 -1
  122. package/dist/chunk-C3H7RTFR.cjs.map +0 -1
  123. package/dist/chunk-DJ5SWJDY.js.map +0 -1
  124. package/dist/chunk-DKHGWHXP.cjs +0 -169
  125. package/dist/chunk-DKHGWHXP.cjs.map +0 -1
  126. package/dist/chunk-F2F4UEFD.cjs +0 -75
  127. package/dist/chunk-F2F4UEFD.cjs.map +0 -1
  128. package/dist/chunk-FGP3QXWL.cjs +0 -163
  129. package/dist/chunk-FGP3QXWL.cjs.map +0 -1
  130. package/dist/chunk-G2G4KSC5.js +0 -30
  131. package/dist/chunk-G2G4KSC5.js.map +0 -1
  132. package/dist/chunk-HN6UAQAE.cjs +0 -83
  133. package/dist/chunk-HN6UAQAE.cjs.map +0 -1
  134. package/dist/chunk-HS74X2OJ.cjs +0 -172
  135. package/dist/chunk-HS74X2OJ.cjs.map +0 -1
  136. package/dist/chunk-HYGXZY25.js +0 -163
  137. package/dist/chunk-HYGXZY25.js.map +0 -1
  138. package/dist/chunk-KQOALKKX.js +0 -75
  139. package/dist/chunk-KQOALKKX.js.map +0 -1
  140. package/dist/chunk-LYOU7CA2.cjs +0 -30
  141. package/dist/chunk-LYOU7CA2.cjs.map +0 -1
  142. package/dist/chunk-M5TMA73F.js +0 -1
  143. package/dist/chunk-M5TMA73F.js.map +0 -1
  144. package/dist/chunk-MX3AMQFC.js +0 -172
  145. package/dist/chunk-MX3AMQFC.js.map +0 -1
  146. package/dist/chunk-QCRLKVB3.cjs +0 -137
  147. package/dist/chunk-QCRLKVB3.cjs.map +0 -1
  148. package/dist/chunk-TF4L2NEC.cjs.map +0 -1
  149. package/dist/chunk-VRFVF5RH.js +0 -169
  150. package/dist/chunk-VRFVF5RH.js.map +0 -1
  151. package/dist/chunk-YHO57D2V.js +0 -83
  152. package/dist/chunk-YHO57D2V.js.map +0 -1
  153. package/dist/syncAiModelsCatalog-CnXRLm2c.d.cts +0 -32
  154. package/dist/syncAiModelsCatalog-DpkN_w7S.d.ts +0 -32
  155. package/dist/types-BYXnCvKx.d.cts +0 -137
  156. package/dist/types-BYXnCvKx.d.ts +0 -137
  157. package/dist/types-CX6QFNNy.d.cts +0 -144
  158. package/dist/types-CuiPDcVs.d.ts +0 -144
  159. package/dist/upsertAiModelRecord-C831wOIF.d.ts +0 -35
  160. package/dist/upsertAiModelRecord-CjY-sny0.d.cts +0 -35
  161. /package/dist/{AiModelsCatalogClient-NUF3CBLW.js.map → chunk-56R4XA2S.js.map} +0 -0
  162. /package/dist/{catalox → profiles}/index.js.map +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-QCRLKVB3.cjs","../src/models/filterModels.ts","../src/models/AiModelsService.ts"],"names":[],"mappings":"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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-QCRLKVB3.cjs","sourcesContent":[null,"import type { AiModelRecord, ModelListFilters } from \"./types.js\";\n\nfunction matchesSearch(record: AiModelRecord, search: string): boolean {\n const q = search.toLowerCase();\n return (\n record.modelId.toLowerCase().includes(q) ||\n record.name.toLowerCase().includes(q) ||\n record.description.toLowerCase().includes(q) ||\n record.canonicalSlug.toLowerCase().includes(q) ||\n record.aliases.some((a) => a.toLowerCase().includes(q))\n );\n}\n\nexport function filterModels(\n models: Iterable<AiModelRecord>,\n filters: ModelListFilters = {},\n): AiModelRecord[] {\n let list = [...models];\n\n if (filters.providerId) {\n list = list.filter((m) => m.providerId === filters.providerId);\n }\n if (filters.status) {\n list = list.filter((m) => m.status === filters.status);\n }\n if (filters.outputModality) {\n list = list.filter((m) => m.outputModalities.includes(filters.outputModality!));\n }\n if (filters.inputModality) {\n list = list.filter((m) => m.inputModalities.includes(filters.inputModality!));\n }\n if (filters.supportedParameter) {\n list = list.filter((m) => m.supportedParameters.includes(filters.supportedParameter!));\n }\n if (filters.supportsTools !== undefined) {\n list = list.filter((m) => m.supportsTools === filters.supportsTools);\n }\n if (filters.supportsReasoning !== undefined) {\n list = list.filter((m) => m.supportsReasoning === filters.supportsReasoning);\n }\n if (filters.search) {\n list = list.filter((m) => matchesSearch(m, filters.search!));\n }\n\n list.sort((a, b) => a.name.localeCompare(b.name));\n\n const offset = filters.offset ?? 0;\n const limit = filters.limit ?? list.length;\n return list.slice(offset, offset + limit);\n}\n\nexport function countModels(\n models: Iterable<AiModelRecord>,\n filters: Omit<ModelListFilters, \"limit\" | \"offset\"> = {},\n): number {\n return filterModels(models, { ...filters, limit: Number.MAX_SAFE_INTEGER, offset: 0 }).length;\n}\n","import type { Catalox, CataloxContext } from \"@x12i/catalox\";\nimport type { CatalogQueryOptions } from \"@x12i/catalox\";\nimport { AiModelsCatalogClient } from \"../catalox/AiModelsCatalogClient.js\";\nimport { countModels, filterModels } from \"./filterModels.js\";\nimport type { AiModelRecord, ModelListFilters, ModelListResult } from \"./types.js\";\n\nexport type AiModelsServiceOptions = {\n catalox: Catalox;\n appId?: string;\n catalogId?: string;\n cacheTtlMs?: number;\n};\n\n/**\n * High-level model catalog API — list, filter, count, and get full model info.\n */\nexport class AiModelsService {\n private readonly client: AiModelsCatalogClient;\n private readonly catalox: Catalox;\n private readonly appId: string;\n private readonly catalogId: string;\n\n constructor(options: AiModelsServiceOptions) {\n this.catalox = options.catalox;\n this.client = new AiModelsCatalogClient(options);\n this.appId = options.appId ?? \"ai-tools\";\n this.catalogId = options.catalogId ?? \"ai-models\";\n }\n\n private context(): CataloxContext {\n return { appId: this.appId, superAdmin: true };\n }\n\n /** Load all models (cached). */\n async getAllModels(): Promise<Map<string, AiModelRecord>> {\n return this.client.getAllModels();\n }\n\n /** List models with in-memory filters (fast after cache warm). */\n async listModels(filters: ModelListFilters = {}): Promise<ModelListResult> {\n const all = await this.getAllModels();\n const total = countModels(all.values(), filters);\n const limit = filters.limit ?? 50;\n const offset = filters.offset ?? 0;\n const models = filterModels(all.values(), { ...filters, limit, offset });\n return { models, total, limit, offset };\n }\n\n /** Count models matching filters. */\n async countModels(filters: Omit<ModelListFilters, \"limit\" | \"offset\"> = {}): Promise<number> {\n const all = await this.getAllModels();\n return countModels(all.values(), filters);\n }\n\n /**\n * Full model record by id or alias (same resolution as cost calculator).\n */\n async getModelInfo(modelIdOrAlias: string): Promise<AiModelRecord | null> {\n return this.client.getModel(modelIdOrAlias);\n }\n\n /**\n * Query via Catalox indexed fields (provider, status, output modality, tools).\n * Falls back to in-memory filter when Catalox returns partial pages.\n */\n async listModelsFromCatalog(\n filters: ModelListFilters = {},\n options?: CatalogQueryOptions,\n ): Promise<ModelListResult> {\n const filter: Record<string, unknown> = {};\n if (filters.providerId) filter.providerId = filters.providerId;\n if (filters.status) filter.status = filters.status;\n if (filters.outputModality) filter.primaryOutputModality = filters.outputModality;\n if (filters.supportsTools !== undefined) filter.supportsTools = filters.supportsTools;\n if (filters.supportsReasoning !== undefined) {\n filter.supportsReasoning = filters.supportsReasoning;\n }\n\n const limit = filters.limit ?? 50;\n const result = await this.catalox.listCatalogItems(this.context(), this.catalogId, {\n limit: Math.min(limit, 10_000),\n filter,\n ...options,\n });\n\n let models = result.items.map((item) => item.data as unknown as AiModelRecord);\n\n if (filters.supportedParameter) {\n models = models.filter((m) => m.supportedParameters?.includes(filters.supportedParameter!));\n }\n if (filters.inputModality) {\n models = models.filter((m) => m.inputModalities?.includes(filters.inputModality!));\n }\n if (filters.search) {\n models = filterModels(models, { search: filters.search });\n }\n\n return {\n models,\n total: models.length,\n limit,\n offset: filters.offset ?? 0,\n };\n }\n\n async resolve(\n modelIdOrAlias: string,\n provider?: string,\n ): Promise<import(\"../sync/modelNameResolver/types.js\").ModelResolutionResult> {\n return this.client.resolveModel({ model: modelIdOrAlias, provider });\n }\n\n async refresh(): Promise<void> {\n await this.client.refresh();\n }\n}\n\n/** Convenience: getModelInfo */\nexport async function getModelInfo(\n service: AiModelsService,\n modelIdOrAlias: string,\n): Promise<AiModelRecord | null> {\n return service.getModelInfo(modelIdOrAlias);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-TF4L2NEC.cjs","../src/cache/modelCache.ts","../src/catalog/aiModelsCatalogDescriptor.ts","../src/sync/openRouterRoutingEnv.ts","../src/sync/modelNameResolver/constants.ts","../src/sync/modelNameResolver/normalize.ts","../src/sync/modelNameResolver/catalogIndexes.ts","../src/sync/modelNameResolver/ModelNameResolver.ts"],"names":[],"mappings":"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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-TF4L2NEC.cjs","sourcesContent":[null,"import { createNxCache } from \"nx-cache\";\nimport type { AiModelRecord } from \"../cost/types.js\";\n\nconst cache = createNxCache<Map<string, AiModelRecord>, { cachedAt: string; count: number }>();\n\nexport const DEFAULT_MODEL_CACHE_TTL_MS = 60 * 60 * 1000;\n\nexport type ModelCacheMetadata = { cachedAt: string; count: number };\n\nexport function readCachedModels(\n appId: string,\n ttlMs = DEFAULT_MODEL_CACHE_TTL_MS,\n): Map<string, AiModelRecord> | null {\n const res = cache.read(\"ai-models\", { appId });\n if (!res.found) return null;\n\n const cachedAt = res.metadata?.cachedAt;\n if (cachedAt) {\n const age = Date.now() - new Date(cachedAt).getTime();\n if (age > ttlMs) return null;\n } else if (res.meta.isExpired) {\n return null;\n }\n\n return res.value;\n}\n\nexport function writeCachedModels(\n appId: string,\n models: Map<string, AiModelRecord>,\n ttlMs = DEFAULT_MODEL_CACHE_TTL_MS,\n): void {\n cache.write(\"ai-models\", models, {\n scope: { appId },\n ttlMs,\n metadata: { cachedAt: new Date().toISOString(), count: models.size },\n });\n}\n\nexport function invalidateModelsCache(appId: string): void {\n cache.resetKey(\"ai-models\", { appId });\n}\n","import type { CatalogDescriptor } from \"@x12i/catalox\";\n\nexport const AI_MODELS_CATALOG_ID = \"ai-models\";\nexport const AI_TOOLS_APP_ID = \"ai-tools\";\n\nexport const AI_MODELS_DESCRIPTOR: CatalogDescriptor = {\n catalogId: AI_MODELS_CATALOG_ID,\n label: \"AI Models\",\n description:\n \"Full mirror of OpenRouter Models API metadata and pricing, synced on a schedule.\",\n itemLabel: \"Model\",\n sourceMode: \"native\",\n status: \"active\",\n visibility: \"visible\",\n capabilities: {\n canList: true,\n canGet: true,\n canCreate: false,\n canEdit: false,\n canDelete: false,\n canExport: true,\n canValidate: true,\n },\n identity: {\n itemIdStrategy: \"natural\",\n itemIdField: \"modelId\",\n titleField: \"name\",\n subtitleField: \"providerId\",\n statusField: \"status\",\n updatedAtField: \"syncedAt\",\n },\n queryableFields: [\n { key: \"modelId\", label: \"Model ID\", type: \"string\", indexed: true, filterable: true },\n { key: \"providerId\", label: \"Provider\", type: \"string\", indexed: true, filterable: true },\n { key: \"name\", label: \"Name\", type: \"string\", filterable: true },\n { key: \"canonicalSlug\", label: \"Canonical Slug\", type: \"string\", indexed: true, filterable: true },\n { key: \"contextLength\", label: \"Context Length\", type: \"number\", sortable: true },\n {\n key: \"status\",\n label: \"Status\",\n type: \"enum\",\n indexed: true,\n filterable: true,\n enumValues: [\"active\", \"deprecated\", \"unknown\"],\n },\n {\n key: \"primaryOutputModality\",\n label: \"Primary Output\",\n type: \"string\",\n indexed: true,\n filterable: true,\n },\n { key: \"supportsTools\", label: \"Tools\", type: \"boolean\", indexed: true, filterable: true },\n {\n key: \"supportsReasoning\",\n label: \"Reasoning\",\n type: \"boolean\",\n indexed: true,\n filterable: true,\n },\n { key: \"supportsStreaming\", label: \"Streams\", type: \"boolean\", filterable: true },\n { key: \"isModerated\", label: \"Moderated\", type: \"boolean\", filterable: true },\n { key: \"syncedAt\", label: \"Synced At\", type: \"datetime\", sortable: true },\n ],\n defaultSort: { field: \"syncedAt\", direction: \"desc\" },\n};\n","import { loadDotenv } from \"@x12i/env\";\n\n/**\n * Env naming for vendor direct API keys: `{VENDOR}_API_KEY`\n * where VENDOR is the provider id in UPPER_SNAKE (hyphens → underscores).\n *\n * Examples: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `META_LLAMA_API_KEY`, `X_AI_API_KEY`\n */\nexport function providerIdToEnvKeyPrefix(providerId: string): string {\n return providerId\n .trim()\n .toLowerCase()\n .replace(/-/g, \"_\")\n .toUpperCase();\n}\n\nexport function vendorApiKeyEnvName(providerId: string): string {\n return `${providerIdToEnvKeyPrefix(providerId)}_API_KEY`;\n}\n\nexport type OpenRouterRoutingConfig = {\n /** OPENROUTER_API_KEY is set and non-empty */\n hasOpenRouterKey: boolean;\n /** USE_OPENROUTER=true or USE_OPENROUTER=1 */\n useOpenRouterExplicit: boolean;\n /** Read `{PROVIDER}_API_KEY` for a catalog provider id */\n getVendorApiKey(providerId: string): string | undefined;\n};\n\n/**\n * Load routing hints from process env and optional `.env` (via @x12/env).\n */\nexport function loadOpenRouterRoutingEnv(\n env: Record<string, string | undefined> = process.env,\n): OpenRouterRoutingConfig {\n const dotenv = loadDotenv();\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(dotenv)) {\n if (v !== undefined) merged[k] = v;\n }\n for (const [k, v] of Object.entries(env)) {\n if (v !== undefined) merged[k] = v;\n }\n\n const openRouterKey = merged.OPENROUTER_API_KEY?.trim();\n const useRaw = merged.USE_OPENROUTER?.trim().toLowerCase();\n const useOpenRouterExplicit = useRaw === \"true\" || useRaw === \"1\";\n\n return {\n hasOpenRouterKey: Boolean(openRouterKey),\n useOpenRouterExplicit,\n getVendorApiKey(providerId: string) {\n const name = vendorApiKeyEnvName(providerId);\n const val = merged[name]?.trim();\n return val || undefined;\n },\n };\n}\n\n/**\n * Default route via OpenRouter when:\n * 1. OPENROUTER_API_KEY is set AND USE_OPENROUTER=true|1, or\n * 2. OPENROUTER_API_KEY is set AND the vendor's `{VENDOR}_API_KEY` is missing.\n */\nexport function shouldDefaultRouteViaOpenRouter(\n providerId: string | undefined,\n config: OpenRouterRoutingConfig,\n): boolean {\n if (!config.hasOpenRouterKey) return false;\n if (config.useOpenRouterExplicit) return true;\n if (providerId && providerId !== \"openrouter\") {\n return !config.getVendorApiKey(providerId);\n }\n return false;\n}\n","export const DEFAULT_CONFIDENCE_THRESHOLD = 0.6;\n\nexport const PROVIDER_NORMALISATION_MAP: Record<string, string> = {\n \"open-router\": \"openrouter\",\n or: \"openrouter\",\n oai: \"openai\",\n \"open-ai\": \"openai\",\n claude: \"anthropic\",\n ant: \"anthropic\",\n gemini: \"google\",\n gcp: \"google\",\n \"google-ai\": \"google\",\n vertex: \"google\",\n meta: \"meta-llama\",\n llama: \"meta-llama\",\n \"mistral-ai\": \"mistral\",\n \"cohere-ai\": \"cohere\",\n};\n\nexport const LOCAL_PROVIDERS = new Set([\n \"ollama\",\n \"lmstudio\",\n \"lm-studio\",\n \"localai\",\n \"local-ai\",\n \"llamacpp\",\n \"llama.cpp\",\n \"llamafile\",\n \"jan\",\n \"koboldcpp\",\n]);\n\nexport const PROVIDER_INFERENCE_MAP: Array<{\n pattern: RegExp;\n provider: string;\n notes?: string;\n}> = [\n { pattern: /^gpt-/, provider: \"openai\" },\n { pattern: /^o1($|-)/, provider: \"openai\" },\n { pattern: /^o3($|-)/, provider: \"openai\" },\n { pattern: /^o4($|-)/, provider: \"openai\" },\n { pattern: /^chatgpt-/, provider: \"openai\" },\n { pattern: /^text-davinci/, provider: \"openai\" },\n { pattern: /^dall-e/, provider: \"openai\" },\n { pattern: /^whisper/, provider: \"openai\" },\n { pattern: /^tts-/, provider: \"openai\" },\n { pattern: /^claude-/, provider: \"anthropic\" },\n { pattern: /^gemini-/, provider: \"google\" },\n { pattern: /^palm-/, provider: \"google\" },\n { pattern: /^bison/, provider: \"google\" },\n { pattern: /^llama-?[23]/, provider: \"meta-llama\" },\n { pattern: /^llama/, provider: \"meta-llama\" },\n { pattern: /^codellama/, provider: \"meta-llama\" },\n { pattern: /^mistral-/, provider: \"mistral\" },\n { pattern: /^mixtral-/, provider: \"mistral\" },\n { pattern: /^codestral/, provider: \"mistral\" },\n { pattern: /^ministral/, provider: \"mistral\" },\n { pattern: /^command-/, provider: \"cohere\" },\n { pattern: /^c4ai-/, provider: \"cohere\" },\n { pattern: /^deepseek-/, provider: \"deepseek\" },\n { pattern: /^grok-/, provider: \"x-ai\" },\n { pattern: /^qwen/, provider: \"qwen\" },\n { pattern: /^yi-/, provider: \"01-ai\" },\n { pattern: /^sonar/, provider: \"perplexity\" },\n { pattern: /^pplx-/, provider: \"perplexity\" },\n { pattern: /^titan-/, provider: \"amazon\" },\n { pattern: /^nova-/, provider: \"amazon\" },\n];\n\nexport const SHORTHAND_MAP: Record<string, string> = {\n gpt4: \"openai/gpt-4\",\n gpt4o: \"openai/gpt-4o\",\n \"gpt-4-omni\": \"openai/gpt-4o\",\n gpt4omni: \"openai/gpt-4o\",\n \"gpt4-turbo\": \"openai/gpt-4-turbo\",\n gpt4turbo: \"openai/gpt-4-turbo\",\n \"gpt4-mini\": \"openai/gpt-4o-mini\",\n \"gpt-4o-mini\": \"openai/gpt-4o-mini\",\n o1: \"openai/o1\",\n \"o1-mini\": \"openai/o1-mini\",\n o3: \"openai/o3\",\n \"o3-mini\": \"openai/o3-mini\",\n \"o4-mini\": \"openai/o4-mini\",\n \"3.5-turbo\": \"openai/gpt-3.5-turbo\",\n gpt35: \"openai/gpt-3.5-turbo\",\n gpt3: \"openai/gpt-3.5-turbo\",\n claude3: \"anthropic/claude-3-5-sonnet-20241022\",\n \"claude-3\": \"anthropic/claude-3-5-sonnet-20241022\",\n \"claude3-sonnet\": \"anthropic/claude-3-5-sonnet-20241022\",\n \"claude-sonnet\": \"anthropic/claude-3-5-sonnet-20241022\",\n \"claude-haiku\": \"anthropic/claude-3-5-haiku-20241022\",\n \"claude3-haiku\": \"anthropic/claude-3-5-haiku-20241022\",\n \"claude-opus\": \"anthropic/claude-opus-4\",\n \"claude3-opus\": \"anthropic/claude-3-opus-20240229\",\n claude4: \"anthropic/claude-opus-4\",\n \"claude4-sonnet\": \"anthropic/claude-sonnet-4\",\n \"claude4-opus\": \"anthropic/claude-opus-4\",\n sonnet: \"anthropic/claude-3-5-sonnet-20241022\",\n haiku: \"anthropic/claude-3-5-haiku-20241022\",\n opus: \"anthropic/claude-opus-4\",\n gemini: \"google/gemini-pro\",\n \"gemini-pro\": \"google/gemini-pro\",\n \"gemini-flash\": \"google/gemini-flash-1.5\",\n gemini2: \"google/gemini-2.0-flash-001\",\n \"gemini-2\": \"google/gemini-2.0-flash-001\",\n llama3: \"meta-llama/llama-3.1-8b-instruct\",\n \"llama-3\": \"meta-llama/llama-3.1-8b-instruct\",\n llama2: \"meta-llama/llama-2-13b-chat\",\n \"llama-2\": \"meta-llama/llama-2-13b-chat\",\n mistral: \"mistral/mistral-7b-instruct\",\n \"mistral-large\": \"mistral/mistral-large-latest\",\n mixtral: \"mistral/mixtral-8x7b-instruct\",\n deepseek: \"deepseek/deepseek-chat\",\n \"deepseek-r1\": \"deepseek/deepseek-r1\",\n};\n","import { PROVIDER_NORMALISATION_MAP } from \"./constants.js\";\n\nexport function normalizeString(input: string): string {\n let s = input.trim();\n s = s.replace(/\\s+/g, \" \").replace(/ /g, \"-\");\n s = s.toLowerCase();\n s = s.replace(/^\\/+|\\/+$/g, \"\");\n s = s.replace(/\\/+/g, \"/\");\n if (\n (s.startsWith('\"') && s.endsWith('\"')) ||\n (s.startsWith(\"'\") && s.endsWith(\"'\"))\n ) {\n s = s.slice(1, -1);\n }\n return s;\n}\n\nexport function normalizeProvider(provider: string | undefined): string | undefined {\n if (provider === undefined || provider === \"\") return undefined;\n const n = normalizeString(provider);\n return PROVIDER_NORMALISATION_MAP[n] ?? n;\n}\n\nexport function tokenise(s: string): string[] {\n return s.split(/[-_./]+/).filter(Boolean);\n}\n\nexport function modelSlug(modelId: string): string {\n const slash = modelId.indexOf(\"/\");\n return slash >= 0 ? modelId.slice(slash + 1) : modelId;\n}\n","import type { AiModelRecord } from \"../../models/types.js\";\nimport { normalizeString } from \"./normalize.js\";\nimport type { CatalogIndexes } from \"./types.js\";\n\nexport function buildCatalogIndexes(catalog: Map<string, AiModelRecord>): CatalogIndexes {\n const aliasIndex = new Map<string, string>();\n const slugIndex = new Map<string, string>();\n const prefixCounts = new Map<string, number>();\n\n for (const record of catalog.values()) {\n for (const alias of record.aliases) {\n aliasIndex.set(normalizeString(alias), record.modelId);\n }\n if (record.canonicalSlug) {\n slugIndex.set(normalizeString(record.canonicalSlug), record.modelId);\n }\n const pid = record.providerId;\n prefixCounts.set(pid, (prefixCounts.get(pid) ?? 0) + 1);\n }\n\n const providerPrefixesBySize = [...prefixCounts.entries()]\n .sort((a, b) => b[1] - a[1])\n .map(([p]) => p);\n\n return { aliasIndex, slugIndex, providerPrefixesBySize };\n}\n","import { ModelResolutionError } from \"../../errors.js\";\nimport type { AiModelRecord } from \"../../models/types.js\";\nimport {\n loadOpenRouterRoutingEnv,\n shouldDefaultRouteViaOpenRouter,\n} from \"../openRouterRoutingEnv.js\";\nimport { buildCatalogIndexes } from \"./catalogIndexes.js\";\nimport {\n DEFAULT_CONFIDENCE_THRESHOLD,\n LOCAL_PROVIDERS,\n PROVIDER_INFERENCE_MAP,\n SHORTHAND_MAP,\n} from \"./constants.js\";\nimport { modelSlug, normalizeProvider, normalizeString, tokenise } from \"./normalize.js\";\nimport type {\n CatalogIndexes,\n ModelResolutionInput,\n ModelResolutionNotFound,\n ModelResolutionResult,\n ModelResolutionSuccess,\n ModelResolverOptions,\n ResolutionStrategy,\n ResolverContext,\n} from \"./types.js\";\n\ntype MatchCandidate = {\n modelId: string;\n record: AiModelRecord | null;\n confidence: number;\n strategy: ResolutionStrategy;\n reason: string;\n};\n\nconst VERSION_STRIP_PATTERNS: Array<{ re: RegExp; label: string }> = [\n { re: /-\\d{4}-\\d{2}-\\d{2}$/, label: \"date YYYY-MM-DD\" },\n { re: /-\\d{8}$/, label: \"date YYYYMMDD\" },\n { re: /-v\\d+$/, label: \"version -vN\" },\n { re: /-\\d+\\.\\d+\\.\\d+$/, label: \"semver\" },\n { re: /:\\d+[a-z]?$/i, label: \"colon version\" },\n { re: /-\\d{4,}$/, label: \"build number\" },\n { re: /@\\d+$/, label: \"epoch @NNNN\" },\n];\n\nexport class ModelNameResolver {\n private readonly catalog: Map<string, AiModelRecord>;\n private readonly indexes: CatalogIndexes;\n private readonly ctx: ResolverContext;\n\n constructor(\n catalog: Map<string, AiModelRecord>,\n options: ModelResolverOptions = {},\n ) {\n this.catalog = catalog;\n this.indexes = buildCatalogIndexes(catalog);\n this.ctx = {\n catalog,\n indexes: this.indexes,\n options: {\n confidenceThreshold: options.confidenceThreshold ?? DEFAULT_CONFIDENCE_THRESHOLD,\n aliasRegistry: options.aliasRegistry,\n additionalShorthands: options.additionalShorthands ?? {},\n additionalProviderPatterns: options.additionalProviderPatterns ?? [],\n additionalLocalProviders: options.additionalLocalProviders ?? [],\n routingEnv: options.routingEnv ?? loadOpenRouterRoutingEnv(),\n },\n };\n }\n\n resolve(input: ModelResolutionInput): ModelResolutionResult {\n const attempted: ResolutionStrategy[] = [];\n const threshold = this.ctx.options.confidenceThreshold;\n\n let provider = normalizeProvider(input.provider);\n let model = normalizeString(input.model);\n const normalisedInput = model;\n\n // S0 — alias registry on model string\n if (this.ctx.options.aliasRegistry) {\n attempted.push(\"alias-registry\");\n const entry = this.ctx.options.aliasRegistry.get(model);\n if (entry) {\n model = normalizeString(entry.modelId);\n provider = normalizeProvider(entry.provider) ?? provider;\n }\n }\n\n // Alias used as provider name (e.g. provider=\"best\")\n if (this.ctx.options.aliasRegistry && provider) {\n const aliasAsProvider = this.ctx.options.aliasRegistry.get(provider);\n if (aliasAsProvider) {\n attempted.push(\"alias-as-provider-correction\");\n model = normalizeString(aliasAsProvider.modelId);\n provider = normalizeProvider(aliasAsProvider.provider) ?? provider;\n }\n }\n\n // S10 — local provider (before catalog strategies)\n const localProviders = new Set([\n ...LOCAL_PROVIDERS,\n ...this.ctx.options.additionalLocalProviders.map((p) => normalizeString(p)),\n ]);\n if (provider && localProviders.has(provider)) {\n attempted.push(\"local-provider-passthrough\");\n return this.success({\n modelId: model,\n record: null,\n confidence: 0.99,\n strategy: \"local-provider-passthrough\",\n reason: `Local provider \"${provider}\" — model not looked up in catalog`,\n resolvedVia: attempted,\n normalisedInput,\n provider,\n originalProvider: input.provider,\n });\n }\n\n const preCorrection = [...attempted];\n\n const { match, rejected } = this.runPipeline(model, provider, attempted, threshold, []);\n if (match) {\n const via = [\n ...preCorrection.filter((s) => !match.resolvedVia.includes(s)),\n ...match.resolvedVia,\n ];\n return this.success({\n modelId: match.modelId,\n record: match.record,\n confidence: match.confidence,\n strategy: match.strategy,\n reason: match.reason,\n resolvedVia: via,\n normalisedInput,\n provider,\n originalProvider: input.provider,\n });\n }\n\n const notFound: ModelResolutionNotFound = {\n found: false,\n modelId: null,\n record: null,\n attemptedStrategies: attempted,\n reason: \"No catalog entry matched after all strategies.\",\n bestRejectedCandidate: rejected,\n };\n return notFound;\n }\n\n resolveMany(inputs: ModelResolutionInput[]): ModelResolutionResult[] {\n return inputs.map((i) => this.resolve(i));\n }\n\n resolveOrThrow(input: ModelResolutionInput): ModelResolutionSuccess {\n const result = this.resolve(input);\n if (result.found) return result;\n throw new ModelResolutionError(input, result);\n }\n\n private runPipeline(\n model: string,\n provider: string | undefined,\n attempted: ResolutionStrategy[],\n threshold: number,\n resolvedVia: ResolutionStrategy[],\n depth = 0,\n ): {\n match: (MatchCandidate & { resolvedVia: ResolutionStrategy[] }) | null;\n rejected?: ModelResolutionNotFound[\"bestRejectedCandidate\"];\n } {\n if (depth > 12) return { match: null };\n\n const tryMatch = (\n strategy: ResolutionStrategy,\n fn: () => MatchCandidate | null,\n ): (MatchCandidate & { resolvedVia: ResolutionStrategy[] }) | null => {\n if (!attempted.includes(strategy)) attempted.push(strategy);\n const m = fn();\n if (m && m.confidence >= threshold) {\n return { ...m, resolvedVia: [...resolvedVia, strategy] };\n }\n return null;\n };\n\n let hit = tryMatch(\"exact-match\", () => this.exactMatch(model));\n if (hit) return { match: hit };\n\n hit = tryMatch(\"catalog-alias-match\", () => this.catalogAliasMatch(model));\n if (hit) return { match: hit };\n\n hit = tryMatch(\"canonical-slug-match\", () => this.slugMatch(model));\n if (hit) return { match: hit };\n\n hit = tryMatch(\"provider-prefix-injection\", () =>\n this.providerPrefixInjection(model, provider),\n );\n if (hit) return { match: hit };\n\n hit = tryMatch(\"cross-provider-correction\", () => this.crossProviderCorrection(model));\n if (hit) return { match: hit };\n\n const stripped = this.stripVersionSuffixes(model);\n if (stripped && stripped !== model) {\n if (!attempted.includes(\"version-suffix-strip\")) attempted.push(\"version-suffix-strip\");\n const inner = this.runPipeline(\n stripped,\n provider,\n attempted,\n threshold,\n [...resolvedVia, \"version-suffix-strip\"],\n depth + 1,\n );\n if (inner.match) {\n return {\n match: {\n ...inner.match,\n confidence: 0.85,\n strategy: \"version-suffix-strip\",\n reason: `Stripped version suffix from \"${model}\" → \"${stripped}\" then ${inner.match.reason}`,\n resolvedVia: [...resolvedVia, \"version-suffix-strip\", ...inner.match.resolvedVia],\n },\n };\n }\n }\n\n hit = tryMatch(\"date-suffix-strip\", () => this.dateSuffixMatch(model));\n if (hit) return { match: hit };\n\n const shorthand = this.shorthandMap()[model];\n if (shorthand) {\n if (!attempted.includes(\"shorthand-expansion\")) attempted.push(\"shorthand-expansion\");\n const inner = this.runPipeline(\n normalizeString(shorthand),\n provider,\n attempted,\n threshold,\n [...resolvedVia, \"shorthand-expansion\"],\n depth + 1,\n );\n if (inner.match) {\n return {\n match: {\n ...inner.match,\n confidence: 0.8,\n strategy: \"shorthand-expansion\",\n reason: `Expanded shorthand \"${model}\" → \"${shorthand}\" then ${inner.match.reason}`,\n resolvedVia: [...resolvedVia, \"shorthand-expansion\", ...inner.match.resolvedVia],\n },\n };\n }\n }\n\n const partial = this.partialMatch(model, provider);\n if (partial) {\n if (!attempted.includes(\"partial-name-match\")) attempted.push(\"partial-name-match\");\n if (partial.confidence >= threshold) {\n return {\n match: { ...partial, resolvedVia: [...resolvedVia, \"partial-name-match\"] },\n };\n }\n return {\n match: null,\n rejected: {\n modelId: partial.modelId,\n confidence: partial.confidence,\n reason: partial.reason,\n },\n };\n }\n\n return { match: null };\n }\n\n private exactMatch(model: string): MatchCandidate | null {\n const record = this.catalog.get(model);\n if (!record) return null;\n return {\n modelId: model,\n record,\n confidence: 1,\n strategy: \"exact-match\",\n reason: `Exact catalog match for \"${model}\"`,\n };\n }\n\n private catalogAliasMatch(model: string): MatchCandidate | null {\n const modelId = this.indexes.aliasIndex.get(model);\n if (!modelId) return null;\n const record = this.catalog.get(modelId);\n if (!record) return null;\n return {\n modelId,\n record,\n confidence: 1,\n strategy: \"catalog-alias-match\",\n reason: `Catalog alias \"${model}\" → \"${modelId}\"`,\n };\n }\n\n private slugMatch(model: string): MatchCandidate | null {\n const modelId = this.indexes.slugIndex.get(model);\n if (!modelId) return null;\n const record = this.catalog.get(modelId);\n if (!record) return null;\n return {\n modelId,\n record,\n confidence: 0.95,\n strategy: \"canonical-slug-match\",\n reason: `Canonical slug match \"${model}\" → \"${modelId}\"`,\n };\n }\n\n private inferProviderFromSlug(slug: string): string | undefined {\n const patterns = [\n ...this.ctx.options.additionalProviderPatterns,\n ...PROVIDER_INFERENCE_MAP,\n ];\n for (const { pattern, provider } of patterns) {\n if (pattern.test(slug)) return provider;\n }\n return undefined;\n }\n\n private providerPrefixInjection(\n model: string,\n provider: string | undefined,\n ): MatchCandidate | null {\n if (model.includes(\"/\")) return null;\n\n const prefixes: string[] = [];\n if (provider && provider !== \"openrouter\") {\n prefixes.push(provider);\n }\n const inferred = this.inferProviderFromSlug(model);\n if (inferred && !prefixes.includes(inferred)) prefixes.push(inferred);\n for (const p of this.indexes.providerPrefixesBySize) {\n if (!prefixes.includes(p)) prefixes.push(p);\n }\n\n for (const prefix of prefixes) {\n const candidate = `${prefix}/${model}`;\n let record = this.catalog.get(candidate);\n let modelId = candidate;\n if (!record) {\n const latest = this.findLatestVersioned(candidate);\n if (latest) {\n record = latest.record;\n modelId = latest.modelId;\n }\n }\n if (record) {\n const viaInference = inferred === prefix;\n return {\n modelId,\n record,\n confidence: 0.95,\n strategy: \"provider-prefix-injection\",\n reason: viaInference\n ? `Injected provider prefix \"${prefix}/\" inferred from model name pattern`\n : `Injected provider prefix \"${prefix}/\"`,\n };\n }\n }\n return null;\n }\n\n private crossProviderCorrection(model: string): MatchCandidate | null {\n if (!model.includes(\"/\")) return null;\n const [wrongPrefix, ...rest] = model.split(\"/\");\n const slug = rest.join(\"/\");\n const inferred = this.inferProviderFromSlug(slug);\n if (!inferred || inferred === wrongPrefix) return null;\n const candidate = `${inferred}/${slug}`;\n let record = this.catalog.get(candidate);\n let modelId = candidate;\n if (!record) {\n const latest = this.findLatestVersioned(candidate);\n if (!latest) return null;\n record = latest.record;\n modelId = latest.modelId;\n }\n return {\n modelId,\n record,\n confidence: 0.9,\n strategy: \"cross-provider-correction\",\n reason: `Corrected provider prefix from \"${wrongPrefix}\" to \"${inferred}\" based on model name pattern`,\n };\n }\n\n private stripVersionSuffixes(model: string): string | null {\n for (const { re } of VERSION_STRIP_PATTERNS) {\n if (re.test(model)) {\n return model.replace(re, \"\");\n }\n }\n return null;\n }\n\n private dateSuffixMatch(model: string): MatchCandidate | null {\n if (model.includes(\"/\")) {\n const [prefix, slug] = model.split(\"/\", 2);\n const stripped = this.stripVersionSuffixes(slug);\n if (stripped && stripped !== slug) {\n const candidate = `${prefix}/${stripped}`;\n const record = this.catalog.get(candidate);\n if (record) {\n return {\n modelId: candidate,\n record,\n confidence: 0.85,\n strategy: \"date-suffix-strip\",\n reason: `Stripped date from slug \"${slug}\" → \"${stripped}\"`,\n };\n }\n }\n }\n\n const latest = this.findLatestVersioned(model);\n if (latest) {\n return {\n modelId: latest.modelId,\n record: latest.record,\n confidence: 0.85,\n strategy: \"date-suffix-strip\",\n reason: `Matched \"${model}\" to versioned catalog entry \"${latest.modelId}\" (latest)`,\n };\n }\n return null;\n }\n\n private findLatestVersioned(\n baseModelId: string,\n ): { modelId: string; record: AiModelRecord } | null {\n const candidates: Array<{ modelId: string; record: AiModelRecord; suffix: string }> = [];\n for (const [modelId, record] of this.catalog) {\n if (modelId === baseModelId) continue;\n if (modelId.startsWith(`${baseModelId}-`)) {\n candidates.push({\n modelId,\n record,\n suffix: modelId.slice(baseModelId.length + 1),\n });\n }\n }\n if (candidates.length === 0) return null;\n candidates.sort((a, b) => b.suffix.localeCompare(a.suffix));\n const best = candidates[0]!;\n return { modelId: best.modelId, record: best.record };\n }\n\n private shorthandMap(): Record<string, string> {\n return { ...SHORTHAND_MAP, ...this.ctx.options.additionalShorthands };\n }\n\n private partialMatch(\n model: string,\n provider: string | undefined,\n ): (MatchCandidate & { resolvedVia?: ResolutionStrategy[] }) | null {\n let best: { modelId: string; record: AiModelRecord; score: number } | null = null;\n const inputTokens = tokenise(model);\n if (inputTokens.length === 0) return null;\n\n for (const record of this.catalog.values()) {\n const recordTokens = new Set([\n ...tokenise(record.modelId),\n ...tokenise(record.name ?? \"\"),\n ]);\n const intersection = inputTokens.filter((t) => recordTokens.has(t));\n const overlapRatio = intersection.length / inputTokens.length;\n let score = overlapRatio * 0.6;\n\n if (record.modelId.includes(model)) score += 0.3;\n const slug = modelSlug(record.modelId);\n if (model.includes(slug)) score += 0.2;\n\n if (provider && provider === record.providerId) score += 0.15;\n\n const lenPenalty =\n (Math.abs(model.length - slug.length) / Math.max(model.length, slug.length, 1)) * 0.1;\n score -= lenPenalty;\n\n if (!best || score > best.score) {\n best = { modelId: record.modelId, record, score };\n }\n }\n\n if (!best || best.score < 0.65) return null;\n return {\n modelId: best.modelId,\n record: best.record,\n confidence: 0.65,\n strategy: \"partial-name-match\",\n reason: `Partial token match (score ${best.score.toFixed(2)})`,\n };\n }\n\n private computeRoutedViaOpenRouter(\n modelId: string,\n record: AiModelRecord | null,\n provider: string | undefined,\n originalProvider: string | undefined,\n ): boolean {\n const norm = normalizeProvider(originalProvider) ?? provider;\n if (norm === \"openrouter\") return true;\n if (norm && norm !== \"openrouter\") {\n if (shouldDefaultRouteViaOpenRouter(norm, this.ctx.options.routingEnv)) return true;\n return false;\n }\n\n const recordProvider = record?.providerId;\n if (recordProvider && shouldDefaultRouteViaOpenRouter(recordProvider, this.ctx.options.routingEnv)) {\n return true;\n }\n\n if (record?.availableOnOpenRouter && modelId.includes(\"/\")) return true;\n return false;\n }\n\n private success(args: {\n modelId: string;\n record: AiModelRecord | null;\n confidence: number;\n strategy: ResolutionStrategy;\n reason: string;\n resolvedVia: ResolutionStrategy[];\n normalisedInput: string;\n provider?: string;\n originalProvider?: string;\n }): ModelResolutionSuccess {\n return {\n found: true,\n modelId: args.modelId,\n record: args.record,\n routedViaOpenRouter: this.computeRoutedViaOpenRouter(\n args.modelId,\n args.record,\n args.provider,\n args.originalProvider,\n ),\n confidence: args.confidence,\n resolvedVia: args.resolvedVia,\n resolvedReason: args.reason,\n normalisedInput: args.normalisedInput,\n };\n }\n}\n"]}
@@ -1,169 +0,0 @@
1
- import {
2
- batchUpsertAiModelRecords
3
- } from "./chunk-HYGXZY25.js";
4
- import {
5
- normalizeOpenRouterModel
6
- } from "./chunk-6QGDZTGH.js";
7
- import {
8
- AI_MODELS_CATALOG_ID,
9
- AI_MODELS_DESCRIPTOR,
10
- AI_TOOLS_APP_ID,
11
- invalidateModelsCache
12
- } from "./chunk-DJ5SWJDY.js";
13
- import {
14
- AiToolsError,
15
- SyncError
16
- } from "./chunk-AJEKEWWB.js";
17
-
18
- // src/catalog/ensureAiModelsCatalog.ts
19
- async function ensureAiModelsCatalog(catalox, options = {}) {
20
- const appId = options.appId ?? AI_TOOLS_APP_ID;
21
- const catalogId = options.catalogId ?? AI_MODELS_CATALOG_ID;
22
- const ctx = { appId, superAdmin: true };
23
- try {
24
- await catalox.ensureCatalog(ctx, {
25
- catalogId,
26
- name: AI_MODELS_DESCRIPTOR.label,
27
- status: "active"
28
- });
29
- await catalox.bindCatalogToApp(ctx, {
30
- appId,
31
- catalogId,
32
- access: { canRead: true, canWrite: true, canAdmin: true }
33
- });
34
- await catalox.upsertCatalogDescriptor(ctx, catalogId, {
35
- descriptorVersion: "1.0.0",
36
- descriptor: AI_MODELS_DESCRIPTOR
37
- });
38
- } catch (cause) {
39
- throw new AiToolsError(
40
- "CATALOG_BOOTSTRAP_FAILED",
41
- `Failed to bootstrap catalog "${catalogId}" for app "${appId}".`,
42
- cause
43
- );
44
- }
45
- }
46
-
47
- // src/sync/OpenRouterSyncProvider.ts
48
- function buildFetchHeaders(apiKey) {
49
- const headers = { Accept: "application/json" };
50
- if (apiKey?.trim()) headers.Authorization = `Bearer ${apiKey.trim()}`;
51
- return headers;
52
- }
53
- function buildModelsUrl(baseUrl, query) {
54
- const url = new URL(`${baseUrl.replace(/\/$/, "")}/models`);
55
- const q = { output_modalities: "all", ...query };
56
- for (const [key, value] of Object.entries(q)) {
57
- if (value !== void 0 && value !== "") url.searchParams.set(key, value);
58
- }
59
- return url.toString();
60
- }
61
- var OpenRouterSyncProvider = class {
62
- apiKey;
63
- baseUrl;
64
- query;
65
- constructor(options = {}) {
66
- this.apiKey = options.apiKey;
67
- this.baseUrl = options.baseUrl ?? "https://openrouter.ai/api/v1";
68
- this.query = options.query ?? { output_modalities: "all" };
69
- }
70
- /**
71
- * Fetches the full OpenRouter model catalog (public, no API key required).
72
- * @see https://openrouter.ai/api/v1/models
73
- */
74
- async fetchModels() {
75
- const url = buildModelsUrl(this.baseUrl, this.query);
76
- let response;
77
- try {
78
- response = await fetch(url, { headers: buildFetchHeaders(this.apiKey) });
79
- } catch (cause) {
80
- throw new SyncError("OPENROUTER_MODELS_FETCH_FAILED", `Failed to fetch OpenRouter models from ${url}`, cause);
81
- }
82
- if (response.status === 401 || response.status === 403) {
83
- throw new SyncError(
84
- "OPENROUTER_AUTH_FAILED",
85
- this.apiKey ? "OpenRouter API key is invalid or unauthorized." : "OpenRouter returned unauthorized \u2014 remove OPENROUTER_API_KEY to use the public models endpoint."
86
- );
87
- }
88
- if (!response.ok) {
89
- const body = await response.text().catch(() => "");
90
- throw new SyncError(
91
- "OPENROUTER_MODELS_FETCH_FAILED",
92
- `OpenRouter models fetch failed (${response.status}): ${body.slice(0, 200)}`
93
- );
94
- }
95
- const json = await response.json();
96
- const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
97
- return (json.data ?? []).map((row) => normalizeOpenRouterModel(row, syncedAt));
98
- }
99
- /** Build the URL used for the last fetch pattern (for debugging). */
100
- getModelsUrl() {
101
- return buildModelsUrl(this.baseUrl, this.query);
102
- }
103
- };
104
-
105
- // src/sync/syncAiModelsCatalog.ts
106
- async function syncAiModelsCatalog(options) {
107
- const start = Date.now();
108
- const appId = options.appId ?? AI_TOOLS_APP_ID;
109
- const catalogId = options.catalogId ?? AI_MODELS_CATALOG_ID;
110
- const ctx = { appId, superAdmin: true };
111
- if (options.forceCache) {
112
- invalidateModelsCache(appId);
113
- }
114
- await ensureAiModelsCatalog(options.catalox, { appId, catalogId });
115
- const provider = new OpenRouterSyncProvider({
116
- apiKey: options.openRouterApiKey,
117
- query: options.openRouterQuery ?? { output_modalities: "all" }
118
- });
119
- let models;
120
- try {
121
- models = await provider.fetchModels();
122
- } catch (error) {
123
- if (error instanceof SyncError) throw error;
124
- throw new SyncError("SYNC_FETCH_FAILED", "Failed to fetch models from OpenRouter.", error);
125
- }
126
- if (options.verbose) {
127
- console.log(`[sync] fetched ${models.length} models from ${provider.getModelsUrl()}`);
128
- }
129
- const syncedModelIds = models.map((m) => m.modelId);
130
- if (options.dryRun) {
131
- return {
132
- fetched: models.length,
133
- upserted: 0,
134
- skipped: models.length,
135
- errors: [],
136
- syncedModelIds,
137
- durationMs: Date.now() - start
138
- };
139
- }
140
- const upsert = await batchUpsertAiModelRecords(
141
- options.firestore,
142
- catalogId,
143
- ctx,
144
- models,
145
- { onProgress: options.onProgress }
146
- );
147
- invalidateModelsCache(appId);
148
- if (upsert.failed.length > 0 && upsert.upserted === 0) {
149
- throw new SyncError(
150
- "SYNC_UPSERT_FAILED",
151
- `All ${upsert.failed.length} model upserts failed. First error: ${upsert.failed[0].error}`
152
- );
153
- }
154
- return {
155
- fetched: models.length,
156
- upserted: upsert.upserted,
157
- skipped: models.length - upsert.upserted,
158
- errors: upsert.failed,
159
- syncedModelIds,
160
- durationMs: Date.now() - start
161
- };
162
- }
163
-
164
- export {
165
- ensureAiModelsCatalog,
166
- OpenRouterSyncProvider,
167
- syncAiModelsCatalog
168
- };
169
- //# sourceMappingURL=chunk-VRFVF5RH.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/catalog/ensureAiModelsCatalog.ts","../src/sync/OpenRouterSyncProvider.ts","../src/sync/syncAiModelsCatalog.ts"],"sourcesContent":["import type { Catalox, CataloxContext } from \"@x12i/catalox\";\nimport { AiToolsError } from \"../errors.js\";\nimport {\n AI_MODELS_CATALOG_ID,\n AI_MODELS_DESCRIPTOR,\n AI_TOOLS_APP_ID,\n} from \"./aiModelsCatalogDescriptor.js\";\n\nexport type EnsureAiModelsCatalogOptions = {\n appId?: string;\n catalogId?: string;\n};\n\nexport async function ensureAiModelsCatalog(\n catalox: Catalox,\n options: EnsureAiModelsCatalogOptions = {},\n): Promise<void> {\n const appId = options.appId ?? AI_TOOLS_APP_ID;\n const catalogId = options.catalogId ?? AI_MODELS_CATALOG_ID;\n\n const ctx: CataloxContext = { appId, superAdmin: true };\n\n try {\n await catalox.ensureCatalog(ctx, {\n catalogId,\n name: AI_MODELS_DESCRIPTOR.label,\n status: \"active\",\n });\n\n await catalox.bindCatalogToApp(ctx, {\n appId,\n catalogId,\n access: { canRead: true, canWrite: true, canAdmin: true },\n });\n\n await catalox.upsertCatalogDescriptor(ctx, catalogId, {\n descriptorVersion: \"1.0.0\",\n descriptor: AI_MODELS_DESCRIPTOR,\n });\n } catch (cause) {\n throw new AiToolsError(\n \"CATALOG_BOOTSTRAP_FAILED\",\n `Failed to bootstrap catalog \"${catalogId}\" for app \"${appId}\".`,\n cause,\n );\n }\n}\n","import { SyncError } from \"../errors.js\";\nimport { normalizeOpenRouterModel } from \"../models/normalizeOpenRouterModel.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\nimport type {\n OpenRouterModelsQuery,\n OpenRouterModelsResponse,\n} from \"../models/openrouter.types.js\";\n\nexport type OpenRouterSyncProviderOptions = {\n /** Optional — public GET /models needs no key. */\n apiKey?: string;\n baseUrl?: string;\n /** Query params passed to OpenRouter (default: all modalities). */\n query?: OpenRouterModelsQuery;\n};\n\nfunction buildFetchHeaders(apiKey?: string): Record<string, string> {\n const headers: Record<string, string> = { Accept: \"application/json\" };\n if (apiKey?.trim()) headers.Authorization = `Bearer ${apiKey.trim()}`;\n return headers;\n}\n\nfunction buildModelsUrl(baseUrl: string, query?: OpenRouterModelsQuery): string {\n const url = new URL(`${baseUrl.replace(/\\/$/, \"\")}/models`);\n const q = { output_modalities: \"all\", ...query };\n for (const [key, value] of Object.entries(q)) {\n if (value !== undefined && value !== \"\") url.searchParams.set(key, value);\n }\n return url.toString();\n}\n\nexport class OpenRouterSyncProvider {\n private readonly apiKey?: string;\n private readonly baseUrl: string;\n private readonly query?: OpenRouterModelsQuery;\n\n constructor(options: OpenRouterSyncProviderOptions = {}) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://openrouter.ai/api/v1\";\n this.query = options.query ?? { output_modalities: \"all\" };\n }\n\n /**\n * Fetches the full OpenRouter model catalog (public, no API key required).\n * @see https://openrouter.ai/api/v1/models\n */\n async fetchModels(): Promise<AiModelRecord[]> {\n const url = buildModelsUrl(this.baseUrl, this.query);\n let response: Response;\n\n try {\n response = await fetch(url, { headers: buildFetchHeaders(this.apiKey) });\n } catch (cause) {\n throw new SyncError(\"OPENROUTER_MODELS_FETCH_FAILED\", `Failed to fetch OpenRouter models from ${url}`, cause);\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SyncError(\n \"OPENROUTER_AUTH_FAILED\",\n this.apiKey\n ? \"OpenRouter API key is invalid or unauthorized.\"\n : \"OpenRouter returned unauthorized — remove OPENROUTER_API_KEY to use the public models endpoint.\",\n );\n }\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new SyncError(\n \"OPENROUTER_MODELS_FETCH_FAILED\",\n `OpenRouter models fetch failed (${response.status}): ${body.slice(0, 200)}`,\n );\n }\n\n const json = (await response.json()) as OpenRouterModelsResponse;\n const syncedAt = new Date().toISOString();\n return (json.data ?? []).map((row) => normalizeOpenRouterModel(row, syncedAt));\n }\n\n /** Build the URL used for the last fetch pattern (for debugging). */\n getModelsUrl(): string {\n return buildModelsUrl(this.baseUrl, this.query);\n }\n}\n","import type { Catalox, CataloxContext } from \"@x12i/catalox\";\nimport type { Firestore } from \"firebase-admin/firestore\";\nimport { ensureAiModelsCatalog } from \"../catalog/ensureAiModelsCatalog.js\";\nimport { AI_MODELS_CATALOG_ID, AI_TOOLS_APP_ID } from \"../catalog/aiModelsCatalogDescriptor.js\";\nimport { invalidateModelsCache } from \"../cache/modelCache.js\";\nimport {\n batchUpsertAiModelRecords,\n type BatchUpsertProgress,\n} from \"../catalox/upsertAiModelRecord.js\";\nimport { SyncError } from \"../errors.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\nimport type { OpenRouterModelsQuery } from \"../models/openrouter.types.js\";\nimport { OpenRouterSyncProvider } from \"./OpenRouterSyncProvider.js\";\n\nexport type SyncOptions = {\n catalox: Catalox;\n firestore: Firestore;\n openRouterApiKey?: string;\n openRouterQuery?: OpenRouterModelsQuery;\n appId?: string;\n catalogId?: string;\n dryRun?: boolean;\n verbose?: boolean;\n forceCache?: boolean;\n onProgress?: (progress: BatchUpsertProgress) => void;\n};\n\nexport type SyncResult = {\n fetched: number;\n upserted: number;\n skipped: number;\n errors: Array<{ modelId: string; error: string }>;\n durationMs: number;\n /** Model ids written (or that would be written on dry-run). */\n syncedModelIds: string[];\n};\n\nexport async function syncAiModelsCatalog(options: SyncOptions): Promise<SyncResult> {\n const start = Date.now();\n const appId = options.appId ?? AI_TOOLS_APP_ID;\n const catalogId = options.catalogId ?? AI_MODELS_CATALOG_ID;\n const ctx: CataloxContext = { appId, superAdmin: true };\n\n if (options.forceCache) {\n invalidateModelsCache(appId);\n }\n\n await ensureAiModelsCatalog(options.catalox, { appId, catalogId });\n\n const provider = new OpenRouterSyncProvider({\n apiKey: options.openRouterApiKey,\n query: options.openRouterQuery ?? { output_modalities: \"all\" },\n });\n\n let models: AiModelRecord[];\n try {\n models = await provider.fetchModels();\n } catch (error) {\n if (error instanceof SyncError) throw error;\n throw new SyncError(\"SYNC_FETCH_FAILED\", \"Failed to fetch models from OpenRouter.\", error);\n }\n\n if (options.verbose) {\n console.log(`[sync] fetched ${models.length} models from ${provider.getModelsUrl()}`);\n }\n\n const syncedModelIds = models.map((m) => m.modelId);\n\n if (options.dryRun) {\n return {\n fetched: models.length,\n upserted: 0,\n skipped: models.length,\n errors: [],\n syncedModelIds,\n durationMs: Date.now() - start,\n };\n }\n\n const upsert = await batchUpsertAiModelRecords(\n options.firestore,\n catalogId,\n ctx,\n models,\n { onProgress: options.onProgress },\n );\n\n invalidateModelsCache(appId);\n\n if (upsert.failed.length > 0 && upsert.upserted === 0) {\n throw new SyncError(\n \"SYNC_UPSERT_FAILED\",\n `All ${upsert.failed.length} model upserts failed. First error: ${upsert.failed[0]!.error}`,\n );\n }\n\n return {\n fetched: models.length,\n upserted: upsert.upserted,\n skipped: models.length - upsert.upserted,\n errors: upsert.failed,\n syncedModelIds,\n durationMs: Date.now() - start,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,83 +0,0 @@
1
- // src/cost/CostCalculator.ts
2
- var CostCalculator = class {
3
- constructor(catalog, options = {}) {
4
- this.catalog = catalog;
5
- this.aliasRegistry = options.aliasRegistry;
6
- this.includeBreakdown = options.includeBreakdown ?? true;
7
- this.resolverOptions = options.resolverOptions;
8
- }
9
- catalog;
10
- aliasRegistry;
11
- includeBreakdown;
12
- resolverOptions;
13
- async calculate(input) {
14
- const resolved = await this.catalog.resolveModel(
15
- { model: input.modelUsed, provider: input.provider },
16
- {
17
- ...this.resolverOptions,
18
- aliasRegistry: this.aliasRegistry ?? this.resolverOptions?.aliasRegistry
19
- }
20
- );
21
- if (!resolved.found || !resolved.record) {
22
- console.warn(
23
- `[ai-tools] Unknown model "${input.modelUsed}" \u2014 returning zero-cost fallback.`
24
- );
25
- const emptyPricing = {
26
- promptUsdPerToken: 0,
27
- completionUsdPerToken: 0,
28
- imageUsdPerUnit: 0,
29
- requestUsdPerRequest: 0,
30
- pricedAt: (/* @__PURE__ */ new Date()).toISOString(),
31
- source: "manual"
32
- };
33
- return {
34
- cost: 0,
35
- resolvedModelId: input.modelUsed,
36
- routedViaOpenRouter: resolved.found ? resolved.routedViaOpenRouter : input.provider === "openrouter",
37
- isAuthoritative: false,
38
- pricingSnapshot: emptyPricing,
39
- source: "estimate-fallback"
40
- };
41
- }
42
- const { record, routedViaOpenRouter, modelId } = resolved;
43
- const pricing = record.pricing;
44
- const { tokens } = input;
45
- let promptCost = tokens.prompt * pricing.promptUsdPerToken;
46
- let completionCost = tokens.completion * pricing.completionUsdPerToken;
47
- const cachingCost = (tokens.cacheWrite ?? 0) * (pricing.cacheWriteUsdPerToken ?? 0) + (tokens.cached ?? 0) * (pricing.cacheReadUsdPerToken ?? 0);
48
- const reasoningCost = (tokens.reasoning ?? 0) * (pricing.reasoningUsdPerToken ?? pricing.promptUsdPerToken);
49
- const audioCost = (tokens.audio ?? 0) * pricing.promptUsdPerToken;
50
- const imageCost = (tokens.image ?? 0) * (pricing.imageUsdPerUnit ?? 0);
51
- const requestFlat = pricing.requestUsdPerRequest;
52
- if (routedViaOpenRouter) {
53
- promptCost += tokens.prompt * (pricing.openRouterMarkupUsdPerInputToken ?? 0);
54
- completionCost += tokens.completion * (pricing.openRouterMarkupUsdPerOutputToken ?? 0);
55
- }
56
- const cost = promptCost + completionCost + cachingCost + reasoningCost + audioCost + imageCost + requestFlat;
57
- const result = {
58
- cost,
59
- resolvedModelId: modelId,
60
- routedViaOpenRouter,
61
- isAuthoritative: true,
62
- pricingSnapshot: pricing,
63
- source: "catalog"
64
- };
65
- if (this.includeBreakdown) {
66
- result.breakdown = {
67
- promptCostUsd: promptCost,
68
- completionCostUsd: completionCost,
69
- cachingCostUsd: cachingCost || void 0,
70
- reasoningCostUsd: reasoningCost || void 0,
71
- audioCostUsd: audioCost || void 0,
72
- imageCostUsd: imageCost || void 0,
73
- requestFlatCostUsd: requestFlat || void 0
74
- };
75
- }
76
- return result;
77
- }
78
- };
79
-
80
- export {
81
- CostCalculator
82
- };
83
- //# sourceMappingURL=chunk-YHO57D2V.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cost/CostCalculator.ts"],"sourcesContent":["import type { AliasRegistry } from \"../aliases/AliasRegistry.js\";\nimport type { AiModelsCatalogClient } from \"../catalox/AiModelsCatalogClient.js\";\nimport type { ModelResolverOptions } from \"../sync/modelNameResolver/types.js\";\nimport type { AiCostResult, AiModelPricing, AiUsageInput } from \"./types.js\";\n\nexport type CostCalculatorOptions = {\n aliasRegistry?: AliasRegistry;\n includeBreakdown?: boolean;\n resolverOptions?: ModelResolverOptions;\n};\n\nexport class CostCalculator {\n private readonly aliasRegistry?: AliasRegistry;\n private readonly includeBreakdown: boolean;\n private readonly resolverOptions?: ModelResolverOptions;\n\n constructor(\n private readonly catalog: AiModelsCatalogClient,\n options: CostCalculatorOptions = {},\n ) {\n this.aliasRegistry = options.aliasRegistry;\n this.includeBreakdown = options.includeBreakdown ?? true;\n this.resolverOptions = options.resolverOptions;\n }\n\n async calculate(input: AiUsageInput): Promise<AiCostResult> {\n const resolved = await this.catalog.resolveModel(\n { model: input.modelUsed, provider: input.provider },\n {\n ...this.resolverOptions,\n aliasRegistry: this.aliasRegistry ?? this.resolverOptions?.aliasRegistry,\n },\n );\n\n if (!resolved.found || !resolved.record) {\n console.warn(\n `[ai-tools] Unknown model \"${input.modelUsed}\" — returning zero-cost fallback.`,\n );\n const emptyPricing: AiModelPricing = {\n promptUsdPerToken: 0,\n completionUsdPerToken: 0,\n imageUsdPerUnit: 0,\n requestUsdPerRequest: 0,\n pricedAt: new Date().toISOString(),\n source: \"manual\",\n };\n return {\n cost: 0,\n resolvedModelId: input.modelUsed,\n routedViaOpenRouter:\n resolved.found ? resolved.routedViaOpenRouter : input.provider === \"openrouter\",\n isAuthoritative: false,\n pricingSnapshot: emptyPricing,\n source: \"estimate-fallback\",\n };\n }\n\n const { record, routedViaOpenRouter, modelId } = resolved;\n const pricing = record.pricing;\n const { tokens } = input;\n\n let promptCost = tokens.prompt * pricing.promptUsdPerToken;\n let completionCost = tokens.completion * pricing.completionUsdPerToken;\n\n const cachingCost =\n (tokens.cacheWrite ?? 0) * (pricing.cacheWriteUsdPerToken ?? 0) +\n (tokens.cached ?? 0) * (pricing.cacheReadUsdPerToken ?? 0);\n\n const reasoningCost =\n (tokens.reasoning ?? 0) *\n (pricing.reasoningUsdPerToken ?? pricing.promptUsdPerToken);\n\n const audioCost = (tokens.audio ?? 0) * pricing.promptUsdPerToken;\n const imageCost = (tokens.image ?? 0) * (pricing.imageUsdPerUnit ?? 0);\n const requestFlat = pricing.requestUsdPerRequest;\n\n if (routedViaOpenRouter) {\n promptCost +=\n tokens.prompt * (pricing.openRouterMarkupUsdPerInputToken ?? 0);\n completionCost +=\n tokens.completion * (pricing.openRouterMarkupUsdPerOutputToken ?? 0);\n }\n\n const cost =\n promptCost +\n completionCost +\n cachingCost +\n reasoningCost +\n audioCost +\n imageCost +\n requestFlat;\n\n const result: AiCostResult = {\n cost,\n resolvedModelId: modelId,\n routedViaOpenRouter,\n isAuthoritative: true,\n pricingSnapshot: pricing,\n source: \"catalog\",\n };\n\n if (this.includeBreakdown) {\n result.breakdown = {\n promptCostUsd: promptCost,\n completionCostUsd: completionCost,\n cachingCostUsd: cachingCost || undefined,\n reasoningCostUsd: reasoningCost || undefined,\n audioCostUsd: audioCost || undefined,\n imageCostUsd: imageCost || undefined,\n requestFlatCostUsd: requestFlat || undefined,\n };\n }\n\n return result;\n }\n}\n"],"mappings":";AAWO,IAAM,iBAAN,MAAqB;AAAA,EAK1B,YACmB,SACjB,UAAiC,CAAC,GAClC;AAFiB;AAGjB,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,mBAAmB,QAAQ,oBAAoB;AACpD,SAAK,kBAAkB,QAAQ;AAAA,EACjC;AAAA,EANmB;AAAA,EALF;AAAA,EACA;AAAA,EACA;AAAA,EAWjB,MAAM,UAAU,OAA4C;AAC1D,UAAM,WAAW,MAAM,KAAK,QAAQ;AAAA,MAClC,EAAE,OAAO,MAAM,WAAW,UAAU,MAAM,SAAS;AAAA,MACnD;AAAA,QACE,GAAG,KAAK;AAAA,QACR,eAAe,KAAK,iBAAiB,KAAK,iBAAiB;AAAA,MAC7D;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,SAAS,CAAC,SAAS,QAAQ;AACvC,cAAQ;AAAA,QACN,6BAA6B,MAAM,SAAS;AAAA,MAC9C;AACA,YAAM,eAA+B;AAAA,QACnC,mBAAmB;AAAA,QACnB,uBAAuB;AAAA,QACvB,iBAAiB;AAAA,QACjB,sBAAsB;AAAA,QACtB,WAAU,oBAAI,KAAK,GAAE,YAAY;AAAA,QACjC,QAAQ;AAAA,MACV;AACA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,iBAAiB,MAAM;AAAA,QACvB,qBACE,SAAS,QAAQ,SAAS,sBAAsB,MAAM,aAAa;AAAA,QACrE,iBAAiB;AAAA,QACjB,iBAAiB;AAAA,QACjB,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,UAAM,EAAE,QAAQ,qBAAqB,QAAQ,IAAI;AACjD,UAAM,UAAU,OAAO;AACvB,UAAM,EAAE,OAAO,IAAI;AAEnB,QAAI,aAAa,OAAO,SAAS,QAAQ;AACzC,QAAI,iBAAiB,OAAO,aAAa,QAAQ;AAEjD,UAAM,eACH,OAAO,cAAc,MAAM,QAAQ,yBAAyB,MAC5D,OAAO,UAAU,MAAM,QAAQ,wBAAwB;AAE1D,UAAM,iBACH,OAAO,aAAa,MACpB,QAAQ,wBAAwB,QAAQ;AAE3C,UAAM,aAAa,OAAO,SAAS,KAAK,QAAQ;AAChD,UAAM,aAAa,OAAO,SAAS,MAAM,QAAQ,mBAAmB;AACpE,UAAM,cAAc,QAAQ;AAE5B,QAAI,qBAAqB;AACvB,oBACE,OAAO,UAAU,QAAQ,oCAAoC;AAC/D,wBACE,OAAO,cAAc,QAAQ,qCAAqC;AAAA,IACtE;AAEA,UAAM,OACJ,aACA,iBACA,cACA,gBACA,YACA,YACA;AAEF,UAAM,SAAuB;AAAA,MAC3B;AAAA,MACA,iBAAiB;AAAA,MACjB;AAAA,MACA,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,QAAQ;AAAA,IACV;AAEA,QAAI,KAAK,kBAAkB;AACzB,aAAO,YAAY;AAAA,QACjB,eAAe;AAAA,QACf,mBAAmB;AAAA,QACnB,gBAAgB,eAAe;AAAA,QAC/B,kBAAkB,iBAAiB;AAAA,QACnC,cAAc,aAAa;AAAA,QAC3B,cAAc,aAAa;AAAA,QAC3B,oBAAoB,eAAe;AAAA,MACrC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -1,32 +0,0 @@
1
- import { Catalox } from '@x12i/catalox';
2
- import { Firestore } from 'firebase-admin/firestore';
3
- import { B as BatchUpsertProgress } from './upsertAiModelRecord-CjY-sny0.cjs';
4
- import { d as OpenRouterModelsQuery } from './types-BYXnCvKx.cjs';
5
-
6
- type SyncOptions = {
7
- catalox: Catalox;
8
- firestore: Firestore;
9
- openRouterApiKey?: string;
10
- openRouterQuery?: OpenRouterModelsQuery;
11
- appId?: string;
12
- catalogId?: string;
13
- dryRun?: boolean;
14
- verbose?: boolean;
15
- forceCache?: boolean;
16
- onProgress?: (progress: BatchUpsertProgress) => void;
17
- };
18
- type SyncResult = {
19
- fetched: number;
20
- upserted: number;
21
- skipped: number;
22
- errors: Array<{
23
- modelId: string;
24
- error: string;
25
- }>;
26
- durationMs: number;
27
- /** Model ids written (or that would be written on dry-run). */
28
- syncedModelIds: string[];
29
- };
30
- declare function syncAiModelsCatalog(options: SyncOptions): Promise<SyncResult>;
31
-
32
- export { type SyncOptions as S, type SyncResult as a, syncAiModelsCatalog as s };
@@ -1,32 +0,0 @@
1
- import { Catalox } from '@x12i/catalox';
2
- import { Firestore } from 'firebase-admin/firestore';
3
- import { B as BatchUpsertProgress } from './upsertAiModelRecord-C831wOIF.js';
4
- import { d as OpenRouterModelsQuery } from './types-BYXnCvKx.js';
5
-
6
- type SyncOptions = {
7
- catalox: Catalox;
8
- firestore: Firestore;
9
- openRouterApiKey?: string;
10
- openRouterQuery?: OpenRouterModelsQuery;
11
- appId?: string;
12
- catalogId?: string;
13
- dryRun?: boolean;
14
- verbose?: boolean;
15
- forceCache?: boolean;
16
- onProgress?: (progress: BatchUpsertProgress) => void;
17
- };
18
- type SyncResult = {
19
- fetched: number;
20
- upserted: number;
21
- skipped: number;
22
- errors: Array<{
23
- modelId: string;
24
- error: string;
25
- }>;
26
- durationMs: number;
27
- /** Model ids written (or that would be written on dry-run). */
28
- syncedModelIds: string[];
29
- };
30
- declare function syncAiModelsCatalog(options: SyncOptions): Promise<SyncResult>;
31
-
32
- export { type SyncOptions as S, type SyncResult as a, syncAiModelsCatalog as s };
@@ -1,137 +0,0 @@
1
- /** OpenRouter Models API — https://openrouter.ai/api/v1/models */
2
- type OpenRouterOutputModality = "text" | "image" | "audio" | "embeddings" | "video" | "speech" | "transcription" | "all";
3
- type OpenRouterModelsQuery = {
4
- /** Comma-separated or "all" — default on our sync is "all". */
5
- output_modalities?: string;
6
- supported_parameters?: string;
7
- };
8
- type OpenRouterPricingApi = {
9
- prompt: string;
10
- completion: string;
11
- request: string;
12
- image: string;
13
- web_search?: string;
14
- internal_reasoning?: string;
15
- input_cache_read?: string;
16
- input_cache_write?: string;
17
- };
18
- type OpenRouterArchitectureApi = {
19
- modality?: string;
20
- input_modalities: string[];
21
- output_modalities: string[];
22
- tokenizer: string;
23
- instruct_type: string | null;
24
- };
25
- type OpenRouterTopProviderApi = {
26
- context_length: number;
27
- max_completion_tokens: number | null;
28
- is_moderated: boolean;
29
- };
30
- type OpenRouterDefaultParametersApi = {
31
- temperature?: number | null;
32
- top_p?: number | null;
33
- top_k?: number | null;
34
- frequency_penalty?: number | null;
35
- presence_penalty?: number | null;
36
- repetition_penalty?: number | null;
37
- };
38
- type OpenRouterModelApi = {
39
- id: string;
40
- canonical_slug: string;
41
- hugging_face_id?: string | null;
42
- name: string;
43
- created: number;
44
- description: string;
45
- context_length: number;
46
- architecture: OpenRouterArchitectureApi;
47
- pricing: OpenRouterPricingApi;
48
- top_provider: OpenRouterTopProviderApi;
49
- per_request_limits: unknown | null;
50
- supported_parameters: string[];
51
- default_parameters: OpenRouterDefaultParametersApi | null;
52
- supported_voices?: unknown | null;
53
- knowledge_cutoff?: string | null;
54
- expiration_date?: string | null;
55
- links?: {
56
- details?: string;
57
- } | null;
58
- };
59
- type OpenRouterModelsResponse = {
60
- data: OpenRouterModelApi[];
61
- };
62
-
63
- type AiModelPricing = {
64
- promptUsdPerToken: number;
65
- completionUsdPerToken: number;
66
- imageUsdPerUnit: number;
67
- requestUsdPerRequest: number;
68
- cacheReadUsdPerToken?: number;
69
- cacheWriteUsdPerToken?: number;
70
- reasoningUsdPerToken?: number;
71
- webSearchUsdPerRequest?: number;
72
- openRouterMarkupUsdPerInputToken?: number;
73
- openRouterMarkupUsdPerOutputToken?: number;
74
- pricedAt: string;
75
- source: "openrouter" | "direct" | "manual";
76
- };
77
- /**
78
- * Canonical catalog record — mirrors OpenRouter Models API fields plus normalized pricing.
79
- * Stored as-is in Catalox `data`; scalar fields duplicated in `indexed` for queries.
80
- */
81
- type AiModelRecord = {
82
- modelId: string;
83
- name: string;
84
- providerId: string;
85
- canonicalSlug: string;
86
- status: "active" | "deprecated" | "unknown";
87
- description: string;
88
- created: number;
89
- expirationDate: string | null;
90
- contextLength: number;
91
- maxCompletionTokens: number | null;
92
- isModerated: boolean;
93
- modality: string;
94
- inputModalities: string[];
95
- outputModalities: string[];
96
- tokenizer: string;
97
- instructType: string | null;
98
- supportedParameters: string[];
99
- defaultParameters: OpenRouterDefaultParametersApi | null;
100
- perRequestLimits: unknown | null;
101
- pricing: AiModelPricing;
102
- /** Raw OpenRouter pricing strings (USD per token/request/unit). */
103
- openRouterPricing: OpenRouterPricingApi;
104
- architecture: OpenRouterArchitectureApi;
105
- topProvider: OpenRouterTopProviderApi;
106
- /** Full OpenRouter API object — complete mirror for forward compatibility. */
107
- openRouter: OpenRouterModelApi;
108
- aliases: string[];
109
- availableOnOpenRouter: boolean;
110
- supportsStreaming: boolean;
111
- supportsTools: boolean;
112
- /** Exposes reasoning/thinking tokens (OpenRouter `reasoning` param and/or `internal_reasoning` pricing). */
113
- supportsReasoning: boolean;
114
- primaryOutputModality: string;
115
- syncedAt: string;
116
- syncSource: "openrouter" | "manual";
117
- };
118
- type ModelListFilters = {
119
- providerId?: string;
120
- status?: AiModelRecord["status"];
121
- outputModality?: string;
122
- inputModality?: string;
123
- supportedParameter?: string;
124
- supportsTools?: boolean;
125
- supportsReasoning?: boolean;
126
- search?: string;
127
- limit?: number;
128
- offset?: number;
129
- };
130
- type ModelListResult = {
131
- models: AiModelRecord[];
132
- total: number;
133
- limit: number;
134
- offset: number;
135
- };
136
-
137
- export type { AiModelPricing as A, ModelListFilters as M, OpenRouterArchitectureApi as O, AiModelRecord as a, ModelListResult as b, OpenRouterModelApi as c, OpenRouterModelsQuery as d, OpenRouterModelsResponse as e, OpenRouterOutputModality as f, OpenRouterPricingApi as g, OpenRouterTopProviderApi as h };