@x12i/ai-tools 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/{AiModelsCatalogClient-B5FMI9gj.d.cts → AiModelsCatalogClient-C9ZJHhv3.d.ts} +4 -1
  2. package/dist/{AiModelsCatalogClient-CPPNI6Ry.d.ts → AiModelsCatalogClient-DgBdVFk-.d.cts} +4 -1
  3. package/dist/aliases/index.d.cts +3 -3
  4. package/dist/aliases/index.d.ts +3 -3
  5. package/dist/catalog/index.cjs +6 -5
  6. package/dist/catalog/index.cjs.map +1 -1
  7. package/dist/catalog/index.d.cts +4 -4
  8. package/dist/catalog/index.d.ts +4 -4
  9. package/dist/catalog/index.js +5 -4
  10. package/dist/{chunk-EYHMQVAL.js → chunk-54GKLIDW.js} +22 -10
  11. package/dist/chunk-54GKLIDW.js.map +1 -0
  12. package/dist/{chunk-XAWBTX3N.cjs → chunk-75ZVXZAV.cjs} +7 -7
  13. package/dist/{chunk-XAWBTX3N.cjs.map → chunk-75ZVXZAV.cjs.map} +1 -1
  14. package/dist/{chunk-YQDSN6R6.cjs → chunk-76FHWQH3.cjs} +3 -3
  15. package/dist/{chunk-YQDSN6R6.cjs.map → chunk-76FHWQH3.cjs.map} +1 -1
  16. package/dist/{chunk-EDMCKHO6.cjs → chunk-BCX5CLJJ.cjs} +15 -2
  17. package/dist/chunk-BCX5CLJJ.cjs.map +1 -0
  18. package/dist/{chunk-OPN6BGNH.js → chunk-D6OIUYNC.js} +117 -5
  19. package/dist/{chunk-OPN6BGNH.js.map → chunk-D6OIUYNC.js.map} +1 -1
  20. package/dist/{chunk-WOHMHXRZ.cjs → chunk-DDRWORUU.cjs} +30 -276
  21. package/dist/chunk-DDRWORUU.cjs.map +1 -0
  22. package/dist/{chunk-5XAAMBDO.cjs → chunk-HBNYVRLZ.cjs} +123 -11
  23. package/dist/chunk-HBNYVRLZ.cjs.map +1 -0
  24. package/dist/chunk-HEB73GKJ.js +263 -0
  25. package/dist/chunk-HEB73GKJ.js.map +1 -0
  26. package/dist/{chunk-VJHLO2R3.js → chunk-KSJSLKYI.js} +2 -2
  27. package/dist/{chunk-SIH4GPV4.js → chunk-MOLWV5LV.js} +2 -2
  28. package/dist/{chunk-CTM35DMA.js → chunk-PN4FF6YF.js} +10 -253
  29. package/dist/chunk-PN4FF6YF.js.map +1 -0
  30. package/dist/{chunk-DXZOL3VN.cjs → chunk-RSHI4OOY.cjs} +46 -34
  31. package/dist/chunk-RSHI4OOY.cjs.map +1 -0
  32. package/dist/{chunk-B3V2EHRY.js → chunk-SLSKQRMI.js} +15 -2
  33. package/dist/{chunk-B3V2EHRY.js.map → chunk-SLSKQRMI.js.map} +1 -1
  34. package/dist/{chunk-XOKUDUUI.cjs → chunk-TMA6QSNH.cjs} +3 -3
  35. package/dist/{chunk-XOKUDUUI.cjs.map → chunk-TMA6QSNH.cjs.map} +1 -1
  36. package/dist/{chunk-6BQBKROR.js → chunk-VBROBIVI.js} +3 -3
  37. package/dist/{chunk-6BQBKROR.js.map → chunk-VBROBIVI.js.map} +1 -1
  38. package/dist/chunk-WSUFQR3D.cjs +266 -0
  39. package/dist/chunk-WSUFQR3D.cjs.map +1 -0
  40. package/dist/{chunk-PRCICORG.cjs → chunk-X42KFOUO.cjs} +6 -6
  41. package/dist/{chunk-PRCICORG.cjs.map → chunk-X42KFOUO.cjs.map} +1 -1
  42. package/dist/{chunk-AB5GNXJ4.js → chunk-ZPUZ7DBO.js} +2 -2
  43. package/dist/cli/index.cjs +16 -15
  44. package/dist/cli/index.cjs.map +1 -1
  45. package/dist/cli/index.js +7 -6
  46. package/dist/cli/index.js.map +1 -1
  47. package/dist/cost/index.cjs +4 -3
  48. package/dist/cost/index.cjs.map +1 -1
  49. package/dist/cost/index.d.cts +4 -4
  50. package/dist/cost/index.d.ts +4 -4
  51. package/dist/cost/index.js +3 -2
  52. package/dist/index.cjs +12 -9
  53. package/dist/index.cjs.map +1 -1
  54. package/dist/index.d.cts +6 -6
  55. package/dist/index.d.ts +6 -6
  56. package/dist/index.js +11 -8
  57. package/dist/{modelCache-CJftI-Ko.d.cts → modelCache-sL3dBfRM.d.cts} +1 -1
  58. package/dist/{modelCache-BzRn6t_C.d.ts → modelCache-xzoTUue2.d.ts} +1 -1
  59. package/dist/{modelNameResolver-5XkBMctP.d.ts → modelNameResolver-2WroQlqt.d.ts} +2 -1
  60. package/dist/{modelNameResolver-C5CSTGFF.d.cts → modelNameResolver-Bxlehrbp.d.cts} +2 -1
  61. package/dist/models/index.cjs +7 -6
  62. package/dist/models/index.cjs.map +1 -1
  63. package/dist/models/index.d.cts +3 -3
  64. package/dist/models/index.d.ts +3 -3
  65. package/dist/models/index.js +6 -5
  66. package/dist/{resolveUsageModel-BFwf80Hz.d.ts → resolveUsageModel-DrFuiuIW.d.ts} +2 -2
  67. package/dist/{resolveUsageModel-C_YmGR1M.d.cts → resolveUsageModel-xKZ2QpHy.d.cts} +2 -2
  68. package/dist/sync/index.cjs +7 -5
  69. package/dist/sync/index.cjs.map +1 -1
  70. package/dist/sync/index.d.cts +3 -3
  71. package/dist/sync/index.d.ts +3 -3
  72. package/dist/sync/index.js +6 -4
  73. package/dist/{types-BrzJWsTU.d.ts → types-BZYGjN2O.d.cts} +21 -2
  74. package/dist/{types-BrzJWsTU.d.cts → types-BZYGjN2O.d.ts} +21 -2
  75. package/package.json +1 -1
  76. package/dist/chunk-5XAAMBDO.cjs.map +0 -1
  77. package/dist/chunk-CTM35DMA.js.map +0 -1
  78. package/dist/chunk-DXZOL3VN.cjs.map +0 -1
  79. package/dist/chunk-EDMCKHO6.cjs.map +0 -1
  80. package/dist/chunk-EYHMQVAL.js.map +0 -1
  81. package/dist/chunk-WOHMHXRZ.cjs.map +0 -1
  82. /package/dist/{chunk-VJHLO2R3.js.map → chunk-KSJSLKYI.js.map} +0 -0
  83. /package/dist/{chunk-SIH4GPV4.js.map → chunk-MOLWV5LV.js.map} +0 -0
  84. /package/dist/{chunk-AB5GNXJ4.js.map → chunk-ZPUZ7DBO.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-5XAAMBDO.cjs","../src/cache/modelCache.ts","../src/catalog/catalogSources.ts","../src/catalog/normalizeX12iCatalogModel.ts","../src/catalog/loadCatalogSources.ts","../src/data/models-catalog.json","../src/data/openrouter-models-catalog.json","../src/catalog/catalogLoadCache.ts","../src/catalog/AiModelsCatalogClient.ts"],"names":[],"mappings":"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CA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACE,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACF,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACF,IAAA;AACF,EAAA;AACF;AL2MU;AACA;AMz2BV;AACY,EAAA;AACV,EAAA;AACA,EAAA;AACA,EAAA;AACU,EAAA;AACR,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACS,EAAA;AACP,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACU,EAAA;AACR,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-5XAAMBDO.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\n/** Default in-memory catalog cache lifetime (24 hours). */\nexport const DEFAULT_CATALOG_CACHE_TTL_MS = 24 * 60 * 60 * 1000;\n\n/** @alias DEFAULT_CATALOG_CACHE_TTL_MS */\nexport const DEFAULT_MODEL_CACHE_TTL_MS = DEFAULT_CATALOG_CACHE_TTL_MS;\n\nexport function resolveCatalogCacheTtlMs(override?: number): number {\n if (override !== undefined) return override;\n const raw = process.env.AI_TOOLS_CACHE_TTL_MS;\n if (!raw) return DEFAULT_CATALOG_CACHE_TTL_MS;\n const n = Number.parseInt(raw, 10);\n return Number.isFinite(n) && n > 0 ? n : DEFAULT_CATALOG_CACHE_TTL_MS;\n}\n\nexport type ModelCacheMetadata = { cachedAt: string; count: number };\n\nexport function readCachedModels(\n scopeKey: string,\n ttlMs = DEFAULT_CATALOG_CACHE_TTL_MS,\n): Map<string, AiModelRecord> | null {\n const res = cache.read(\"ai-models\", { appId: scopeKey });\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 scopeKey: string,\n models: Map<string, AiModelRecord>,\n ttlMs = DEFAULT_CATALOG_CACHE_TTL_MS,\n): void {\n cache.write(\"ai-models\", models, {\n scope: { appId: scopeKey },\n ttlMs,\n metadata: { cachedAt: new Date().toISOString(), count: models.size },\n });\n}\n\nexport function invalidateModelsCache(scopeKey: string): void {\n cache.resetKey(\"ai-models\", { appId: scopeKey });\n}\n","/** Remote catalog URLs (primary). */\nexport const DEFAULT_DIRECT_CATALOG_URL =\n \"https://open-assets.x12i.com/models-catalog.json\";\n\nexport const DEFAULT_OPENROUTER_CATALOG_URL =\n \"https://open-assets.x12i.com/openrouter-models-catalog.json\";\n\nexport type CatalogSourceKind = \"direct\" | \"openrouter\";\n\nexport type CatalogLoadSource = {\n kind: CatalogSourceKind;\n url: string;\n /** Bundled fallback (imported JSON). */\n bundled: X12iModelsCatalogFile;\n};\n\nexport type X12iCatalogPricing = {\n input?: number | null;\n output?: number | null;\n cachedInput?: number | null;\n cacheHit?: number | null;\n cacheWrite?: number | null;\n cacheWrite5m?: number | null;\n cacheWrite1h?: number | null;\n textInput?: number | null;\n textOutput?: number | null;\n audioInput?: number | null;\n imageInput?: number | null;\n internalReasoning?: number | null;\n webSearchPerRequest?: number | null;\n inputBelow200k?: number | null;\n inputAbove200k?: number | null;\n outputBelow200k?: number | null;\n outputAbove200k?: number | null;\n [key: string]: unknown;\n};\n\nexport type X12iCatalogModelEntry = {\n provider: string;\n modelId: string;\n displayName?: string;\n canonicalSlug?: string;\n family?: string;\n status?: string;\n modalities?: string[] | { input?: string[]; output?: string[] };\n contextWindow?: number;\n maxCompletionTokens?: number;\n pricing?: X12iCatalogPricing;\n capabilities?: {\n reasoning?: boolean | string;\n toolCalling?: boolean;\n structuredOutputs?: boolean;\n };\n aliases?: string[];\n sourceUrl?: string;\n};\n\n/**\n * Raw catalog JSON from open-assets.x12i.com (or bundled `src/data`).\n *\n * `schema` and `version` are publisher metadata only — this library never reads or\n * compares them. Remote catalogs are always treated as the latest pricing source.\n */\nexport type X12iModelsCatalogFile = {\n /** Publisher schema id (informational). */\n schema?: string;\n /** Publisher catalog revision (informational; not used for cache or compatibility). */\n version?: string;\n verifiedAt?: string;\n models: X12iCatalogModelEntry[];\n [key: string]: unknown;\n};\n","import { computeSupportsReasoning } from \"../models/reasoningModel.js\";\nimport type { AiModelPricing, AiModelRecord } from \"../models/types.js\";\nimport type { OpenRouterModelApi, OpenRouterPricingApi } from \"../models/openrouter.types.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport type { CatalogSourceKind, X12iCatalogModelEntry, X12iCatalogPricing } from \"./catalogSources.js\";\n\nconst TOKENS_PER_UNIT = 1_000_000;\n\nfunction usdPerToken(perMillion?: number | null): number {\n if (perMillion == null || !Number.isFinite(perMillion)) return 0;\n return perMillion / TOKENS_PER_UNIT;\n}\n\nfunction firstRate(\n raw: X12iCatalogPricing,\n ...keys: (keyof X12iCatalogPricing)[]\n): number | undefined {\n for (const key of keys) {\n const v = raw[key];\n if (typeof v === \"number\" && Number.isFinite(v)) return v;\n }\n return undefined;\n}\n\nexport function canonicalCatalogModelId(provider: string, modelId: string): string {\n const m = normalizeString(modelId);\n if (m.includes(\"/\")) return m;\n const p = normalizeProvider(provider) ?? normalizeString(provider);\n return `${p}/${m}`;\n}\n\nfunction mapStatus(status?: string): AiModelRecord[\"status\"] {\n if (!status) return \"active\";\n const s = status.toLowerCase();\n if (s === \"deprecated\" || s === \"legacy\") return \"deprecated\";\n if (s === \"active\" || s === \"preview\" || s === \"announced\") return \"active\";\n return \"unknown\";\n}\n\nfunction mapModalities(\n modalities?: X12iCatalogModelEntry[\"modalities\"],\n): { input: string[]; output: string[]; modality: string } {\n if (Array.isArray(modalities)) {\n return {\n input: modalities,\n output: modalities.includes(\"text\") ? [\"text\"] : modalities.slice(0, 1),\n modality: modalities.join(\"+\"),\n };\n }\n if (modalities && typeof modalities === \"object\") {\n const input = modalities.input ?? [\"text\"];\n const output = modalities.output ?? [\"text\"];\n return { input, output, modality: `${input.join(\"+\")}->${output.join(\"+\")}` };\n }\n return { input: [\"text\"], output: [\"text\"], modality: \"text->text\" };\n}\n\nfunction pricingToOpenRouterApi(\n raw: X12iCatalogPricing,\n perMillion = true,\n): OpenRouterPricingApi {\n const scale = perMillion ? (n?: number) => (n ?? 0) / TOKENS_PER_UNIT : (n?: number) => n ?? 0;\n return {\n prompt: String(scale(firstRate(raw, \"input\", \"textInput\"))),\n completion: String(scale(firstRate(raw, \"output\", \"textOutput\"))),\n request: \"0\",\n image: String(scale(firstRate(raw, \"imageInput\"))),\n input_cache_read: raw.cachedInput != null ? String(scale(raw.cachedInput)) : undefined,\n input_cache_write: raw.cacheWrite != null ? String(scale(raw.cacheWrite)) : undefined,\n internal_reasoning:\n raw.internalReasoning != null ? String(scale(raw.internalReasoning)) : undefined,\n web_search:\n raw.webSearchPerRequest != null ? String(raw.webSearchPerRequest) : undefined,\n };\n}\n\nfunction pricingFromX12i(\n raw: X12iCatalogPricing,\n pricedAt: string,\n source: AiModelPricing[\"source\"],\n): AiModelPricing {\n return {\n promptUsdPerToken: usdPerToken(firstRate(raw, \"input\", \"textInput\")),\n completionUsdPerToken: usdPerToken(firstRate(raw, \"output\", \"textOutput\")),\n imageUsdPerUnit: usdPerToken(firstRate(raw, \"imageInput\")),\n requestUsdPerRequest: usdPerToken(\n typeof raw.webSearchPerRequest === \"number\" ? raw.webSearchPerRequest * 1000 : 0,\n ),\n cacheReadUsdPerToken: usdPerToken(\n firstRate(raw, \"cachedInput\", \"cacheHit\"),\n ),\n cacheWriteUsdPerToken: usdPerToken(\n firstRate(raw, \"cacheWrite\", \"cacheWrite5m\", \"cacheWrite1h\"),\n ),\n reasoningUsdPerToken: usdPerToken(raw.internalReasoning),\n webSearchUsdPerRequest:\n typeof raw.webSearchPerRequest === \"number\" ? raw.webSearchPerRequest : undefined,\n pricedAt,\n source,\n };\n}\n\nfunction stubOpenRouterApi(\n modelId: string,\n entry: X12iCatalogModelEntry,\n modalities: ReturnType<typeof mapModalities>,\n pricing: OpenRouterPricingApi,\n): OpenRouterModelApi {\n return {\n id: modelId,\n canonical_slug: entry.canonicalSlug ?? modelId,\n name: entry.displayName ?? modelId,\n created: 0,\n description: entry.displayName ?? \"\",\n context_length: entry.contextWindow ?? 0,\n architecture: {\n modality: modalities.modality,\n input_modalities: modalities.input,\n output_modalities: modalities.output,\n tokenizer: \"\",\n instruct_type: null,\n },\n pricing,\n top_provider: {\n context_length: entry.contextWindow ?? 0,\n max_completion_tokens: entry.maxCompletionTokens ?? null,\n is_moderated: false,\n },\n per_request_limits: null,\n supported_parameters: entry.capabilities?.toolCalling ? [\"tools\"] : [],\n default_parameters: null,\n };\n}\n\nexport function normalizeX12iCatalogModel(\n entry: X12iCatalogModelEntry,\n kind: CatalogSourceKind,\n verifiedAt: string,\n): AiModelRecord | null {\n const pricingRaw = entry.pricing;\n if (!pricingRaw) return null;\n\n const inputRate = firstRate(pricingRaw, \"input\", \"textInput\", \"inputBelow200k\");\n const outputRate = firstRate(pricingRaw, \"output\", \"textOutput\", \"outputBelow200k\");\n if (inputRate == null && outputRate == null) return null;\n\n const modelId = canonicalCatalogModelId(entry.provider, entry.modelId);\n const providerId =\n kind === \"openrouter\" && modelId.includes(\"/\")\n ? modelId.split(\"/\")[0]!\n : normalizeProvider(entry.provider) ?? entry.provider;\n\n const modalities = mapModalities(entry.modalities);\n const pricedAt = verifiedAt || new Date().toISOString();\n const pricingSource: AiModelPricing[\"source\"] =\n kind === \"openrouter\" ? \"openrouter\" : \"direct\";\n const pricing = pricingFromX12i(pricingRaw, pricedAt, pricingSource);\n const openRouterPricing = pricingToOpenRouterApi(pricingRaw, true);\n const openRouter = stubOpenRouterApi(modelId, entry, modalities, openRouterPricing);\n\n const supportedParameters = openRouter.supported_parameters ?? [];\n const supportsReasoning =\n entry.capabilities?.reasoning === true ||\n computeSupportsReasoning({\n supportedParameters,\n pricing,\n openRouterPricing,\n });\n\n const aliases = new Set<string>(entry.aliases ?? []);\n aliases.add(entry.modelId);\n if (entry.displayName) aliases.add(entry.displayName);\n const slash = modelId.indexOf(\"/\");\n if (slash > 0) aliases.add(modelId.slice(slash + 1));\n\n return {\n modelId,\n name: entry.displayName ?? modelId,\n providerId,\n canonicalSlug: entry.canonicalSlug ?? modelId,\n status: mapStatus(entry.status),\n description: entry.displayName ?? \"\",\n created: 0,\n expirationDate: null,\n contextLength: entry.contextWindow ?? 0,\n maxCompletionTokens: entry.maxCompletionTokens ?? null,\n isModerated: false,\n modality: modalities.modality,\n inputModalities: modalities.input,\n outputModalities: modalities.output,\n tokenizer: \"\",\n instructType: null,\n supportedParameters,\n defaultParameters: null,\n perRequestLimits: null,\n pricing,\n openRouterPricing,\n architecture: openRouter.architecture,\n topProvider: openRouter.top_provider,\n openRouter,\n aliases: [...aliases],\n availableOnOpenRouter: kind === \"openrouter\",\n supportsStreaming: modalities.output.includes(\"text\"),\n supportsTools: entry.capabilities?.toolCalling === true,\n supportsReasoning,\n primaryOutputModality: modalities.output[0] ?? \"text\",\n syncedAt: pricedAt,\n syncSource: kind === \"openrouter\" ? \"openrouter\" : \"manual\",\n };\n}\n\nexport function modelsFromX12iCatalogFile(\n file: { models: X12iCatalogModelEntry[]; verifiedAt?: string },\n kind: CatalogSourceKind,\n): Map<string, AiModelRecord> {\n const map = new Map<string, AiModelRecord>();\n const verifiedAt = file.verifiedAt ?? new Date().toISOString().slice(0, 10);\n for (const entry of file.models) {\n const record = normalizeX12iCatalogModel(entry, kind, verifiedAt);\n if (record) map.set(record.modelId, record);\n }\n return map;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n DEFAULT_DIRECT_CATALOG_URL,\n DEFAULT_OPENROUTER_CATALOG_URL,\n type CatalogLoadSource,\n type X12iModelsCatalogFile,\n} from \"./catalogSources.js\";\n\nexport { DEFAULT_DIRECT_CATALOG_URL, DEFAULT_OPENROUTER_CATALOG_URL };\nimport { modelsFromX12iCatalogFile } from \"./normalizeX12iCatalogModel.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\n\nimport bundledDirect from \"../data/models-catalog.json\" with { type: \"json\" };\nimport bundledOpenRouter from \"../data/openrouter-models-catalog.json\" with { type: \"json\" };\n\nconst dataDir = dirname(fileURLToPath(import.meta.url));\n\nexport type LoadCatalogOptions = {\n directCatalogUrl?: string;\n openRouterCatalogUrl?: string;\n /** When true, skip HTTP and use bundled `src/data` only. */\n bundledOnly?: boolean;\n fetchTimeoutMs?: number;\n};\n\nexport type LoadedCatalogs = {\n direct: Map<string, AiModelRecord>;\n openrouter: Map<string, AiModelRecord>;\n meta: {\n directSource: \"remote\" | \"bundled\";\n openRouterSource: \"remote\" | \"bundled\";\n directUrl: string;\n openRouterUrl: string;\n directCount: number;\n openRouterCount: number;\n };\n};\n\nasync function fetchCatalogJson(url: string, timeoutMs: number): Promise<X12iModelsCatalogFile> {\n const res = await fetch(url, {\n signal: AbortSignal.timeout(timeoutMs),\n headers: { accept: \"application/json\" },\n });\n if (!res.ok) {\n throw new Error(`HTTP ${res.status} fetching ${url}`);\n }\n return (await res.json()) as X12iModelsCatalogFile;\n}\n\nasync function loadOneSource(\n source: CatalogLoadSource,\n options: LoadCatalogOptions,\n): Promise<{ file: X12iModelsCatalogFile; from: \"remote\" | \"bundled\" }> {\n if (options.bundledOnly) {\n return { file: source.bundled, from: \"bundled\" };\n }\n\n try {\n const file = await fetchCatalogJson(source.url, options.fetchTimeoutMs ?? 30_000);\n return { file, from: \"remote\" };\n } catch (err) {\n console.warn(\n `[ai-tools] Failed to load ${source.kind} catalog from ${source.url} (${err instanceof Error ? err.message : err}); using bundled fallback.`,\n );\n return { file: source.bundled, from: \"bundled\" };\n }\n}\n\n/** Load direct-provider and OpenRouter catalogs (remote with bundled fallback). */\nexport async function loadCatalogSources(\n options: LoadCatalogOptions = {},\n): Promise<LoadedCatalogs> {\n const directUrl = options.directCatalogUrl ?? DEFAULT_DIRECT_CATALOG_URL;\n const openRouterUrl = options.openRouterCatalogUrl ?? DEFAULT_OPENROUTER_CATALOG_URL;\n\n const sources: CatalogLoadSource[] = [\n {\n kind: \"direct\",\n url: directUrl,\n bundled: bundledDirect as X12iModelsCatalogFile,\n },\n {\n kind: \"openrouter\",\n url: openRouterUrl,\n bundled: bundledOpenRouter as X12iModelsCatalogFile,\n },\n ];\n\n const [directLoad, orLoad] = await Promise.all(\n sources.map((s) => loadOneSource(s, options)),\n );\n\n const direct = modelsFromX12iCatalogFile(directLoad.file, \"direct\");\n const openrouter = modelsFromX12iCatalogFile(orLoad.file, \"openrouter\");\n\n return {\n direct,\n openrouter,\n meta: {\n directSource: directLoad.from,\n openRouterSource: orLoad.from,\n directUrl,\n openRouterUrl,\n directCount: direct.size,\n openRouterCount: openrouter.size,\n },\n };\n}\n\n/** Read bundled JSON from disk (CLI / tests without import assertions). */\nexport async function readBundledCatalogFiles(): Promise<LoadedCatalogs> {\n const directPath = join(dataDir, \"../data/models-catalog.json\");\n const orPath = join(dataDir, \"../data/openrouter-models-catalog.json\");\n const [directRaw, orRaw] = await Promise.all([\n readFile(directPath, \"utf8\"),\n readFile(orPath, \"utf8\"),\n ]);\n const directFile = JSON.parse(directRaw) as X12iModelsCatalogFile;\n const orFile = JSON.parse(orRaw) as X12iModelsCatalogFile;\n return {\n direct: modelsFromX12iCatalogFile(directFile, \"direct\"),\n openrouter: modelsFromX12iCatalogFile(orFile, \"openrouter\"),\n meta: {\n directSource: \"bundled\",\n openRouterSource: \"bundled\",\n directUrl: DEFAULT_DIRECT_CATALOG_URL,\n openRouterUrl: DEFAULT_OPENROUTER_CATALOG_URL,\n directCount: directFile.models.length,\n openRouterCount: orFile.models.length,\n },\n };\n}\n","{\r\n \"schema\": \"x12i.ai-models.catalog\",\r\n \"version\": \"0.1.0\",\r\n \"currency\": \"USD\",\r\n \"pricingUnit\": \"1M_tokens\",\r\n \"verifiedAt\": \"2026-05-27\",\r\n \"notes\": [\r\n \"All token prices are listed per 1M tokens unless otherwise stated.\",\r\n \"Null means pricing was not found or not public in the checked official source.\",\r\n \"Some providers price audio, image, video, search, batch, cache, and regional processing separately.\",\r\n \"This catalog intentionally does not include OpenRouter pricing.\"\r\n ],\r\n \"models\": [\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-5.5\",\r\n \"displayName\": \"GPT-5.5\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"cachedInput\": 0.5,\r\n \"output\": 30,\r\n \"batchDiscount\": \"50%\",\r\n \"priorityMultiplier\": 2.5,\r\n \"dataResidencyMultiplier\": 1.1\r\n },\r\n \"sourceUrl\": \"https://openai.com/api/pricing/\"\r\n },\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-5.5-pro\",\r\n \"displayName\": \"GPT-5.5 Pro\",\r\n \"family\": \"gpt\",\r\n \"status\": \"announced\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 30,\r\n \"output\": 180\r\n },\r\n \"sourceUrl\": \"https://openai.com/index/introducing-gpt-5-5/\"\r\n },\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-5.4\",\r\n \"displayName\": \"GPT-5.4\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"pricing\": {\r\n \"input\": 2.5,\r\n \"cachedInput\": 0.25,\r\n \"output\": 15,\r\n \"batchDiscount\": \"50%\",\r\n \"dataResidencyMultiplier\": 1.1\r\n },\r\n \"sourceUrl\": \"https://openai.com/api/pricing/\"\r\n },\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-5.4-mini\",\r\n \"displayName\": \"GPT-5.4 Mini\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"pricing\": {\r\n \"input\": 0.75,\r\n \"cachedInput\": 0.075,\r\n \"output\": 4.5,\r\n \"batchDiscount\": \"50%\",\r\n \"dataResidencyMultiplier\": 1.1\r\n },\r\n \"sourceUrl\": \"https://openai.com/api/pricing/\"\r\n },\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-realtime-2\",\r\n \"displayName\": \"GPT Realtime 2\",\r\n \"family\": \"gpt-realtime\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"audio\", \"image\"],\r\n \"pricing\": {\r\n \"textInput\": 4,\r\n \"textCachedInput\": 0.4,\r\n \"textOutput\": 24,\r\n \"audioInput\": 32,\r\n \"audioCachedInput\": 0.4,\r\n \"audioOutput\": 64,\r\n \"imageInput\": 5,\r\n \"imageCachedInput\": 0.5\r\n },\r\n \"sourceUrl\": \"https://openai.com/api/pricing/\"\r\n },\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-image-2\",\r\n \"displayName\": \"GPT Image 2\",\r\n \"family\": \"gpt-image\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"image\", \"text\"],\r\n \"pricing\": {\r\n \"imageInput\": 8,\r\n \"imageCachedInput\": 2,\r\n \"imageOutput\": 30,\r\n \"textInput\": 5,\r\n \"textCachedInput\": 1.25\r\n },\r\n \"sourceUrl\": \"https://openai.com/api/pricing/\"\r\n },\r\n\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-opus-4-7\",\r\n \"displayName\": \"Claude Opus 4.7\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"cacheWrite5m\": 6.25,\r\n \"cacheWrite1h\": 10,\r\n \"cacheHit\": 0.5,\r\n \"output\": 25,\r\n \"batchInput\": 2.5,\r\n \"batchOutput\": 12.5,\r\n \"fastModeInput\": 30,\r\n \"fastModeOutput\": 150\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-opus-4-6\",\r\n \"displayName\": \"Claude Opus 4.6\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"cacheWrite5m\": 6.25,\r\n \"cacheWrite1h\": 10,\r\n \"cacheHit\": 0.5,\r\n \"output\": 25,\r\n \"batchInput\": 2.5,\r\n \"batchOutput\": 12.5,\r\n \"fastModeInput\": 30,\r\n \"fastModeOutput\": 150\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-opus-4-5\",\r\n \"displayName\": \"Claude Opus 4.5\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"cacheWrite5m\": 6.25,\r\n \"cacheWrite1h\": 10,\r\n \"cacheHit\": 0.5,\r\n \"output\": 25,\r\n \"batchInput\": 2.5,\r\n \"batchOutput\": 12.5\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-sonnet-4-6\",\r\n \"displayName\": \"Claude Sonnet 4.6\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 3,\r\n \"cacheWrite5m\": 3.75,\r\n \"cacheWrite1h\": 6,\r\n \"cacheHit\": 0.3,\r\n \"output\": 15,\r\n \"batchInput\": 1.5,\r\n \"batchOutput\": 7.5\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-sonnet-4-5\",\r\n \"displayName\": \"Claude Sonnet 4.5\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"pricing\": {\r\n \"input\": 3,\r\n \"cacheWrite5m\": 3.75,\r\n \"cacheWrite1h\": 6,\r\n \"cacheHit\": 0.3,\r\n \"output\": 15,\r\n \"batchInput\": 1.5,\r\n \"batchOutput\": 7.5\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-haiku-4-5\",\r\n \"displayName\": \"Claude Haiku 4.5\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"cacheWrite5m\": 1.25,\r\n \"cacheWrite1h\": 2,\r\n \"cacheHit\": 0.1,\r\n \"output\": 5,\r\n \"batchInput\": 0.5,\r\n \"batchOutput\": 2.5\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-3.5-flash\",\r\n \"displayName\": \"Gemini 3.5 Flash\",\r\n \"family\": \"gemini\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\"],\r\n \"pricing\": {\r\n \"input\": 0.25,\r\n \"audioInput\": 0.5,\r\n \"output\": 1.5,\r\n \"cachedInput\": 0.025,\r\n \"audioCachedInput\": 0.05,\r\n \"cacheStoragePerHour\": 1,\r\n \"batchInput\": 0.125,\r\n \"batchAudioInput\": 0.25,\r\n \"batchOutput\": 0.75,\r\n \"googleSearchAfterFreePer1kQueries\": 14,\r\n \"googleMapsAfterFreePer1kQueries\": 14\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-3.1-pro-preview\",\r\n \"displayName\": \"Gemini 3.1 Pro Preview\",\r\n \"family\": \"gemini\",\r\n \"status\": \"preview\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\"],\r\n \"pricing\": {\r\n \"input\": 0.45,\r\n \"audioInput\": 0.9,\r\n \"output\": 2.7,\r\n \"cachedInput\": 0.045,\r\n \"audioCachedInput\": 0.09,\r\n \"cacheStoragePerHour\": 1.8,\r\n \"googleSearchAfterFreePer1kQueries\": 14,\r\n \"googleMapsAfterFreePer1kQueries\": 14\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-3.1-flash-lite-preview\",\r\n \"displayName\": \"Gemini 3.1 Flash-Lite Preview\",\r\n \"family\": \"gemini\",\r\n \"status\": \"preview\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\"],\r\n \"pricing\": {\r\n \"input\": 0.25,\r\n \"audioInput\": 0.5,\r\n \"output\": 1.5,\r\n \"cachedInput\": 0.025,\r\n \"audioCachedInput\": 0.05,\r\n \"cacheStoragePerHour\": 1,\r\n \"batchInput\": 0.125,\r\n \"batchAudioInput\": 0.25,\r\n \"batchOutput\": 0.75,\r\n \"googleSearchAfterFreePer1kQueries\": 14\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-2.5-flash\",\r\n \"displayName\": \"Gemini 2.5 Flash\",\r\n \"family\": \"gemini\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\"],\r\n \"pricing\": {\r\n \"input\": 0.1,\r\n \"audioInput\": 0.7,\r\n \"output\": 0.4,\r\n \"cachedInput\": 0.025,\r\n \"audioCachedInput\": 0.175,\r\n \"cacheStoragePerHour\": 1\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-2.5-flash-lite\",\r\n \"displayName\": \"Gemini 2.5 Flash-Lite\",\r\n \"family\": \"gemini\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\"],\r\n \"pricing\": {\r\n \"input\": 0.05,\r\n \"audioInput\": 0.35,\r\n \"output\": 0.2,\r\n \"cachedInput\": 0.025,\r\n \"audioCachedInput\": 0.175,\r\n \"cacheStoragePerHour\": 1\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-2.5-computer-use-preview-10-2025\",\r\n \"displayName\": \"Gemini 2.5 Computer Use Preview\",\r\n \"family\": \"gemini\",\r\n \"status\": \"preview\",\r\n \"modalities\": [\"text\", \"image\", \"browser-control\"],\r\n \"pricing\": {\r\n \"inputBelow200k\": 1.25,\r\n \"inputAbove200k\": 2.5,\r\n \"outputBelow200k\": 10,\r\n \"outputAbove200k\": 15\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-embedding-2\",\r\n \"displayName\": \"Gemini Embedding 2\",\r\n \"family\": \"gemini-embedding\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\", \"pdf\"],\r\n \"pricing\": {\r\n \"textInput\": 0.2,\r\n \"imageInput\": 0.45,\r\n \"audioInput\": 6.5,\r\n \"videoInput\": 12\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-embedding-001\",\r\n \"displayName\": \"Gemini Embedding\",\r\n \"family\": \"gemini-embedding\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 0.15,\r\n \"batchInput\": 0.075\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"deepseek\",\r\n \"modelId\": \"deepseek-v4-flash\",\r\n \"displayName\": \"DeepSeek V4 Flash\",\r\n \"family\": \"deepseek-v4\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"maxOutputTokens\": 384000,\r\n \"pricing\": {\r\n \"inputCacheHit\": 0.0028,\r\n \"inputCacheMiss\": 0.14,\r\n \"output\": 0.28\r\n },\r\n \"capabilities\": {\r\n \"thinkingMode\": true,\r\n \"jsonOutput\": true,\r\n \"toolCalls\": true,\r\n \"fimCompletion\": true\r\n },\r\n \"sourceUrl\": \"https://api-docs.deepseek.com/quick_start/pricing\"\r\n },\r\n {\r\n \"provider\": \"deepseek\",\r\n \"modelId\": \"deepseek-v4-pro\",\r\n \"displayName\": \"DeepSeek V4 Pro\",\r\n \"family\": \"deepseek-v4\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"maxOutputTokens\": 384000,\r\n \"pricing\": {\r\n \"inputCacheHit\": 0.003625,\r\n \"inputCacheMiss\": 0.435,\r\n \"output\": 0.87,\r\n \"note\": \"DeepSeek states the 75% reduction becomes official pricing after the promotion ends on 2026-05-31 15:59 UTC.\"\r\n },\r\n \"capabilities\": {\r\n \"thinkingMode\": true,\r\n \"jsonOutput\": true,\r\n \"toolCalls\": true,\r\n \"fimCompletion\": true\r\n },\r\n \"sourceUrl\": \"https://api-docs.deepseek.com/quick_start/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"xai\",\r\n \"modelId\": \"grok-4.3\",\r\n \"displayName\": \"Grok 4.3\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"cachedInput\": 0.2,\r\n \"output\": 2.5\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": \"configurable\",\r\n \"toolCalling\": true\r\n },\r\n \"sourceUrl\": \"https://docs.x.ai/developers/pricing\"\r\n },\r\n {\r\n \"provider\": \"xai\",\r\n \"modelId\": \"grok-build-0.1\",\r\n \"displayName\": \"Grok Build 0.1\",\r\n \"family\": \"grok-build\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"code\"],\r\n \"contextWindow\": 256000,\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"cachedInput\": 0.2,\r\n \"output\": 2\r\n },\r\n \"sourceUrl\": \"https://docs.x.ai/developers/pricing\"\r\n },\r\n {\r\n \"provider\": \"xai\",\r\n \"modelId\": \"grok-4.20-multi-agent-0309\",\r\n \"displayName\": \"Grok 4.20 Multi-Agent\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"cachedInput\": 0.2,\r\n \"output\": 2.5\r\n },\r\n \"sourceUrl\": \"https://docs.x.ai/developers/pricing\"\r\n },\r\n {\r\n \"provider\": \"xai\",\r\n \"modelId\": \"grok-4.20-0309-reasoning\",\r\n \"displayName\": \"Grok 4.20 Reasoning\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"cachedInput\": 0.2,\r\n \"output\": 2.5\r\n },\r\n \"sourceUrl\": \"https://docs.x.ai/developers/pricing\"\r\n },\r\n {\r\n \"provider\": \"xai\",\r\n \"modelId\": \"grok-4.20-0309-non-reasoning\",\r\n \"displayName\": \"Grok 4.20 Non-Reasoning\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"cachedInput\": 0.2,\r\n \"output\": 2.5\r\n },\r\n \"sourceUrl\": \"https://docs.x.ai/developers/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"cohere\",\r\n \"modelId\": \"command-a\",\r\n \"displayName\": \"Command A\",\r\n \"family\": \"command\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"output\": 2\r\n },\r\n \"sourceUrl\": \"https://cohere.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"cohere\",\r\n \"modelId\": \"command\",\r\n \"displayName\": \"Command\",\r\n \"family\": \"command\",\r\n \"status\": \"legacy\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"output\": 2\r\n },\r\n \"sourceUrl\": \"https://cohere.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"cohere\",\r\n \"modelId\": \"command-light\",\r\n \"displayName\": \"Command Light\",\r\n \"family\": \"command\",\r\n \"status\": \"legacy\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 0.3,\r\n \"output\": 0.6\r\n },\r\n \"sourceUrl\": \"https://cohere.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"cohere\",\r\n \"modelId\": \"command-r-03-2024\",\r\n \"displayName\": \"Command R 03-2024\",\r\n \"family\": \"command-r\",\r\n \"status\": \"legacy\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 0.5,\r\n \"output\": 1.5\r\n },\r\n \"sourceUrl\": \"https://cohere.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"cohere\",\r\n \"modelId\": \"command-r-plus-08-2024\",\r\n \"displayName\": \"Command R+ 08-2024\",\r\n \"family\": \"command-r\",\r\n \"status\": \"legacy\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 2.5,\r\n \"output\": 10\r\n },\r\n \"sourceUrl\": \"https://cohere.com/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"perplexity\",\r\n \"modelId\": \"sonar-pro\",\r\n \"displayName\": \"Sonar Pro\",\r\n \"family\": \"sonar\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"search\"],\r\n \"pricing\": {\r\n \"input\": 3,\r\n \"output\": 15,\r\n \"searchRequestFeePer1k\": {\r\n \"fastLow\": 6,\r\n \"fastMedium\": 10,\r\n \"fastHigh\": 14,\r\n \"proLow\": 14,\r\n \"proMedium\": 18,\r\n \"proHigh\": 22\r\n }\r\n },\r\n \"sourceUrl\": \"https://docs.perplexity.ai/docs/getting-started/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"groq\",\r\n \"modelId\": \"openai/gpt-oss-20b\",\r\n \"displayName\": \"GPT OSS 20B 128k\",\r\n \"family\": \"gpt-oss\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 128000,\r\n \"pricing\": {\r\n \"input\": 0.075,\r\n \"output\": 0.3\r\n },\r\n \"sourceUrl\": \"https://groq.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"groq\",\r\n \"modelId\": \"openai/gpt-oss-120b\",\r\n \"displayName\": \"GPT OSS 120B 128k\",\r\n \"family\": \"gpt-oss\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 128000,\r\n \"pricing\": {\r\n \"input\": 0.15,\r\n \"output\": 0.6\r\n },\r\n \"sourceUrl\": \"https://groq.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"groq\",\r\n \"modelId\": \"meta-llama/llama-4-scout-17b-16e-instruct\",\r\n \"displayName\": \"Llama 4 Scout 17Bx16E 128k\",\r\n \"family\": \"llama\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 128000,\r\n \"pricing\": {\r\n \"input\": 0.11,\r\n \"output\": 0.34\r\n },\r\n \"sourceUrl\": \"https://groq.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"groq\",\r\n \"modelId\": \"qwen/qwen3-32b\",\r\n \"displayName\": \"Qwen3 32B 131k\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 131000,\r\n \"pricing\": {\r\n \"input\": 0.29,\r\n \"output\": 0.59\r\n },\r\n \"sourceUrl\": \"https://groq.com/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"mistral\",\r\n \"modelId\": \"mistral-medium-3\",\r\n \"displayName\": \"Mistral Medium 3\",\r\n \"family\": \"mistral\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\", \"tools\"],\r\n \"pricing\": {\r\n \"input\": 0.4,\r\n \"output\": 2\r\n },\r\n \"sourceUrl\": \"https://mistral.ai/news/mistral-medium-3\"\r\n },\r\n\r\n {\r\n \"provider\": \"ai21\",\r\n \"modelId\": \"jamba-large-1.7\",\r\n \"displayName\": \"Jamba Large 1.7\",\r\n \"family\": \"jamba\",\r\n \"status\": \"needs_verification\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": null,\r\n \"output\": null\r\n },\r\n \"notes\": \"AI21 docs say pricing depends on platform/endpoints and links to account/billing; public token prices were not exposed clearly in the checked official docs.\",\r\n \"sourceUrl\": \"https://docs.ai21.com/docs/usage-cost\"\r\n }\r\n ]\r\n}","{\r\n \"schema\": \"x12i.openrouter-models.catalog\",\r\n \"version\": \"0.1.0\",\r\n \"currency\": \"USD\",\r\n \"pricingUnit\": \"1M_tokens\",\r\n \"source\": {\r\n \"provider\": \"openrouter\",\r\n \"catalogUrl\": \"https://openrouter.ai/api/v1/models\",\r\n \"pricingUrl\": \"https://openrouter.ai/pricing\",\r\n \"verifiedAt\": \"2026-05-27\",\r\n \"normalization\": \"OpenRouter pricing fields are per-token decimal strings. Values below are normalized to USD per 1M tokens.\"\r\n },\r\n \"notes\": [\r\n \"This catalog is OpenRouter-specific and should not be merged with direct-provider pricing.\",\r\n \"Router models beginning with ~ are dynamic aliases that redirect to latest model families.\",\r\n \"Models ending with :free are free OpenRouter variants and may have rate limits or availability limits.\",\r\n \"webSearch is kept as a separate field because OpenRouter exposes it separately from token pricing.\",\r\n \"This is a seed catalog. In production, generate the full file from https://openrouter.ai/api/v1/models.\"\r\n ],\r\n \"models\": [\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.7-max\",\r\n \"canonicalSlug\": \"qwen/qwen3.7-max-20260520\",\r\n \"displayName\": \"Qwen: Qwen3.7 Max\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"output\": 3.75,\r\n \"cachedInput\": 0.25,\r\n \"cacheWrite\": 1.5625\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"x-ai/grok-build-0.1\",\r\n \"canonicalSlug\": \"x-ai/grok-build-0.1-20260520\",\r\n \"displayName\": \"xAI: Grok Build 0.1\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 256000,\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"output\": 2,\r\n \"cachedInput\": 0.2,\r\n \"webSearchPerRequest\": 0.005\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"google/gemini-3.5-flash\",\r\n \"canonicalSlug\": \"google/gemini-3.5-flash-20260519\",\r\n \"displayName\": \"Google: Gemini 3.5 Flash\",\r\n \"family\": \"gemini\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\", \"file\", \"audio\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 65536,\r\n \"knowledgeCutoff\": \"2025-01-01\",\r\n \"pricing\": {\r\n \"input\": 1.5,\r\n \"output\": 9,\r\n \"imageInput\": 1.5,\r\n \"audioInput\": 3,\r\n \"cachedInput\": 0.15,\r\n \"cacheWrite\": 0.08333333333333334,\r\n \"internalReasoning\": 9,\r\n \"webSearchPerRequest\": 0.014\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"anthropic/claude-opus-4.7-fast\",\r\n \"canonicalSlug\": \"anthropic/claude-4.7-opus-fast-20260512\",\r\n \"displayName\": \"Anthropic: Claude Opus 4.7 Fast\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"maxCompletionTokens\": 128000,\r\n \"pricing\": {\r\n \"input\": 30,\r\n \"output\": 150,\r\n \"cachedInput\": 3,\r\n \"cacheWrite\": 37.5,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"perceptron/perceptron-mk1\",\r\n \"canonicalSlug\": \"perceptron/perceptron-mk1-20260512\",\r\n \"displayName\": \"Perceptron: Perceptron Mk1\",\r\n \"family\": \"perceptron\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 32768,\r\n \"maxCompletionTokens\": 8192,\r\n \"pricing\": {\r\n \"input\": 0.15,\r\n \"output\": 1.5\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"inclusionai/ring-2.6-1t\",\r\n \"canonicalSlug\": \"inclusionai/ring-2.6-1t-20260508\",\r\n \"displayName\": \"inclusionAI: Ring-2.6-1T\",\r\n \"family\": \"ring\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 0.075,\r\n \"output\": 0.625,\r\n \"cachedInput\": 0.015\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"google/gemini-3.1-flash-lite\",\r\n \"canonicalSlug\": \"google/gemini-3.1-flash-lite-20260507\",\r\n \"displayName\": \"Google: Gemini 3.1 Flash Lite\",\r\n \"family\": \"gemini\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\", \"file\", \"audio\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 0.25,\r\n \"output\": 1.5,\r\n \"imageInput\": 0.25,\r\n \"audioInput\": 0.5,\r\n \"cachedInput\": 0.025,\r\n \"cacheWrite\": 0.08333333333333334,\r\n \"internalReasoning\": 1.5,\r\n \"webSearchPerRequest\": 0.014\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"openai/gpt-chat-latest\",\r\n \"canonicalSlug\": \"openai/gpt-chat-latest-20260505\",\r\n \"displayName\": \"OpenAI: GPT Chat Latest\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 400000,\r\n \"maxCompletionTokens\": 128000,\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"output\": 30,\r\n \"cachedInput\": 0.5,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"x-ai/grok-4.3\",\r\n \"canonicalSlug\": \"x-ai/grok-4.3-20260430\",\r\n \"displayName\": \"xAI: Grok 4.3\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"output\": 2.5,\r\n \"cachedInput\": 0.2,\r\n \"webSearchPerRequest\": 0.005\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"ibm-granite/granite-4.1-8b\",\r\n \"canonicalSlug\": \"ibm-granite/granite-4.1-8b-20260429\",\r\n \"displayName\": \"IBM: Granite 4.1 8B\",\r\n \"family\": \"granite\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 131072,\r\n \"maxCompletionTokens\": 131072,\r\n \"pricing\": {\r\n \"input\": 0.05,\r\n \"output\": 0.1,\r\n \"cachedInput\": 0.05\r\n },\r\n \"capabilities\": {\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"mistralai/mistral-medium-3-5\",\r\n \"canonicalSlug\": \"mistralai/mistral-medium-3.5-20260430\",\r\n \"displayName\": \"Mistral: Mistral Medium 3.5\",\r\n \"family\": \"mistral\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"pricing\": {\r\n \"input\": 1.5,\r\n \"output\": 7.5\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"openrouter/owl-alpha\",\r\n \"canonicalSlug\": \"openrouter/owl-alpha\",\r\n \"displayName\": \"Owl Alpha\",\r\n \"family\": \"owl\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048756,\r\n \"maxCompletionTokens\": 262144,\r\n \"pricing\": {\r\n \"input\": 0,\r\n \"output\": 0\r\n },\r\n \"capabilities\": {\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~anthropic/claude-haiku-latest\",\r\n \"canonicalSlug\": \"~anthropic/claude-haiku-latest\",\r\n \"displayName\": \"Anthropic Claude Haiku Latest\",\r\n \"family\": \"claude-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 200000,\r\n \"maxCompletionTokens\": 64000,\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"output\": 5,\r\n \"cachedInput\": 0.1,\r\n \"cacheWrite\": 1.25,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~openai/gpt-mini-latest\",\r\n \"canonicalSlug\": \"~openai/gpt-mini-latest\",\r\n \"displayName\": \"OpenAI GPT Mini Latest\",\r\n \"family\": \"gpt-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 400000,\r\n \"maxCompletionTokens\": 128000,\r\n \"knowledgeCutoff\": \"2025-08-31\",\r\n \"pricing\": {\r\n \"input\": 0.75,\r\n \"output\": 4.5,\r\n \"cachedInput\": 0.075,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~google/gemini-pro-latest\",\r\n \"canonicalSlug\": \"~google/gemini-pro-latest\",\r\n \"displayName\": \"Google Gemini Pro Latest\",\r\n \"family\": \"gemini-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\", \"audio\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 2,\r\n \"output\": 12,\r\n \"imageInput\": 2,\r\n \"audioInput\": 2,\r\n \"cachedInput\": 0.2,\r\n \"cacheWrite\": 0.375,\r\n \"internalReasoning\": 12,\r\n \"webSearchPerRequest\": 0.014\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~moonshotai/kimi-latest\",\r\n \"canonicalSlug\": \"~moonshotai/kimi-latest\",\r\n \"displayName\": \"MoonshotAI Kimi Latest\",\r\n \"family\": \"kimi-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 262142,\r\n \"pricing\": {\r\n \"input\": 0.73,\r\n \"output\": 3.49,\r\n \"cachedInput\": 0.25\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~google/gemini-flash-latest\",\r\n \"canonicalSlug\": \"~google/gemini-flash-latest\",\r\n \"displayName\": \"Google Gemini Flash Latest\",\r\n \"family\": \"gemini-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\", \"file\", \"audio\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 65536,\r\n \"knowledgeCutoff\": \"2025-01-01\",\r\n \"pricing\": {\r\n \"input\": 1.5,\r\n \"output\": 9,\r\n \"imageInput\": 1.5,\r\n \"audioInput\": 3,\r\n \"cachedInput\": 0.15,\r\n \"cacheWrite\": 0.08333333333333334,\r\n \"internalReasoning\": 9,\r\n \"webSearchPerRequest\": 0.014\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~anthropic/claude-sonnet-latest\",\r\n \"canonicalSlug\": \"~anthropic/claude-sonnet-latest\",\r\n \"displayName\": \"Anthropic Claude Sonnet Latest\",\r\n \"family\": \"claude-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"maxCompletionTokens\": 128000,\r\n \"pricing\": {\r\n \"input\": 3,\r\n \"output\": 15,\r\n \"cachedInput\": 0.3,\r\n \"cacheWrite\": 3.75,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~openai/gpt-latest\",\r\n \"canonicalSlug\": \"~openai/gpt-latest\",\r\n \"displayName\": \"OpenAI GPT Latest\",\r\n \"family\": \"gpt-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1050000,\r\n \"maxCompletionTokens\": 128000,\r\n \"knowledgeCutoff\": \"2025-12-01\",\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"output\": 30,\r\n \"cachedInput\": 0.5,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.5-plus-20260420\",\r\n \"canonicalSlug\": \"qwen/qwen3.5-plus-20260420\",\r\n \"displayName\": \"Qwen: Qwen3.5 Plus 2026-04-20\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 0.3,\r\n \"output\": 1.8,\r\n \"cacheWrite\": 0.375\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.6-flash\",\r\n \"canonicalSlug\": \"qwen/qwen3.6-flash\",\r\n \"displayName\": \"Qwen: Qwen3.6 Flash\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 0.1875,\r\n \"output\": 1.125,\r\n \"cacheWrite\": 0.234375\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.6-35b-a3b\",\r\n \"canonicalSlug\": \"qwen/qwen3.6-35b-a3b-20260415\",\r\n \"displayName\": \"Qwen: Qwen3.6 35B A3B\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 262140,\r\n \"pricing\": {\r\n \"input\": 0.14,\r\n \"output\": 1\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.6-max-preview\",\r\n \"canonicalSlug\": \"qwen/qwen3.6-max-preview-20260420\",\r\n \"displayName\": \"Qwen: Qwen3.6 Max Preview\",\r\n \"family\": \"qwen\",\r\n \"status\": \"preview\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 1.04,\r\n \"output\": 6.24,\r\n \"cacheWrite\": 1.3\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.6-27b\",\r\n \"canonicalSlug\": \"qwen/qwen3.6-27b-20260422\",\r\n \"displayName\": \"Qwen: Qwen3.6 27B\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 262140,\r\n \"pricing\": {\r\n \"input\": 0.29,\r\n \"output\": 3.2\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"openai/gpt-5.5-pro\",\r\n \"canonicalSlug\": \"openai/gpt-5.5-pro-20260423\",\r\n \"displayName\": \"OpenAI: GPT-5.5 Pro\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1050000,\r\n \"maxCompletionTokens\": 128000,\r\n \"knowledgeCutoff\": \"2025-12-01\",\r\n \"pricing\": {\r\n \"input\": 30,\r\n \"output\": 180,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"openai/gpt-5.5\",\r\n \"canonicalSlug\": \"openai/gpt-5.5-20260423\",\r\n \"displayName\": \"OpenAI: GPT-5.5\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1050000,\r\n \"maxCompletionTokens\": 128000,\r\n \"knowledgeCutoff\": \"2025-12-01\",\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"output\": 30,\r\n \"cachedInput\": 0.5,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"deepseek/deepseek-v4-pro\",\r\n \"canonicalSlug\": \"deepseek/deepseek-v4-pro-20260423\",\r\n \"displayName\": \"DeepSeek: DeepSeek V4 Pro\",\r\n \"family\": \"deepseek\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 384000,\r\n \"pricing\": {\r\n \"input\": 0.435,\r\n \"output\": 0.87,\r\n \"cachedInput\": 0.003625\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"deepseek/deepseek-v4-flash\",\r\n \"canonicalSlug\": \"deepseek/deepseek-v4-flash-20260423\",\r\n \"displayName\": \"DeepSeek: DeepSeek V4 Flash\",\r\n \"family\": \"deepseek\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 16384,\r\n \"pricing\": {\r\n \"input\": 0.1,\r\n \"output\": 0.2,\r\n \"cachedInput\": 0.02\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"deepseek/deepseek-v4-flash:free\",\r\n \"canonicalSlug\": \"deepseek/deepseek-v4-flash-20260423\",\r\n \"displayName\": \"DeepSeek: DeepSeek V4 Flash Free\",\r\n \"family\": \"deepseek\",\r\n \"status\": \"free\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 384000,\r\n \"pricing\": {\r\n \"input\": 0,\r\n \"output\": 0\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"inclusionai/ling-2.6-1t\",\r\n \"canonicalSlug\": \"inclusionai/ling-2.6-1t-20260423\",\r\n \"displayName\": \"inclusionAI: Ling-2.6-1T\",\r\n \"family\": \"ling\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 32768,\r\n \"pricing\": {\r\n \"input\": 0.075,\r\n \"output\": 0.625,\r\n \"cachedInput\": 0.015\r\n },\r\n \"capabilities\": {\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"tencent/hy3-preview\",\r\n \"canonicalSlug\": \"tencent/hy3-preview-20260421\",\r\n \"displayName\": \"Tencent: Hy3 Preview\",\r\n \"family\": \"hy3\",\r\n \"status\": \"preview\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 262144,\r\n \"pricing\": {\r\n \"input\": 0.066,\r\n \"output\": 0.26,\r\n \"cachedInput\": 0.029\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"xiaomi/mimo-v2.5-pro\",\r\n \"canonicalSlug\": \"xiaomi/mimo-v2.5-pro-20260422\",\r\n \"displayName\": \"Xiaomi: MiMo-V2.5-Pro\",\r\n \"family\": \"mimo\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 131072,\r\n \"pricing\": {\r\n \"input\": 0.435,\r\n \"output\": 0.87,\r\n \"cachedInput\": 0.0036\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"xiaomi/mimo-v2.5\",\r\n \"canonicalSlug\": \"xiaomi/mimo-v2.5-20260422\",\r\n \"displayName\": \"Xiaomi: MiMo-V2.5\",\r\n \"family\": \"mimo\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"audio\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 131072,\r\n \"pricing\": {\r\n \"input\": 0.14,\r\n \"output\": 0.28,\r\n \"cachedInput\": 0.0028\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"openai/gpt-5.4-image-2\",\r\n \"canonicalSlug\": \"openai/gpt-5.4-image-2-20260421\",\r\n \"displayName\": \"OpenAI: GPT-5.4 Image 2\",\r\n \"family\": \"gpt-image\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\", \"image\"]\r\n },\r\n \"contextWindow\": 272000,\r\n \"pricing\": {\r\n \"input\": 8,\r\n \"output\": 15\r\n },\r\n \"capabilities\": {\r\n \"imageGeneration\": true,\r\n \"structuredOutputs\": true\r\n }\r\n }\r\n ]\r\n}","import { resolveCatalogCacheTtlMs } from \"../cache/modelCache.js\";\nimport { loadCatalogSources, type LoadCatalogOptions, type LoadedCatalogs } from \"./loadCatalogSources.js\";\n\ntype CacheSlot = {\n loadedAt: number;\n data: LoadedCatalogs;\n};\n\nconst slots = new Map<string, CacheSlot>();\nconst inflight = new Map<string, Promise<LoadedCatalogs>>();\n\nfunction slotKey(options: LoadCatalogOptions, cacheKey: string): string {\n return [\n cacheKey,\n options.bundledOnly ? \"bundled\" : \"remote\",\n options.directCatalogUrl ?? \"\",\n options.openRouterCatalogUrl ?? \"\",\n ].join(\"\\0\");\n}\n\nexport function invalidateCatalogLoadCache(cacheKey = \"default\"): void {\n for (const key of [...slots.keys()]) {\n if (key.startsWith(`${cacheKey}\\0`)) slots.delete(key);\n }\n for (const key of [...inflight.keys()]) {\n if (key.startsWith(`${cacheKey}\\0`)) inflight.delete(key);\n }\n}\n\nexport type LoadCatalogCachedOptions = {\n cacheKey?: string;\n ttlMs?: number;\n /** Bypass cache and fetch again (e.g. `catalog refresh`). */\n forceRefresh?: boolean;\n};\n\n/**\n * Load catalogs with a process-wide in-memory cache.\n * Remote fetches run at most once per TTL window (default 24h); concurrent callers share one in-flight request.\n */\nexport async function loadCatalogSourcesCached(\n options: LoadCatalogOptions = {},\n cacheOptions: LoadCatalogCachedOptions = {},\n): Promise<LoadedCatalogs> {\n if (options.bundledOnly) {\n return loadCatalogSources(options);\n }\n\n const ttlMs = resolveCatalogCacheTtlMs(cacheOptions.ttlMs);\n const key = slotKey(options, cacheOptions.cacheKey ?? \"default\");\n\n if (!cacheOptions.forceRefresh) {\n const slot = slots.get(key);\n if (slot && Date.now() - slot.loadedAt < ttlMs) {\n return slot.data;\n }\n } else {\n slots.delete(key);\n inflight.delete(key);\n }\n\n const pending = inflight.get(key);\n if (pending) return pending;\n\n const promise = loadCatalogSources(options)\n .then((data) => {\n slots.set(key, { loadedAt: Date.now(), data });\n inflight.delete(key);\n return data;\n })\n .catch((err) => {\n inflight.delete(key);\n throw err;\n });\n\n inflight.set(key, promise);\n return promise;\n}\n","import { resolveCatalogCacheTtlMs, writeCachedModels } from \"../cache/modelCache.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\nimport { ModelNameResolver } from \"../sync/modelNameResolver/ModelNameResolver.js\";\nimport { normalizeProvider } from \"../sync/modelNameResolver/normalize.js\";\nimport type {\n ModelResolutionInput,\n ModelResolutionResult,\n ModelResolverOptions,\n} from \"../sync/modelNameResolver/types.js\";\nimport {\n invalidateCatalogLoadCache,\n loadCatalogSourcesCached,\n} from \"./catalogLoadCache.js\";\nimport type { LoadCatalogOptions } from \"./loadCatalogSources.js\";\n\nexport type AiModelsCatalogClientOptions = LoadCatalogOptions & {\n cacheTtlMs?: number;\n /** Cache scope key (default: `default`). */\n cacheKey?: string;\n resolverOptions?: Omit<ModelResolverOptions, \"aliasRegistry\">;\n};\n\nfunction isOpenRouterProvider(provider?: string): boolean {\n return normalizeProvider(provider) === \"openrouter\";\n}\n\nexport class AiModelsCatalogClient {\n private readonly cacheTtlMs: number;\n private readonly cacheKey: string;\n private readonly loadOptions: LoadCatalogOptions;\n private readonly resolverOptions?: ModelResolverOptions;\n\n private directModels: Map<string, AiModelRecord> | null = null;\n private openRouterModels: Map<string, AiModelRecord> | null = null;\n private loadedAt = 0;\n private loadPromise: Promise<void> | null = null;\n\n constructor(options: AiModelsCatalogClientOptions = {}) {\n this.cacheTtlMs = resolveCatalogCacheTtlMs(options.cacheTtlMs);\n this.cacheKey = options.cacheKey ?? \"default\";\n this.loadOptions = {\n directCatalogUrl: options.directCatalogUrl,\n openRouterCatalogUrl: options.openRouterCatalogUrl,\n bundledOnly: options.bundledOnly,\n fetchTimeoutMs: options.fetchTimeoutMs,\n };\n this.resolverOptions = options.resolverOptions;\n }\n\n private isInstanceCacheValid(): boolean {\n return (\n this.directModels !== null &&\n this.openRouterModels !== null &&\n Date.now() - this.loadedAt < this.cacheTtlMs\n );\n }\n\n private applyLoaded(\n direct: Map<string, AiModelRecord>,\n openrouter: Map<string, AiModelRecord>,\n ): void {\n this.directModels = direct;\n this.openRouterModels = openrouter;\n this.loadedAt = Date.now();\n writeCachedModels(`${this.cacheKey}:direct`, direct, this.cacheTtlMs);\n writeCachedModels(`${this.cacheKey}:openrouter`, openrouter, this.cacheTtlMs);\n }\n\n private async ensureLoaded(forceRefresh = false): Promise<void> {\n if (!forceRefresh && this.isInstanceCacheValid()) return;\n\n if (this.loadPromise) return this.loadPromise;\n\n this.loadPromise = (async () => {\n const loaded = await loadCatalogSourcesCached(this.loadOptions, {\n cacheKey: this.cacheKey,\n ttlMs: this.cacheTtlMs,\n forceRefresh,\n });\n this.applyLoaded(loaded.direct, loaded.openrouter);\n })().finally(() => {\n this.loadPromise = null;\n });\n\n await this.loadPromise;\n }\n\n mergedModels(): Map<string, AiModelRecord> {\n const map = new Map<string, AiModelRecord>();\n for (const r of this.directModels?.values() ?? []) {\n map.set(r.modelId, r);\n }\n for (const r of this.openRouterModels?.values() ?? []) {\n map.set(r.modelId, r);\n }\n return map;\n }\n\n private catalogForProvider(provider?: string): Map<string, AiModelRecord> {\n if (isOpenRouterProvider(provider)) {\n return this.openRouterModels ?? new Map();\n }\n return this.directModels ?? new Map();\n }\n\n private resolver(\n models: Map<string, AiModelRecord>,\n options?: ModelResolverOptions,\n ): ModelNameResolver {\n return new ModelNameResolver(models, { ...this.resolverOptions, ...options });\n }\n\n async getAllModels(): Promise<Map<string, AiModelRecord>> {\n await this.ensureLoaded();\n return this.mergedModels();\n }\n\n async getDirectModels(): Promise<Map<string, AiModelRecord>> {\n await this.ensureLoaded();\n return new Map(this.directModels);\n }\n\n async getOpenRouterModels(): Promise<Map<string, AiModelRecord>> {\n await this.ensureLoaded();\n return new Map(this.openRouterModels);\n }\n\n async resolveModel(\n input: ModelResolutionInput,\n options?: ModelResolverOptions,\n ): Promise<ModelResolutionResult> {\n await this.ensureLoaded();\n\n const primary = this.catalogForProvider(input.provider);\n const secondary = isOpenRouterProvider(input.provider)\n ? (this.directModels ?? new Map())\n : (this.openRouterModels ?? new Map());\n\n let result = this.resolver(primary, options).resolve(input);\n if (result.found && result.record) return result;\n\n if (secondary.size > 0) {\n const fallback = this.resolver(secondary, options).resolve(input);\n if (fallback.found && fallback.record) return fallback;\n if (!result.found && fallback.found) result = fallback;\n }\n\n if (!result.found) {\n result = this.resolver(this.mergedModels(), options).resolve(input);\n }\n\n return result;\n }\n\n async getModel(\n modelId: string,\n provider?: string,\n options?: ModelResolverOptions,\n ): Promise<AiModelRecord | null> {\n const result = await this.resolveModel({ model: modelId, provider }, options);\n return result.found ? result.record : null;\n }\n\n /** Clear caches and fetch catalogs again immediately. */\n async refresh(): Promise<void> {\n invalidateCatalogLoadCache(this.cacheKey);\n this.directModels = null;\n this.openRouterModels = null;\n this.loadedAt = 0;\n this.loadPromise = null;\n await this.ensureLoaded(true);\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cost/constants.ts","../src/cost/enrichCostResult.ts","../src/cost/extractUsageInput.ts","../src/cost/resolveUsageModel.ts","../src/cost/aiProfilesMatch.ts","../src/cost/costModelResolution.ts","../src/cost/profilePricing.ts","../src/cost/CostCalculator.ts"],"sourcesContent":["/** Default OpenRouter platform surcharge when catalog markup fields are absent (5%). */\nexport const DEFAULT_OPENROUTER_MARKUP_RATE = 0.05;\n\n/** ai-profiles tiered pricing threshold (tokens). */\nexport const PROFILE_TIERED_CONTEXT_THRESHOLD = 200_000;\n","import type { ExtractUsageInputResult } from \"./extractUsageInput.js\";\nimport type { AiCostExtraction, AiCostResult, AiUsageInput } from \"./types.js\";\n\nexport function toCostExtraction(\n provenance: ExtractUsageInputResult[\"provenance\"],\n): AiCostExtraction {\n return {\n model: { field: provenance.model.field, path: provenance.model.path },\n tokens: {\n source: provenance.tokens.source,\n path: provenance.tokens.path,\n estimated: provenance.tokens.estimated,\n },\n ...(provenance.modelUsed\n ? {\n modelUsed: {\n field: provenance.modelUsed.field,\n path: provenance.modelUsed.path,\n },\n }\n : {}),\n ...(provenance.provider\n ? {\n provider: {\n field: provenance.provider.field,\n path: provenance.provider.path,\n },\n }\n : {}),\n };\n}\n\n/** Attach usage, provider, and model fields callers expect on every cost response. */\nexport function enrichCostResult(\n result: Omit<\n AiCostResult,\n \"usage\" | \"provider\" | \"usedModel\" | \"model\" | \"extraction\"\n >,\n input: AiUsageInput,\n extraction?: AiCostExtraction,\n): AiCostResult {\n /** Original model id from the caller — never replaced by catalog resolution. */\n const receivedModelId = input.usedModel ?? input.modelUsed ?? input.model;\n\n return {\n ...result,\n provider: input.provider,\n usage: { ...input.tokens },\n ...(receivedModelId ? { usedModel: receivedModelId } : {}),\n ...(input.model && input.model !== receivedModelId ? { model: input.model } : {}),\n ...(extraction ? { extraction } : {}),\n };\n}\n","import type { AiUsageInput } from \"./types.js\";\n\n/** Model id field priority (higher wins). Runtime ids beat request/config aliases. */\nexport const MODEL_FIELD_PRIORITY: readonly { key: string; score: number }[] = [\n { key: \"usedModel\", score: 1000 },\n { key: \"modelUsed\", score: 990 },\n { key: \"resolvedModel\", score: 980 },\n { key: \"model\", score: 500 },\n { key: \"xynthesisModel\", score: 120 },\n { key: \"skillModel\", score: 110 },\n] as const;\n\n/** Path segments that boost or penalize a model candidate. */\nconst MODEL_PATH_BONUS: readonly { pattern: RegExp; bonus: number }[] = [\n { pattern: /(^|\\.)response(\\.|$)/i, bonus: 40 },\n { pattern: /(^|\\.)outer\\.input(\\.|$)/i, bonus: 35 },\n { pattern: /(^|\\.)config(?!\\.rawConfig)(\\.|$)/i, bonus: 30 },\n { pattern: /(^|\\.)outer\\.input\\.config(\\.|$)/i, bonus: 28 },\n { pattern: /(^|\\.)usage(\\.|$)/i, bonus: 15 },\n { pattern: /(^|\\.)rawConfig(\\.|$)/i, bonus: -40 },\n { pattern: /workingMemory/i, bonus: -50 },\n { pattern: /requestExample/i, bonus: -80 },\n { pattern: /graphsStudio/i, bonus: -80 },\n];\n\nconst PROVIDER_FIELD_PRIORITY: readonly { key: string; score: number }[] = [\n { key: \"provider\", score: 500 },\n { key: \"providerId\", score: 480 },\n] as const;\n\nconst PROVIDER_PATH_BONUS: readonly { pattern: RegExp; bonus: number }[] = [\n { pattern: /(^|\\.)config(?!\\.rawConfig)(\\.|$)/i, bonus: 30 },\n { pattern: /(^|\\.)outer\\.input(\\.|$)/i, bonus: 20 },\n { pattern: /(^|\\.)rawConfig(\\.|$)/i, bonus: -20 },\n];\n\nconst PROMPT_TOKEN_KEYS = new Set([\n \"prompt\",\n \"prompt_tokens\",\n \"promptTokens\",\n \"input_tokens\",\n \"inputTokens\",\n \"estimatedInputTokens\",\n \"input\",\n]);\n\nconst COMPLETION_TOKEN_KEYS = new Set([\n \"completion\",\n \"completion_tokens\",\n \"completionTokens\",\n \"output_tokens\",\n \"outputTokens\",\n \"estimatedOutputTokens\",\n \"output\",\n]);\n\nconst OPTIONAL_TOKEN_KEYS: Record<string, keyof AiUsageInput[\"tokens\"]> = {\n total: \"total\",\n total_tokens: \"total\",\n totalTokens: \"total\",\n cached: \"cached\",\n cached_tokens: \"cached\",\n cache_read_tokens: \"cached\",\n cacheReadTokens: \"cached\",\n cacheWrite: \"cacheWrite\",\n cache_write_tokens: \"cacheWrite\",\n cacheWriteTokens: \"cacheWrite\",\n reasoning: \"reasoning\",\n reasoning_tokens: \"reasoning\",\n reasoningTokens: \"reasoning\",\n audio: \"audio\",\n audio_tokens: \"audio\",\n image: \"image\",\n image_tokens: \"image\",\n};\n\nexport type FieldProvenance = {\n field: string;\n path: string;\n score: number;\n};\n\nexport type TokenExtractionProvenance = {\n source: \"usage\" | \"tokens\" | \"diagnostics\" | \"estimated\";\n path: string;\n estimated?: boolean;\n};\n\nexport type ExtractUsageInputResult = {\n input: AiUsageInput;\n provenance: {\n model: FieldProvenance;\n modelUsed?: FieldProvenance;\n provider?: FieldProvenance;\n tokens: TokenExtractionProvenance;\n };\n};\n\nexport type ExtractUsageInputOptions = {\n /** Default when no provider field is found (default: `openrouter`). */\n defaultProvider?: string;\n};\n\ntype ModelCandidate = FieldProvenance & { value: string };\ntype ProviderCandidate = FieldProvenance & { value: string };\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === \"object\" && !Array.isArray(v);\n}\n\nfunction modelKeyScore(key: string): number {\n return MODEL_FIELD_PRIORITY.find((e) => e.key === key)?.score ?? 0;\n}\n\nfunction providerKeyScore(key: string): number {\n return PROVIDER_FIELD_PRIORITY.find((e) => e.key === key)?.score ?? 0;\n}\n\nfunction pathBonus(path: string, rules: readonly { pattern: RegExp; bonus: number }[]): number {\n let bonus = 0;\n for (const { pattern, bonus: b } of rules) {\n if (pattern.test(path)) bonus += b;\n }\n return bonus;\n}\n\nfunction normalizeModelValue(v: unknown): string | undefined {\n if (typeof v !== \"string\") return undefined;\n const t = v.trim();\n return t.length > 0 ? t : undefined;\n}\n\nfunction normalizeProviderValue(v: unknown): string | undefined {\n if (typeof v !== \"string\") return undefined;\n const t = v.trim().toLowerCase();\n if (!t || t === \"null\") return undefined;\n return t;\n}\n\nfunction collectModelCandidates(\n node: unknown,\n path: string,\n out: ModelCandidate[],\n depth: number,\n maxDepth: number,\n): void {\n if (depth > maxDepth || node === null || node === undefined) return;\n\n if (isPlainObject(node)) {\n for (const [key, value] of Object.entries(node)) {\n const childPath = path ? `${path}.${key}` : key;\n const base = modelKeyScore(key);\n if (base > 0) {\n const model = normalizeModelValue(value);\n if (model) {\n out.push({\n field: key,\n path: childPath,\n value: model,\n score: base + pathBonus(childPath, MODEL_PATH_BONUS),\n });\n }\n }\n collectModelCandidates(value, childPath, out, depth + 1, maxDepth);\n }\n return;\n }\n\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n collectModelCandidates(node[i], `${path}[${i}]`, out, depth + 1, maxDepth);\n }\n }\n}\n\nfunction collectProviderCandidates(\n node: unknown,\n path: string,\n out: ProviderCandidate[],\n depth: number,\n maxDepth: number,\n): void {\n if (depth > maxDepth || node === null || node === undefined) return;\n\n if (isPlainObject(node)) {\n for (const [key, value] of Object.entries(node)) {\n const childPath = path ? `${path}.${key}` : key;\n const base = providerKeyScore(key);\n if (base > 0) {\n const provider = normalizeProviderValue(value);\n if (provider) {\n out.push({\n field: key,\n path: childPath,\n value: provider,\n score: base + pathBonus(childPath, PROVIDER_PATH_BONUS),\n });\n }\n }\n collectProviderCandidates(value, childPath, out, depth + 1, maxDepth);\n }\n return;\n }\n\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n collectProviderCandidates(node[i], `${path}[${i}]`, out, depth + 1, maxDepth);\n }\n }\n}\n\nfunction readNumber(obj: Record<string, unknown>, keys: Set<string>): number | undefined {\n for (const [k, v] of Object.entries(obj)) {\n if (!keys.has(k)) continue;\n if (typeof v === \"number\" && Number.isFinite(v) && v >= 0) return v;\n }\n return undefined;\n}\n\nfunction readOptionalNumbers(\n obj: Record<string, unknown>,\n): Partial<AiUsageInput[\"tokens\"]> {\n const extra: Partial<AiUsageInput[\"tokens\"]> = {};\n for (const [k, v] of Object.entries(obj)) {\n const target = OPTIONAL_TOKEN_KEYS[k];\n if (!target || typeof v !== \"number\" || !Number.isFinite(v) || v < 0) continue;\n extra[target] = v;\n }\n return extra;\n}\n\nfunction looksLikeUsageObject(obj: Record<string, unknown>): boolean {\n const hasPrompt = readNumber(obj, PROMPT_TOKEN_KEYS) !== undefined;\n const hasCompletion = readNumber(obj, COMPLETION_TOKEN_KEYS) !== undefined;\n return hasPrompt && hasCompletion;\n}\n\nfunction looksLikeDiagnosticsObject(obj: Record<string, unknown>): boolean {\n return (\n typeof obj.estimatedInputTokens === \"number\" &&\n typeof obj.estimatedOutputTokens === \"number\"\n );\n}\n\ntype TokenCandidate = {\n tokens: AiUsageInput[\"tokens\"];\n provenance: TokenExtractionProvenance;\n score: number;\n};\n\nfunction tokensFromObject(\n obj: Record<string, unknown>,\n source: TokenExtractionProvenance[\"source\"],\n path: string,\n estimated: boolean,\n score: number,\n): TokenCandidate | null {\n const prompt = readNumber(obj, PROMPT_TOKEN_KEYS);\n const completion = readNumber(obj, COMPLETION_TOKEN_KEYS);\n if (prompt === undefined || completion === undefined) return null;\n\n const extra = readOptionalNumbers(obj);\n const total =\n typeof extra.total === \"number\" ? extra.total : prompt + completion;\n\n return {\n tokens: {\n prompt,\n completion,\n total,\n ...extra,\n },\n provenance: { source, path, estimated },\n score,\n };\n}\n\nfunction collectTokenCandidates(\n node: unknown,\n path: string,\n out: TokenCandidate[],\n depth: number,\n maxDepth: number,\n): void {\n if (depth > maxDepth || node === null || node === undefined) return;\n\n if (isPlainObject(node)) {\n if (path.endsWith(\"diagnostics\") || looksLikeDiagnosticsObject(node)) {\n const cand = tokensFromObject(node, \"diagnostics\", path, true, 200);\n if (cand) out.push(cand);\n } else if (path.endsWith(\"usage\") || path.endsWith(\"tokens\") || looksLikeUsageObject(node)) {\n const source = path.endsWith(\"tokens\") ? \"tokens\" : \"usage\";\n const estimated = false;\n const score = path.endsWith(\"usage\") ? 500 : 450;\n const cand = tokensFromObject(node, source, path, estimated, score);\n if (cand) out.push(cand);\n }\n\n for (const [key, value] of Object.entries(node)) {\n const childPath = path ? `${path}.${key}` : key;\n if (key === \"usage\" || key === \"tokens\" || key === \"diagnostics\") {\n if (isPlainObject(value)) {\n collectTokenCandidates(value, childPath, out, depth + 1, maxDepth);\n }\n } else {\n collectTokenCandidates(value, childPath, out, depth + 1, maxDepth);\n }\n }\n return;\n }\n\n if (Array.isArray(node)) {\n for (let i = 0; i < node.length; i++) {\n collectTokenCandidates(node[i], `${path}[${i}]`, out, depth + 1, maxDepth);\n }\n }\n}\n\nfunction pickBestModel(candidates: ModelCandidate[]): ModelCandidate | null {\n if (candidates.length === 0) return null;\n return [...candidates].sort((a, b) => b.score - a.score)[0]!;\n}\n\nfunction pickBestProvider(candidates: ProviderCandidate[]): ProviderCandidate | null {\n if (candidates.length === 0) return null;\n return [...candidates].sort((a, b) => b.score - a.score)[0]!;\n}\n\nfunction pickBestTokens(candidates: TokenCandidate[]): TokenCandidate | null {\n if (candidates.length === 0) return null;\n return [...candidates].sort((a, b) => b.score - a.score)[0]!;\n}\n\nfunction inferProviderFromModel(model: string, fallback: string): string {\n const slash = model.indexOf(\"/\");\n if (slash > 0) {\n const prefix = model.slice(0, slash).toLowerCase();\n if (prefix !== \"openrouter\") return prefix;\n }\n return fallback;\n}\n\n/**\n * Extract {@link AiUsageInput} from activity logs, gateway records, MongoDB exports,\n * or any nested JSON shape (e.g. `outer.input`, `config`, `metadata.diagnostics`).\n */\nexport function extractUsageInput(\n record: unknown,\n options: ExtractUsageInputOptions = {},\n): ExtractUsageInputResult {\n const defaultProvider = options.defaultProvider ?? \"openrouter\";\n const maxDepth = 24;\n\n const modelCandidates: ModelCandidate[] = [];\n const providerCandidates: ProviderCandidate[] = [];\n const tokenCandidates: TokenCandidate[] = [];\n\n collectModelCandidates(record, \"\", modelCandidates, 0, maxDepth);\n collectProviderCandidates(record, \"\", providerCandidates, 0, maxDepth);\n collectTokenCandidates(record, \"\", tokenCandidates, 0, maxDepth);\n\n const bestModel = pickBestModel(modelCandidates);\n if (!bestModel) {\n throw new Error(\n \"[ai-tools] Could not extract a model from the record (looked for usedModel, modelUsed, model, …).\",\n );\n }\n\n const runtimeFields = new Set([\"usedModel\", \"modelUsed\", \"resolvedModel\"]);\n const isRuntimeModel = runtimeFields.has(bestModel.field);\n const requestModel = modelCandidates.find(\n (c) => c.field === \"model\" && c.path !== bestModel.path,\n );\n\n const bestProvider = pickBestProvider(providerCandidates);\n const provider =\n bestProvider?.value ??\n inferProviderFromModel(bestModel.value, defaultProvider);\n\n const bestTokens = pickBestTokens(tokenCandidates);\n if (!bestTokens) {\n throw new Error(\n \"[ai-tools] Could not extract token usage from the record (usage, tokens, or metadata.diagnostics).\",\n );\n }\n\n const input: AiUsageInput = {\n tokens: bestTokens.tokens,\n provider,\n ...(isRuntimeModel\n ? { modelUsed: bestModel.value, model: requestModel?.value }\n : { model: bestModel.value }),\n };\n\n const provenance: ExtractUsageInputResult[\"provenance\"] = {\n model: {\n field: bestModel.field,\n path: bestModel.path,\n score: bestModel.score,\n },\n tokens: bestTokens.provenance,\n };\n\n if (bestProvider) {\n provenance.provider = {\n field: bestProvider.field,\n path: bestProvider.path,\n score: bestProvider.score,\n };\n }\n\n if (isRuntimeModel && requestModel) {\n provenance.modelUsed = {\n field: bestModel.field,\n path: bestModel.path,\n score: bestModel.score,\n };\n } else if (input.modelUsed) {\n provenance.modelUsed = provenance.model;\n }\n\n return { input, provenance };\n}\n","import type { AiUsageInput } from \"./types.js\";\n\n/** Prefer runtime id (`usedModel` / `modelUsed`); fall back to `model`. */\nexport function resolveUsageModel(input: AiUsageInput): string {\n const value = input.usedModel ?? input.modelUsed ?? input.model;\n if (!value?.trim()) {\n throw new Error(\n \"[ai-tools] Cost calculation requires `usedModel`, `modelUsed`, or `model` on usage input.\",\n );\n }\n return value.trim();\n}\n","import { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\nimport { AIProfilesError, resolveAIProfile } from \"@x12i/ai-profiles\";\nimport type {\n AIProfileBackend,\n AIProfileChoice,\n AIModelPricing,\n AIProfilesRegistry,\n InstructionTier,\n ResolvedAIProfile,\n} from \"@x12i/ai-profiles\";\nimport { providerHintForProfiles } from \"./costModelResolution.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport { stripModelVersionSuffix } from \"../sync/modelNameResolver/stripVersionSuffix.js\";\n\nconst require = createRequire(import.meta.url);\n\ntype LoadRegistryFn = (options?: {\n source?: \"auto\" | \"remote\" | \"bundled\";\n refresh?: boolean;\n}) => Promise<AIProfilesRegistry>;\n\nfunction loadProfilesRegistry(): Promise<AIProfilesRegistry> {\n const entry = dirname(require.resolve(\"@x12i/ai-profiles\"));\n const loader = require(join(entry, \"loader/loadAIProfilesRegistry.js\")) as {\n loadAIProfilesRegistry: LoadRegistryFn;\n };\n return loader.loadAIProfilesRegistry({ source: \"auto\" });\n}\n\nexport type AiProfilesModelMatch = {\n provider: string;\n modelId: string;\n canonicalModelId: string;\n pricing?: AIModelPricing;\n instructionTier: InstructionTier;\n backend: AIProfileBackend;\n matchedVia: \"profile\" | \"shortcut\" | \"profile-alias\" | \"model-id\";\n profile?: string;\n choice?: string;\n};\n\nfunction profileKey(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction canonicalModelId(provider: string, modelId: string): string {\n const normalized = normalizeString(modelId);\n if (normalized.includes(\"/\")) return normalized;\n const p = normalizeProvider(provider) ?? normalizeString(provider);\n return `${p}/${normalized}`;\n}\n\ntype IndexedChoice = {\n provider: string;\n modelId: string;\n canonicalModelId: string;\n pricing?: AIModelPricing;\n profile: string;\n choice: string;\n};\n\nlet cachedIndex: {\n cacheKey: string;\n byKey: Map<string, IndexedChoice[]>;\n} | null = null;\n\n/** Index bare model ids only — profile/shortcut names resolve via {@link resolveAIProfile}. */\nfunction indexRegistry(registry: AIProfilesRegistry): Map<string, IndexedChoice[]> {\n const byKey = new Map<string, IndexedChoice[]>();\n\n const add = (key: string, entry: IndexedChoice) => {\n const k = profileKey(key);\n if (!k) return;\n const list = byKey.get(k) ?? [];\n if (\n list.some(\n (e) =>\n e.canonicalModelId === entry.canonicalModelId &&\n e.choice === entry.choice &&\n e.profile === entry.profile,\n )\n ) {\n return;\n }\n list.push(entry);\n byKey.set(k, list);\n };\n\n for (const profile of Object.values(registry.profiles)) {\n for (const [choiceKey, choice] of Object.entries(profile.choices)) {\n const entry = choiceEntry(choice, profile.profile, choiceKey);\n add(choice.modelId, entry);\n add(canonicalModelId(choice.provider, choice.modelId), entry);\n }\n }\n\n return byKey;\n}\n\nfunction choiceEntry(\n choice: AIProfileChoice,\n profile: string,\n choiceKey: string,\n): IndexedChoice {\n const canonical = canonicalModelId(choice.provider, choice.modelId);\n return {\n provider: normalizeProvider(choice.provider) ?? choice.provider,\n modelId: normalizeString(choice.modelId),\n canonicalModelId: canonical,\n pricing: choice.pricing,\n profile,\n choice: choiceKey,\n };\n}\n\nasync function getProfileIndex(): Promise<Map<string, IndexedChoice[]>> {\n const registry = await loadProfilesRegistry();\n const cacheKey = `${registry.version}:${registry.generatedAt ?? \"\"}:${registry.source}`;\n if (cachedIndex?.cacheKey === cacheKey) {\n return cachedIndex.byKey;\n }\n const byKey = indexRegistry(registry);\n cachedIndex = { cacheKey, byKey };\n return byKey;\n}\n\nfunction scoreCandidate(\n entry: IndexedChoice,\n model: string,\n providerHint?: string,\n): number {\n const normalized = normalizeString(model);\n let score = 0;\n\n if (normalized === entry.canonicalModelId) score += 100;\n if (normalized === entry.modelId) score += 80;\n if (providerHint && entry.provider === providerHint) score += 50;\n if (entry.pricing) score += 2;\n\n return score;\n}\n\nfunction pickBest(\n candidates: IndexedChoice[],\n model: string,\n providerHint?: string,\n): IndexedChoice | null {\n if (candidates.length === 0) return null;\n if (candidates.length === 1) return candidates[0]!;\n\n let best = candidates[0]!;\n let bestScore = scoreCandidate(best, model, providerHint);\n for (let i = 1; i < candidates.length; i++) {\n const c = candidates[i]!;\n const s = scoreCandidate(c, model, providerHint);\n if (s > bestScore) {\n best = c;\n bestScore = s;\n }\n }\n return best;\n}\n\nfunction resolvedToMatch(resolved: ResolvedAIProfile): AiProfilesModelMatch {\n return {\n provider: normalizeProvider(resolved.provider) ?? resolved.provider,\n modelId: normalizeString(resolved.modelId),\n canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),\n pricing: resolved.pricing,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n matchedVia: resolved.shortcut ? \"shortcut\" : \"profile\",\n profile: resolved.profile,\n choice: resolved.choice,\n };\n}\n\nasync function fromIndexed(entry: IndexedChoice): Promise<AiProfilesModelMatch> {\n const resolved = await resolveAIProfile(entry.profile, { choice: entry.choice });\n return {\n provider: normalizeProvider(resolved.provider) ?? resolved.provider,\n modelId: normalizeString(resolved.modelId),\n canonicalModelId: canonicalModelId(resolved.provider, resolved.modelId),\n pricing: resolved.pricing ?? entry.pricing,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n matchedVia: \"model-id\",\n profile: resolved.profile,\n choice: resolved.choice,\n };\n}\n\nasync function lookupInIndex(\n index: Map<string, IndexedChoice[]>,\n model: string,\n provider?: string,\n): Promise<AiProfilesModelMatch | null> {\n const providerHint = provider ? normalizeProvider(provider) : undefined;\n const keys = [\n profileKey(model),\n profileKey(normalizeString(model)),\n ];\n if (providerHint) {\n keys.push(profileKey(canonicalModelId(providerHint, model)));\n }\n\n const pooled: IndexedChoice[] = [];\n for (const key of keys) {\n const hits = index.get(key);\n if (hits) pooled.push(...hits);\n }\n\n const bare = normalizeString(model);\n if (!bare.includes(\"/\")) {\n for (const list of index.values()) {\n for (const entry of list) {\n if (entry.modelId === bare) pooled.push(entry);\n }\n }\n }\n\n const unique = new Map<string, IndexedChoice>();\n for (const e of pooled) {\n unique.set(`${e.profile}:${e.choice}:${e.canonicalModelId}`, e);\n }\n\n const best = pickBest([...unique.values()], model, providerHint);\n return best ? fromIndexed(best) : null;\n}\n\n/**\n * Resolve a model string via @x12i/ai-profiles — profile/shortcut names, aliases,\n * or a concrete model id that appears on a profile choice.\n */\nexport async function matchModelInAiProfiles(\n model: string,\n provider?: string,\n): Promise<AiProfilesModelMatch | null> {\n try {\n const resolved = await resolveAIProfile(model);\n return resolvedToMatch(resolved);\n } catch (err) {\n if (!(err instanceof AIProfilesError) || err.code !== \"UNKNOWN_PROFILE\") {\n throw err;\n }\n }\n\n const index = await getProfileIndex();\n const hint = providerHintForProfiles(model, provider);\n const direct = await lookupInIndex(index, model, hint);\n if (direct) return direct;\n\n const stripped = stripModelVersionSuffix(model);\n if (stripped && stripped !== normalizeString(model)) {\n return lookupInIndex(\n index,\n stripped,\n providerHintForProfiles(stripped, provider),\n );\n }\n\n return null;\n}\n\n/** @internal Test-only — reset module cache between tests. */\nexport function resetAiProfilesMatchCacheForTests(): void {\n cachedIndex = null;\n}\n","import type { AiModelsCatalogClient } from \"../catalog/AiModelsCatalogClient.js\";\nimport { LOCAL_PROVIDERS } from \"../sync/modelNameResolver/constants.js\";\nimport {\n loadOpenRouterRoutingEnv,\n shouldDefaultRouteViaOpenRouter,\n} from \"../sync/openRouterRoutingEnv.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport type {\n ModelResolutionInput,\n ModelResolutionResult,\n ModelResolverOptions,\n} from \"../sync/modelNameResolver/types.js\";\nimport type { OpenRouterRoutingConfig } from \"../sync/openRouterRoutingEnv.js\";\n\nexport function isOpenRouterProvider(provider?: string): boolean {\n return normalizeProvider(provider) === \"openrouter\";\n}\n\nexport function isLocalProvider(provider?: string): boolean {\n const p = normalizeProvider(provider) ?? normalizeString(provider ?? \"\");\n return LOCAL_PROVIDERS.has(p);\n}\n\n/** Catalog resolver returned success without a priced record (Ollama, LM Studio, …). */\nexport function isLocalProviderResolution(\n resolved: ModelResolutionResult | null,\n inputProvider?: string,\n): boolean {\n if (!resolved?.found || resolved.record) return false;\n if (resolved.resolvedVia.includes(\"local-provider-passthrough\")) return true;\n return isLocalProvider(inputProvider);\n}\n\n/**\n * Vendor id for a model slug (`openai/gpt-4o` → `openai`).\n * Ignores `openrouter` as a provider hint — it is a routing layer, not the model owner.\n */\nexport function underlyingProviderFromModel(\n model: string,\n providerHint?: string,\n): string | undefined {\n const normalized = normalizeString(model);\n if (normalized.includes(\"/\")) {\n const prefix = normalized.split(\"/\")[0]!;\n if (!isOpenRouterProvider(prefix)) return prefix;\n }\n if (providerHint && !isOpenRouterProvider(providerHint)) {\n return normalizeProvider(providerHint);\n }\n return undefined;\n}\n\n/** Provider hint for ai-profiles index lookup (openrouter → underlying vendor). */\nexport function providerHintForProfiles(\n model: string,\n provider?: string,\n): string | undefined {\n if (isOpenRouterProvider(provider)) {\n return underlyingProviderFromModel(model, provider);\n }\n return normalizeProvider(provider);\n}\n\n/**\n * Catalog resolve attempts for direct API and OpenRouter usage.\n * Tries the caller hint, inferred vendor, no hint, and openrouter routing.\n */\nexport function buildCatalogResolveAttempts(\n model: string,\n provider?: string,\n): ModelResolutionInput[] {\n const attempts: ModelResolutionInput[] = [];\n const seen = new Set<string>();\n const add = (m: string, p?: string) => {\n const key = `${p ?? \"\"}\\0${normalizeString(m)}`;\n if (seen.has(key)) return;\n seen.add(key);\n attempts.push({ model: m, provider: p });\n };\n\n add(model, provider);\n\n const underlying = underlyingProviderFromModel(model, provider);\n if (provider) add(model, undefined);\n if (underlying) add(model, underlying);\n if (!isOpenRouterProvider(provider)) {\n add(model, \"openrouter\");\n }\n\n return attempts;\n}\n\nexport async function resolveFromCatalogAttempts(\n catalog: AiModelsCatalogClient,\n attempts: ModelResolutionInput[],\n options?: ModelResolverOptions,\n): Promise<ModelResolutionResult | null> {\n let last: ModelResolutionResult | null = null;\n let localPassthrough: ModelResolutionResult | null = null;\n\n for (const attempt of attempts) {\n const result = await catalog.resolveModel(attempt, options);\n last = result;\n if (result.found && result.record) return result;\n if (\n result.found &&\n !result.record &&\n isLocalProviderResolution(result, attempt.provider)\n ) {\n localPassthrough = result;\n }\n }\n\n return localPassthrough ?? last;\n}\n\nexport function resolveRoutedViaOpenRouter(\n inputProvider: string | undefined,\n resolved: ModelResolutionResult | null,\n modelId?: string,\n routingEnv?: OpenRouterRoutingConfig,\n): boolean {\n const env = routingEnv ?? loadOpenRouterRoutingEnv();\n\n if (isOpenRouterProvider(inputProvider)) return true;\n\n if (resolved?.found) {\n return resolved.routedViaOpenRouter;\n }\n\n const vendor = underlyingProviderFromModel(\n modelId ?? (resolved?.found ? resolved.modelId : \"\") ?? \"\",\n inputProvider,\n );\n if (vendor && shouldDefaultRouteViaOpenRouter(vendor, env)) {\n return true;\n }\n\n return false;\n}\n","import type { AIModelPricing } from \"@x12i/ai-profiles\";\nimport {\n DEFAULT_OPENROUTER_MARKUP_RATE,\n PROFILE_TIERED_CONTEXT_THRESHOLD,\n} from \"./constants.js\";\nimport type { AiModelPricing, AiUsageInput } from \"./types.js\";\n\nconst TOKENS_PER_UNIT = 1_000_000;\n\nfunction usdPerToken(perMillion?: number): number {\n return (perMillion ?? 0) / TOKENS_PER_UNIT;\n}\n\nfunction pickInputRatePerMillion(\n pricing: AIModelPricing,\n promptTokens: number,\n): number | undefined {\n if (\n pricing.inputBelow200k !== undefined &&\n pricing.inputAbove200k !== undefined\n ) {\n return promptTokens <= PROFILE_TIERED_CONTEXT_THRESHOLD\n ? pricing.inputBelow200k\n : pricing.inputAbove200k;\n }\n return pricing.input ?? pricing.inputBelow200k ?? pricing.inputAbove200k;\n}\n\nfunction pickOutputRatePerMillion(\n pricing: AIModelPricing,\n promptTokens: number,\n): number | undefined {\n if (\n pricing.outputBelow200k !== undefined &&\n pricing.outputAbove200k !== undefined\n ) {\n return promptTokens <= PROFILE_TIERED_CONTEXT_THRESHOLD\n ? pricing.outputBelow200k\n : pricing.outputAbove200k;\n }\n return pricing.output ?? pricing.outputBelow200k ?? pricing.outputAbove200k;\n}\n\nexport type AiProfilesPricingOptions = {\n promptTokens?: number;\n routedViaOpenRouter?: boolean;\n};\n\nexport function aiProfilesPricingToCatalogPricing(\n pricing: AIModelPricing,\n pricedAt: string,\n options: AiProfilesPricingOptions = {},\n): AiModelPricing {\n const promptTokens = options.promptTokens ?? 0;\n const promptUsdPerToken = usdPerToken(pickInputRatePerMillion(pricing, promptTokens));\n const completionUsdPerToken = usdPerToken(\n pickOutputRatePerMillion(pricing, promptTokens),\n );\n\n const snapshot: AiModelPricing = {\n promptUsdPerToken,\n completionUsdPerToken,\n cacheReadUsdPerToken: usdPerToken(pricing.cachedInput ?? pricing.cacheHit),\n cacheWriteUsdPerToken: usdPerToken(pricing.cacheWrite5m ?? pricing.cacheWrite1h),\n imageUsdPerUnit: 0,\n requestUsdPerRequest: 0,\n pricedAt,\n source: \"manual\",\n };\n\n if (options.routedViaOpenRouter) {\n snapshot.openRouterMarkupUsdPerInputToken =\n promptUsdPerToken * DEFAULT_OPENROUTER_MARKUP_RATE;\n snapshot.openRouterMarkupUsdPerOutputToken =\n completionUsdPerToken * DEFAULT_OPENROUTER_MARKUP_RATE;\n }\n\n return snapshot;\n}\n\nexport function computeCostFromPricing(\n input: AiUsageInput,\n pricing: AiModelPricing,\n routedViaOpenRouter: boolean,\n includeBreakdown: boolean,\n): { cost: number; breakdown?: import(\"./types.js\").AiCostResult[\"breakdown\"] } {\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 if (!includeBreakdown) {\n return { cost };\n }\n\n return {\n cost,\n 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","import type { AliasRegistry } from \"../aliases/AliasRegistry.js\";\nimport type { AiModelsCatalogClient } from \"../catalog/AiModelsCatalogClient.js\";\nimport { UnknownModelCostError } from \"../errors.js\";\nimport { normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport { stripModelVersionSuffix } from \"../sync/modelNameResolver/stripVersionSuffix.js\";\nimport type {\n ModelResolutionResult,\n ModelResolverOptions,\n} from \"../sync/modelNameResolver/types.js\";\nimport { matchModelInAiProfiles } from \"./aiProfilesMatch.js\";\nimport {\n buildCatalogResolveAttempts,\n isLocalProvider,\n isLocalProviderResolution,\n resolveFromCatalogAttempts,\n resolveRoutedViaOpenRouter,\n} from \"./costModelResolution.js\";\nimport {\n aiProfilesPricingToCatalogPricing,\n computeCostFromPricing,\n} from \"./profilePricing.js\";\nimport { enrichCostResult, toCostExtraction } from \"./enrichCostResult.js\";\nimport {\n extractUsageInput,\n type ExtractUsageInputOptions,\n} from \"./extractUsageInput.js\";\nimport { resolveUsageModel } from \"./resolveUsageModel.js\";\nimport type { AiCostResult, AiCostWarning, AiModelPricing, AiUsageInput } from \"./types.js\";\n\nexport type CostCalculatorOptions = {\n aliasRegistry?: AliasRegistry;\n includeBreakdown?: boolean;\n resolverOptions?: ModelResolverOptions;\n /** When true, throw {@link UnknownModelCostError} instead of zero-cost fallback. */\n throwOnUnknownModel?: boolean;\n};\n\nfunction emptyPricing(): AiModelPricing {\n return {\n promptUsdPerToken: 0,\n completionUsdPerToken: 0,\n imageUsdPerUnit: 0,\n requestUsdPerRequest: 0,\n pricedAt: new Date().toISOString(),\n source: \"manual\",\n };\n}\n\nfunction mergeAttempts(\n ...groups: ReturnType<typeof buildCatalogResolveAttempts>[]\n): ReturnType<typeof buildCatalogResolveAttempts> {\n const seen = new Set<string>();\n const out: ReturnType<typeof buildCatalogResolveAttempts> = [];\n for (const group of groups) {\n for (const a of group) {\n const key = `${a.provider ?? \"\"}\\0${a.model}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(a);\n }\n }\n return out;\n}\n\nexport class CostCalculator {\n private readonly aliasRegistry?: AliasRegistry;\n private readonly includeBreakdown: boolean;\n private readonly resolverOptions?: ModelResolverOptions;\n private readonly throwOnUnknownModel: boolean;\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 this.throwOnUnknownModel = options.throwOnUnknownModel ?? false;\n }\n\n /**\n * Extract model, provider, and token usage from an activity / gateway record\n * (MongoDB export, nested `outer`, `config`, `metadata.diagnostics`, etc.)\n * then run {@link calculate}.\n */\n async calculateFromRecord(\n record: unknown,\n extractOptions?: ExtractUsageInputOptions,\n ): Promise<AiCostResult> {\n const { input, provenance } = extractUsageInput(record, extractOptions);\n const warnings: AiCostWarning[] = [];\n if (provenance.tokens.estimated) {\n warnings.push({\n code: \"ESTIMATED_TOKEN_USAGE\",\n message: `Token counts are estimates from ${provenance.tokens.path} (not billed usage).`,\n });\n }\n const result = await this.calculate(input);\n const enriched = enrichCostResult(result, input, toCostExtraction(provenance));\n if (warnings.length > 0) {\n enriched.warnings = [...(enriched.warnings ?? []), ...warnings];\n }\n return enriched;\n }\n\n async calculate(input: AiUsageInput): Promise<AiCostResult> {\n const modelInput = resolveUsageModel(input);\n const resolverOpts = {\n ...this.resolverOptions,\n aliasRegistry: this.aliasRegistry ?? this.resolverOptions?.aliasRegistry,\n };\n\n let resolved = await resolveFromCatalogAttempts(\n this.catalog,\n buildCatalogResolveAttempts(modelInput, input.provider),\n resolverOpts,\n );\n\n if (isLocalProviderResolution(resolved, input.provider)) {\n return this.localProviderResult(modelInput, input, resolved);\n }\n\n let profileMatch = null as Awaited<ReturnType<typeof matchModelInAiProfiles>>;\n const warnings: AiCostWarning[] = [];\n\n if (!resolved?.found || !resolved.record) {\n if (!isLocalProvider(input.provider)) {\n profileMatch = await matchModelInAiProfiles(modelInput, input.provider);\n }\n if (profileMatch) {\n resolved = await resolveFromCatalogAttempts(\n this.catalog,\n mergeAttempts(\n buildCatalogResolveAttempts(\n profileMatch.canonicalModelId,\n input.provider ?? profileMatch.provider,\n ),\n buildCatalogResolveAttempts(\n profileMatch.canonicalModelId,\n profileMatch.provider,\n ),\n ),\n resolverOpts,\n );\n }\n\n if (isLocalProviderResolution(resolved, input.provider)) {\n return this.localProviderResult(modelInput, input, resolved);\n }\n\n if ((!resolved?.found || !resolved.record) && profileMatch?.pricing) {\n const routedViaOpenRouter = resolveRoutedViaOpenRouter(\n input.provider,\n resolved,\n profileMatch.canonicalModelId,\n resolverOpts?.routingEnv,\n );\n const pricing = aiProfilesPricingToCatalogPricing(\n profileMatch.pricing,\n new Date().toISOString(),\n {\n promptTokens: input.tokens.prompt,\n routedViaOpenRouter,\n },\n );\n const { cost, breakdown } = computeCostFromPricing(\n input,\n pricing,\n routedViaOpenRouter,\n this.includeBreakdown,\n );\n\n warnings.push({\n code: \"AI_PROFILES_ESTIMATE\",\n message: `Catalog has no pricing for \"${modelInput}\"; estimated from ai-profiles (${profileMatch.matchedVia} → ${profileMatch.canonicalModelId}).`,\n });\n if (\n routedViaOpenRouter &&\n pricing.openRouterMarkupUsdPerInputToken !== undefined\n ) {\n warnings.push({\n code: \"OPENROUTER_MARKUP_ESTIMATED\",\n message:\n \"OpenRouter markup estimated at 5% of base token rates (catalog markup fields absent).\",\n });\n }\n\n console.warn(`[ai-tools] ${warnings.map((w) => w.message).join(\" \")}`);\n\n return this.finish(\n {\n cost,\n breakdown,\n resolvedModelId: profileMatch.canonicalModelId,\n routedViaOpenRouter,\n isAuthoritative: false,\n pricingSnapshot: pricing,\n source: \"ai-profiles\",\n warnings,\n },\n input,\n resolved,\n );\n }\n }\n\n if (!resolved?.found || !resolved.record) {\n return this.unknownModelResult(modelInput, input, resolved);\n }\n\n const { record, modelId } = resolved;\n const routedViaOpenRouter = resolveRoutedViaOpenRouter(\n input.provider,\n resolved,\n modelId,\n resolverOpts?.routingEnv,\n );\n const pricing = record.pricing;\n const { cost, breakdown } = computeCostFromPricing(\n input,\n pricing,\n routedViaOpenRouter,\n this.includeBreakdown,\n );\n\n return this.finish(\n {\n cost,\n breakdown,\n resolvedModelId: modelId,\n routedViaOpenRouter,\n isAuthoritative: true,\n pricingSnapshot: pricing,\n source: \"catalog\",\n },\n input,\n resolved,\n );\n }\n\n private versionSuffixWarnings(\n input: AiUsageInput,\n pricedModelId: string,\n resolved?: ModelResolutionResult | null,\n ): AiCostWarning[] {\n const received = input.usedModel ?? input.modelUsed ?? input.model;\n if (!received) return [];\n\n const normalizedReceived = normalizeString(received);\n const normalizedPriced = normalizeString(pricedModelId);\n if (normalizedReceived === normalizedPriced) return [];\n\n const stripped = stripModelVersionSuffix(received);\n const viaResolver =\n resolved?.found === true &&\n resolved.resolvedVia.some(\n (s) => s === \"version-suffix-strip\" || s === \"date-suffix-strip\",\n );\n const pricedViaStrip =\n stripped !== null && normalizeString(stripped) === normalizedPriced;\n\n if (!viaResolver && !pricedViaStrip) return [];\n\n return [\n {\n code: \"VERSION_SUFFIX_PRICING\",\n message: `Priced using catalog model \"${pricedModelId}\" (no exact pricing for \"${received}\").`,\n },\n ];\n }\n\n private finish(\n partial: Omit<\n AiCostResult,\n \"usage\" | \"provider\" | \"usedModel\" | \"model\" | \"extraction\"\n >,\n input: AiUsageInput,\n resolved?: ModelResolutionResult | null,\n ): AiCostResult {\n const enriched = enrichCostResult(partial, input);\n const suffixWarnings = this.versionSuffixWarnings(\n input,\n partial.resolvedModelId,\n resolved,\n );\n if (suffixWarnings.length > 0) {\n enriched.warnings = [...(enriched.warnings ?? []), ...suffixWarnings];\n }\n return enriched;\n }\n\n private localProviderResult(\n modelInput: string,\n input: AiUsageInput,\n resolved: Awaited<ReturnType<typeof resolveFromCatalogAttempts>>,\n ): AiCostResult {\n const warnings: AiCostWarning[] = [\n {\n code: \"LOCAL_PROVIDER_NO_PRICING\",\n message: `Local provider \"${input.provider}\" has no catalog pricing for \"${modelInput}\".`,\n },\n ];\n console.warn(`[ai-tools] ${warnings[0]!.message}`);\n return this.finish(\n {\n cost: 0,\n resolvedModelId: resolved?.found ? resolved.modelId : modelInput,\n routedViaOpenRouter: false,\n isAuthoritative: false,\n pricingSnapshot: emptyPricing(),\n source: \"local\",\n warnings,\n },\n input,\n );\n }\n\n private unknownModelResult(\n modelInput: string,\n input: AiUsageInput,\n resolved: Awaited<ReturnType<typeof resolveFromCatalogAttempts>>,\n ): AiCostResult {\n if (this.throwOnUnknownModel) {\n throw new UnknownModelCostError(modelInput, input.provider);\n }\n\n const warnings: AiCostWarning[] = [\n {\n code: \"UNKNOWN_MODEL\",\n message: `Unknown model \"${modelInput}\" (provider: \"${input.provider}\") — returning zero-cost fallback.`,\n },\n ];\n console.warn(`[ai-tools] ${warnings[0]!.message}`);\n\n return this.finish(\n {\n cost: 0,\n resolvedModelId: modelInput,\n routedViaOpenRouter: resolveRoutedViaOpenRouter(\n input.provider,\n resolved,\n modelInput,\n this.resolverOptions?.routingEnv,\n ),\n isAuthoritative: false,\n pricingSnapshot: emptyPricing(),\n source: \"estimate-fallback\",\n unknownModel: true,\n warnings,\n },\n input,\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;AACO,IAAM,iCAAiC;AAGvC,IAAM,mCAAmC;;;ACDzC,SAAS,iBACd,YACkB;AAClB,SAAO;AAAA,IACL,OAAO,EAAE,OAAO,WAAW,MAAM,OAAO,MAAM,WAAW,MAAM,KAAK;AAAA,IACpE,QAAQ;AAAA,MACN,QAAQ,WAAW,OAAO;AAAA,MAC1B,MAAM,WAAW,OAAO;AAAA,MACxB,WAAW,WAAW,OAAO;AAAA,IAC/B;AAAA,IACA,GAAI,WAAW,YACX;AAAA,MACE,WAAW;AAAA,QACT,OAAO,WAAW,UAAU;AAAA,QAC5B,MAAM,WAAW,UAAU;AAAA,MAC7B;AAAA,IACF,IACA,CAAC;AAAA,IACL,GAAI,WAAW,WACX;AAAA,MACE,UAAU;AAAA,QACR,OAAO,WAAW,SAAS;AAAA,QAC3B,MAAM,WAAW,SAAS;AAAA,MAC5B;AAAA,IACF,IACA,CAAC;AAAA,EACP;AACF;AAGO,SAAS,iBACd,QAIA,OACA,YACc;AAEd,QAAM,kBAAkB,MAAM,aAAa,MAAM,aAAa,MAAM;AAEpE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU,MAAM;AAAA,IAChB,OAAO,EAAE,GAAG,MAAM,OAAO;AAAA,IACzB,GAAI,kBAAkB,EAAE,WAAW,gBAAgB,IAAI,CAAC;AAAA,IACxD,GAAI,MAAM,SAAS,MAAM,UAAU,kBAAkB,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,IAC/E,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,EACrC;AACF;;;ACjDO,IAAM,uBAAkE;AAAA,EAC7E,EAAE,KAAK,aAAa,OAAO,IAAK;AAAA,EAChC,EAAE,KAAK,aAAa,OAAO,IAAI;AAAA,EAC/B,EAAE,KAAK,iBAAiB,OAAO,IAAI;AAAA,EACnC,EAAE,KAAK,SAAS,OAAO,IAAI;AAAA,EAC3B,EAAE,KAAK,kBAAkB,OAAO,IAAI;AAAA,EACpC,EAAE,KAAK,cAAc,OAAO,IAAI;AAClC;AAGA,IAAM,mBAAkE;AAAA,EACtE,EAAE,SAAS,yBAAyB,OAAO,GAAG;AAAA,EAC9C,EAAE,SAAS,6BAA6B,OAAO,GAAG;AAAA,EAClD,EAAE,SAAS,sCAAsC,OAAO,GAAG;AAAA,EAC3D,EAAE,SAAS,qCAAqC,OAAO,GAAG;AAAA,EAC1D,EAAE,SAAS,sBAAsB,OAAO,GAAG;AAAA,EAC3C,EAAE,SAAS,0BAA0B,OAAO,IAAI;AAAA,EAChD,EAAE,SAAS,kBAAkB,OAAO,IAAI;AAAA,EACxC,EAAE,SAAS,mBAAmB,OAAO,IAAI;AAAA,EACzC,EAAE,SAAS,iBAAiB,OAAO,IAAI;AACzC;AAEA,IAAM,0BAAqE;AAAA,EACzE,EAAE,KAAK,YAAY,OAAO,IAAI;AAAA,EAC9B,EAAE,KAAK,cAAc,OAAO,IAAI;AAClC;AAEA,IAAM,sBAAqE;AAAA,EACzE,EAAE,SAAS,sCAAsC,OAAO,GAAG;AAAA,EAC3D,EAAE,SAAS,6BAA6B,OAAO,GAAG;AAAA,EAClD,EAAE,SAAS,0BAA0B,OAAO,IAAI;AAClD;AAEA,IAAM,oBAAoB,oBAAI,IAAI;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,wBAAwB,oBAAI,IAAI;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,sBAAoE;AAAA,EACxE,OAAO;AAAA,EACP,cAAc;AAAA,EACd,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,cAAc;AAAA,EACd,OAAO;AAAA,EACP,cAAc;AAChB;AAgCA,SAAS,cAAc,GAA0C;AAC/D,SAAO,MAAM,QAAQ,OAAO,MAAM,YAAY,CAAC,MAAM,QAAQ,CAAC;AAChE;AAEA,SAAS,cAAc,KAAqB;AAC1C,SAAO,qBAAqB,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,GAAG,SAAS;AACnE;AAEA,SAAS,iBAAiB,KAAqB;AAC7C,SAAO,wBAAwB,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,GAAG,SAAS;AACtE;AAEA,SAAS,UAAU,MAAc,OAA8D;AAC7F,MAAI,QAAQ;AACZ,aAAW,EAAE,SAAS,OAAO,EAAE,KAAK,OAAO;AACzC,QAAI,QAAQ,KAAK,IAAI,EAAG,UAAS;AAAA,EACnC;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,GAAgC;AAC3D,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,QAAM,IAAI,EAAE,KAAK;AACjB,SAAO,EAAE,SAAS,IAAI,IAAI;AAC5B;AAEA,SAAS,uBAAuB,GAAgC;AAC9D,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,QAAM,IAAI,EAAE,KAAK,EAAE,YAAY;AAC/B,MAAI,CAAC,KAAK,MAAM,OAAQ,QAAO;AAC/B,SAAO;AACT;AAEA,SAAS,uBACP,MACA,MACA,KACA,OACA,UACM;AACN,MAAI,QAAQ,YAAY,SAAS,QAAQ,SAAS,OAAW;AAE7D,MAAI,cAAc,IAAI,GAAG;AACvB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,YAAM,YAAY,OAAO,GAAG,IAAI,IAAI,GAAG,KAAK;AAC5C,YAAM,OAAO,cAAc,GAAG;AAC9B,UAAI,OAAO,GAAG;AACZ,cAAM,QAAQ,oBAAoB,KAAK;AACvC,YAAI,OAAO;AACT,cAAI,KAAK;AAAA,YACP,OAAO;AAAA,YACP,MAAM;AAAA,YACN,OAAO;AAAA,YACP,OAAO,OAAO,UAAU,WAAW,gBAAgB;AAAA,UACrD,CAAC;AAAA,QACH;AAAA,MACF;AACA,6BAAuB,OAAO,WAAW,KAAK,QAAQ,GAAG,QAAQ;AAAA,IACnE;AACA;AAAA,EACF;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,6BAAuB,KAAK,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,GAAG,QAAQ;AAAA,IAC3E;AAAA,EACF;AACF;AAEA,SAAS,0BACP,MACA,MACA,KACA,OACA,UACM;AACN,MAAI,QAAQ,YAAY,SAAS,QAAQ,SAAS,OAAW;AAE7D,MAAI,cAAc,IAAI,GAAG;AACvB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,YAAM,YAAY,OAAO,GAAG,IAAI,IAAI,GAAG,KAAK;AAC5C,YAAM,OAAO,iBAAiB,GAAG;AACjC,UAAI,OAAO,GAAG;AACZ,cAAM,WAAW,uBAAuB,KAAK;AAC7C,YAAI,UAAU;AACZ,cAAI,KAAK;AAAA,YACP,OAAO;AAAA,YACP,MAAM;AAAA,YACN,OAAO;AAAA,YACP,OAAO,OAAO,UAAU,WAAW,mBAAmB;AAAA,UACxD,CAAC;AAAA,QACH;AAAA,MACF;AACA,gCAA0B,OAAO,WAAW,KAAK,QAAQ,GAAG,QAAQ;AAAA,IACtE;AACA;AAAA,EACF;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,gCAA0B,KAAK,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,GAAG,QAAQ;AAAA,IAC9E;AAAA,EACF;AACF;AAEA,SAAS,WAAW,KAA8B,MAAuC;AACvF,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,QAAI,CAAC,KAAK,IAAI,CAAC,EAAG;AAClB,QAAI,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,KAAK,KAAK,EAAG,QAAO;AAAA,EACpE;AACA,SAAO;AACT;AAEA,SAAS,oBACP,KACiC;AACjC,QAAM,QAAyC,CAAC;AAChD,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,UAAM,SAAS,oBAAoB,CAAC;AACpC,QAAI,CAAC,UAAU,OAAO,MAAM,YAAY,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,EAAG;AACtE,UAAM,MAAM,IAAI;AAAA,EAClB;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,KAAuC;AACnE,QAAM,YAAY,WAAW,KAAK,iBAAiB,MAAM;AACzD,QAAM,gBAAgB,WAAW,KAAK,qBAAqB,MAAM;AACjE,SAAO,aAAa;AACtB;AAEA,SAAS,2BAA2B,KAAuC;AACzE,SACE,OAAO,IAAI,yBAAyB,YACpC,OAAO,IAAI,0BAA0B;AAEzC;AAQA,SAAS,iBACP,KACA,QACA,MACA,WACA,OACuB;AACvB,QAAM,SAAS,WAAW,KAAK,iBAAiB;AAChD,QAAM,aAAa,WAAW,KAAK,qBAAqB;AACxD,MAAI,WAAW,UAAa,eAAe,OAAW,QAAO;AAE7D,QAAM,QAAQ,oBAAoB,GAAG;AACrC,QAAM,QACJ,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ,SAAS;AAE3D,SAAO;AAAA,IACL,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL;AAAA,IACA,YAAY,EAAE,QAAQ,MAAM,UAAU;AAAA,IACtC;AAAA,EACF;AACF;AAEA,SAAS,uBACP,MACA,MACA,KACA,OACA,UACM;AACN,MAAI,QAAQ,YAAY,SAAS,QAAQ,SAAS,OAAW;AAE7D,MAAI,cAAc,IAAI,GAAG;AACvB,QAAI,KAAK,SAAS,aAAa,KAAK,2BAA2B,IAAI,GAAG;AACpE,YAAM,OAAO,iBAAiB,MAAM,eAAe,MAAM,MAAM,GAAG;AAClE,UAAI,KAAM,KAAI,KAAK,IAAI;AAAA,IACzB,WAAW,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,QAAQ,KAAK,qBAAqB,IAAI,GAAG;AAC1F,YAAM,SAAS,KAAK,SAAS,QAAQ,IAAI,WAAW;AACpD,YAAM,YAAY;AAClB,YAAM,QAAQ,KAAK,SAAS,OAAO,IAAI,MAAM;AAC7C,YAAM,OAAO,iBAAiB,MAAM,QAAQ,MAAM,WAAW,KAAK;AAClE,UAAI,KAAM,KAAI,KAAK,IAAI;AAAA,IACzB;AAEA,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,YAAM,YAAY,OAAO,GAAG,IAAI,IAAI,GAAG,KAAK;AAC5C,UAAI,QAAQ,WAAW,QAAQ,YAAY,QAAQ,eAAe;AAChE,YAAI,cAAc,KAAK,GAAG;AACxB,iCAAuB,OAAO,WAAW,KAAK,QAAQ,GAAG,QAAQ;AAAA,QACnE;AAAA,MACF,OAAO;AACL,+BAAuB,OAAO,WAAW,KAAK,QAAQ,GAAG,QAAQ;AAAA,MACnE;AAAA,IACF;AACA;AAAA,EACF;AAEA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,6BAAuB,KAAK,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,GAAG,QAAQ;AAAA,IAC3E;AAAA,EACF;AACF;AAEA,SAAS,cAAc,YAAqD;AAC1E,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,SAAO,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC5D;AAEA,SAAS,iBAAiB,YAA2D;AACnF,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,SAAO,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC5D;AAEA,SAAS,eAAe,YAAqD;AAC3E,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,SAAO,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC5D;AAEA,SAAS,uBAAuB,OAAe,UAA0B;AACvE,QAAM,QAAQ,MAAM,QAAQ,GAAG;AAC/B,MAAI,QAAQ,GAAG;AACb,UAAM,SAAS,MAAM,MAAM,GAAG,KAAK,EAAE,YAAY;AACjD,QAAI,WAAW,aAAc,QAAO;AAAA,EACtC;AACA,SAAO;AACT;AAMO,SAAS,kBACd,QACA,UAAoC,CAAC,GACZ;AACzB,QAAM,kBAAkB,QAAQ,mBAAmB;AACnD,QAAM,WAAW;AAEjB,QAAM,kBAAoC,CAAC;AAC3C,QAAM,qBAA0C,CAAC;AACjD,QAAM,kBAAoC,CAAC;AAE3C,yBAAuB,QAAQ,IAAI,iBAAiB,GAAG,QAAQ;AAC/D,4BAA0B,QAAQ,IAAI,oBAAoB,GAAG,QAAQ;AACrE,yBAAuB,QAAQ,IAAI,iBAAiB,GAAG,QAAQ;AAE/D,QAAM,YAAY,cAAc,eAAe;AAC/C,MAAI,CAAC,WAAW;AACd,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,gBAAgB,oBAAI,IAAI,CAAC,aAAa,aAAa,eAAe,CAAC;AACzE,QAAM,iBAAiB,cAAc,IAAI,UAAU,KAAK;AACxD,QAAM,eAAe,gBAAgB;AAAA,IACnC,CAAC,MAAM,EAAE,UAAU,WAAW,EAAE,SAAS,UAAU;AAAA,EACrD;AAEA,QAAM,eAAe,iBAAiB,kBAAkB;AACxD,QAAM,WACJ,cAAc,SACd,uBAAuB,UAAU,OAAO,eAAe;AAEzD,QAAM,aAAa,eAAe,eAAe;AACjD,MAAI,CAAC,YAAY;AACf,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAsB;AAAA,IAC1B,QAAQ,WAAW;AAAA,IACnB;AAAA,IACA,GAAI,iBACA,EAAE,WAAW,UAAU,OAAO,OAAO,cAAc,MAAM,IACzD,EAAE,OAAO,UAAU,MAAM;AAAA,EAC/B;AAEA,QAAM,aAAoD;AAAA,IACxD,OAAO;AAAA,MACL,OAAO,UAAU;AAAA,MACjB,MAAM,UAAU;AAAA,MAChB,OAAO,UAAU;AAAA,IACnB;AAAA,IACA,QAAQ,WAAW;AAAA,EACrB;AAEA,MAAI,cAAc;AAChB,eAAW,WAAW;AAAA,MACpB,OAAO,aAAa;AAAA,MACpB,MAAM,aAAa;AAAA,MACnB,OAAO,aAAa;AAAA,IACtB;AAAA,EACF;AAEA,MAAI,kBAAkB,cAAc;AAClC,eAAW,YAAY;AAAA,MACrB,OAAO,UAAU;AAAA,MACjB,MAAM,UAAU;AAAA,MAChB,OAAO,UAAU;AAAA,IACnB;AAAA,EACF,WAAW,MAAM,WAAW;AAC1B,eAAW,YAAY,WAAW;AAAA,EACpC;AAEA,SAAO,EAAE,OAAO,WAAW;AAC7B;;;ACnaO,SAAS,kBAAkB,OAA6B;AAC7D,QAAM,QAAQ,MAAM,aAAa,MAAM,aAAa,MAAM;AAC1D,MAAI,CAAC,OAAO,KAAK,GAAG;AAClB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO,MAAM,KAAK;AACpB;;;ACXA,SAAS,qBAAqB;AAC9B,SAAS,SAAS,YAAY;AAC9B,SAAS,iBAAiB,wBAAwB;;;ACY3C,SAAS,qBAAqB,UAA4B;AAC/D,SAAO,kBAAkB,QAAQ,MAAM;AACzC;AAEO,SAAS,gBAAgB,UAA4B;AAC1D,QAAM,IAAI,kBAAkB,QAAQ,KAAK,gBAAgB,YAAY,EAAE;AACvE,SAAO,gBAAgB,IAAI,CAAC;AAC9B;AAGO,SAAS,0BACd,UACA,eACS;AACT,MAAI,CAAC,UAAU,SAAS,SAAS,OAAQ,QAAO;AAChD,MAAI,SAAS,YAAY,SAAS,4BAA4B,EAAG,QAAO;AACxE,SAAO,gBAAgB,aAAa;AACtC;AAMO,SAAS,4BACd,OACA,cACoB;AACpB,QAAM,aAAa,gBAAgB,KAAK;AACxC,MAAI,WAAW,SAAS,GAAG,GAAG;AAC5B,UAAM,SAAS,WAAW,MAAM,GAAG,EAAE,CAAC;AACtC,QAAI,CAAC,qBAAqB,MAAM,EAAG,QAAO;AAAA,EAC5C;AACA,MAAI,gBAAgB,CAAC,qBAAqB,YAAY,GAAG;AACvD,WAAO,kBAAkB,YAAY;AAAA,EACvC;AACA,SAAO;AACT;AAGO,SAAS,wBACd,OACA,UACoB;AACpB,MAAI,qBAAqB,QAAQ,GAAG;AAClC,WAAO,4BAA4B,OAAO,QAAQ;AAAA,EACpD;AACA,SAAO,kBAAkB,QAAQ;AACnC;AAMO,SAAS,4BACd,OACA,UACwB;AACxB,QAAM,WAAmC,CAAC;AAC1C,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAM,CAAC,GAAW,MAAe;AACrC,UAAM,MAAM,GAAG,KAAK,EAAE,KAAK,gBAAgB,CAAC,CAAC;AAC7C,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,aAAS,KAAK,EAAE,OAAO,GAAG,UAAU,EAAE,CAAC;AAAA,EACzC;AAEA,MAAI,OAAO,QAAQ;AAEnB,QAAM,aAAa,4BAA4B,OAAO,QAAQ;AAC9D,MAAI,SAAU,KAAI,OAAO,MAAS;AAClC,MAAI,WAAY,KAAI,OAAO,UAAU;AACrC,MAAI,CAAC,qBAAqB,QAAQ,GAAG;AACnC,QAAI,OAAO,YAAY;AAAA,EACzB;AAEA,SAAO;AACT;AAEA,eAAsB,2BACpB,SACA,UACA,SACuC;AACvC,MAAI,OAAqC;AACzC,MAAI,mBAAiD;AAErD,aAAW,WAAW,UAAU;AAC9B,UAAM,SAAS,MAAM,QAAQ,aAAa,SAAS,OAAO;AAC1D,WAAO;AACP,QAAI,OAAO,SAAS,OAAO,OAAQ,QAAO;AAC1C,QACE,OAAO,SACP,CAAC,OAAO,UACR,0BAA0B,QAAQ,QAAQ,QAAQ,GAClD;AACA,yBAAmB;AAAA,IACrB;AAAA,EACF;AAEA,SAAO,oBAAoB;AAC7B;AAEO,SAAS,2BACd,eACA,UACA,SACA,YACS;AACT,QAAM,MAAM,cAAc,yBAAyB;AAEnD,MAAI,qBAAqB,aAAa,EAAG,QAAO;AAEhD,MAAI,UAAU,OAAO;AACnB,WAAO,SAAS;AAAA,EAClB;AAEA,QAAM,SAAS;AAAA,IACb,YAAY,UAAU,QAAQ,SAAS,UAAU,OAAO;AAAA,IACxD;AAAA,EACF;AACA,MAAI,UAAU,gCAAgC,QAAQ,GAAG,GAAG;AAC1D,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;AD5HA,IAAMA,WAAU,cAAc,YAAY,GAAG;AAO7C,SAAS,uBAAoD;AAC3D,QAAM,QAAQ,QAAQA,SAAQ,QAAQ,mBAAmB,CAAC;AAC1D,QAAM,SAASA,SAAQ,KAAK,OAAO,kCAAkC,CAAC;AAGtE,SAAO,OAAO,uBAAuB,EAAE,QAAQ,OAAO,CAAC;AACzD;AAcA,SAAS,WAAW,OAAuB;AACzC,SAAO,MAAM,KAAK,EAAE,YAAY;AAClC;AAEA,SAAS,iBAAiB,UAAkB,SAAyB;AACnE,QAAM,aAAa,gBAAgB,OAAO;AAC1C,MAAI,WAAW,SAAS,GAAG,EAAG,QAAO;AACrC,QAAM,IAAI,kBAAkB,QAAQ,KAAK,gBAAgB,QAAQ;AACjE,SAAO,GAAG,CAAC,IAAI,UAAU;AAC3B;AAWA,IAAI,cAGO;AAGX,SAAS,cAAc,UAA4D;AACjF,QAAM,QAAQ,oBAAI,IAA6B;AAE/C,QAAM,MAAM,CAAC,KAAa,UAAyB;AACjD,UAAM,IAAI,WAAW,GAAG;AACxB,QAAI,CAAC,EAAG;AACR,UAAM,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC;AAC9B,QACE,KAAK;AAAA,MACH,CAAC,MACC,EAAE,qBAAqB,MAAM,oBAC7B,EAAE,WAAW,MAAM,UACnB,EAAE,YAAY,MAAM;AAAA,IACxB,GACA;AACA;AAAA,IACF;AACA,SAAK,KAAK,KAAK;AACf,UAAM,IAAI,GAAG,IAAI;AAAA,EACnB;AAEA,aAAW,WAAW,OAAO,OAAO,SAAS,QAAQ,GAAG;AACtD,eAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG;AACjE,YAAM,QAAQ,YAAY,QAAQ,QAAQ,SAAS,SAAS;AAC5D,UAAI,OAAO,SAAS,KAAK;AACzB,UAAI,iBAAiB,OAAO,UAAU,OAAO,OAAO,GAAG,KAAK;AAAA,IAC9D;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,YACP,QACA,SACA,WACe;AACf,QAAM,YAAY,iBAAiB,OAAO,UAAU,OAAO,OAAO;AAClE,SAAO;AAAA,IACL,UAAU,kBAAkB,OAAO,QAAQ,KAAK,OAAO;AAAA,IACvD,SAAS,gBAAgB,OAAO,OAAO;AAAA,IACvC,kBAAkB;AAAA,IAClB,SAAS,OAAO;AAAA,IAChB;AAAA,IACA,QAAQ;AAAA,EACV;AACF;AAEA,eAAe,kBAAyD;AACtE,QAAM,WAAW,MAAM,qBAAqB;AAC5C,QAAM,WAAW,GAAG,SAAS,OAAO,IAAI,SAAS,eAAe,EAAE,IAAI,SAAS,MAAM;AACrF,MAAI,aAAa,aAAa,UAAU;AACtC,WAAO,YAAY;AAAA,EACrB;AACA,QAAM,QAAQ,cAAc,QAAQ;AACpC,gBAAc,EAAE,UAAU,MAAM;AAChC,SAAO;AACT;AAEA,SAAS,eACP,OACA,OACA,cACQ;AACR,QAAM,aAAa,gBAAgB,KAAK;AACxC,MAAI,QAAQ;AAEZ,MAAI,eAAe,MAAM,iBAAkB,UAAS;AACpD,MAAI,eAAe,MAAM,QAAS,UAAS;AAC3C,MAAI,gBAAgB,MAAM,aAAa,aAAc,UAAS;AAC9D,MAAI,MAAM,QAAS,UAAS;AAE5B,SAAO;AACT;AAEA,SAAS,SACP,YACA,OACA,cACsB;AACtB,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,MAAI,WAAW,WAAW,EAAG,QAAO,WAAW,CAAC;AAEhD,MAAI,OAAO,WAAW,CAAC;AACvB,MAAI,YAAY,eAAe,MAAM,OAAO,YAAY;AACxD,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,IAAI,WAAW,CAAC;AACtB,UAAM,IAAI,eAAe,GAAG,OAAO,YAAY;AAC/C,QAAI,IAAI,WAAW;AACjB,aAAO;AACP,kBAAY;AAAA,IACd;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,UAAmD;AAC1E,SAAO;AAAA,IACL,UAAU,kBAAkB,SAAS,QAAQ,KAAK,SAAS;AAAA,IAC3D,SAAS,gBAAgB,SAAS,OAAO;AAAA,IACzC,kBAAkB,iBAAiB,SAAS,UAAU,SAAS,OAAO;AAAA,IACtE,SAAS,SAAS;AAAA,IAClB,iBAAiB,SAAS;AAAA,IAC1B,SAAS,SAAS;AAAA,IAClB,YAAY,SAAS,WAAW,aAAa;AAAA,IAC7C,SAAS,SAAS;AAAA,IAClB,QAAQ,SAAS;AAAA,EACnB;AACF;AAEA,eAAe,YAAY,OAAqD;AAC9E,QAAM,WAAW,MAAM,iBAAiB,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,CAAC;AAC/E,SAAO;AAAA,IACL,UAAU,kBAAkB,SAAS,QAAQ,KAAK,SAAS;AAAA,IAC3D,SAAS,gBAAgB,SAAS,OAAO;AAAA,IACzC,kBAAkB,iBAAiB,SAAS,UAAU,SAAS,OAAO;AAAA,IACtE,SAAS,SAAS,WAAW,MAAM;AAAA,IACnC,iBAAiB,SAAS;AAAA,IAC1B,SAAS,SAAS;AAAA,IAClB,YAAY;AAAA,IACZ,SAAS,SAAS;AAAA,IAClB,QAAQ,SAAS;AAAA,EACnB;AACF;AAEA,eAAe,cACb,OACA,OACA,UACsC;AACtC,QAAM,eAAe,WAAW,kBAAkB,QAAQ,IAAI;AAC9D,QAAM,OAAO;AAAA,IACX,WAAW,KAAK;AAAA,IAChB,WAAW,gBAAgB,KAAK,CAAC;AAAA,EACnC;AACA,MAAI,cAAc;AAChB,SAAK,KAAK,WAAW,iBAAiB,cAAc,KAAK,CAAC,CAAC;AAAA,EAC7D;AAEA,QAAM,SAA0B,CAAC;AACjC,aAAW,OAAO,MAAM;AACtB,UAAM,OAAO,MAAM,IAAI,GAAG;AAC1B,QAAI,KAAM,QAAO,KAAK,GAAG,IAAI;AAAA,EAC/B;AAEA,QAAM,OAAO,gBAAgB,KAAK;AAClC,MAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AACvB,eAAW,QAAQ,MAAM,OAAO,GAAG;AACjC,iBAAW,SAAS,MAAM;AACxB,YAAI,MAAM,YAAY,KAAM,QAAO,KAAK,KAAK;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,oBAAI,IAA2B;AAC9C,aAAW,KAAK,QAAQ;AACtB,WAAO,IAAI,GAAG,EAAE,OAAO,IAAI,EAAE,MAAM,IAAI,EAAE,gBAAgB,IAAI,CAAC;AAAA,EAChE;AAEA,QAAM,OAAO,SAAS,CAAC,GAAG,OAAO,OAAO,CAAC,GAAG,OAAO,YAAY;AAC/D,SAAO,OAAO,YAAY,IAAI,IAAI;AACpC;AAMA,eAAsB,uBACpB,OACA,UACsC;AACtC,MAAI;AACF,UAAM,WAAW,MAAM,iBAAiB,KAAK;AAC7C,WAAO,gBAAgB,QAAQ;AAAA,EACjC,SAAS,KAAK;AACZ,QAAI,EAAE,eAAe,oBAAoB,IAAI,SAAS,mBAAmB;AACvE,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM,gBAAgB;AACpC,QAAM,OAAO,wBAAwB,OAAO,QAAQ;AACpD,QAAM,SAAS,MAAM,cAAc,OAAO,OAAO,IAAI;AACrD,MAAI,OAAQ,QAAO;AAEnB,QAAM,WAAW,wBAAwB,KAAK;AAC9C,MAAI,YAAY,aAAa,gBAAgB,KAAK,GAAG;AACnD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,wBAAwB,UAAU,QAAQ;AAAA,IAC5C;AAAA,EACF;AAEA,SAAO;AACT;;;AEhQA,IAAM,kBAAkB;AAExB,SAAS,YAAY,YAA6B;AAChD,UAAQ,cAAc,KAAK;AAC7B;AAEA,SAAS,wBACP,SACA,cACoB;AACpB,MACE,QAAQ,mBAAmB,UAC3B,QAAQ,mBAAmB,QAC3B;AACA,WAAO,gBAAgB,mCACnB,QAAQ,iBACR,QAAQ;AAAA,EACd;AACA,SAAO,QAAQ,SAAS,QAAQ,kBAAkB,QAAQ;AAC5D;AAEA,SAAS,yBACP,SACA,cACoB;AACpB,MACE,QAAQ,oBAAoB,UAC5B,QAAQ,oBAAoB,QAC5B;AACA,WAAO,gBAAgB,mCACnB,QAAQ,kBACR,QAAQ;AAAA,EACd;AACA,SAAO,QAAQ,UAAU,QAAQ,mBAAmB,QAAQ;AAC9D;AAOO,SAAS,kCACd,SACA,UACA,UAAoC,CAAC,GACrB;AAChB,QAAM,eAAe,QAAQ,gBAAgB;AAC7C,QAAM,oBAAoB,YAAY,wBAAwB,SAAS,YAAY,CAAC;AACpF,QAAM,wBAAwB;AAAA,IAC5B,yBAAyB,SAAS,YAAY;AAAA,EAChD;AAEA,QAAM,WAA2B;AAAA,IAC/B;AAAA,IACA;AAAA,IACA,sBAAsB,YAAY,QAAQ,eAAe,QAAQ,QAAQ;AAAA,IACzE,uBAAuB,YAAY,QAAQ,gBAAgB,QAAQ,YAAY;AAAA,IAC/E,iBAAiB;AAAA,IACjB,sBAAsB;AAAA,IACtB;AAAA,IACA,QAAQ;AAAA,EACV;AAEA,MAAI,QAAQ,qBAAqB;AAC/B,aAAS,mCACP,oBAAoB;AACtB,aAAS,oCACP,wBAAwB;AAAA,EAC5B;AAEA,SAAO;AACT;AAEO,SAAS,uBACd,OACA,SACA,qBACA,kBAC8E;AAC9E,QAAM,EAAE,OAAO,IAAI;AAEnB,MAAI,aAAa,OAAO,SAAS,QAAQ;AACzC,MAAI,iBAAiB,OAAO,aAAa,QAAQ;AAEjD,QAAM,eACH,OAAO,cAAc,MAAM,QAAQ,yBAAyB,MAC5D,OAAO,UAAU,MAAM,QAAQ,wBAAwB;AAE1D,QAAM,iBACH,OAAO,aAAa,MACpB,QAAQ,wBAAwB,QAAQ;AAE3C,QAAM,aAAa,OAAO,SAAS,KAAK,QAAQ;AAChD,QAAM,aAAa,OAAO,SAAS,MAAM,QAAQ,mBAAmB;AACpE,QAAM,cAAc,QAAQ;AAE5B,MAAI,qBAAqB;AACvB,kBACE,OAAO,UAAU,QAAQ,oCAAoC;AAC/D,sBACE,OAAO,cAAc,QAAQ,qCAAqC;AAAA,EACtE;AAEA,QAAM,OACJ,aACA,iBACA,cACA,gBACA,YACA,YACA;AAEF,MAAI,CAAC,kBAAkB;AACrB,WAAO,EAAE,KAAK;AAAA,EAChB;AAEA,SAAO;AAAA,IACL;AAAA,IACA,WAAW;AAAA,MACT,eAAe;AAAA,MACf,mBAAmB;AAAA,MACnB,gBAAgB,eAAe;AAAA,MAC/B,kBAAkB,iBAAiB;AAAA,MACnC,cAAc,aAAa;AAAA,MAC3B,cAAc,aAAa;AAAA,MAC3B,oBAAoB,eAAe;AAAA,IACrC;AAAA,EACF;AACF;;;AClGA,SAAS,eAA+B;AACtC,SAAO;AAAA,IACL,mBAAmB;AAAA,IACnB,uBAAuB;AAAA,IACvB,iBAAiB;AAAA,IACjB,sBAAsB;AAAA,IACtB,WAAU,oBAAI,KAAK,GAAE,YAAY;AAAA,IACjC,QAAQ;AAAA,EACV;AACF;AAEA,SAAS,iBACJ,QAC6C;AAChD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAsD,CAAC;AAC7D,aAAW,SAAS,QAAQ;AAC1B,eAAW,KAAK,OAAO;AACrB,YAAM,MAAM,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK;AAC3C,UAAI,KAAK,IAAI,GAAG,EAAG;AACnB,WAAK,IAAI,GAAG;AACZ,UAAI,KAAK,CAAC;AAAA,IACZ;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,iBAAN,MAAqB;AAAA,EAM1B,YACmB,SACjB,UAAiC,CAAC,GAClC;AAFiB;AAGjB,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,mBAAmB,QAAQ,oBAAoB;AACpD,SAAK,kBAAkB,QAAQ;AAC/B,SAAK,sBAAsB,QAAQ,uBAAuB;AAAA,EAC5D;AAAA,EAPmB;AAAA,EANF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBjB,MAAM,oBACJ,QACA,gBACuB;AACvB,UAAM,EAAE,OAAO,WAAW,IAAI,kBAAkB,QAAQ,cAAc;AACtE,UAAM,WAA4B,CAAC;AACnC,QAAI,WAAW,OAAO,WAAW;AAC/B,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,mCAAmC,WAAW,OAAO,IAAI;AAAA,MACpE,CAAC;AAAA,IACH;AACA,UAAM,SAAS,MAAM,KAAK,UAAU,KAAK;AACzC,UAAM,WAAW,iBAAiB,QAAQ,OAAO,iBAAiB,UAAU,CAAC;AAC7E,QAAI,SAAS,SAAS,GAAG;AACvB,eAAS,WAAW,CAAC,GAAI,SAAS,YAAY,CAAC,GAAI,GAAG,QAAQ;AAAA,IAChE;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,OAA4C;AAC1D,UAAM,aAAa,kBAAkB,KAAK;AAC1C,UAAM,eAAe;AAAA,MACnB,GAAG,KAAK;AAAA,MACR,eAAe,KAAK,iBAAiB,KAAK,iBAAiB;AAAA,IAC7D;AAEA,QAAI,WAAW,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,4BAA4B,YAAY,MAAM,QAAQ;AAAA,MACtD;AAAA,IACF;AAEA,QAAI,0BAA0B,UAAU,MAAM,QAAQ,GAAG;AACvD,aAAO,KAAK,oBAAoB,YAAY,OAAO,QAAQ;AAAA,IAC7D;AAEA,QAAI,eAAe;AACnB,UAAM,WAA4B,CAAC;AAEnC,QAAI,CAAC,UAAU,SAAS,CAAC,SAAS,QAAQ;AACxC,UAAI,CAAC,gBAAgB,MAAM,QAAQ,GAAG;AACpC,uBAAe,MAAM,uBAAuB,YAAY,MAAM,QAAQ;AAAA,MACxE;AACA,UAAI,cAAc;AAChB,mBAAW,MAAM;AAAA,UACf,KAAK;AAAA,UACL;AAAA,YACE;AAAA,cACE,aAAa;AAAA,cACb,MAAM,YAAY,aAAa;AAAA,YACjC;AAAA,YACA;AAAA,cACE,aAAa;AAAA,cACb,aAAa;AAAA,YACf;AAAA,UACF;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,UAAI,0BAA0B,UAAU,MAAM,QAAQ,GAAG;AACvD,eAAO,KAAK,oBAAoB,YAAY,OAAO,QAAQ;AAAA,MAC7D;AAEA,WAAK,CAAC,UAAU,SAAS,CAAC,SAAS,WAAW,cAAc,SAAS;AACnE,cAAMC,uBAAsB;AAAA,UAC1B,MAAM;AAAA,UACN;AAAA,UACA,aAAa;AAAA,UACb,cAAc;AAAA,QAChB;AACA,cAAMC,WAAU;AAAA,UACd,aAAa;AAAA,WACb,oBAAI,KAAK,GAAE,YAAY;AAAA,UACvB;AAAA,YACE,cAAc,MAAM,OAAO;AAAA,YAC3B,qBAAAD;AAAA,UACF;AAAA,QACF;AACA,cAAM,EAAE,MAAAE,OAAM,WAAAC,WAAU,IAAI;AAAA,UAC1B;AAAA,UACAF;AAAA,UACAD;AAAA,UACA,KAAK;AAAA,QACP;AAEA,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,SAAS,+BAA+B,UAAU,kCAAkC,aAAa,UAAU,WAAM,aAAa,gBAAgB;AAAA,QAChJ,CAAC;AACD,YACEA,wBACAC,SAAQ,qCAAqC,QAC7C;AACA,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,SACE;AAAA,UACJ,CAAC;AAAA,QACH;AAEA,gBAAQ,KAAK,cAAc,SAAS,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,GAAG,CAAC,EAAE;AAErE,eAAO,KAAK;AAAA,UACV;AAAA,YACE,MAAAC;AAAA,YACA,WAAAC;AAAA,YACA,iBAAiB,aAAa;AAAA,YAC9B,qBAAAH;AAAA,YACA,iBAAiB;AAAA,YACjB,iBAAiBC;AAAA,YACjB,QAAQ;AAAA,YACR;AAAA,UACF;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,UAAU,SAAS,CAAC,SAAS,QAAQ;AACxC,aAAO,KAAK,mBAAmB,YAAY,OAAO,QAAQ;AAAA,IAC5D;AAEA,UAAM,EAAE,QAAQ,QAAQ,IAAI;AAC5B,UAAM,sBAAsB;AAAA,MAC1B,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB;AACA,UAAM,UAAU,OAAO;AACvB,UAAM,EAAE,MAAM,UAAU,IAAI;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,QACA;AAAA,QACA,iBAAiB;AAAA,QACjB;AAAA,QACA,iBAAiB;AAAA,QACjB,iBAAiB;AAAA,QACjB,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,sBACN,OACA,eACA,UACiB;AACjB,UAAM,WAAW,MAAM,aAAa,MAAM,aAAa,MAAM;AAC7D,QAAI,CAAC,SAAU,QAAO,CAAC;AAEvB,UAAM,qBAAqB,gBAAgB,QAAQ;AACnD,UAAM,mBAAmB,gBAAgB,aAAa;AACtD,QAAI,uBAAuB,iBAAkB,QAAO,CAAC;AAErD,UAAM,WAAW,wBAAwB,QAAQ;AACjD,UAAM,cACJ,UAAU,UAAU,QACpB,SAAS,YAAY;AAAA,MACnB,CAAC,MAAM,MAAM,0BAA0B,MAAM;AAAA,IAC/C;AACF,UAAM,iBACJ,aAAa,QAAQ,gBAAgB,QAAQ,MAAM;AAErD,QAAI,CAAC,eAAe,CAAC,eAAgB,QAAO,CAAC;AAE7C,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,SAAS,+BAA+B,aAAa,4BAA4B,QAAQ;AAAA,MAC3F;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,OACN,SAIA,OACA,UACc;AACd,UAAM,WAAW,iBAAiB,SAAS,KAAK;AAChD,UAAM,iBAAiB,KAAK;AAAA,MAC1B;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF;AACA,QAAI,eAAe,SAAS,GAAG;AAC7B,eAAS,WAAW,CAAC,GAAI,SAAS,YAAY,CAAC,GAAI,GAAG,cAAc;AAAA,IACtE;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,oBACN,YACA,OACA,UACc;AACd,UAAM,WAA4B;AAAA,MAChC;AAAA,QACE,MAAM;AAAA,QACN,SAAS,mBAAmB,MAAM,QAAQ,iCAAiC,UAAU;AAAA,MACvF;AAAA,IACF;AACA,YAAQ,KAAK,cAAc,SAAS,CAAC,EAAG,OAAO,EAAE;AACjD,WAAO,KAAK;AAAA,MACV;AAAA,QACE,MAAM;AAAA,QACN,iBAAiB,UAAU,QAAQ,SAAS,UAAU;AAAA,QACtD,qBAAqB;AAAA,QACrB,iBAAiB;AAAA,QACjB,iBAAiB,aAAa;AAAA,QAC9B,QAAQ;AAAA,QACR;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,mBACN,YACA,OACA,UACc;AACd,QAAI,KAAK,qBAAqB;AAC5B,YAAM,IAAI,sBAAsB,YAAY,MAAM,QAAQ;AAAA,IAC5D;AAEA,UAAM,WAA4B;AAAA,MAChC;AAAA,QACE,MAAM;AAAA,QACN,SAAS,kBAAkB,UAAU,iBAAiB,MAAM,QAAQ;AAAA,MACtE;AAAA,IACF;AACA,YAAQ,KAAK,cAAc,SAAS,CAAC,EAAG,OAAO,EAAE;AAEjD,WAAO,KAAK;AAAA,MACV;AAAA,QACE,MAAM;AAAA,QACN,iBAAiB;AAAA,QACjB,qBAAqB;AAAA,UACnB,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA,KAAK,iBAAiB;AAAA,QACxB;AAAA,QACA,iBAAiB;AAAA,QACjB,iBAAiB,aAAa;AAAA,QAC9B,QAAQ;AAAA,QACR,cAAc;AAAA,QACd;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;","names":["require","routedViaOpenRouter","pricing","cost","breakdown"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-DXZOL3VN.cjs","../src/sync/modelNameResolver/catalogIndexes.ts","../src/sync/modelNameResolver/ModelNameResolver.ts","../src/models/reasoningModel.ts"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACA;ACdO,SAAS,mBAAA,CAAoB,OAAA,EAAqD;AACvF,EAAA,MAAM,WAAA,kBAAa,IAAI,GAAA,CAAoB,CAAA;AAC3C,EAAA,MAAM,UAAA,kBAAY,IAAI,GAAA,CAAoB,CAAA;AAC1C,EAAA,MAAM,aAAA,kBAAe,IAAI,GAAA,CAAoB,CAAA;AAE7C,EAAA,IAAA,CAAA,MAAW,OAAA,GAAU,OAAA,CAAQ,MAAA,CAAO,CAAA,EAAG;AACrC,IAAA,IAAA,CAAA,MAAW,MAAA,GAAS,MAAA,CAAO,OAAA,EAAS;AAClC,MAAA,UAAA,CAAW,GAAA,CAAI,+CAAA,KAAqB,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA;AAAA,IACvD;AACA,IAAA,GAAA,CAAI,MAAA,CAAO,aAAA,EAAe;AACxB,MAAA,SAAA,CAAU,GAAA,CAAI,+CAAA,MAAgB,CAAO,aAAa,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA;AAAA,IACrE;AACA,IAAA,MAAM,IAAA,EAAM,MAAA,CAAO,UAAA;AACnB,IAAA,YAAA,CAAa,GAAA,CAAI,GAAA,EAAA,kBAAM,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA,UAAK,GAAA,EAAA,EAAK,CAAC,CAAA;AAAA,EACxD;AAEA,EAAA,MAAM,uBAAA,EAAyB,CAAC,GAAG,YAAA,CAAa,OAAA,CAAQ,CAAC,CAAA,CACtD,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,EAAA,GAAM,CAAA,CAAE,CAAC,EAAA,EAAI,CAAA,CAAE,CAAC,CAAC,CAAA,CAC1B,GAAA,CAAI,CAAC,CAAC,CAAC,CAAA,EAAA,GAAM,CAAC,CAAA;AAEjB,EAAA,OAAO,EAAE,UAAA,EAAY,SAAA,EAAW,uBAAuB,CAAA;AACzD;ADWA;AACA;AEHO,IAAM,kBAAA,EAAN,MAAwB;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,WAAA,CACE,OAAA,EACA,QAAA,EAAgC,CAAC,CAAA,EACjC;AACA,IAAA,IAAA,CAAK,QAAA,EAAU,OAAA;AACf,IAAA,IAAA,CAAK,QAAA,EAAU,mBAAA,CAAoB,OAAO,CAAA;AAC1C,IAAA,IAAA,CAAK,IAAA,EAAM;AAAA,MACT,OAAA;AAAA,MACA,OAAA,EAAS,IAAA,CAAK,OAAA;AAAA,MACd,OAAA,EAAS;AAAA,QACP,mBAAA,mBAAqB,OAAA,CAAQ,mBAAA,UAAuB,gDAAA;AAAA,QACpD,aAAA,EAAe,OAAA,CAAQ,aAAA;AAAA,QACvB,oBAAA,mBAAsB,OAAA,CAAQ,oBAAA,UAAwB,CAAC,GAAA;AAAA,QACvD,0BAAA,mBAA4B,OAAA,CAAQ,0BAAA,UAA8B,CAAC,GAAA;AAAA,QACnE,wBAAA,mBAA0B,OAAA,CAAQ,wBAAA,UAA4B,CAAC,GAAA;AAAA,QAC/D,UAAA,mBAAY,OAAA,CAAQ,UAAA,UAAc,wDAAA;AAAyB,MAC7D;AAAA,IACF,CAAA;AAAA,EACF;AAAA,EAEA,OAAA,CAAQ,KAAA,EAAoD;AAC1D,IAAA,MAAM,UAAA,EAAkC,CAAC,CAAA;AACzC,IAAA,MAAM,UAAA,EAAY,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,mBAAA;AAEnC,IAAA,IAAI,SAAA,EAAW,iDAAA,KAAkB,CAAM,QAAQ,CAAA;AAC/C,IAAA,IAAI,MAAA,EAAQ,+CAAA,KAAgB,CAAM,KAAK,CAAA;AACvC,IAAA,MAAM,gBAAA,EAAkB,KAAA;AAGxB,IAAA,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,aAAA,EAAe;AAClC,MAAA,SAAA,CAAU,IAAA,CAAK,gBAAgB,CAAA;AAC/B,MAAA,MAAM,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,aAAA,CAAc,GAAA,CAAI,KAAK,CAAA;AACtD,MAAA,GAAA,CAAI,KAAA,EAAO;AACT,QAAA,MAAA,EAAQ,+CAAA,KAAgB,CAAM,OAAO,CAAA;AACrC,QAAA,SAAA,mBAAW,iDAAA,KAAkB,CAAM,QAAQ,CAAA,UAAK,UAAA;AAAA,MAClD;AAAA,IACF;AAGA,IAAA,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,cAAA,GAAiB,QAAA,EAAU;AAC9C,MAAA,MAAM,gBAAA,EAAkB,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,aAAA,CAAc,GAAA,CAAI,QAAQ,CAAA;AACnE,MAAA,GAAA,CAAI,eAAA,EAAiB;AACnB,QAAA,SAAA,CAAU,IAAA,CAAK,8BAA8B,CAAA;AAC7C,QAAA,MAAA,EAAQ,+CAAA,eAAgB,CAAgB,OAAO,CAAA;AAC/C,QAAA,SAAA,mBAAW,iDAAA,eAAkB,CAAgB,QAAQ,CAAA,UAAK,UAAA;AAAA,MAC5D;AAAA,IACF;AAGA,IAAA,MAAM,eAAA,kBAAiB,IAAI,GAAA,CAAI;AAAA,MAC7B,GAAG,iCAAA;AAAA,MACH,GAAG,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,wBAAA,CAAyB,GAAA,CAAI,CAAC,CAAA,EAAA,GAAM,+CAAA,CAAiB,CAAC;AAAA,IAC5E,CAAC,CAAA;AACD,IAAA,GAAA,CAAI,SAAA,GAAY,cAAA,CAAe,GAAA,CAAI,QAAQ,CAAA,EAAG;AAC5C,MAAA,SAAA,CAAU,IAAA,CAAK,4BAA4B,CAAA;AAC3C,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ;AAAA,QAClB,OAAA,EAAS,KAAA;AAAA,QACT,MAAA,EAAQ,IAAA;AAAA,QACR,UAAA,EAAY,IAAA;AAAA,QACZ,QAAA,EAAU,4BAAA;AAAA,QACV,MAAA,EAAQ,CAAA,gBAAA,EAAmB,QAAQ,CAAA,uCAAA,CAAA;AAAA,QACnC,WAAA,EAAa,SAAA;AAAA,QACb,eAAA;AAAA,QACA,QAAA;AAAA,QACA,gBAAA,EAAkB,KAAA,CAAM;AAAA,MAC1B,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,MAAM,cAAA,EAAgB,CAAC,GAAG,SAAS,CAAA;AAEnC,IAAA,MAAM,EAAE,KAAA,EAAO,SAAS,EAAA,EAAI,IAAA,CAAK,WAAA,CAAY,KAAA,EAAO,QAAA,EAAU,SAAA,EAAW,SAAA,EAAW,CAAC,CAAC,CAAA;AACtF,IAAA,GAAA,CAAI,KAAA,EAAO;AACT,MAAA,MAAM,IAAA,EAAM;AAAA,QACV,GAAG,aAAA,CAAc,MAAA,CAAO,CAAC,CAAA,EAAA,GAAM,CAAC,KAAA,CAAM,WAAA,CAAY,QAAA,CAAS,CAAC,CAAC,CAAA;AAAA,QAC7D,GAAG,KAAA,CAAM;AAAA,MACX,CAAA;AACA,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ;AAAA,QAClB,OAAA,EAAS,KAAA,CAAM,OAAA;AAAA,QACf,MAAA,EAAQ,KAAA,CAAM,MAAA;AAAA,QACd,UAAA,EAAY,KAAA,CAAM,UAAA;AAAA,QAClB,QAAA,EAAU,KAAA,CAAM,QAAA;AAAA,QAChB,MAAA,EAAQ,KAAA,CAAM,MAAA;AAAA,QACd,WAAA,EAAa,GAAA;AAAA,QACb,eAAA;AAAA,QACA,QAAA;AAAA,QACA,gBAAA,EAAkB,KAAA,CAAM;AAAA,MAC1B,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,MAAM,SAAA,EAAoC;AAAA,MACxC,KAAA,EAAO,KAAA;AAAA,MACP,OAAA,EAAS,IAAA;AAAA,MACT,MAAA,EAAQ,IAAA;AAAA,MACR,mBAAA,EAAqB,SAAA;AAAA,MACrB,MAAA,EAAQ,gDAAA;AAAA,MACR,qBAAA,EAAuB;AAAA,IACzB,CAAA;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEA,WAAA,CAAY,MAAA,EAAyD;AACnE,IAAA,OAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,EAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA;AAAA,EAC1C;AAAA,EAEA,cAAA,CAAe,KAAA,EAAqD;AAClE,IAAA,MAAM,OAAA,EAAS,IAAA,CAAK,OAAA,CAAQ,KAAK,CAAA;AACjC,IAAA,GAAA,CAAI,MAAA,CAAO,KAAA,EAAO,OAAO,MAAA;AACzB,IAAA,MAAM,IAAI,2CAAA,CAAqB,KAAA,EAAO,MAAM,CAAA;AAAA,EAC9C;AAAA,EAEQ,WAAA,CACN,KAAA,EACA,QAAA,EACA,SAAA,EACA,SAAA,EACA,WAAA,EACA,MAAA,EAAQ,CAAA,EAIR;AACA,IAAA,GAAA,CAAI,MAAA,EAAQ,EAAA,EAAI,OAAO,EAAE,KAAA,EAAO,KAAK,CAAA;AAErC,IAAA,MAAM,SAAA,EAAW,CACf,QAAA,EACA,EAAA,EAAA,GACoE;AACpE,MAAA,GAAA,CAAI,CAAC,SAAA,CAAU,QAAA,CAAS,QAAQ,CAAA,EAAG,SAAA,CAAU,IAAA,CAAK,QAAQ,CAAA;AAC1D,MAAA,MAAM,EAAA,EAAI,EAAA,CAAG,CAAA;AACb,MAAA,GAAA,CAAI,EAAA,GAAK,CAAA,CAAE,WAAA,GAAc,SAAA,EAAW;AAClC,QAAA,OAAO,EAAE,GAAG,CAAA,EAAG,WAAA,EAAa,CAAC,GAAG,WAAA,EAAa,QAAQ,EAAE,CAAA;AAAA,MACzD;AACA,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAEA,IAAA,IAAI,IAAA,EAAM,QAAA,CAAS,aAAA,EAAe,CAAA,EAAA,GAAM,IAAA,CAAK,UAAA,CAAW,KAAK,CAAC,CAAA;AAC9D,IAAA,GAAA,CAAI,GAAA,EAAK,OAAO,EAAE,KAAA,EAAO,IAAI,CAAA;AAE7B,IAAA,IAAA,EAAM,QAAA,CAAS,qBAAA,EAAuB,CAAA,EAAA,GAAM,IAAA,CAAK,iBAAA,CAAkB,KAAK,CAAC,CAAA;AACzE,IAAA,GAAA,CAAI,GAAA,EAAK,OAAO,EAAE,KAAA,EAAO,IAAI,CAAA;AAE7B,IAAA,IAAA,EAAM,QAAA,CAAS,sBAAA,EAAwB,CAAA,EAAA,GAAM,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAClE,IAAA,GAAA,CAAI,GAAA,EAAK,OAAO,EAAE,KAAA,EAAO,IAAI,CAAA;AAE7B,IAAA,IAAA,EAAM,QAAA;AAAA,MAAS,2BAAA;AAAA,MAA6B,CAAA,EAAA,GAC1C,IAAA,CAAK,uBAAA,CAAwB,KAAA,EAAO,QAAQ;AAAA,IAC9C,CAAA;AACA,IAAA,GAAA,CAAI,GAAA,EAAK,OAAO,EAAE,KAAA,EAAO,IAAI,CAAA;AAE7B,IAAA,IAAA,EAAM,QAAA,CAAS,2BAAA,EAA6B,CAAA,EAAA,GAAM,IAAA,CAAK,uBAAA,CAAwB,KAAK,CAAC,CAAA;AACrF,IAAA,GAAA,CAAI,GAAA,EAAK,OAAO,EAAE,KAAA,EAAO,IAAI,CAAA;AAE7B,IAAA,MAAM,SAAA,EAAW,uDAAA,KAA6B,CAAA;AAC9C,IAAA,GAAA,CAAI,SAAA,GAAY,SAAA,IAAa,KAAA,EAAO;AAClC,MAAA,GAAA,CAAI,CAAC,SAAA,CAAU,QAAA,CAAS,sBAAsB,CAAA,EAAG,SAAA,CAAU,IAAA,CAAK,sBAAsB,CAAA;AACtF,MAAA,MAAM,MAAA,EAAQ,IAAA,CAAK,WAAA;AAAA,QACjB,QAAA;AAAA,QACA,QAAA;AAAA,QACA,SAAA;AAAA,QACA,SAAA;AAAA,QACA,CAAC,GAAG,WAAA,EAAa,sBAAsB,CAAA;AAAA,QACvC,MAAA,EAAQ;AAAA,MACV,CAAA;AACA,MAAA,GAAA,CAAI,KAAA,CAAM,KAAA,EAAO;AACf,QAAA,OAAO;AAAA,UACL,KAAA,EAAO;AAAA,YACL,GAAG,KAAA,CAAM,KAAA;AAAA,YACT,UAAA,EAAY,IAAA;AAAA,YACZ,QAAA,EAAU,sBAAA;AAAA,YACV,MAAA,EAAQ,CAAA,8BAAA,EAAiC,KAAK,CAAA,UAAA,EAAQ,QAAQ,CAAA,OAAA,EAAU,KAAA,CAAM,KAAA,CAAM,MAAM,CAAA,CAAA;AACV,YAAA;AAClF,UAAA;AACF,QAAA;AACF,MAAA;AACF,IAAA;AAEqE,IAAA;AACxC,IAAA;AAEc,IAAA;AAC5B,IAAA;AACuE,MAAA;AACjE,MAAA;AACQ,QAAA;AACzB,QAAA;AACA,QAAA;AACA,QAAA;AACsC,QAAA;AAC9B,QAAA;AACV,MAAA;AACiB,MAAA;AACR,QAAA;AACE,UAAA;AACI,YAAA;AACG,YAAA;AACF,YAAA;AACuE,YAAA;AACF,YAAA;AACjF,UAAA;AACF,QAAA;AACF,MAAA;AACF,IAAA;AAEiD,IAAA;AACpC,IAAA;AACuE,MAAA;AAC7C,MAAA;AAC5B,QAAA;AACoE,UAAA;AAC3E,QAAA;AACF,MAAA;AACO,MAAA;AACE,QAAA;AACG,QAAA;AACS,UAAA;AACG,UAAA;AACJ,UAAA;AAClB,QAAA;AACF,MAAA;AACF,IAAA;AAEqB,IAAA;AACvB,EAAA;AAEyD,EAAA;AAClB,IAAA;AACjB,IAAA;AACb,IAAA;AACI,MAAA;AACT,MAAA;AACY,MAAA;AACF,MAAA;AAC+B,MAAA;AAC3C,IAAA;AACF,EAAA;AAEgE,EAAA;AACb,IAAA;AAC5B,IAAA;AACkB,IAAA;AACnB,IAAA;AACb,IAAA;AACL,MAAA;AACA,MAAA;AACY,MAAA;AACF,MAAA;AACoC,MAAA;AAChD,IAAA;AACF,EAAA;AAEwD,EAAA;AACN,IAAA;AAC3B,IAAA;AACkB,IAAA;AACnB,IAAA;AACb,IAAA;AACL,MAAA;AACA,MAAA;AACY,MAAA;AACF,MAAA;AAC2C,MAAA;AACvD,IAAA;AACF,EAAA;AAEgE,EAAA;AAC7C,IAAA;AACK,MAAA;AACjB,MAAA;AACL,IAAA;AAC8C,IAAA;AACb,MAAA;AACjC,IAAA;AACO,IAAA;AACT,EAAA;AAKyB,EAAA;AACS,IAAA;AAEJ,IAAA;AACe,IAAA;AACnB,MAAA;AACxB,IAAA;AACiD,IAAA;AACmB,IAAA;AACf,IAAA;AACT,MAAA;AAC5C,IAAA;AAE+B,IAAA;AACO,MAAA;AACG,MAAA;AACzB,MAAA;AACD,MAAA;AACsC,QAAA;AACrC,QAAA;AACM,UAAA;AACC,UAAA;AACnB,QAAA;AACF,MAAA;AACY,MAAA;AACwB,QAAA;AAC3B,QAAA;AACL,UAAA;AACA,UAAA;AACY,UAAA;AACF,UAAA;AAGN,UAAA;AACN,QAAA;AACF,MAAA;AACF,IAAA;AACO,IAAA;AACT,EAAA;AAEsE,EAAA;AACnC,IAAA;AACa,IAAA;AACpB,IAAA;AACsB,IAAA;AACE,IAAA;AACb,IAAA;AACE,IAAA;AACzB,IAAA;AACD,IAAA;AACsC,MAAA;AAC7B,MAAA;AACJ,MAAA;AACC,MAAA;AACnB,IAAA;AACO,IAAA;AACL,MAAA;AACA,MAAA;AACY,MAAA;AACF,MAAA;AAC6D,MAAA;AACzE,IAAA;AACF,EAAA;AAE8D,EAAA;AACnC,IAAA;AACkB,MAAA;AACC,MAAA;AACP,MAAA;AACM,QAAA;AACE,QAAA;AAC7B,QAAA;AACH,UAAA;AACI,YAAA;AACT,YAAA;AACY,YAAA;AACF,YAAA;AAC8C,YAAA;AAC1D,UAAA;AACF,QAAA;AACF,MAAA;AACF,IAAA;AAE6C,IAAA;AACjC,IAAA;AACH,MAAA;AACW,QAAA;AACD,QAAA;AACH,QAAA;AACF,QAAA;AAC8D,QAAA;AAC1E,MAAA;AACF,IAAA;AACO,IAAA;AACT,EAAA;AAIqD,EAAA;AACoC,IAAA;AACzC,IAAA;AACf,MAAA;AACc,MAAA;AACzB,QAAA;AACd,UAAA;AACA,UAAA;AAC4C,UAAA;AAC7C,QAAA;AACH,MAAA;AACF,IAAA;AACoC,IAAA;AACsB,IAAA;AACjC,IAAA;AAC2B,IAAA;AACtD,EAAA;AAE+C,EAAA;AACuB,IAAA;AACtE,EAAA;AAKoE,EAAA;AACW,IAAA;AAC3C,IAAA;AACG,IAAA;AAEO,IAAA;AACb,MAAA;AACD,QAAA;AACG,QAAA;AAC9B,MAAA;AACiE,MAAA;AACX,MAAA;AAC5B,MAAA;AAEkB,MAAA;AACR,MAAA;AACF,MAAA;AAEsB,MAAA;AAG2B,MAAA;AAC3E,MAAA;AAEwB,MAAA;AACiB,QAAA;AAClD,MAAA;AACF,IAAA;AAEuC,IAAA;AAChC,IAAA;AACS,MAAA;AACD,MAAA;AACD,MAAA;AACF,MAAA;AACiD,MAAA;AAC7D,IAAA;AACF,EAAA;AAOW,EAAA;AAC2C,IAAA;AAClB,IAAA;AACC,IAAA;AAC8C,MAAA;AACxE,MAAA;AACT,IAAA;AAE+B,IAAA;AACqE,IAAA;AAC3F,MAAA;AACT,IAAA;AAEmE,IAAA;AAC5D,IAAA;AACT,EAAA;AAY2B,EAAA;AAClB,IAAA;AACE,MAAA;AACO,MAAA;AACD,MAAA;AACa,MAAA;AACnB,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACP,MAAA;AACiB,MAAA;AACC,MAAA;AACG,MAAA;AACC,MAAA;AACxB,IAAA;AACF,EAAA;AACF;AFrF4G;AACA;AGzb7B;AAawB;AACpE,EAAA;AACiC,IAAA;AAClE,EAAA;AACF;AAQW;AAC4B,EAAA;AAC+B,EAAA;AAC3D,IAAA;AACT,EAAA;AAC8C,EAAA;AAChD;AAK8E;AACP,EAAA;AACvE;AAQsE;AACzB,EAAA;AAC5B,IAAA;AACf,EAAA;AACqC,EAAA;AACvC;AH6Z4G;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-DXZOL3VN.cjs","sourcesContent":[null,"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 { stripModelSlugSuffix, stripModelVersionSuffix } from \"./stripVersionSuffix.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\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 = stripModelVersionSuffix(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 dateSuffixMatch(model: string): MatchCandidate | null {\n if (model.includes(\"/\")) {\n const [prefix, slug] = model.split(\"/\", 2);\n const stripped = stripModelSlugSuffix(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","import type { AiModelRecord } from \"./types.js\";\n\n/** OpenRouter `supported_parameters` values that indicate reasoning API support. */\nexport const REASONING_SUPPORTED_PARAMETERS = [\"reasoning\", \"include_reasoning\"] as const;\n\nexport type ReasoningModelInput = Pick<\n AiModelRecord,\n \"supportedParameters\" | \"pricing\" | \"openRouterPricing\"\n> & {\n supportsReasoning?: boolean;\n};\n\n/**\n * Whether the model accepts OpenRouter's `reasoning` request parameter\n * (effort, max_tokens, exclude, enabled).\n */\nexport function supportsReasoningParameter(model: Pick<AiModelRecord, \"supportedParameters\">): boolean {\n return model.supportedParameters.some((p) =>\n (REASONING_SUPPORTED_PARAMETERS as readonly string[]).includes(p),\n );\n}\n\n/**\n * Whether the model bills separate reasoning / thinking tokens\n * (`internal_reasoning` in OpenRouter pricing).\n */\nexport function hasReasoningPricing(\n model: Pick<AiModelRecord, \"pricing\" | \"openRouterPricing\">,\n): boolean {\n const raw = model.openRouterPricing?.internal_reasoning;\n if (raw !== undefined && raw !== null && String(raw).trim() !== \"\") {\n return true;\n }\n return model.pricing.reasoningUsdPerToken !== undefined;\n}\n\n/**\n * Compute `supportsReasoning` from catalog fields (used when normalizing catalog entries).\n */\nexport function computeSupportsReasoning(model: ReasoningModelInput): boolean {\n return supportsReasoningParameter(model) || hasReasoningPricing(model);\n}\n\n/**\n * True when the model supports reasoning tokens (API param and/or separate reasoning pricing).\n *\n * Prefer `model.supportsReasoning` on {@link AiModelRecord} after catalog load;\n * this helper also works when only partial fields are available.\n */\nexport function isReasoningModel(model: ReasoningModelInput): boolean {\n if (model.supportsReasoning !== undefined) {\n return model.supportsReasoning;\n }\n return computeSupportsReasoning(model);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-EDMCKHO6.cjs","../src/sync/modelNameResolver/constants.ts","../src/sync/modelNameResolver/normalize.ts","../src/sync/openRouterRoutingEnv.ts","../src/sync/modelNameResolver/stripVersionSuffix.ts"],"names":["stripped"],"mappings":"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AA;AACjB;AAEO,SAAS,mBAAA,CAAoB,UAAA,EAA4B;AAC9D,EAAA,OAAO,CAAA,EAAA;AACT;AAcgB;AAGR,EAAA;AACA,EAAA;AACN,EAAA;AACM,IAAA;AACN,EAAA;AACA,EAAA;AACM,IAAA;AACN,EAAA;AAEM,EAAA;AACA,EAAA;AACA,EAAA;AAEC,EAAA;AACL,IAAA;AACA,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACF,IAAA;AACF,EAAA;AACF;AAOgB;AAIT,EAAA;AACD,EAAA;AACA,EAAA;AACF,IAAA;AACF,EAAA;AACO,EAAA;AACT;AHkGU;AACA;AI1KG;AACL,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACR;AAGgB;AACd,EAAA;AACM,IAAA;AACF,MAAA;AACF,IAAA;AACF,EAAA;AACO,EAAA;AACT;AAMgB;AACR,EAAA;AACD,EAAA;AAED,EAAA;AACI,IAAA;AACA,IAAA;AACA,IAAA;AACAA,IAAAA;AACFA,IAAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACF,EAAA;AAEM,EAAA;AACC,EAAA;AACT;AJmKU;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-EDMCKHO6.cjs","sourcesContent":[null,"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 { 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","import { normalizeString } from \"./normalize.js\";\n\n/** Patterns stripped when resolving versioned runtime model ids to catalog entries. */\nexport const VERSION_STRIP_PATTERNS: ReadonlyArray<{ 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\n/** Strip version/date suffix from a bare slug (no `provider/` prefix). */\nexport function stripModelSlugSuffix(slug: string): string | null {\n for (const { re } of VERSION_STRIP_PATTERNS) {\n if (re.test(slug)) {\n return slug.replace(re, \"\");\n }\n }\n return null;\n}\n\n/**\n * Strip a version/date suffix from a model id (`gpt-5.5-2026-04-23` → `gpt-5.5`,\n * `openai/gpt-4o-2024-08-06` → `openai/gpt-4o`). Returns null when nothing was stripped.\n */\nexport function stripModelVersionSuffix(model: string): string | null {\n const normalized = normalizeString(model);\n if (!normalized) return null;\n\n if (normalized.includes(\"/\")) {\n const slash = normalized.indexOf(\"/\");\n const prefix = normalized.slice(0, slash);\n const slug = normalized.slice(slash + 1);\n const stripped = stripModelSlugSuffix(slug);\n if (stripped && stripped !== slug) {\n return `${prefix}/${stripped}`;\n }\n return null;\n }\n\n const stripped = stripModelSlugSuffix(normalized);\n return stripped && stripped !== normalized ? stripped : null;\n}\n"]}