@x12i/ai-tools 2.1.5 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/{AiModelsCatalogClient-DgBdVFk-.d.cts → AiModelsCatalogClient-CQf-zHc6.d.cts} +1 -1
  2. package/dist/{AiModelsCatalogClient-C9ZJHhv3.d.ts → AiModelsCatalogClient-Cohl3zfe.d.ts} +1 -1
  3. package/dist/aliases/index.d.cts +4 -3
  4. package/dist/aliases/index.d.ts +4 -3
  5. package/dist/catalog/index.cjs +5 -4
  6. package/dist/catalog/index.cjs.map +1 -1
  7. package/dist/catalog/index.d.cts +5 -4
  8. package/dist/catalog/index.d.ts +5 -4
  9. package/dist/catalog/index.js +4 -3
  10. package/dist/{chunk-4ILJWO64.js → chunk-3CUSLNEV.js} +8 -1
  11. package/dist/chunk-3CUSLNEV.js.map +1 -0
  12. package/dist/{chunk-IYRZYLUP.cjs → chunk-3JDAPUZM.cjs} +14 -12
  13. package/dist/chunk-3JDAPUZM.cjs.map +1 -0
  14. package/dist/chunk-6T7QT6YH.cjs +7 -0
  15. package/dist/chunk-6T7QT6YH.cjs.map +1 -0
  16. package/dist/{chunk-OZHZUMNR.js → chunk-A7JKTDSD.js} +5 -3
  17. package/dist/{chunk-OZHZUMNR.js.map → chunk-A7JKTDSD.js.map} +1 -1
  18. package/dist/{chunk-4UA2V5R2.cjs → chunk-AGLZXZCH.cjs} +23 -21
  19. package/dist/chunk-AGLZXZCH.cjs.map +1 -0
  20. package/dist/{chunk-SYDW33AL.cjs → chunk-EDZOFPLV.cjs} +8 -1
  21. package/dist/chunk-EDZOFPLV.cjs.map +1 -0
  22. package/dist/{chunk-RK4QKTQ2.cjs → chunk-EE3Z75GO.cjs} +5 -5
  23. package/dist/{chunk-RK4QKTQ2.cjs.map → chunk-EE3Z75GO.cjs.map} +1 -1
  24. package/dist/{chunk-WJFOQS6I.js → chunk-FHJDIYPJ.js} +3 -3
  25. package/dist/{chunk-CM3GY62V.cjs → chunk-H7W5LMP6.cjs} +31 -15
  26. package/dist/chunk-H7W5LMP6.cjs.map +1 -0
  27. package/dist/{chunk-DIVRTJUA.js → chunk-LHJV2YLY.js} +13 -3
  28. package/dist/{chunk-DIVRTJUA.js.map → chunk-LHJV2YLY.js.map} +1 -1
  29. package/dist/chunk-OPKL4YNL.js +7 -0
  30. package/dist/chunk-OPKL4YNL.js.map +1 -0
  31. package/dist/{chunk-YQVY7CWT.js → chunk-U2LOUZP7.js} +3 -2
  32. package/dist/chunk-U2LOUZP7.js.map +1 -0
  33. package/dist/{chunk-MN6K2YHF.js → chunk-VR4P5QB2.js} +6 -4
  34. package/dist/{chunk-MN6K2YHF.js.map → chunk-VR4P5QB2.js.map} +1 -1
  35. package/dist/{chunk-YY2AGHRV.cjs → chunk-VVCG536Q.cjs} +7 -7
  36. package/dist/{chunk-YY2AGHRV.cjs.map → chunk-VVCG536Q.cjs.map} +1 -1
  37. package/dist/{chunk-DYVCBK2C.js → chunk-WVJZCVI7.js} +2 -2
  38. package/dist/{chunk-U3BAEJ2C.cjs → chunk-XKJFO6VG.cjs} +16 -6
  39. package/dist/chunk-XKJFO6VG.cjs.map +1 -0
  40. package/dist/{chunk-WBHH3JEK.js → chunk-YERYMWKM.js} +28 -12
  41. package/dist/chunk-YERYMWKM.js.map +1 -0
  42. package/dist/{chunk-5IZ7PLY2.cjs → chunk-YGOZDVK3.cjs} +4 -3
  43. package/dist/chunk-YGOZDVK3.cjs.map +1 -0
  44. package/dist/cli/index.cjs +17 -16
  45. package/dist/cli/index.cjs.map +1 -1
  46. package/dist/cli/index.js +8 -7
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/cost/index.cjs +6 -5
  49. package/dist/cost/index.cjs.map +1 -1
  50. package/dist/cost/index.d.cts +6 -5
  51. package/dist/cost/index.d.ts +6 -5
  52. package/dist/cost/index.js +5 -4
  53. package/dist/index.cjs +13 -9
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.d.cts +9 -9
  56. package/dist/index.d.ts +9 -9
  57. package/dist/index.js +12 -8
  58. package/dist/{modelCache-xzoTUue2.d.ts → modelCache-Bbw8Yc8Y.d.ts} +1 -1
  59. package/dist/{modelCache-sL3dBfRM.d.cts → modelCache-_mEwDBW7.d.cts} +1 -1
  60. package/dist/{modelNameResolver-2WroQlqt.d.ts → modelNameResolver-6k18Wvys.d.ts} +1 -1
  61. package/dist/{modelNameResolver-Bxlehrbp.d.cts → modelNameResolver-MoyOpdC3.d.cts} +1 -1
  62. package/dist/models/index.cjs +7 -6
  63. package/dist/models/index.cjs.map +1 -1
  64. package/dist/models/index.d.cts +5 -4
  65. package/dist/models/index.d.ts +5 -4
  66. package/dist/models/index.js +6 -5
  67. package/dist/profiles/index.cjs +6 -2
  68. package/dist/profiles/index.cjs.map +1 -1
  69. package/dist/profiles/index.d.cts +8 -3
  70. package/dist/profiles/index.d.ts +8 -3
  71. package/dist/profiles/index.js +5 -1
  72. package/dist/{resolveModelVendor-DQpJpk0w.d.ts → resolveModelVendor-Bb-TvXHF.d.ts} +3 -3
  73. package/dist/{resolveModelVendor-uphYBFMY.d.ts → resolveModelVendor-CF9l_SVN.d.ts} +1 -1
  74. package/dist/{resolveModelVendor-XvmXsVzo.d.cts → resolveModelVendor-CI64t5sk.d.cts} +3 -3
  75. package/dist/{resolveModelVendor-B0t5nq-v.d.cts → resolveModelVendor-Ck059GDf.d.cts} +1 -1
  76. package/dist/sync/index.cjs +2 -2
  77. package/dist/sync/index.d.cts +5 -4
  78. package/dist/sync/index.d.ts +5 -4
  79. package/dist/sync/index.js +1 -1
  80. package/dist/{types-BZYGjN2O.d.ts → types-CILRAzjr.d.cts} +4 -0
  81. package/dist/{types-BZYGjN2O.d.cts → types-CILRAzjr.d.ts} +4 -0
  82. package/package.json +2 -2
  83. package/dist/chunk-4ILJWO64.js.map +0 -1
  84. package/dist/chunk-4UA2V5R2.cjs.map +0 -1
  85. package/dist/chunk-5IZ7PLY2.cjs.map +0 -1
  86. package/dist/chunk-CM3GY62V.cjs.map +0 -1
  87. package/dist/chunk-IYRZYLUP.cjs.map +0 -1
  88. package/dist/chunk-SYDW33AL.cjs.map +0 -1
  89. package/dist/chunk-U3BAEJ2C.cjs.map +0 -1
  90. package/dist/chunk-WBHH3JEK.js.map +0 -1
  91. package/dist/chunk-YQVY7CWT.js.map +0 -1
  92. /package/dist/{chunk-WJFOQS6I.js.map → chunk-FHJDIYPJ.js.map} +0 -0
  93. /package/dist/{chunk-DYVCBK2C.js.map → chunk-WVJZCVI7.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-U3BAEJ2C.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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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;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;ALgNU;AACA;AM92BV;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,MA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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-U3BAEJ2C.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 {\n matchModelInAiProfiles,\n type AiProfilesModelMatch,\n} from \"../cost/aiProfilesMatch.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\nimport { ModelNameResolver } from \"../sync/modelNameResolver/ModelNameResolver.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport {\n isEffectiveOpenRouterTransport,\n loadOpenRouterRoutingEnv,\n} from \"../sync/openRouterRoutingEnv.js\";\nimport type {\n ModelResolutionInput,\n ModelResolutionResult,\n ModelResolutionSuccess,\n ModelResolverOptions,\n ResolutionStrategy,\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\nfunction profileResolutionStrategy(\n matchedVia: AiProfilesModelMatch[\"matchedVia\"],\n): ResolutionStrategy {\n switch (matchedVia) {\n case \"shortcut\":\n return \"ai-profiles-shortcut\";\n case \"profile\":\n case \"profile-alias\":\n return \"ai-profiles-profile\";\n default:\n return \"ai-profiles-model-id\";\n }\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 mergedOptions = { ...this.resolverOptions, ...options };\n let result = this.resolveFromCatalogMaps(input, mergedOptions);\n\n if (!result.found) {\n const viaProfile = await this.resolveViaProfile(input, mergedOptions);\n if (viaProfile) return viaProfile;\n return result;\n }\n\n return this.alignForOpenRouterTransport(result, input);\n }\n\n private resolveFromCatalogMaps(\n input: ModelResolutionInput,\n options?: ModelResolverOptions,\n ): ModelResolutionResult {\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) {\n return this.alignForOpenRouterTransport(result, input);\n }\n\n if (secondary.size > 0) {\n const fallback = this.resolver(secondary, options).resolve(input);\n if (fallback.found && fallback.record) {\n return this.alignForOpenRouterTransport(fallback, input);\n }\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 if (result.found) {\n return this.alignForOpenRouterTransport(result, input);\n }\n\n return result;\n }\n\n private alignForOpenRouterTransport(\n result: ModelResolutionSuccess,\n input: ModelResolutionInput,\n ): ModelResolutionSuccess {\n if (!result.routedViaOpenRouter) return result;\n\n let { modelId, record } = result;\n if (!modelId.includes(\"/\")) {\n const vendor =\n record?.providerId ??\n normalizeProvider(input.provider) ??\n undefined;\n if (vendor && vendor !== \"openrouter\") {\n modelId = `${vendor}/${modelId}`;\n }\n }\n\n const orRecord = this.openRouterModels?.get(modelId);\n if (orRecord) {\n record = orRecord;\n }\n\n if (modelId === result.modelId && record === result.record) return result;\n return { ...result, modelId, record };\n }\n\n private async resolveViaProfile(\n input: ModelResolutionInput,\n options?: ModelResolverOptions,\n ): Promise<ModelResolutionSuccess | null> {\n const profileMatch = await matchModelInAiProfiles(input.model, input.provider);\n if (!profileMatch) return null;\n\n const strategy = profileResolutionStrategy(profileMatch.matchedVia);\n const attempts: ModelResolutionInput[] = [];\n const seen = new Set<string>();\n const add = (model: string, provider?: string) => {\n const key = `${provider ?? \"\"}\\0${normalizeString(model)}`;\n if (seen.has(key)) return;\n seen.add(key);\n attempts.push({ model, provider });\n };\n\n add(profileMatch.canonicalModelId, input.provider ?? profileMatch.provider);\n add(profileMatch.canonicalModelId, profileMatch.provider);\n if (!isOpenRouterProvider(input.provider)) {\n add(profileMatch.canonicalModelId, \"openrouter\");\n }\n\n let catalogResult: ModelResolutionResult | null = null;\n for (const attempt of attempts) {\n const result = this.resolveFromCatalogMaps(attempt, options);\n catalogResult = result;\n if (result.found && result.record) break;\n }\n\n const normalisedInput = normalizeString(input.model);\n if (!catalogResult?.found) {\n const routingEnv = options?.routingEnv ?? loadOpenRouterRoutingEnv();\n const routedViaOpenRouter = isEffectiveOpenRouterTransport(routingEnv, {\n provider: input.provider ?? profileMatch.provider,\n modelId: profileMatch.canonicalModelId,\n routeViaOpenRouter: options?.routeViaOpenRouter,\n });\n\n const aligned = this.alignForOpenRouterTransport(\n {\n found: true,\n modelId: profileMatch.canonicalModelId,\n record: null,\n routedViaOpenRouter,\n confidence: 0.85,\n resolvedVia: [strategy],\n resolvedReason: `Resolved profile \"${input.model}\" → ${profileMatch.canonicalModelId} via ai-profiles (${profileMatch.matchedVia})`,\n normalisedInput,\n profile: profileMatch.profile,\n choice: profileMatch.choice,\n },\n { model: profileMatch.canonicalModelId, provider: profileMatch.provider },\n );\n\n return {\n ...aligned,\n resolvedVia: [strategy],\n profile: profileMatch.profile,\n choice: profileMatch.choice,\n };\n }\n\n const viaProfile = catalogResult as ModelResolutionSuccess;\n return {\n ...viaProfile,\n resolvedVia: [strategy, ...viaProfile.resolvedVia],\n resolvedReason: `Resolved profile \"${input.model}\" → ${viaProfile.modelId} via ai-profiles (${profileMatch.matchedVia})`,\n normalisedInput,\n profile: profileMatch.profile,\n choice: profileMatch.choice,\n };\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/costModelResolution.ts","../src/cost/aiProfilesMatch.ts"],"sourcesContent":["import type { AiModelsCatalogClient } from \"../catalog/AiModelsCatalogClient.js\";\nimport { LOCAL_PROVIDERS } from \"../sync/modelNameResolver/constants.js\";\nimport {\n loadOpenRouterRoutingEnv,\n shouldDefaultRouteViaOpenRouter,\n} from \"../sync/openRouterRoutingEnv.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport type {\n ModelResolutionInput,\n ModelResolutionResult,\n ModelResolverOptions,\n} from \"../sync/modelNameResolver/types.js\";\nimport type { OpenRouterRoutingConfig } from \"../sync/openRouterRoutingEnv.js\";\n\nexport function isOpenRouterProvider(provider?: string): boolean {\n return normalizeProvider(provider) === \"openrouter\";\n}\n\nexport function isLocalProvider(provider?: string): boolean {\n const p = normalizeProvider(provider) ?? normalizeString(provider ?? \"\");\n return LOCAL_PROVIDERS.has(p);\n}\n\n/** Catalog resolver returned success without a priced record (Ollama, LM Studio, …). */\nexport function isLocalProviderResolution(\n resolved: ModelResolutionResult | null,\n inputProvider?: string,\n): boolean {\n if (!resolved?.found || resolved.record) return false;\n if (resolved.resolvedVia.includes(\"local-provider-passthrough\")) return true;\n return isLocalProvider(inputProvider);\n}\n\n/**\n * Vendor id for a model slug (`openai/gpt-4o` → `openai`).\n * Ignores `openrouter` as a provider hint — it is a routing layer, not the model owner.\n */\nexport function underlyingProviderFromModel(\n model: string,\n providerHint?: string,\n): string | undefined {\n const normalized = normalizeString(model);\n if (normalized.includes(\"/\")) {\n const prefix = normalized.split(\"/\")[0]!;\n if (!isOpenRouterProvider(prefix)) return prefix;\n }\n if (providerHint && !isOpenRouterProvider(providerHint)) {\n return normalizeProvider(providerHint);\n }\n return undefined;\n}\n\n/** Provider hint for ai-profiles index lookup (openrouter → underlying vendor). */\nexport function providerHintForProfiles(\n model: string,\n provider?: string,\n): string | undefined {\n if (isOpenRouterProvider(provider)) {\n return underlyingProviderFromModel(model, provider);\n }\n return normalizeProvider(provider);\n}\n\n/**\n * Catalog resolve attempts for direct API and OpenRouter usage.\n * Tries the caller hint, inferred vendor, no hint, and openrouter routing.\n */\nexport function buildCatalogResolveAttempts(\n model: string,\n provider?: string,\n): ModelResolutionInput[] {\n const attempts: ModelResolutionInput[] = [];\n const seen = new Set<string>();\n const add = (m: string, p?: string) => {\n const key = `${p ?? \"\"}\\0${normalizeString(m)}`;\n if (seen.has(key)) return;\n seen.add(key);\n attempts.push({ model: m, provider: p });\n };\n\n add(model, provider);\n\n const underlying = underlyingProviderFromModel(model, provider);\n if (provider) add(model, undefined);\n if (underlying) add(model, underlying);\n if (!isOpenRouterProvider(provider)) {\n add(model, \"openrouter\");\n }\n\n return attempts;\n}\n\nexport async function resolveFromCatalogAttempts(\n catalog: AiModelsCatalogClient,\n attempts: ModelResolutionInput[],\n options?: ModelResolverOptions,\n): Promise<ModelResolutionResult | null> {\n let last: ModelResolutionResult | null = null;\n let localPassthrough: ModelResolutionResult | null = null;\n\n for (const attempt of attempts) {\n const result = await catalog.resolveModel(attempt, options);\n last = result;\n if (result.found && result.record) return result;\n if (\n result.found &&\n !result.record &&\n isLocalProviderResolution(result, attempt.provider)\n ) {\n localPassthrough = result;\n }\n }\n\n return localPassthrough ?? last;\n}\n\nexport function resolveRoutedViaOpenRouter(\n inputProvider: string | undefined,\n resolved: ModelResolutionResult | null,\n modelId?: string,\n routingEnv?: OpenRouterRoutingConfig,\n): boolean {\n const env = routingEnv ?? loadOpenRouterRoutingEnv();\n\n if (isOpenRouterProvider(inputProvider)) return true;\n\n if (resolved?.found) {\n return resolved.routedViaOpenRouter;\n }\n\n const vendor = underlyingProviderFromModel(\n modelId ?? (resolved?.found ? resolved.modelId : \"\") ?? \"\",\n inputProvider,\n );\n if (vendor && shouldDefaultRouteViaOpenRouter(vendor, env)) {\n return true;\n }\n\n return false;\n}\n","import {\n AIProfilesError,\n buildOpenRouterModelId,\n getChoiceOpenRouterModelId,\n getChoicePricing,\n getChoiceVendorModelId,\n loadAIProfilesRegistry,\n resolveAIProfile,\n} from \"@x12i/ai-profiles\";\nimport type {\n AIProfileBackend,\n AIProfileChoice,\n AIModelPricing,\n AIProfilesRegistry,\n InstructionTier,\n RegistrySourceMode,\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\nexport type AiProfilesModelMatch = {\n provider: string;\n modelId: string;\n canonicalModelId: string;\n pricing?: AIModelPricing;\n instructionTier: InstructionTier;\n backend: AIProfileBackend;\n matchedVia: \"profile\" | \"shortcut\" | \"profile-alias\" | \"model-id\";\n profile?: string;\n choice?: string;\n};\n\nfunction profileKey(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction canonicalModelId(provider: string, modelId: string): string {\n const normalized = normalizeString(modelId);\n if (normalized.includes(\"/\")) return normalized;\n return buildOpenRouterModelId(provider, normalized);\n}\n\ntype IndexedChoice = {\n provider: string;\n modelId: string;\n canonicalModelId: string;\n pricing?: AIModelPricing;\n profile: string;\n choice: string;\n};\n\nlet cachedIndex: {\n cacheKey: string;\n byKey: Map<string, IndexedChoice[]>;\n} | null = null;\n\nexport type MatchModelInAiProfilesOptions = {\n source?: RegistrySourceMode;\n};\n\n/** When set (tests), overrides default `auto` registry/catalog source. */\nlet registrySourceOverride: RegistrySourceMode | undefined;\n\nfunction registrySource(options?: MatchModelInAiProfilesOptions): RegistrySourceMode {\n return options?.source ?? registrySourceOverride ?? \"auto\";\n}\n\n/** ai-profiles reuses catalog/registry memory cache regardless of requested source unless refresh is set. */\nfunction profileResolveOptions(source: RegistrySourceMode) {\n return source === \"auto\" ? { source } : { source, refresh: true as const };\n}\n\n/** Index bare model ids only — profile/shortcut names resolve via {@link resolveAIProfile}. */\nfunction indexRegistry(registry: AIProfilesRegistry): Map<string, IndexedChoice[]> {\n const byKey = new Map<string, IndexedChoice[]>();\n\n const add = (key: string, entry: IndexedChoice) => {\n const k = profileKey(key);\n if (!k) return;\n const list = byKey.get(k) ?? [];\n if (\n list.some(\n (e) =>\n e.canonicalModelId === entry.canonicalModelId &&\n e.choice === entry.choice &&\n e.profile === entry.profile,\n )\n ) {\n return;\n }\n list.push(entry);\n byKey.set(k, list);\n };\n\n for (const profile of Object.values(registry.profiles)) {\n for (const [choiceKey, choice] of Object.entries(profile.choices)) {\n const entry = choiceEntry(choice, profile.profile, choiceKey);\n add(getChoiceVendorModelId(choice), entry);\n add(canonicalModelId(choice.provider, getChoiceVendorModelId(choice)), entry);\n }\n }\n\n return byKey;\n}\n\nfunction choiceEntry(\n choice: AIProfileChoice,\n profile: string,\n choiceKey: string,\n): IndexedChoice {\n const vendorModelId = getChoiceVendorModelId(choice);\n const provider = normalizeProvider(choice.provider) ?? choice.provider;\n const canonical =\n getChoiceOpenRouterModelId(choice) ??\n canonicalModelId(choice.provider, vendorModelId);\n return {\n provider,\n modelId: normalizeString(vendorModelId),\n canonicalModelId: canonical,\n pricing: getChoicePricing(choice),\n profile,\n choice: choiceKey,\n };\n}\n\nasync function getProfileIndex(\n source: RegistrySourceMode,\n): Promise<Map<string, IndexedChoice[]>> {\n const registry = await loadAIProfilesRegistry(profileResolveOptions(source));\n const cacheKey = `${source}:${registry.version}:${registry.generatedAt ?? \"\"}:${registry.source}`;\n if (cachedIndex?.cacheKey === cacheKey) {\n return cachedIndex.byKey;\n }\n const byKey = indexRegistry(registry);\n cachedIndex = { cacheKey, byKey };\n return byKey;\n}\n\nfunction scoreCandidate(\n entry: IndexedChoice,\n model: string,\n providerHint?: string,\n): number {\n const normalized = normalizeString(model);\n let score = 0;\n\n if (normalized === entry.canonicalModelId) score += 100;\n if (normalized === entry.modelId) score += 80;\n if (providerHint && entry.provider === providerHint) score += 50;\n if (entry.pricing) score += 2;\n\n return score;\n}\n\nfunction pickBest(\n candidates: IndexedChoice[],\n model: string,\n providerHint?: string,\n): IndexedChoice | null {\n if (candidates.length === 0) return null;\n if (candidates.length === 1) return candidates[0]!;\n\n let best = candidates[0]!;\n let bestScore = scoreCandidate(best, model, providerHint);\n for (let i = 1; i < candidates.length; i++) {\n const c = candidates[i]!;\n const s = scoreCandidate(c, model, providerHint);\n if (s > bestScore) {\n best = c;\n bestScore = s;\n }\n }\n return best;\n}\n\nfunction resolvedToMatch(resolved: ResolvedAIProfile): AiProfilesModelMatch {\n const direct = resolved.invocation.direct;\n const canonical =\n resolved.invocation.openrouter?.modelId ??\n buildOpenRouterModelId(direct.provider, direct.modelId);\n return {\n provider: normalizeProvider(direct.provider) ?? direct.provider,\n modelId: normalizeString(direct.modelId),\n canonicalModelId: canonical,\n pricing: resolved.pricing,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n matchedVia: resolved.shortcut ? \"shortcut\" : \"profile\",\n profile: resolved.profile,\n choice: resolved.choice,\n };\n}\n\nasync function fromIndexed(\n entry: IndexedChoice,\n source: RegistrySourceMode,\n): Promise<AiProfilesModelMatch> {\n const resolved = await resolveAIProfile(entry.profile, {\n choice: entry.choice,\n ...profileResolveOptions(source),\n });\n const direct = resolved.invocation.direct;\n return {\n provider: normalizeProvider(direct.provider) ?? direct.provider,\n modelId: normalizeString(direct.modelId),\n canonicalModelId:\n resolved.invocation.openrouter?.modelId ??\n buildOpenRouterModelId(direct.provider, direct.modelId),\n pricing: resolved.pricing ?? entry.pricing,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n matchedVia: \"model-id\",\n profile: resolved.profile,\n choice: resolved.choice,\n };\n}\n\nasync function lookupInIndex(\n index: Map<string, IndexedChoice[]>,\n model: string,\n source: RegistrySourceMode,\n provider?: string,\n): Promise<AiProfilesModelMatch | null> {\n const providerHint = provider ? normalizeProvider(provider) : undefined;\n const keys = [\n profileKey(model),\n profileKey(normalizeString(model)),\n ];\n if (providerHint) {\n keys.push(profileKey(canonicalModelId(providerHint, model)));\n }\n\n const pooled: IndexedChoice[] = [];\n for (const key of keys) {\n const hits = index.get(key);\n if (hits) pooled.push(...hits);\n }\n\n const bare = normalizeString(model);\n if (!bare.includes(\"/\")) {\n for (const list of index.values()) {\n for (const entry of list) {\n if (entry.modelId === bare) pooled.push(entry);\n }\n }\n }\n\n const unique = new Map<string, IndexedChoice>();\n for (const e of pooled) {\n unique.set(`${e.profile}:${e.choice}:${e.canonicalModelId}`, e);\n }\n\n const best = pickBest([...unique.values()], model, providerHint);\n return best ? fromIndexed(best, source) : null;\n}\n\n/**\n * Resolve a model string via @x12i/ai-profiles — profile/shortcut names, aliases,\n * or a concrete model id that appears on a profile choice.\n */\nexport async function matchModelInAiProfiles(\n model: string,\n provider?: string,\n options?: MatchModelInAiProfilesOptions,\n): Promise<AiProfilesModelMatch | null> {\n const source = registrySource(options);\n const resolveOpts = profileResolveOptions(source);\n\n try {\n const resolved = await resolveAIProfile(model, resolveOpts);\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(source);\n const hint = providerHintForProfiles(model, provider);\n const direct = await lookupInIndex(index, model, source, hint);\n if (direct) return direct;\n\n const stripped = stripModelVersionSuffix(model);\n if (stripped && stripped !== normalizeString(model)) {\n return lookupInIndex(\n index,\n stripped,\n source,\n providerHintForProfiles(stripped, provider),\n );\n }\n\n return null;\n}\n\n/** @internal Test-only — reset module cache between tests. */\nexport function resetAiProfilesMatchCacheForTests(\n options?: { source?: RegistrySourceMode },\n): void {\n cachedIndex = null;\n registrySourceOverride = options?.source ?? \"bundled\";\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/profiles/resolveProfileForAsk.ts","../src/profiles/index.ts"],"sourcesContent":["import { resolveAIProfile } from \"@x12i/ai-profiles\";\nimport type {\n AIProfileBackend,\n InstructionTier,\n RegistrySourceMode,\n ResolvedAIProfile,\n} from \"@x12i/ai-profiles\";\n\nexport type ResolveProfileForAskInput = {\n profile: string;\n choice?: string;\n source?: RegistrySourceMode;\n refresh?: boolean;\n};\n\n/** FuncX / ask-node model config derived from {@link ResolvedAIProfile}. */\nexport type AskProfileModelConfig = {\n provider: ResolvedAIProfile[\"provider\"];\n model: string;\n instructionTier: InstructionTier;\n backend: AIProfileBackend;\n profile: string;\n choice: string;\n temperature: number;\n outputMode: ResolvedAIProfile[\"runtime\"][\"outputMode\"];\n toolPolicy: ResolvedAIProfile[\"runtime\"][\"toolPolicy\"];\n reasoningEffort: ResolvedAIProfile[\"runtime\"][\"reasoningEffort\"];\n executionMode: ResolvedAIProfile[\"runtime\"][\"executionMode\"];\n requireCitations: boolean;\n allowWeb: boolean;\n allowFileSearch: boolean;\n allowCodeExecution: boolean;\n humanReview: ResolvedAIProfile[\"runtime\"][\"humanReview\"];\n metadata?: Record<string, unknown>;\n pricing?: ResolvedAIProfile[\"pricing\"];\n resolved: ResolvedAIProfile;\n};\n\nexport function profileConfigFromResolved(\n resolved: ResolvedAIProfile,\n): AskProfileModelConfig {\n return {\n provider: resolved.provider,\n model: resolved.modelId,\n instructionTier: resolved.instructionTier,\n backend: resolved.backend,\n profile: resolved.profile,\n choice: resolved.choice,\n temperature: resolved.runtime.temperature,\n outputMode: resolved.runtime.outputMode,\n toolPolicy: resolved.runtime.toolPolicy,\n reasoningEffort: resolved.runtime.reasoningEffort,\n executionMode: resolved.runtime.executionMode,\n requireCitations: resolved.runtime.requireCitations,\n allowWeb: resolved.runtime.allowWeb,\n allowFileSearch: resolved.runtime.allowFileSearch,\n allowCodeExecution: resolved.runtime.allowCodeExecution,\n humanReview: resolved.runtime.humanReview,\n ...(resolved.metadata !== undefined ? { metadata: resolved.metadata } : {}),\n ...(resolved.pricing !== undefined ? { pricing: resolved.pricing } : {}),\n resolved,\n };\n}\n\n/**\n * Resolve a profile (+ optional choice) into ask-node / FuncX model configuration.\n * Uses {@link ResolvedAIProfile.instructionTier} and {@link ResolvedAIProfile.backend}\n * from `@x12i/ai-profiles` — do not duplicate preset tables locally.\n */\nexport async function resolveProfileForAsk(\n input: ResolveProfileForAskInput,\n): Promise<AskProfileModelConfig> {\n const resolved = await resolveAIProfile(input.profile, {\n choice: input.choice,\n source: input.source,\n refresh: input.refresh,\n });\n return profileConfigFromResolved(resolved);\n}\n","export {\n resolveProfileForAsk,\n profileConfigFromResolved,\n} from \"./resolveProfileForAsk.js\";\nexport type {\n AskProfileModelConfig,\n ResolveProfileForAskInput,\n} from \"./resolveProfileForAsk.js\";\n\nexport type {\n ResolvedAIProfile,\n InstructionTier,\n AIProfileBackend,\n AIProfileSummary,\n AIShortcutSummary,\n ResolveAIProfileOptions,\n RegistrySourceMode,\n} from \"@x12i/ai-profiles\";\n\nexport {\n resolveAIProfile,\n listAIProfiles,\n listAIShortcuts,\n isKnownProfileOrShortcut,\n} from \"@x12i/ai-profiles\";\n"],"mappings":";AAAA,SAAS,wBAAwB;AAsC1B,SAAS,0BACd,UACuB;AACvB,SAAO;AAAA,IACL,UAAU,SAAS;AAAA,IACnB,OAAO,SAAS;AAAA,IAChB,iBAAiB,SAAS;AAAA,IAC1B,SAAS,SAAS;AAAA,IAClB,SAAS,SAAS;AAAA,IAClB,QAAQ,SAAS;AAAA,IACjB,aAAa,SAAS,QAAQ;AAAA,IAC9B,YAAY,SAAS,QAAQ;AAAA,IAC7B,YAAY,SAAS,QAAQ;AAAA,IAC7B,iBAAiB,SAAS,QAAQ;AAAA,IAClC,eAAe,SAAS,QAAQ;AAAA,IAChC,kBAAkB,SAAS,QAAQ;AAAA,IACnC,UAAU,SAAS,QAAQ;AAAA,IAC3B,iBAAiB,SAAS,QAAQ;AAAA,IAClC,oBAAoB,SAAS,QAAQ;AAAA,IACrC,aAAa,SAAS,QAAQ;AAAA,IAC9B,GAAI,SAAS,aAAa,SAAY,EAAE,UAAU,SAAS,SAAS,IAAI,CAAC;AAAA,IACzE,GAAI,SAAS,YAAY,SAAY,EAAE,SAAS,SAAS,QAAQ,IAAI,CAAC;AAAA,IACtE;AAAA,EACF;AACF;AAOA,eAAsB,qBACpB,OACgC;AAChC,QAAM,WAAW,MAAM,iBAAiB,MAAM,SAAS;AAAA,IACrD,QAAQ,MAAM;AAAA,IACd,QAAQ,MAAM;AAAA,IACd,SAAS,MAAM;AAAA,EACjB,CAAC;AACD,SAAO,0BAA0B,QAAQ;AAC3C;;;AC3DA;AAAA,EACE,oBAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":["resolveAIProfile"]}