@x12i/ai-tools 1.0.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +146 -204
- package/dist/AiModelsCatalogClient-B5FMI9gj.d.cts +58 -0
- package/dist/AiModelsCatalogClient-CPPNI6Ry.d.ts +58 -0
- package/dist/aliases/index.cjs +4 -3
- package/dist/aliases/index.cjs.map +1 -1
- package/dist/aliases/index.d.cts +3 -5
- package/dist/aliases/index.d.ts +3 -5
- package/dist/aliases/index.js +2 -2
- package/dist/catalog/index.cjs +18 -9
- package/dist/catalog/index.cjs.map +1 -1
- package/dist/catalog/index.d.cts +13 -100
- package/dist/catalog/index.d.ts +13 -100
- package/dist/catalog/index.js +31 -23
- package/dist/{chunk-AJEKEWWB.js → chunk-2PTCWPHV.js} +17 -3
- package/dist/chunk-2PTCWPHV.js.map +1 -0
- package/dist/chunk-56R4XA2S.js +1 -0
- package/dist/chunk-5GUKLOEK.cjs +1 -0
- package/dist/chunk-5GUKLOEK.cjs.map +1 -0
- package/dist/chunk-5XAAMBDO.cjs +1988 -0
- package/dist/chunk-5XAAMBDO.cjs.map +1 -0
- package/dist/chunk-6BQBKROR.js +95 -0
- package/dist/chunk-6BQBKROR.js.map +1 -0
- package/dist/chunk-AB5GNXJ4.js +46 -0
- package/dist/chunk-AB5GNXJ4.js.map +1 -0
- package/dist/{chunk-O2A6OVEH.js → chunk-ANVONYJF.js} +2 -2
- package/dist/{chunk-O2A6OVEH.js.map → chunk-ANVONYJF.js.map} +1 -1
- package/dist/chunk-B3V2EHRY.js +225 -0
- package/dist/chunk-B3V2EHRY.js.map +1 -0
- package/dist/{chunk-QWAX7VQO.cjs → chunk-BAHBDADJ.cjs} +11 -11
- package/dist/{chunk-QWAX7VQO.cjs.map → chunk-BAHBDADJ.cjs.map} +1 -1
- package/dist/{chunk-TF4L2NEC.cjs → chunk-DXZOL3VN.cjs} +62 -313
- package/dist/chunk-DXZOL3VN.cjs.map +1 -0
- package/dist/chunk-EDMCKHO6.cjs +225 -0
- package/dist/chunk-EDMCKHO6.cjs.map +1 -0
- package/dist/{chunk-DJ5SWJDY.js → chunk-EYHMQVAL.js} +48 -299
- package/dist/chunk-EYHMQVAL.js.map +1 -0
- package/dist/chunk-GS7T56RP.cjs +8 -0
- package/dist/chunk-GS7T56RP.cjs.map +1 -0
- package/dist/chunk-NF2SKQR7.cjs +973 -0
- package/dist/chunk-NF2SKQR7.cjs.map +1 -0
- package/dist/chunk-OPN6BGNH.js +1985 -0
- package/dist/chunk-OPN6BGNH.js.map +1 -0
- package/dist/{chunk-7Q742NI3.cjs → chunk-PADNCGZB.cjs} +17 -3
- package/dist/chunk-PADNCGZB.cjs.map +1 -0
- package/dist/chunk-PRCICORG.cjs +95 -0
- package/dist/chunk-PRCICORG.cjs.map +1 -0
- package/dist/{chunk-6QGDZTGH.js → chunk-SIH4GPV4.js} +4 -29
- package/dist/chunk-SIH4GPV4.js.map +1 -0
- package/dist/chunk-U2YDDUVP.js +970 -0
- package/dist/chunk-U2YDDUVP.js.map +1 -0
- package/dist/{chunk-4NAY6HRP.js → chunk-VJHLO2R3.js} +7 -58
- package/dist/chunk-VJHLO2R3.js.map +1 -0
- package/dist/chunk-XAWBTX3N.cjs +46 -0
- package/dist/chunk-XAWBTX3N.cjs.map +1 -0
- package/dist/{chunk-AV6OE2YQ.cjs → chunk-XOKUDUUI.cjs} +14 -39
- package/dist/chunk-XOKUDUUI.cjs.map +1 -0
- package/dist/chunk-YQDSN6R6.cjs +86 -0
- package/dist/chunk-YQDSN6R6.cjs.map +1 -0
- package/dist/cli/index.cjs +59 -201
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +53 -198
- package/dist/cli/index.js.map +1 -1
- package/dist/cost/index.cjs +19 -3
- package/dist/cost/index.cjs.map +1 -1
- package/dist/cost/index.d.cts +10 -50
- package/dist/cost/index.d.ts +10 -50
- package/dist/cost/index.js +18 -3
- package/dist/index.cjs +24 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -13
- package/dist/index.d.ts +13 -13
- package/dist/index.js +44 -37
- package/dist/modelCache-BzRn6t_C.d.ts +113 -0
- package/dist/modelCache-CJftI-Ko.d.cts +113 -0
- package/dist/{modelNameResolver-DqFt7g6W.d.ts → modelNameResolver-5XkBMctP.d.ts} +2 -6
- package/dist/{modelNameResolver-D9V_GfUK.d.cts → modelNameResolver-C5CSTGFF.d.cts} +2 -6
- package/dist/models/index.cjs +9 -6
- package/dist/models/index.cjs.map +1 -1
- package/dist/models/index.d.cts +9 -31
- package/dist/models/index.d.ts +9 -31
- package/dist/models/index.js +9 -7
- package/dist/resolveUsageModel-BFwf80Hz.d.ts +140 -0
- package/dist/resolveUsageModel-C_YmGR1M.d.cts +140 -0
- package/dist/sync/index.cjs +7 -9
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +3 -8
- package/dist/sync/index.d.ts +3 -8
- package/dist/sync/index.js +8 -11
- package/dist/toolbox/index.cjs +1 -0
- package/dist/toolbox/index.cjs.map +1 -1
- package/dist/types-BrzJWsTU.d.cts +277 -0
- package/dist/types-BrzJWsTU.d.ts +277 -0
- package/package.json +9 -20
- package/src/data/models-catalog.json +670 -0
- package/src/data/openrouter-models-catalog.json +857 -0
- package/dist/AiModelsCatalogClient-4RF5BCDL.cjs +0 -9
- package/dist/AiModelsCatalogClient-4RF5BCDL.cjs.map +0 -1
- package/dist/AiModelsCatalogClient-CNeqFiFs.d.cts +0 -30
- package/dist/AiModelsCatalogClient-NUF3CBLW.js +0 -9
- package/dist/AiModelsCatalogClient-nwFoEaqL.d.ts +0 -30
- package/dist/catalox/index.cjs +0 -21
- package/dist/catalox/index.cjs.map +0 -1
- package/dist/catalox/index.d.cts +0 -11
- package/dist/catalox/index.d.ts +0 -11
- package/dist/catalox/index.js +0 -21
- package/dist/catalox/index.js.map +0 -1
- package/dist/chunk-4NAY6HRP.js.map +0 -1
- package/dist/chunk-6QGDZTGH.js.map +0 -1
- package/dist/chunk-7Q742NI3.cjs.map +0 -1
- package/dist/chunk-AJEKEWWB.js.map +0 -1
- package/dist/chunk-AV6OE2YQ.cjs.map +0 -1
- package/dist/chunk-C3H7RTFR.cjs +0 -1
- package/dist/chunk-C3H7RTFR.cjs.map +0 -1
- package/dist/chunk-DJ5SWJDY.js.map +0 -1
- package/dist/chunk-DKHGWHXP.cjs +0 -169
- package/dist/chunk-DKHGWHXP.cjs.map +0 -1
- package/dist/chunk-F2F4UEFD.cjs +0 -75
- package/dist/chunk-F2F4UEFD.cjs.map +0 -1
- package/dist/chunk-FGP3QXWL.cjs +0 -163
- package/dist/chunk-FGP3QXWL.cjs.map +0 -1
- package/dist/chunk-G2G4KSC5.js +0 -30
- package/dist/chunk-G2G4KSC5.js.map +0 -1
- package/dist/chunk-HN6UAQAE.cjs +0 -83
- package/dist/chunk-HN6UAQAE.cjs.map +0 -1
- package/dist/chunk-HS74X2OJ.cjs +0 -172
- package/dist/chunk-HS74X2OJ.cjs.map +0 -1
- package/dist/chunk-HYGXZY25.js +0 -163
- package/dist/chunk-HYGXZY25.js.map +0 -1
- package/dist/chunk-KQOALKKX.js +0 -75
- package/dist/chunk-KQOALKKX.js.map +0 -1
- package/dist/chunk-LYOU7CA2.cjs +0 -30
- package/dist/chunk-LYOU7CA2.cjs.map +0 -1
- package/dist/chunk-M5TMA73F.js +0 -1
- package/dist/chunk-M5TMA73F.js.map +0 -1
- package/dist/chunk-MX3AMQFC.js +0 -172
- package/dist/chunk-MX3AMQFC.js.map +0 -1
- package/dist/chunk-QCRLKVB3.cjs +0 -137
- package/dist/chunk-QCRLKVB3.cjs.map +0 -1
- package/dist/chunk-TF4L2NEC.cjs.map +0 -1
- package/dist/chunk-VRFVF5RH.js +0 -169
- package/dist/chunk-VRFVF5RH.js.map +0 -1
- package/dist/chunk-YHO57D2V.js +0 -83
- package/dist/chunk-YHO57D2V.js.map +0 -1
- package/dist/syncAiModelsCatalog-CnXRLm2c.d.cts +0 -32
- package/dist/syncAiModelsCatalog-DpkN_w7S.d.ts +0 -32
- package/dist/types-BYXnCvKx.d.cts +0 -137
- package/dist/types-BYXnCvKx.d.ts +0 -137
- package/dist/types-CX6QFNNy.d.cts +0 -144
- package/dist/types-CuiPDcVs.d.ts +0 -144
- package/dist/upsertAiModelRecord-C831wOIF.d.ts +0 -35
- package/dist/upsertAiModelRecord-CjY-sny0.d.cts +0 -35
- /package/dist/{AiModelsCatalogClient-NUF3CBLW.js.map → chunk-56R4XA2S.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-5XAAMBDO.cjs","../src/cache/modelCache.ts","../src/catalog/catalogSources.ts","../src/catalog/normalizeX12iCatalogModel.ts","../src/catalog/loadCatalogSources.ts","../src/data/models-catalog.json","../src/data/openrouter-models-catalog.json","../src/catalog/catalogLoadCache.ts","../src/catalog/AiModelsCatalogClient.ts"],"names":[],"mappings":"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CA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACE,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACF,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AAEA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACF,IAAA;AACF,EAAA;AACF;AL2MU;AACA;AMz2BV;AACY,EAAA;AACV,EAAA;AACA,EAAA;AACA,EAAA;AACU,EAAA;AACR,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACS,EAAA;AACP,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACU,EAAA;AACR,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA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","file":"/Users/ami/Documents/prometheus/x12i/ai-tools/dist/chunk-5XAAMBDO.cjs","sourcesContent":[null,"import { createNxCache } from \"nx-cache\";\nimport type { AiModelRecord } from \"../cost/types.js\";\n\nconst cache = createNxCache<Map<string, AiModelRecord>, { cachedAt: string; count: number }>();\n\n/** Default in-memory catalog cache lifetime (24 hours). */\nexport const DEFAULT_CATALOG_CACHE_TTL_MS = 24 * 60 * 60 * 1000;\n\n/** @alias DEFAULT_CATALOG_CACHE_TTL_MS */\nexport const DEFAULT_MODEL_CACHE_TTL_MS = DEFAULT_CATALOG_CACHE_TTL_MS;\n\nexport function resolveCatalogCacheTtlMs(override?: number): number {\n if (override !== undefined) return override;\n const raw = process.env.AI_TOOLS_CACHE_TTL_MS;\n if (!raw) return DEFAULT_CATALOG_CACHE_TTL_MS;\n const n = Number.parseInt(raw, 10);\n return Number.isFinite(n) && n > 0 ? n : DEFAULT_CATALOG_CACHE_TTL_MS;\n}\n\nexport type ModelCacheMetadata = { cachedAt: string; count: number };\n\nexport function readCachedModels(\n scopeKey: string,\n ttlMs = DEFAULT_CATALOG_CACHE_TTL_MS,\n): Map<string, AiModelRecord> | null {\n const res = cache.read(\"ai-models\", { appId: scopeKey });\n if (!res.found) return null;\n\n const cachedAt = res.metadata?.cachedAt;\n if (cachedAt) {\n const age = Date.now() - new Date(cachedAt).getTime();\n if (age > ttlMs) return null;\n } else if (res.meta.isExpired) {\n return null;\n }\n\n return res.value;\n}\n\nexport function writeCachedModels(\n scopeKey: string,\n models: Map<string, AiModelRecord>,\n ttlMs = DEFAULT_CATALOG_CACHE_TTL_MS,\n): void {\n cache.write(\"ai-models\", models, {\n scope: { appId: scopeKey },\n ttlMs,\n metadata: { cachedAt: new Date().toISOString(), count: models.size },\n });\n}\n\nexport function invalidateModelsCache(scopeKey: string): void {\n cache.resetKey(\"ai-models\", { appId: scopeKey });\n}\n","/** Remote catalog URLs (primary). */\nexport const DEFAULT_DIRECT_CATALOG_URL =\n \"https://open-assets.x12i.com/models-catalog.json\";\n\nexport const DEFAULT_OPENROUTER_CATALOG_URL =\n \"https://open-assets.x12i.com/openrouter-models-catalog.json\";\n\nexport type CatalogSourceKind = \"direct\" | \"openrouter\";\n\nexport type CatalogLoadSource = {\n kind: CatalogSourceKind;\n url: string;\n /** Bundled fallback (imported JSON). */\n bundled: X12iModelsCatalogFile;\n};\n\nexport type X12iCatalogPricing = {\n input?: number | null;\n output?: number | null;\n cachedInput?: number | null;\n cacheHit?: number | null;\n cacheWrite?: number | null;\n cacheWrite5m?: number | null;\n cacheWrite1h?: number | null;\n textInput?: number | null;\n textOutput?: number | null;\n audioInput?: number | null;\n imageInput?: number | null;\n internalReasoning?: number | null;\n webSearchPerRequest?: number | null;\n inputBelow200k?: number | null;\n inputAbove200k?: number | null;\n outputBelow200k?: number | null;\n outputAbove200k?: number | null;\n [key: string]: unknown;\n};\n\nexport type X12iCatalogModelEntry = {\n provider: string;\n modelId: string;\n displayName?: string;\n canonicalSlug?: string;\n family?: string;\n status?: string;\n modalities?: string[] | { input?: string[]; output?: string[] };\n contextWindow?: number;\n maxCompletionTokens?: number;\n pricing?: X12iCatalogPricing;\n capabilities?: {\n reasoning?: boolean | string;\n toolCalling?: boolean;\n structuredOutputs?: boolean;\n };\n aliases?: string[];\n sourceUrl?: string;\n};\n\n/**\n * Raw catalog JSON from open-assets.x12i.com (or bundled `src/data`).\n *\n * `schema` and `version` are publisher metadata only — this library never reads or\n * compares them. Remote catalogs are always treated as the latest pricing source.\n */\nexport type X12iModelsCatalogFile = {\n /** Publisher schema id (informational). */\n schema?: string;\n /** Publisher catalog revision (informational; not used for cache or compatibility). */\n version?: string;\n verifiedAt?: string;\n models: X12iCatalogModelEntry[];\n [key: string]: unknown;\n};\n","import { computeSupportsReasoning } from \"../models/reasoningModel.js\";\nimport type { AiModelPricing, AiModelRecord } from \"../models/types.js\";\nimport type { OpenRouterModelApi, OpenRouterPricingApi } from \"../models/openrouter.types.js\";\nimport { normalizeProvider, normalizeString } from \"../sync/modelNameResolver/normalize.js\";\nimport type { CatalogSourceKind, X12iCatalogModelEntry, X12iCatalogPricing } from \"./catalogSources.js\";\n\nconst TOKENS_PER_UNIT = 1_000_000;\n\nfunction usdPerToken(perMillion?: number | null): number {\n if (perMillion == null || !Number.isFinite(perMillion)) return 0;\n return perMillion / TOKENS_PER_UNIT;\n}\n\nfunction firstRate(\n raw: X12iCatalogPricing,\n ...keys: (keyof X12iCatalogPricing)[]\n): number | undefined {\n for (const key of keys) {\n const v = raw[key];\n if (typeof v === \"number\" && Number.isFinite(v)) return v;\n }\n return undefined;\n}\n\nexport function canonicalCatalogModelId(provider: string, modelId: string): string {\n const m = normalizeString(modelId);\n if (m.includes(\"/\")) return m;\n const p = normalizeProvider(provider) ?? normalizeString(provider);\n return `${p}/${m}`;\n}\n\nfunction mapStatus(status?: string): AiModelRecord[\"status\"] {\n if (!status) return \"active\";\n const s = status.toLowerCase();\n if (s === \"deprecated\" || s === \"legacy\") return \"deprecated\";\n if (s === \"active\" || s === \"preview\" || s === \"announced\") return \"active\";\n return \"unknown\";\n}\n\nfunction mapModalities(\n modalities?: X12iCatalogModelEntry[\"modalities\"],\n): { input: string[]; output: string[]; modality: string } {\n if (Array.isArray(modalities)) {\n return {\n input: modalities,\n output: modalities.includes(\"text\") ? [\"text\"] : modalities.slice(0, 1),\n modality: modalities.join(\"+\"),\n };\n }\n if (modalities && typeof modalities === \"object\") {\n const input = modalities.input ?? [\"text\"];\n const output = modalities.output ?? [\"text\"];\n return { input, output, modality: `${input.join(\"+\")}->${output.join(\"+\")}` };\n }\n return { input: [\"text\"], output: [\"text\"], modality: \"text->text\" };\n}\n\nfunction pricingToOpenRouterApi(\n raw: X12iCatalogPricing,\n perMillion = true,\n): OpenRouterPricingApi {\n const scale = perMillion ? (n?: number) => (n ?? 0) / TOKENS_PER_UNIT : (n?: number) => n ?? 0;\n return {\n prompt: String(scale(firstRate(raw, \"input\", \"textInput\"))),\n completion: String(scale(firstRate(raw, \"output\", \"textOutput\"))),\n request: \"0\",\n image: String(scale(firstRate(raw, \"imageInput\"))),\n input_cache_read: raw.cachedInput != null ? String(scale(raw.cachedInput)) : undefined,\n input_cache_write: raw.cacheWrite != null ? String(scale(raw.cacheWrite)) : undefined,\n internal_reasoning:\n raw.internalReasoning != null ? String(scale(raw.internalReasoning)) : undefined,\n web_search:\n raw.webSearchPerRequest != null ? String(raw.webSearchPerRequest) : undefined,\n };\n}\n\nfunction pricingFromX12i(\n raw: X12iCatalogPricing,\n pricedAt: string,\n source: AiModelPricing[\"source\"],\n): AiModelPricing {\n return {\n promptUsdPerToken: usdPerToken(firstRate(raw, \"input\", \"textInput\")),\n completionUsdPerToken: usdPerToken(firstRate(raw, \"output\", \"textOutput\")),\n imageUsdPerUnit: usdPerToken(firstRate(raw, \"imageInput\")),\n requestUsdPerRequest: usdPerToken(\n typeof raw.webSearchPerRequest === \"number\" ? raw.webSearchPerRequest * 1000 : 0,\n ),\n cacheReadUsdPerToken: usdPerToken(\n firstRate(raw, \"cachedInput\", \"cacheHit\"),\n ),\n cacheWriteUsdPerToken: usdPerToken(\n firstRate(raw, \"cacheWrite\", \"cacheWrite5m\", \"cacheWrite1h\"),\n ),\n reasoningUsdPerToken: usdPerToken(raw.internalReasoning),\n webSearchUsdPerRequest:\n typeof raw.webSearchPerRequest === \"number\" ? raw.webSearchPerRequest : undefined,\n pricedAt,\n source,\n };\n}\n\nfunction stubOpenRouterApi(\n modelId: string,\n entry: X12iCatalogModelEntry,\n modalities: ReturnType<typeof mapModalities>,\n pricing: OpenRouterPricingApi,\n): OpenRouterModelApi {\n return {\n id: modelId,\n canonical_slug: entry.canonicalSlug ?? modelId,\n name: entry.displayName ?? modelId,\n created: 0,\n description: entry.displayName ?? \"\",\n context_length: entry.contextWindow ?? 0,\n architecture: {\n modality: modalities.modality,\n input_modalities: modalities.input,\n output_modalities: modalities.output,\n tokenizer: \"\",\n instruct_type: null,\n },\n pricing,\n top_provider: {\n context_length: entry.contextWindow ?? 0,\n max_completion_tokens: entry.maxCompletionTokens ?? null,\n is_moderated: false,\n },\n per_request_limits: null,\n supported_parameters: entry.capabilities?.toolCalling ? [\"tools\"] : [],\n default_parameters: null,\n };\n}\n\nexport function normalizeX12iCatalogModel(\n entry: X12iCatalogModelEntry,\n kind: CatalogSourceKind,\n verifiedAt: string,\n): AiModelRecord | null {\n const pricingRaw = entry.pricing;\n if (!pricingRaw) return null;\n\n const inputRate = firstRate(pricingRaw, \"input\", \"textInput\", \"inputBelow200k\");\n const outputRate = firstRate(pricingRaw, \"output\", \"textOutput\", \"outputBelow200k\");\n if (inputRate == null && outputRate == null) return null;\n\n const modelId = canonicalCatalogModelId(entry.provider, entry.modelId);\n const providerId =\n kind === \"openrouter\" && modelId.includes(\"/\")\n ? modelId.split(\"/\")[0]!\n : normalizeProvider(entry.provider) ?? entry.provider;\n\n const modalities = mapModalities(entry.modalities);\n const pricedAt = verifiedAt || new Date().toISOString();\n const pricingSource: AiModelPricing[\"source\"] =\n kind === \"openrouter\" ? \"openrouter\" : \"direct\";\n const pricing = pricingFromX12i(pricingRaw, pricedAt, pricingSource);\n const openRouterPricing = pricingToOpenRouterApi(pricingRaw, true);\n const openRouter = stubOpenRouterApi(modelId, entry, modalities, openRouterPricing);\n\n const supportedParameters = openRouter.supported_parameters ?? [];\n const supportsReasoning =\n entry.capabilities?.reasoning === true ||\n computeSupportsReasoning({\n supportedParameters,\n pricing,\n openRouterPricing,\n });\n\n const aliases = new Set<string>(entry.aliases ?? []);\n aliases.add(entry.modelId);\n if (entry.displayName) aliases.add(entry.displayName);\n const slash = modelId.indexOf(\"/\");\n if (slash > 0) aliases.add(modelId.slice(slash + 1));\n\n return {\n modelId,\n name: entry.displayName ?? modelId,\n providerId,\n canonicalSlug: entry.canonicalSlug ?? modelId,\n status: mapStatus(entry.status),\n description: entry.displayName ?? \"\",\n created: 0,\n expirationDate: null,\n contextLength: entry.contextWindow ?? 0,\n maxCompletionTokens: entry.maxCompletionTokens ?? null,\n isModerated: false,\n modality: modalities.modality,\n inputModalities: modalities.input,\n outputModalities: modalities.output,\n tokenizer: \"\",\n instructType: null,\n supportedParameters,\n defaultParameters: null,\n perRequestLimits: null,\n pricing,\n openRouterPricing,\n architecture: openRouter.architecture,\n topProvider: openRouter.top_provider,\n openRouter,\n aliases: [...aliases],\n availableOnOpenRouter: kind === \"openrouter\",\n supportsStreaming: modalities.output.includes(\"text\"),\n supportsTools: entry.capabilities?.toolCalling === true,\n supportsReasoning,\n primaryOutputModality: modalities.output[0] ?? \"text\",\n syncedAt: pricedAt,\n syncSource: kind === \"openrouter\" ? \"openrouter\" : \"manual\",\n };\n}\n\nexport function modelsFromX12iCatalogFile(\n file: { models: X12iCatalogModelEntry[]; verifiedAt?: string },\n kind: CatalogSourceKind,\n): Map<string, AiModelRecord> {\n const map = new Map<string, AiModelRecord>();\n const verifiedAt = file.verifiedAt ?? new Date().toISOString().slice(0, 10);\n for (const entry of file.models) {\n const record = normalizeX12iCatalogModel(entry, kind, verifiedAt);\n if (record) map.set(record.modelId, record);\n }\n return map;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n DEFAULT_DIRECT_CATALOG_URL,\n DEFAULT_OPENROUTER_CATALOG_URL,\n type CatalogLoadSource,\n type X12iModelsCatalogFile,\n} from \"./catalogSources.js\";\n\nexport { DEFAULT_DIRECT_CATALOG_URL, DEFAULT_OPENROUTER_CATALOG_URL };\nimport { modelsFromX12iCatalogFile } from \"./normalizeX12iCatalogModel.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\n\nimport bundledDirect from \"../data/models-catalog.json\" with { type: \"json\" };\nimport bundledOpenRouter from \"../data/openrouter-models-catalog.json\" with { type: \"json\" };\n\nconst dataDir = dirname(fileURLToPath(import.meta.url));\n\nexport type LoadCatalogOptions = {\n directCatalogUrl?: string;\n openRouterCatalogUrl?: string;\n /** When true, skip HTTP and use bundled `src/data` only. */\n bundledOnly?: boolean;\n fetchTimeoutMs?: number;\n};\n\nexport type LoadedCatalogs = {\n direct: Map<string, AiModelRecord>;\n openrouter: Map<string, AiModelRecord>;\n meta: {\n directSource: \"remote\" | \"bundled\";\n openRouterSource: \"remote\" | \"bundled\";\n directUrl: string;\n openRouterUrl: string;\n directCount: number;\n openRouterCount: number;\n };\n};\n\nasync function fetchCatalogJson(url: string, timeoutMs: number): Promise<X12iModelsCatalogFile> {\n const res = await fetch(url, {\n signal: AbortSignal.timeout(timeoutMs),\n headers: { accept: \"application/json\" },\n });\n if (!res.ok) {\n throw new Error(`HTTP ${res.status} fetching ${url}`);\n }\n return (await res.json()) as X12iModelsCatalogFile;\n}\n\nasync function loadOneSource(\n source: CatalogLoadSource,\n options: LoadCatalogOptions,\n): Promise<{ file: X12iModelsCatalogFile; from: \"remote\" | \"bundled\" }> {\n if (options.bundledOnly) {\n return { file: source.bundled, from: \"bundled\" };\n }\n\n try {\n const file = await fetchCatalogJson(source.url, options.fetchTimeoutMs ?? 30_000);\n return { file, from: \"remote\" };\n } catch (err) {\n console.warn(\n `[ai-tools] Failed to load ${source.kind} catalog from ${source.url} (${err instanceof Error ? err.message : err}); using bundled fallback.`,\n );\n return { file: source.bundled, from: \"bundled\" };\n }\n}\n\n/** Load direct-provider and OpenRouter catalogs (remote with bundled fallback). */\nexport async function loadCatalogSources(\n options: LoadCatalogOptions = {},\n): Promise<LoadedCatalogs> {\n const directUrl = options.directCatalogUrl ?? DEFAULT_DIRECT_CATALOG_URL;\n const openRouterUrl = options.openRouterCatalogUrl ?? DEFAULT_OPENROUTER_CATALOG_URL;\n\n const sources: CatalogLoadSource[] = [\n {\n kind: \"direct\",\n url: directUrl,\n bundled: bundledDirect as X12iModelsCatalogFile,\n },\n {\n kind: \"openrouter\",\n url: openRouterUrl,\n bundled: bundledOpenRouter as X12iModelsCatalogFile,\n },\n ];\n\n const [directLoad, orLoad] = await Promise.all(\n sources.map((s) => loadOneSource(s, options)),\n );\n\n const direct = modelsFromX12iCatalogFile(directLoad.file, \"direct\");\n const openrouter = modelsFromX12iCatalogFile(orLoad.file, \"openrouter\");\n\n return {\n direct,\n openrouter,\n meta: {\n directSource: directLoad.from,\n openRouterSource: orLoad.from,\n directUrl,\n openRouterUrl,\n directCount: direct.size,\n openRouterCount: openrouter.size,\n },\n };\n}\n\n/** Read bundled JSON from disk (CLI / tests without import assertions). */\nexport async function readBundledCatalogFiles(): Promise<LoadedCatalogs> {\n const directPath = join(dataDir, \"../data/models-catalog.json\");\n const orPath = join(dataDir, \"../data/openrouter-models-catalog.json\");\n const [directRaw, orRaw] = await Promise.all([\n readFile(directPath, \"utf8\"),\n readFile(orPath, \"utf8\"),\n ]);\n const directFile = JSON.parse(directRaw) as X12iModelsCatalogFile;\n const orFile = JSON.parse(orRaw) as X12iModelsCatalogFile;\n return {\n direct: modelsFromX12iCatalogFile(directFile, \"direct\"),\n openrouter: modelsFromX12iCatalogFile(orFile, \"openrouter\"),\n meta: {\n directSource: \"bundled\",\n openRouterSource: \"bundled\",\n directUrl: DEFAULT_DIRECT_CATALOG_URL,\n openRouterUrl: DEFAULT_OPENROUTER_CATALOG_URL,\n directCount: directFile.models.length,\n openRouterCount: orFile.models.length,\n },\n };\n}\n","{\r\n \"schema\": \"x12i.ai-models.catalog\",\r\n \"version\": \"0.1.0\",\r\n \"currency\": \"USD\",\r\n \"pricingUnit\": \"1M_tokens\",\r\n \"verifiedAt\": \"2026-05-27\",\r\n \"notes\": [\r\n \"All token prices are listed per 1M tokens unless otherwise stated.\",\r\n \"Null means pricing was not found or not public in the checked official source.\",\r\n \"Some providers price audio, image, video, search, batch, cache, and regional processing separately.\",\r\n \"This catalog intentionally does not include OpenRouter pricing.\"\r\n ],\r\n \"models\": [\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-5.5\",\r\n \"displayName\": \"GPT-5.5\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"cachedInput\": 0.5,\r\n \"output\": 30,\r\n \"batchDiscount\": \"50%\",\r\n \"priorityMultiplier\": 2.5,\r\n \"dataResidencyMultiplier\": 1.1\r\n },\r\n \"sourceUrl\": \"https://openai.com/api/pricing/\"\r\n },\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-5.5-pro\",\r\n \"displayName\": \"GPT-5.5 Pro\",\r\n \"family\": \"gpt\",\r\n \"status\": \"announced\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 30,\r\n \"output\": 180\r\n },\r\n \"sourceUrl\": \"https://openai.com/index/introducing-gpt-5-5/\"\r\n },\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-5.4\",\r\n \"displayName\": \"GPT-5.4\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"pricing\": {\r\n \"input\": 2.5,\r\n \"cachedInput\": 0.25,\r\n \"output\": 15,\r\n \"batchDiscount\": \"50%\",\r\n \"dataResidencyMultiplier\": 1.1\r\n },\r\n \"sourceUrl\": \"https://openai.com/api/pricing/\"\r\n },\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-5.4-mini\",\r\n \"displayName\": \"GPT-5.4 Mini\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"pricing\": {\r\n \"input\": 0.75,\r\n \"cachedInput\": 0.075,\r\n \"output\": 4.5,\r\n \"batchDiscount\": \"50%\",\r\n \"dataResidencyMultiplier\": 1.1\r\n },\r\n \"sourceUrl\": \"https://openai.com/api/pricing/\"\r\n },\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-realtime-2\",\r\n \"displayName\": \"GPT Realtime 2\",\r\n \"family\": \"gpt-realtime\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"audio\", \"image\"],\r\n \"pricing\": {\r\n \"textInput\": 4,\r\n \"textCachedInput\": 0.4,\r\n \"textOutput\": 24,\r\n \"audioInput\": 32,\r\n \"audioCachedInput\": 0.4,\r\n \"audioOutput\": 64,\r\n \"imageInput\": 5,\r\n \"imageCachedInput\": 0.5\r\n },\r\n \"sourceUrl\": \"https://openai.com/api/pricing/\"\r\n },\r\n {\r\n \"provider\": \"openai\",\r\n \"modelId\": \"gpt-image-2\",\r\n \"displayName\": \"GPT Image 2\",\r\n \"family\": \"gpt-image\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"image\", \"text\"],\r\n \"pricing\": {\r\n \"imageInput\": 8,\r\n \"imageCachedInput\": 2,\r\n \"imageOutput\": 30,\r\n \"textInput\": 5,\r\n \"textCachedInput\": 1.25\r\n },\r\n \"sourceUrl\": \"https://openai.com/api/pricing/\"\r\n },\r\n\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-opus-4-7\",\r\n \"displayName\": \"Claude Opus 4.7\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"cacheWrite5m\": 6.25,\r\n \"cacheWrite1h\": 10,\r\n \"cacheHit\": 0.5,\r\n \"output\": 25,\r\n \"batchInput\": 2.5,\r\n \"batchOutput\": 12.5,\r\n \"fastModeInput\": 30,\r\n \"fastModeOutput\": 150\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-opus-4-6\",\r\n \"displayName\": \"Claude Opus 4.6\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"cacheWrite5m\": 6.25,\r\n \"cacheWrite1h\": 10,\r\n \"cacheHit\": 0.5,\r\n \"output\": 25,\r\n \"batchInput\": 2.5,\r\n \"batchOutput\": 12.5,\r\n \"fastModeInput\": 30,\r\n \"fastModeOutput\": 150\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-opus-4-5\",\r\n \"displayName\": \"Claude Opus 4.5\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"cacheWrite5m\": 6.25,\r\n \"cacheWrite1h\": 10,\r\n \"cacheHit\": 0.5,\r\n \"output\": 25,\r\n \"batchInput\": 2.5,\r\n \"batchOutput\": 12.5\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-sonnet-4-6\",\r\n \"displayName\": \"Claude Sonnet 4.6\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 3,\r\n \"cacheWrite5m\": 3.75,\r\n \"cacheWrite1h\": 6,\r\n \"cacheHit\": 0.3,\r\n \"output\": 15,\r\n \"batchInput\": 1.5,\r\n \"batchOutput\": 7.5\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-sonnet-4-5\",\r\n \"displayName\": \"Claude Sonnet 4.5\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"pricing\": {\r\n \"input\": 3,\r\n \"cacheWrite5m\": 3.75,\r\n \"cacheWrite1h\": 6,\r\n \"cacheHit\": 0.3,\r\n \"output\": 15,\r\n \"batchInput\": 1.5,\r\n \"batchOutput\": 7.5\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n {\r\n \"provider\": \"anthropic\",\r\n \"modelId\": \"claude-haiku-4-5\",\r\n \"displayName\": \"Claude Haiku 4.5\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\"],\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"cacheWrite5m\": 1.25,\r\n \"cacheWrite1h\": 2,\r\n \"cacheHit\": 0.1,\r\n \"output\": 5,\r\n \"batchInput\": 0.5,\r\n \"batchOutput\": 2.5\r\n },\r\n \"sourceUrl\": \"https://platform.claude.com/docs/en/about-claude/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-3.5-flash\",\r\n \"displayName\": \"Gemini 3.5 Flash\",\r\n \"family\": \"gemini\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\"],\r\n \"pricing\": {\r\n \"input\": 0.25,\r\n \"audioInput\": 0.5,\r\n \"output\": 1.5,\r\n \"cachedInput\": 0.025,\r\n \"audioCachedInput\": 0.05,\r\n \"cacheStoragePerHour\": 1,\r\n \"batchInput\": 0.125,\r\n \"batchAudioInput\": 0.25,\r\n \"batchOutput\": 0.75,\r\n \"googleSearchAfterFreePer1kQueries\": 14,\r\n \"googleMapsAfterFreePer1kQueries\": 14\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-3.1-pro-preview\",\r\n \"displayName\": \"Gemini 3.1 Pro Preview\",\r\n \"family\": \"gemini\",\r\n \"status\": \"preview\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\"],\r\n \"pricing\": {\r\n \"input\": 0.45,\r\n \"audioInput\": 0.9,\r\n \"output\": 2.7,\r\n \"cachedInput\": 0.045,\r\n \"audioCachedInput\": 0.09,\r\n \"cacheStoragePerHour\": 1.8,\r\n \"googleSearchAfterFreePer1kQueries\": 14,\r\n \"googleMapsAfterFreePer1kQueries\": 14\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-3.1-flash-lite-preview\",\r\n \"displayName\": \"Gemini 3.1 Flash-Lite Preview\",\r\n \"family\": \"gemini\",\r\n \"status\": \"preview\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\"],\r\n \"pricing\": {\r\n \"input\": 0.25,\r\n \"audioInput\": 0.5,\r\n \"output\": 1.5,\r\n \"cachedInput\": 0.025,\r\n \"audioCachedInput\": 0.05,\r\n \"cacheStoragePerHour\": 1,\r\n \"batchInput\": 0.125,\r\n \"batchAudioInput\": 0.25,\r\n \"batchOutput\": 0.75,\r\n \"googleSearchAfterFreePer1kQueries\": 14\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-2.5-flash\",\r\n \"displayName\": \"Gemini 2.5 Flash\",\r\n \"family\": \"gemini\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\"],\r\n \"pricing\": {\r\n \"input\": 0.1,\r\n \"audioInput\": 0.7,\r\n \"output\": 0.4,\r\n \"cachedInput\": 0.025,\r\n \"audioCachedInput\": 0.175,\r\n \"cacheStoragePerHour\": 1\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-2.5-flash-lite\",\r\n \"displayName\": \"Gemini 2.5 Flash-Lite\",\r\n \"family\": \"gemini\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\"],\r\n \"pricing\": {\r\n \"input\": 0.05,\r\n \"audioInput\": 0.35,\r\n \"output\": 0.2,\r\n \"cachedInput\": 0.025,\r\n \"audioCachedInput\": 0.175,\r\n \"cacheStoragePerHour\": 1\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-2.5-computer-use-preview-10-2025\",\r\n \"displayName\": \"Gemini 2.5 Computer Use Preview\",\r\n \"family\": \"gemini\",\r\n \"status\": \"preview\",\r\n \"modalities\": [\"text\", \"image\", \"browser-control\"],\r\n \"pricing\": {\r\n \"inputBelow200k\": 1.25,\r\n \"inputAbove200k\": 2.5,\r\n \"outputBelow200k\": 10,\r\n \"outputAbove200k\": 15\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-embedding-2\",\r\n \"displayName\": \"Gemini Embedding 2\",\r\n \"family\": \"gemini-embedding\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"image\", \"video\", \"audio\", \"pdf\"],\r\n \"pricing\": {\r\n \"textInput\": 0.2,\r\n \"imageInput\": 0.45,\r\n \"audioInput\": 6.5,\r\n \"videoInput\": 12\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n {\r\n \"provider\": \"google\",\r\n \"modelId\": \"gemini-embedding-001\",\r\n \"displayName\": \"Gemini Embedding\",\r\n \"family\": \"gemini-embedding\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 0.15,\r\n \"batchInput\": 0.075\r\n },\r\n \"sourceUrl\": \"https://ai.google.dev/gemini-api/docs/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"deepseek\",\r\n \"modelId\": \"deepseek-v4-flash\",\r\n \"displayName\": \"DeepSeek V4 Flash\",\r\n \"family\": \"deepseek-v4\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"maxOutputTokens\": 384000,\r\n \"pricing\": {\r\n \"inputCacheHit\": 0.0028,\r\n \"inputCacheMiss\": 0.14,\r\n \"output\": 0.28\r\n },\r\n \"capabilities\": {\r\n \"thinkingMode\": true,\r\n \"jsonOutput\": true,\r\n \"toolCalls\": true,\r\n \"fimCompletion\": true\r\n },\r\n \"sourceUrl\": \"https://api-docs.deepseek.com/quick_start/pricing\"\r\n },\r\n {\r\n \"provider\": \"deepseek\",\r\n \"modelId\": \"deepseek-v4-pro\",\r\n \"displayName\": \"DeepSeek V4 Pro\",\r\n \"family\": \"deepseek-v4\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"maxOutputTokens\": 384000,\r\n \"pricing\": {\r\n \"inputCacheHit\": 0.003625,\r\n \"inputCacheMiss\": 0.435,\r\n \"output\": 0.87,\r\n \"note\": \"DeepSeek states the 75% reduction becomes official pricing after the promotion ends on 2026-05-31 15:59 UTC.\"\r\n },\r\n \"capabilities\": {\r\n \"thinkingMode\": true,\r\n \"jsonOutput\": true,\r\n \"toolCalls\": true,\r\n \"fimCompletion\": true\r\n },\r\n \"sourceUrl\": \"https://api-docs.deepseek.com/quick_start/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"xai\",\r\n \"modelId\": \"grok-4.3\",\r\n \"displayName\": \"Grok 4.3\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"cachedInput\": 0.2,\r\n \"output\": 2.5\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": \"configurable\",\r\n \"toolCalling\": true\r\n },\r\n \"sourceUrl\": \"https://docs.x.ai/developers/pricing\"\r\n },\r\n {\r\n \"provider\": \"xai\",\r\n \"modelId\": \"grok-build-0.1\",\r\n \"displayName\": \"Grok Build 0.1\",\r\n \"family\": \"grok-build\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"code\"],\r\n \"contextWindow\": 256000,\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"cachedInput\": 0.2,\r\n \"output\": 2\r\n },\r\n \"sourceUrl\": \"https://docs.x.ai/developers/pricing\"\r\n },\r\n {\r\n \"provider\": \"xai\",\r\n \"modelId\": \"grok-4.20-multi-agent-0309\",\r\n \"displayName\": \"Grok 4.20 Multi-Agent\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"cachedInput\": 0.2,\r\n \"output\": 2.5\r\n },\r\n \"sourceUrl\": \"https://docs.x.ai/developers/pricing\"\r\n },\r\n {\r\n \"provider\": \"xai\",\r\n \"modelId\": \"grok-4.20-0309-reasoning\",\r\n \"displayName\": \"Grok 4.20 Reasoning\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"cachedInput\": 0.2,\r\n \"output\": 2.5\r\n },\r\n \"sourceUrl\": \"https://docs.x.ai/developers/pricing\"\r\n },\r\n {\r\n \"provider\": \"xai\",\r\n \"modelId\": \"grok-4.20-0309-non-reasoning\",\r\n \"displayName\": \"Grok 4.20 Non-Reasoning\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"cachedInput\": 0.2,\r\n \"output\": 2.5\r\n },\r\n \"sourceUrl\": \"https://docs.x.ai/developers/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"cohere\",\r\n \"modelId\": \"command-a\",\r\n \"displayName\": \"Command A\",\r\n \"family\": \"command\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"output\": 2\r\n },\r\n \"sourceUrl\": \"https://cohere.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"cohere\",\r\n \"modelId\": \"command\",\r\n \"displayName\": \"Command\",\r\n \"family\": \"command\",\r\n \"status\": \"legacy\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"output\": 2\r\n },\r\n \"sourceUrl\": \"https://cohere.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"cohere\",\r\n \"modelId\": \"command-light\",\r\n \"displayName\": \"Command Light\",\r\n \"family\": \"command\",\r\n \"status\": \"legacy\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 0.3,\r\n \"output\": 0.6\r\n },\r\n \"sourceUrl\": \"https://cohere.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"cohere\",\r\n \"modelId\": \"command-r-03-2024\",\r\n \"displayName\": \"Command R 03-2024\",\r\n \"family\": \"command-r\",\r\n \"status\": \"legacy\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 0.5,\r\n \"output\": 1.5\r\n },\r\n \"sourceUrl\": \"https://cohere.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"cohere\",\r\n \"modelId\": \"command-r-plus-08-2024\",\r\n \"displayName\": \"Command R+ 08-2024\",\r\n \"family\": \"command-r\",\r\n \"status\": \"legacy\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": 2.5,\r\n \"output\": 10\r\n },\r\n \"sourceUrl\": \"https://cohere.com/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"perplexity\",\r\n \"modelId\": \"sonar-pro\",\r\n \"displayName\": \"Sonar Pro\",\r\n \"family\": \"sonar\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"search\"],\r\n \"pricing\": {\r\n \"input\": 3,\r\n \"output\": 15,\r\n \"searchRequestFeePer1k\": {\r\n \"fastLow\": 6,\r\n \"fastMedium\": 10,\r\n \"fastHigh\": 14,\r\n \"proLow\": 14,\r\n \"proMedium\": 18,\r\n \"proHigh\": 22\r\n }\r\n },\r\n \"sourceUrl\": \"https://docs.perplexity.ai/docs/getting-started/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"groq\",\r\n \"modelId\": \"openai/gpt-oss-20b\",\r\n \"displayName\": \"GPT OSS 20B 128k\",\r\n \"family\": \"gpt-oss\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 128000,\r\n \"pricing\": {\r\n \"input\": 0.075,\r\n \"output\": 0.3\r\n },\r\n \"sourceUrl\": \"https://groq.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"groq\",\r\n \"modelId\": \"openai/gpt-oss-120b\",\r\n \"displayName\": \"GPT OSS 120B 128k\",\r\n \"family\": \"gpt-oss\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 128000,\r\n \"pricing\": {\r\n \"input\": 0.15,\r\n \"output\": 0.6\r\n },\r\n \"sourceUrl\": \"https://groq.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"groq\",\r\n \"modelId\": \"meta-llama/llama-4-scout-17b-16e-instruct\",\r\n \"displayName\": \"Llama 4 Scout 17Bx16E 128k\",\r\n \"family\": \"llama\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 128000,\r\n \"pricing\": {\r\n \"input\": 0.11,\r\n \"output\": 0.34\r\n },\r\n \"sourceUrl\": \"https://groq.com/pricing\"\r\n },\r\n {\r\n \"provider\": \"groq\",\r\n \"modelId\": \"qwen/qwen3-32b\",\r\n \"displayName\": \"Qwen3 32B 131k\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\"],\r\n \"contextWindow\": 131000,\r\n \"pricing\": {\r\n \"input\": 0.29,\r\n \"output\": 0.59\r\n },\r\n \"sourceUrl\": \"https://groq.com/pricing\"\r\n },\r\n\r\n {\r\n \"provider\": \"mistral\",\r\n \"modelId\": \"mistral-medium-3\",\r\n \"displayName\": \"Mistral Medium 3\",\r\n \"family\": \"mistral\",\r\n \"status\": \"active\",\r\n \"modalities\": [\"text\", \"vision\", \"tools\"],\r\n \"pricing\": {\r\n \"input\": 0.4,\r\n \"output\": 2\r\n },\r\n \"sourceUrl\": \"https://mistral.ai/news/mistral-medium-3\"\r\n },\r\n\r\n {\r\n \"provider\": \"ai21\",\r\n \"modelId\": \"jamba-large-1.7\",\r\n \"displayName\": \"Jamba Large 1.7\",\r\n \"family\": \"jamba\",\r\n \"status\": \"needs_verification\",\r\n \"modalities\": [\"text\"],\r\n \"pricing\": {\r\n \"input\": null,\r\n \"output\": null\r\n },\r\n \"notes\": \"AI21 docs say pricing depends on platform/endpoints and links to account/billing; public token prices were not exposed clearly in the checked official docs.\",\r\n \"sourceUrl\": \"https://docs.ai21.com/docs/usage-cost\"\r\n }\r\n ]\r\n}","{\r\n \"schema\": \"x12i.openrouter-models.catalog\",\r\n \"version\": \"0.1.0\",\r\n \"currency\": \"USD\",\r\n \"pricingUnit\": \"1M_tokens\",\r\n \"source\": {\r\n \"provider\": \"openrouter\",\r\n \"catalogUrl\": \"https://openrouter.ai/api/v1/models\",\r\n \"pricingUrl\": \"https://openrouter.ai/pricing\",\r\n \"verifiedAt\": \"2026-05-27\",\r\n \"normalization\": \"OpenRouter pricing fields are per-token decimal strings. Values below are normalized to USD per 1M tokens.\"\r\n },\r\n \"notes\": [\r\n \"This catalog is OpenRouter-specific and should not be merged with direct-provider pricing.\",\r\n \"Router models beginning with ~ are dynamic aliases that redirect to latest model families.\",\r\n \"Models ending with :free are free OpenRouter variants and may have rate limits or availability limits.\",\r\n \"webSearch is kept as a separate field because OpenRouter exposes it separately from token pricing.\",\r\n \"This is a seed catalog. In production, generate the full file from https://openrouter.ai/api/v1/models.\"\r\n ],\r\n \"models\": [\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.7-max\",\r\n \"canonicalSlug\": \"qwen/qwen3.7-max-20260520\",\r\n \"displayName\": \"Qwen: Qwen3.7 Max\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"output\": 3.75,\r\n \"cachedInput\": 0.25,\r\n \"cacheWrite\": 1.5625\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"x-ai/grok-build-0.1\",\r\n \"canonicalSlug\": \"x-ai/grok-build-0.1-20260520\",\r\n \"displayName\": \"xAI: Grok Build 0.1\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 256000,\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"output\": 2,\r\n \"cachedInput\": 0.2,\r\n \"webSearchPerRequest\": 0.005\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"google/gemini-3.5-flash\",\r\n \"canonicalSlug\": \"google/gemini-3.5-flash-20260519\",\r\n \"displayName\": \"Google: Gemini 3.5 Flash\",\r\n \"family\": \"gemini\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\", \"file\", \"audio\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 65536,\r\n \"knowledgeCutoff\": \"2025-01-01\",\r\n \"pricing\": {\r\n \"input\": 1.5,\r\n \"output\": 9,\r\n \"imageInput\": 1.5,\r\n \"audioInput\": 3,\r\n \"cachedInput\": 0.15,\r\n \"cacheWrite\": 0.08333333333333334,\r\n \"internalReasoning\": 9,\r\n \"webSearchPerRequest\": 0.014\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"anthropic/claude-opus-4.7-fast\",\r\n \"canonicalSlug\": \"anthropic/claude-4.7-opus-fast-20260512\",\r\n \"displayName\": \"Anthropic: Claude Opus 4.7 Fast\",\r\n \"family\": \"claude\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"maxCompletionTokens\": 128000,\r\n \"pricing\": {\r\n \"input\": 30,\r\n \"output\": 150,\r\n \"cachedInput\": 3,\r\n \"cacheWrite\": 37.5,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"perceptron/perceptron-mk1\",\r\n \"canonicalSlug\": \"perceptron/perceptron-mk1-20260512\",\r\n \"displayName\": \"Perceptron: Perceptron Mk1\",\r\n \"family\": \"perceptron\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 32768,\r\n \"maxCompletionTokens\": 8192,\r\n \"pricing\": {\r\n \"input\": 0.15,\r\n \"output\": 1.5\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"inclusionai/ring-2.6-1t\",\r\n \"canonicalSlug\": \"inclusionai/ring-2.6-1t-20260508\",\r\n \"displayName\": \"inclusionAI: Ring-2.6-1T\",\r\n \"family\": \"ring\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 0.075,\r\n \"output\": 0.625,\r\n \"cachedInput\": 0.015\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"google/gemini-3.1-flash-lite\",\r\n \"canonicalSlug\": \"google/gemini-3.1-flash-lite-20260507\",\r\n \"displayName\": \"Google: Gemini 3.1 Flash Lite\",\r\n \"family\": \"gemini\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\", \"file\", \"audio\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 0.25,\r\n \"output\": 1.5,\r\n \"imageInput\": 0.25,\r\n \"audioInput\": 0.5,\r\n \"cachedInput\": 0.025,\r\n \"cacheWrite\": 0.08333333333333334,\r\n \"internalReasoning\": 1.5,\r\n \"webSearchPerRequest\": 0.014\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"openai/gpt-chat-latest\",\r\n \"canonicalSlug\": \"openai/gpt-chat-latest-20260505\",\r\n \"displayName\": \"OpenAI: GPT Chat Latest\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 400000,\r\n \"maxCompletionTokens\": 128000,\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"output\": 30,\r\n \"cachedInput\": 0.5,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"x-ai/grok-4.3\",\r\n \"canonicalSlug\": \"x-ai/grok-4.3-20260430\",\r\n \"displayName\": \"xAI: Grok 4.3\",\r\n \"family\": \"grok\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"pricing\": {\r\n \"input\": 1.25,\r\n \"output\": 2.5,\r\n \"cachedInput\": 0.2,\r\n \"webSearchPerRequest\": 0.005\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"ibm-granite/granite-4.1-8b\",\r\n \"canonicalSlug\": \"ibm-granite/granite-4.1-8b-20260429\",\r\n \"displayName\": \"IBM: Granite 4.1 8B\",\r\n \"family\": \"granite\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 131072,\r\n \"maxCompletionTokens\": 131072,\r\n \"pricing\": {\r\n \"input\": 0.05,\r\n \"output\": 0.1,\r\n \"cachedInput\": 0.05\r\n },\r\n \"capabilities\": {\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"mistralai/mistral-medium-3-5\",\r\n \"canonicalSlug\": \"mistralai/mistral-medium-3.5-20260430\",\r\n \"displayName\": \"Mistral: Mistral Medium 3.5\",\r\n \"family\": \"mistral\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"pricing\": {\r\n \"input\": 1.5,\r\n \"output\": 7.5\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"openrouter/owl-alpha\",\r\n \"canonicalSlug\": \"openrouter/owl-alpha\",\r\n \"displayName\": \"Owl Alpha\",\r\n \"family\": \"owl\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048756,\r\n \"maxCompletionTokens\": 262144,\r\n \"pricing\": {\r\n \"input\": 0,\r\n \"output\": 0\r\n },\r\n \"capabilities\": {\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~anthropic/claude-haiku-latest\",\r\n \"canonicalSlug\": \"~anthropic/claude-haiku-latest\",\r\n \"displayName\": \"Anthropic Claude Haiku Latest\",\r\n \"family\": \"claude-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 200000,\r\n \"maxCompletionTokens\": 64000,\r\n \"pricing\": {\r\n \"input\": 1,\r\n \"output\": 5,\r\n \"cachedInput\": 0.1,\r\n \"cacheWrite\": 1.25,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~openai/gpt-mini-latest\",\r\n \"canonicalSlug\": \"~openai/gpt-mini-latest\",\r\n \"displayName\": \"OpenAI GPT Mini Latest\",\r\n \"family\": \"gpt-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 400000,\r\n \"maxCompletionTokens\": 128000,\r\n \"knowledgeCutoff\": \"2025-08-31\",\r\n \"pricing\": {\r\n \"input\": 0.75,\r\n \"output\": 4.5,\r\n \"cachedInput\": 0.075,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~google/gemini-pro-latest\",\r\n \"canonicalSlug\": \"~google/gemini-pro-latest\",\r\n \"displayName\": \"Google Gemini Pro Latest\",\r\n \"family\": \"gemini-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\", \"audio\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 2,\r\n \"output\": 12,\r\n \"imageInput\": 2,\r\n \"audioInput\": 2,\r\n \"cachedInput\": 0.2,\r\n \"cacheWrite\": 0.375,\r\n \"internalReasoning\": 12,\r\n \"webSearchPerRequest\": 0.014\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~moonshotai/kimi-latest\",\r\n \"canonicalSlug\": \"~moonshotai/kimi-latest\",\r\n \"displayName\": \"MoonshotAI Kimi Latest\",\r\n \"family\": \"kimi-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 262142,\r\n \"pricing\": {\r\n \"input\": 0.73,\r\n \"output\": 3.49,\r\n \"cachedInput\": 0.25\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~google/gemini-flash-latest\",\r\n \"canonicalSlug\": \"~google/gemini-flash-latest\",\r\n \"displayName\": \"Google Gemini Flash Latest\",\r\n \"family\": \"gemini-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\", \"file\", \"audio\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 65536,\r\n \"knowledgeCutoff\": \"2025-01-01\",\r\n \"pricing\": {\r\n \"input\": 1.5,\r\n \"output\": 9,\r\n \"imageInput\": 1.5,\r\n \"audioInput\": 3,\r\n \"cachedInput\": 0.15,\r\n \"cacheWrite\": 0.08333333333333334,\r\n \"internalReasoning\": 9,\r\n \"webSearchPerRequest\": 0.014\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~anthropic/claude-sonnet-latest\",\r\n \"canonicalSlug\": \"~anthropic/claude-sonnet-latest\",\r\n \"displayName\": \"Anthropic Claude Sonnet Latest\",\r\n \"family\": \"claude-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"maxCompletionTokens\": 128000,\r\n \"pricing\": {\r\n \"input\": 3,\r\n \"output\": 15,\r\n \"cachedInput\": 0.3,\r\n \"cacheWrite\": 3.75,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"~openai/gpt-latest\",\r\n \"canonicalSlug\": \"~openai/gpt-latest\",\r\n \"displayName\": \"OpenAI GPT Latest\",\r\n \"family\": \"gpt-router\",\r\n \"status\": \"router\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1050000,\r\n \"maxCompletionTokens\": 128000,\r\n \"knowledgeCutoff\": \"2025-12-01\",\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"output\": 30,\r\n \"cachedInput\": 0.5,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.5-plus-20260420\",\r\n \"canonicalSlug\": \"qwen/qwen3.5-plus-20260420\",\r\n \"displayName\": \"Qwen: Qwen3.5 Plus 2026-04-20\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 0.3,\r\n \"output\": 1.8,\r\n \"cacheWrite\": 0.375\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.6-flash\",\r\n \"canonicalSlug\": \"qwen/qwen3.6-flash\",\r\n \"displayName\": \"Qwen: Qwen3.6 Flash\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1000000,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 0.1875,\r\n \"output\": 1.125,\r\n \"cacheWrite\": 0.234375\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.6-35b-a3b\",\r\n \"canonicalSlug\": \"qwen/qwen3.6-35b-a3b-20260415\",\r\n \"displayName\": \"Qwen: Qwen3.6 35B A3B\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 262140,\r\n \"pricing\": {\r\n \"input\": 0.14,\r\n \"output\": 1\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.6-max-preview\",\r\n \"canonicalSlug\": \"qwen/qwen3.6-max-preview-20260420\",\r\n \"displayName\": \"Qwen: Qwen3.6 Max Preview\",\r\n \"family\": \"qwen\",\r\n \"status\": \"preview\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 65536,\r\n \"pricing\": {\r\n \"input\": 1.04,\r\n \"output\": 6.24,\r\n \"cacheWrite\": 1.3\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"qwen/qwen3.6-27b\",\r\n \"canonicalSlug\": \"qwen/qwen3.6-27b-20260422\",\r\n \"displayName\": \"Qwen: Qwen3.6 27B\",\r\n \"family\": \"qwen\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 262140,\r\n \"pricing\": {\r\n \"input\": 0.29,\r\n \"output\": 3.2\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"openai/gpt-5.5-pro\",\r\n \"canonicalSlug\": \"openai/gpt-5.5-pro-20260423\",\r\n \"displayName\": \"OpenAI: GPT-5.5 Pro\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1050000,\r\n \"maxCompletionTokens\": 128000,\r\n \"knowledgeCutoff\": \"2025-12-01\",\r\n \"pricing\": {\r\n \"input\": 30,\r\n \"output\": 180,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"openai/gpt-5.5\",\r\n \"canonicalSlug\": \"openai/gpt-5.5-20260423\",\r\n \"displayName\": \"OpenAI: GPT-5.5\",\r\n \"family\": \"gpt\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1050000,\r\n \"maxCompletionTokens\": 128000,\r\n \"knowledgeCutoff\": \"2025-12-01\",\r\n \"pricing\": {\r\n \"input\": 5,\r\n \"output\": 30,\r\n \"cachedInput\": 0.5,\r\n \"webSearchPerRequest\": 0.01\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"deepseek/deepseek-v4-pro\",\r\n \"canonicalSlug\": \"deepseek/deepseek-v4-pro-20260423\",\r\n \"displayName\": \"DeepSeek: DeepSeek V4 Pro\",\r\n \"family\": \"deepseek\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 384000,\r\n \"pricing\": {\r\n \"input\": 0.435,\r\n \"output\": 0.87,\r\n \"cachedInput\": 0.003625\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"deepseek/deepseek-v4-flash\",\r\n \"canonicalSlug\": \"deepseek/deepseek-v4-flash-20260423\",\r\n \"displayName\": \"DeepSeek: DeepSeek V4 Flash\",\r\n \"family\": \"deepseek\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 16384,\r\n \"pricing\": {\r\n \"input\": 0.1,\r\n \"output\": 0.2,\r\n \"cachedInput\": 0.02\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"deepseek/deepseek-v4-flash:free\",\r\n \"canonicalSlug\": \"deepseek/deepseek-v4-flash-20260423\",\r\n \"displayName\": \"DeepSeek: DeepSeek V4 Flash Free\",\r\n \"family\": \"deepseek\",\r\n \"status\": \"free\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 384000,\r\n \"pricing\": {\r\n \"input\": 0,\r\n \"output\": 0\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"inclusionai/ling-2.6-1t\",\r\n \"canonicalSlug\": \"inclusionai/ling-2.6-1t-20260423\",\r\n \"displayName\": \"inclusionAI: Ling-2.6-1T\",\r\n \"family\": \"ling\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 32768,\r\n \"pricing\": {\r\n \"input\": 0.075,\r\n \"output\": 0.625,\r\n \"cachedInput\": 0.015\r\n },\r\n \"capabilities\": {\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"tencent/hy3-preview\",\r\n \"canonicalSlug\": \"tencent/hy3-preview-20260421\",\r\n \"displayName\": \"Tencent: Hy3 Preview\",\r\n \"family\": \"hy3\",\r\n \"status\": \"preview\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 262144,\r\n \"maxCompletionTokens\": 262144,\r\n \"pricing\": {\r\n \"input\": 0.066,\r\n \"output\": 0.26,\r\n \"cachedInput\": 0.029\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"xiaomi/mimo-v2.5-pro\",\r\n \"canonicalSlug\": \"xiaomi/mimo-v2.5-pro-20260422\",\r\n \"displayName\": \"Xiaomi: MiMo-V2.5-Pro\",\r\n \"family\": \"mimo\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 131072,\r\n \"pricing\": {\r\n \"input\": 0.435,\r\n \"output\": 0.87,\r\n \"cachedInput\": 0.0036\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true,\r\n \"structuredOutputs\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"xiaomi/mimo-v2.5\",\r\n \"canonicalSlug\": \"xiaomi/mimo-v2.5-20260422\",\r\n \"displayName\": \"Xiaomi: MiMo-V2.5\",\r\n \"family\": \"mimo\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"audio\", \"video\"],\r\n \"output\": [\"text\"]\r\n },\r\n \"contextWindow\": 1048576,\r\n \"maxCompletionTokens\": 131072,\r\n \"pricing\": {\r\n \"input\": 0.14,\r\n \"output\": 0.28,\r\n \"cachedInput\": 0.0028\r\n },\r\n \"capabilities\": {\r\n \"reasoning\": true,\r\n \"toolCalling\": true\r\n }\r\n },\r\n {\r\n \"provider\": \"openrouter\",\r\n \"modelId\": \"openai/gpt-5.4-image-2\",\r\n \"canonicalSlug\": \"openai/gpt-5.4-image-2-20260421\",\r\n \"displayName\": \"OpenAI: GPT-5.4 Image 2\",\r\n \"family\": \"gpt-image\",\r\n \"status\": \"active\",\r\n \"modalities\": {\r\n \"input\": [\"text\", \"image\", \"file\"],\r\n \"output\": [\"text\", \"image\"]\r\n },\r\n \"contextWindow\": 272000,\r\n \"pricing\": {\r\n \"input\": 8,\r\n \"output\": 15\r\n },\r\n \"capabilities\": {\r\n \"imageGeneration\": true,\r\n \"structuredOutputs\": true\r\n }\r\n }\r\n ]\r\n}","import { resolveCatalogCacheTtlMs } from \"../cache/modelCache.js\";\nimport { loadCatalogSources, type LoadCatalogOptions, type LoadedCatalogs } from \"./loadCatalogSources.js\";\n\ntype CacheSlot = {\n loadedAt: number;\n data: LoadedCatalogs;\n};\n\nconst slots = new Map<string, CacheSlot>();\nconst inflight = new Map<string, Promise<LoadedCatalogs>>();\n\nfunction slotKey(options: LoadCatalogOptions, cacheKey: string): string {\n return [\n cacheKey,\n options.bundledOnly ? \"bundled\" : \"remote\",\n options.directCatalogUrl ?? \"\",\n options.openRouterCatalogUrl ?? \"\",\n ].join(\"\\0\");\n}\n\nexport function invalidateCatalogLoadCache(cacheKey = \"default\"): void {\n for (const key of [...slots.keys()]) {\n if (key.startsWith(`${cacheKey}\\0`)) slots.delete(key);\n }\n for (const key of [...inflight.keys()]) {\n if (key.startsWith(`${cacheKey}\\0`)) inflight.delete(key);\n }\n}\n\nexport type LoadCatalogCachedOptions = {\n cacheKey?: string;\n ttlMs?: number;\n /** Bypass cache and fetch again (e.g. `catalog refresh`). */\n forceRefresh?: boolean;\n};\n\n/**\n * Load catalogs with a process-wide in-memory cache.\n * Remote fetches run at most once per TTL window (default 24h); concurrent callers share one in-flight request.\n */\nexport async function loadCatalogSourcesCached(\n options: LoadCatalogOptions = {},\n cacheOptions: LoadCatalogCachedOptions = {},\n): Promise<LoadedCatalogs> {\n if (options.bundledOnly) {\n return loadCatalogSources(options);\n }\n\n const ttlMs = resolveCatalogCacheTtlMs(cacheOptions.ttlMs);\n const key = slotKey(options, cacheOptions.cacheKey ?? \"default\");\n\n if (!cacheOptions.forceRefresh) {\n const slot = slots.get(key);\n if (slot && Date.now() - slot.loadedAt < ttlMs) {\n return slot.data;\n }\n } else {\n slots.delete(key);\n inflight.delete(key);\n }\n\n const pending = inflight.get(key);\n if (pending) return pending;\n\n const promise = loadCatalogSources(options)\n .then((data) => {\n slots.set(key, { loadedAt: Date.now(), data });\n inflight.delete(key);\n return data;\n })\n .catch((err) => {\n inflight.delete(key);\n throw err;\n });\n\n inflight.set(key, promise);\n return promise;\n}\n","import { resolveCatalogCacheTtlMs, writeCachedModels } from \"../cache/modelCache.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\nimport { ModelNameResolver } from \"../sync/modelNameResolver/ModelNameResolver.js\";\nimport { normalizeProvider } from \"../sync/modelNameResolver/normalize.js\";\nimport type {\n ModelResolutionInput,\n ModelResolutionResult,\n ModelResolverOptions,\n} from \"../sync/modelNameResolver/types.js\";\nimport {\n invalidateCatalogLoadCache,\n loadCatalogSourcesCached,\n} from \"./catalogLoadCache.js\";\nimport type { LoadCatalogOptions } from \"./loadCatalogSources.js\";\n\nexport type AiModelsCatalogClientOptions = LoadCatalogOptions & {\n cacheTtlMs?: number;\n /** Cache scope key (default: `default`). */\n cacheKey?: string;\n resolverOptions?: Omit<ModelResolverOptions, \"aliasRegistry\">;\n};\n\nfunction isOpenRouterProvider(provider?: string): boolean {\n return normalizeProvider(provider) === \"openrouter\";\n}\n\nexport class AiModelsCatalogClient {\n private readonly cacheTtlMs: number;\n private readonly cacheKey: string;\n private readonly loadOptions: LoadCatalogOptions;\n private readonly resolverOptions?: ModelResolverOptions;\n\n private directModels: Map<string, AiModelRecord> | null = null;\n private openRouterModels: Map<string, AiModelRecord> | null = null;\n private loadedAt = 0;\n private loadPromise: Promise<void> | null = null;\n\n constructor(options: AiModelsCatalogClientOptions = {}) {\n this.cacheTtlMs = resolveCatalogCacheTtlMs(options.cacheTtlMs);\n this.cacheKey = options.cacheKey ?? \"default\";\n this.loadOptions = {\n directCatalogUrl: options.directCatalogUrl,\n openRouterCatalogUrl: options.openRouterCatalogUrl,\n bundledOnly: options.bundledOnly,\n fetchTimeoutMs: options.fetchTimeoutMs,\n };\n this.resolverOptions = options.resolverOptions;\n }\n\n private isInstanceCacheValid(): boolean {\n return (\n this.directModels !== null &&\n this.openRouterModels !== null &&\n Date.now() - this.loadedAt < this.cacheTtlMs\n );\n }\n\n private applyLoaded(\n direct: Map<string, AiModelRecord>,\n openrouter: Map<string, AiModelRecord>,\n ): void {\n this.directModels = direct;\n this.openRouterModels = openrouter;\n this.loadedAt = Date.now();\n writeCachedModels(`${this.cacheKey}:direct`, direct, this.cacheTtlMs);\n writeCachedModels(`${this.cacheKey}:openrouter`, openrouter, this.cacheTtlMs);\n }\n\n private async ensureLoaded(forceRefresh = false): Promise<void> {\n if (!forceRefresh && this.isInstanceCacheValid()) return;\n\n if (this.loadPromise) return this.loadPromise;\n\n this.loadPromise = (async () => {\n const loaded = await loadCatalogSourcesCached(this.loadOptions, {\n cacheKey: this.cacheKey,\n ttlMs: this.cacheTtlMs,\n forceRefresh,\n });\n this.applyLoaded(loaded.direct, loaded.openrouter);\n })().finally(() => {\n this.loadPromise = null;\n });\n\n await this.loadPromise;\n }\n\n mergedModels(): Map<string, AiModelRecord> {\n const map = new Map<string, AiModelRecord>();\n for (const r of this.directModels?.values() ?? []) {\n map.set(r.modelId, r);\n }\n for (const r of this.openRouterModels?.values() ?? []) {\n map.set(r.modelId, r);\n }\n return map;\n }\n\n private catalogForProvider(provider?: string): Map<string, AiModelRecord> {\n if (isOpenRouterProvider(provider)) {\n return this.openRouterModels ?? new Map();\n }\n return this.directModels ?? new Map();\n }\n\n private resolver(\n models: Map<string, AiModelRecord>,\n options?: ModelResolverOptions,\n ): ModelNameResolver {\n return new ModelNameResolver(models, { ...this.resolverOptions, ...options });\n }\n\n async getAllModels(): Promise<Map<string, AiModelRecord>> {\n await this.ensureLoaded();\n return this.mergedModels();\n }\n\n async getDirectModels(): Promise<Map<string, AiModelRecord>> {\n await this.ensureLoaded();\n return new Map(this.directModels);\n }\n\n async getOpenRouterModels(): Promise<Map<string, AiModelRecord>> {\n await this.ensureLoaded();\n return new Map(this.openRouterModels);\n }\n\n async resolveModel(\n input: ModelResolutionInput,\n options?: ModelResolverOptions,\n ): Promise<ModelResolutionResult> {\n await this.ensureLoaded();\n\n const primary = this.catalogForProvider(input.provider);\n const secondary = isOpenRouterProvider(input.provider)\n ? (this.directModels ?? new Map())\n : (this.openRouterModels ?? new Map());\n\n let result = this.resolver(primary, options).resolve(input);\n if (result.found && result.record) return result;\n\n if (secondary.size > 0) {\n const fallback = this.resolver(secondary, options).resolve(input);\n if (fallback.found && fallback.record) return fallback;\n if (!result.found && fallback.found) result = fallback;\n }\n\n if (!result.found) {\n result = this.resolver(this.mergedModels(), options).resolve(input);\n }\n\n return result;\n }\n\n async getModel(\n modelId: string,\n provider?: string,\n options?: ModelResolverOptions,\n ): Promise<AiModelRecord | null> {\n const result = await this.resolveModel({ model: modelId, provider }, options);\n return result.found ? result.record : null;\n }\n\n /** Clear caches and fetch catalogs again immediately. */\n async refresh(): Promise<void> {\n invalidateCatalogLoadCache(this.cacheKey);\n this.directModels = null;\n this.openRouterModels = null;\n this.loadedAt = 0;\n this.loadPromise = null;\n await this.ensureLoaded(true);\n }\n}\n"]}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeOpenRouterModel
|
|
3
|
+
} from "./chunk-SIH4GPV4.js";
|
|
4
|
+
import {
|
|
5
|
+
ModelNameResolver
|
|
6
|
+
} from "./chunk-EYHMQVAL.js";
|
|
7
|
+
import {
|
|
8
|
+
SyncError
|
|
9
|
+
} from "./chunk-2PTCWPHV.js";
|
|
10
|
+
|
|
11
|
+
// src/sync/OpenRouterSyncProvider.ts
|
|
12
|
+
function buildFetchHeaders(apiKey) {
|
|
13
|
+
const headers = { Accept: "application/json" };
|
|
14
|
+
if (apiKey?.trim()) headers.Authorization = `Bearer ${apiKey.trim()}`;
|
|
15
|
+
return headers;
|
|
16
|
+
}
|
|
17
|
+
function buildModelsUrl(baseUrl, query) {
|
|
18
|
+
const url = new URL(`${baseUrl.replace(/\/$/, "")}/models`);
|
|
19
|
+
const q = { output_modalities: "all", ...query };
|
|
20
|
+
for (const [key, value] of Object.entries(q)) {
|
|
21
|
+
if (value !== void 0 && value !== "") url.searchParams.set(key, value);
|
|
22
|
+
}
|
|
23
|
+
return url.toString();
|
|
24
|
+
}
|
|
25
|
+
var OpenRouterSyncProvider = class {
|
|
26
|
+
apiKey;
|
|
27
|
+
baseUrl;
|
|
28
|
+
query;
|
|
29
|
+
constructor(options = {}) {
|
|
30
|
+
this.apiKey = options.apiKey;
|
|
31
|
+
this.baseUrl = options.baseUrl ?? "https://openrouter.ai/api/v1";
|
|
32
|
+
this.query = options.query ?? { output_modalities: "all" };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Fetches the full OpenRouter model catalog (public, no API key required).
|
|
36
|
+
* @see https://openrouter.ai/api/v1/models
|
|
37
|
+
*/
|
|
38
|
+
async fetchModels() {
|
|
39
|
+
const url = buildModelsUrl(this.baseUrl, this.query);
|
|
40
|
+
let response;
|
|
41
|
+
try {
|
|
42
|
+
response = await fetch(url, { headers: buildFetchHeaders(this.apiKey) });
|
|
43
|
+
} catch (cause) {
|
|
44
|
+
throw new SyncError("OPENROUTER_MODELS_FETCH_FAILED", `Failed to fetch OpenRouter models from ${url}`, cause);
|
|
45
|
+
}
|
|
46
|
+
if (response.status === 401 || response.status === 403) {
|
|
47
|
+
throw new SyncError(
|
|
48
|
+
"OPENROUTER_AUTH_FAILED",
|
|
49
|
+
this.apiKey ? "OpenRouter API key is invalid or unauthorized." : "OpenRouter returned unauthorized \u2014 remove OPENROUTER_API_KEY to use the public models endpoint."
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
const body = await response.text().catch(() => "");
|
|
54
|
+
throw new SyncError(
|
|
55
|
+
"OPENROUTER_MODELS_FETCH_FAILED",
|
|
56
|
+
`OpenRouter models fetch failed (${response.status}): ${body.slice(0, 200)}`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
const json = await response.json();
|
|
60
|
+
const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
61
|
+
return (json.data ?? []).map((row) => normalizeOpenRouterModel(row, syncedAt));
|
|
62
|
+
}
|
|
63
|
+
/** Build the URL used for the last fetch pattern (for debugging). */
|
|
64
|
+
getModelsUrl() {
|
|
65
|
+
return buildModelsUrl(this.baseUrl, this.query);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// src/sync/modelNameResolver.ts
|
|
70
|
+
function createModelNameResolver(catalog, options) {
|
|
71
|
+
return new ModelNameResolver(catalog, options);
|
|
72
|
+
}
|
|
73
|
+
function resolveModel(input, models, aliasRegistry, provider) {
|
|
74
|
+
const resolver = new ModelNameResolver(models, { aliasRegistry });
|
|
75
|
+
const result = resolver.resolve({ model: input, provider });
|
|
76
|
+
if (!result.found || !result.record) return null;
|
|
77
|
+
return {
|
|
78
|
+
catalogModel: result.record,
|
|
79
|
+
matchedAlias: result.modelId,
|
|
80
|
+
routedViaOpenRouter: result.routedViaOpenRouter
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function isRoutedViaOpenRouter(provider, model, matchedKey) {
|
|
84
|
+
if (provider === "openrouter") return true;
|
|
85
|
+
if (provider && provider !== "openrouter") return false;
|
|
86
|
+
return model.modelId.includes("/") && matchedKey.includes("/");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
OpenRouterSyncProvider,
|
|
91
|
+
createModelNameResolver,
|
|
92
|
+
resolveModel,
|
|
93
|
+
isRoutedViaOpenRouter
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=chunk-6BQBKROR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sync/OpenRouterSyncProvider.ts","../src/sync/modelNameResolver.ts"],"sourcesContent":["import { SyncError } from \"../errors.js\";\nimport { normalizeOpenRouterModel } from \"../models/normalizeOpenRouterModel.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\nimport type {\n OpenRouterModelsQuery,\n OpenRouterModelsResponse,\n} from \"../models/openrouter.types.js\";\n\nexport type OpenRouterSyncProviderOptions = {\n /** Optional — public GET /models needs no key. */\n apiKey?: string;\n baseUrl?: string;\n /** Query params passed to OpenRouter (default: all modalities). */\n query?: OpenRouterModelsQuery;\n};\n\nfunction buildFetchHeaders(apiKey?: string): Record<string, string> {\n const headers: Record<string, string> = { Accept: \"application/json\" };\n if (apiKey?.trim()) headers.Authorization = `Bearer ${apiKey.trim()}`;\n return headers;\n}\n\nfunction buildModelsUrl(baseUrl: string, query?: OpenRouterModelsQuery): string {\n const url = new URL(`${baseUrl.replace(/\\/$/, \"\")}/models`);\n const q = { output_modalities: \"all\", ...query };\n for (const [key, value] of Object.entries(q)) {\n if (value !== undefined && value !== \"\") url.searchParams.set(key, value);\n }\n return url.toString();\n}\n\nexport class OpenRouterSyncProvider {\n private readonly apiKey?: string;\n private readonly baseUrl: string;\n private readonly query?: OpenRouterModelsQuery;\n\n constructor(options: OpenRouterSyncProviderOptions = {}) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://openrouter.ai/api/v1\";\n this.query = options.query ?? { output_modalities: \"all\" };\n }\n\n /**\n * Fetches the full OpenRouter model catalog (public, no API key required).\n * @see https://openrouter.ai/api/v1/models\n */\n async fetchModels(): Promise<AiModelRecord[]> {\n const url = buildModelsUrl(this.baseUrl, this.query);\n let response: Response;\n\n try {\n response = await fetch(url, { headers: buildFetchHeaders(this.apiKey) });\n } catch (cause) {\n throw new SyncError(\"OPENROUTER_MODELS_FETCH_FAILED\", `Failed to fetch OpenRouter models from ${url}`, cause);\n }\n\n if (response.status === 401 || response.status === 403) {\n throw new SyncError(\n \"OPENROUTER_AUTH_FAILED\",\n this.apiKey\n ? \"OpenRouter API key is invalid or unauthorized.\"\n : \"OpenRouter returned unauthorized — remove OPENROUTER_API_KEY to use the public models endpoint.\",\n );\n }\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new SyncError(\n \"OPENROUTER_MODELS_FETCH_FAILED\",\n `OpenRouter models fetch failed (${response.status}): ${body.slice(0, 200)}`,\n );\n }\n\n const json = (await response.json()) as OpenRouterModelsResponse;\n const syncedAt = new Date().toISOString();\n return (json.data ?? []).map((row) => normalizeOpenRouterModel(row, syncedAt));\n }\n\n /** Build the URL used for the last fetch pattern (for debugging). */\n getModelsUrl(): string {\n return buildModelsUrl(this.baseUrl, this.query);\n }\n}\n","import type { AliasRegistry } from \"../aliases/AliasRegistry.js\";\nimport type { AiModelRecord } from \"../models/types.js\";\nimport { ModelNameResolver } from \"./modelNameResolver/ModelNameResolver.js\";\nimport type {\n ModelResolutionInput,\n ModelResolutionResult,\n ModelResolutionSuccess,\n ModelResolverOptions,\n ResolvedModel,\n} from \"./modelNameResolver/types.js\";\n\nexport { ModelNameResolver } from \"./modelNameResolver/ModelNameResolver.js\";\nexport { buildCatalogIndexes } from \"./modelNameResolver/catalogIndexes.js\";\nexport * from \"./modelNameResolver/types.js\";\nexport {\n loadOpenRouterRoutingEnv,\n shouldDefaultRouteViaOpenRouter,\n providerIdToEnvKeyPrefix,\n vendorApiKeyEnvName,\n} from \"./openRouterRoutingEnv.js\";\nexport type { OpenRouterRoutingConfig } from \"./openRouterRoutingEnv.js\";\nexport { normalizeString, normalizeProvider } from \"./modelNameResolver/normalize.js\";\n\nexport function createModelNameResolver(\n catalog: Map<string, AiModelRecord>,\n options?: ModelResolverOptions,\n): ModelNameResolver {\n return new ModelNameResolver(catalog, options);\n}\n\n/** Resolve a model string; returns catalog record only (no resolution metadata). */\nexport function resolveModel(\n input: string,\n models: Map<string, AiModelRecord>,\n aliasRegistry?: AliasRegistry,\n provider?: string,\n): ResolvedModel | null {\n const resolver = new ModelNameResolver(models, { aliasRegistry });\n const result = resolver.resolve({ model: input, provider });\n if (!result.found || !result.record) return null;\n return {\n catalogModel: result.record,\n matchedAlias: result.modelId,\n routedViaOpenRouter: result.routedViaOpenRouter,\n };\n}\n\nexport function isRoutedViaOpenRouter(\n provider: string | undefined,\n model: AiModelRecord,\n matchedKey: string,\n): boolean {\n if (provider === \"openrouter\") return true;\n if (provider && provider !== \"openrouter\") return false;\n return model.modelId.includes(\"/\") && matchedKey.includes(\"/\");\n}\n\nexport type {\n ModelResolutionInput,\n ModelResolutionResult,\n ModelResolutionSuccess,\n ModelResolverOptions,\n};\n"],"mappings":";;;;;;;;;;;AAgBA,SAAS,kBAAkB,QAAyC;AAClE,QAAM,UAAkC,EAAE,QAAQ,mBAAmB;AACrE,MAAI,QAAQ,KAAK,EAAG,SAAQ,gBAAgB,UAAU,OAAO,KAAK,CAAC;AACnE,SAAO;AACT;AAEA,SAAS,eAAe,SAAiB,OAAuC;AAC9E,QAAM,MAAM,IAAI,IAAI,GAAG,QAAQ,QAAQ,OAAO,EAAE,CAAC,SAAS;AAC1D,QAAM,IAAI,EAAE,mBAAmB,OAAO,GAAG,MAAM;AAC/C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,CAAC,GAAG;AAC5C,QAAI,UAAU,UAAa,UAAU,GAAI,KAAI,aAAa,IAAI,KAAK,KAAK;AAAA,EAC1E;AACA,SAAO,IAAI,SAAS;AACtB;AAEO,IAAM,yBAAN,MAA6B;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,UAAyC,CAAC,GAAG;AACvD,SAAK,SAAS,QAAQ;AACtB,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,QAAQ,QAAQ,SAAS,EAAE,mBAAmB,MAAM;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAwC;AAC5C,UAAM,MAAM,eAAe,KAAK,SAAS,KAAK,KAAK;AACnD,QAAI;AAEJ,QAAI;AACF,iBAAW,MAAM,MAAM,KAAK,EAAE,SAAS,kBAAkB,KAAK,MAAM,EAAE,CAAC;AAAA,IACzE,SAAS,OAAO;AACd,YAAM,IAAI,UAAU,kCAAkC,0CAA0C,GAAG,IAAI,KAAK;AAAA,IAC9G;AAEA,QAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtD,YAAM,IAAI;AAAA,QACR;AAAA,QACA,KAAK,SACD,mDACA;AAAA,MACN;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACjD,YAAM,IAAI;AAAA,QACR;AAAA,QACA,mCAAmC,SAAS,MAAM,MAAM,KAAK,MAAM,GAAG,GAAG,CAAC;AAAA,MAC5E;AAAA,IACF;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,UAAM,YAAW,oBAAI,KAAK,GAAE,YAAY;AACxC,YAAQ,KAAK,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,yBAAyB,KAAK,QAAQ,CAAC;AAAA,EAC/E;AAAA;AAAA,EAGA,eAAuB;AACrB,WAAO,eAAe,KAAK,SAAS,KAAK,KAAK;AAAA,EAChD;AACF;;;AC3DO,SAAS,wBACd,SACA,SACmB;AACnB,SAAO,IAAI,kBAAkB,SAAS,OAAO;AAC/C;AAGO,SAAS,aACd,OACA,QACA,eACA,UACsB;AACtB,QAAM,WAAW,IAAI,kBAAkB,QAAQ,EAAE,cAAc,CAAC;AAChE,QAAM,SAAS,SAAS,QAAQ,EAAE,OAAO,OAAO,SAAS,CAAC;AAC1D,MAAI,CAAC,OAAO,SAAS,CAAC,OAAO,OAAQ,QAAO;AAC5C,SAAO;AAAA,IACL,cAAc,OAAO;AAAA,IACrB,cAAc,OAAO;AAAA,IACrB,qBAAqB,OAAO;AAAA,EAC9B;AACF;AAEO,SAAS,sBACd,UACA,OACA,YACS;AACT,MAAI,aAAa,aAAc,QAAO;AACtC,MAAI,YAAY,aAAa,aAAc,QAAO;AAClD,SAAO,MAAM,QAAQ,SAAS,GAAG,KAAK,WAAW,SAAS,GAAG;AAC/D;","names":[]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AiModelsCatalogClient,
|
|
3
|
+
DEFAULT_DIRECT_CATALOG_URL,
|
|
4
|
+
DEFAULT_OPENROUTER_CATALOG_URL,
|
|
5
|
+
loadCatalogSourcesCached
|
|
6
|
+
} from "./chunk-OPN6BGNH.js";
|
|
7
|
+
|
|
8
|
+
// src/catalog/catalogMaintenance.ts
|
|
9
|
+
async function refreshAiModelsCatalog(options = {}) {
|
|
10
|
+
const client = new AiModelsCatalogClient(options);
|
|
11
|
+
await client.refresh();
|
|
12
|
+
const loaded = await loadCatalogSourcesCached(options, {
|
|
13
|
+
cacheKey: options.cacheKey,
|
|
14
|
+
ttlMs: options.cacheTtlMs,
|
|
15
|
+
forceRefresh: false
|
|
16
|
+
});
|
|
17
|
+
return {
|
|
18
|
+
ok: true,
|
|
19
|
+
directCount: loaded.meta.directCount,
|
|
20
|
+
openRouterCount: loaded.meta.openRouterCount,
|
|
21
|
+
directSource: loaded.meta.directSource,
|
|
22
|
+
openRouterSource: loaded.meta.openRouterSource
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
async function verifyAiModelsCatalog(options = {}) {
|
|
26
|
+
const loaded = await loadCatalogSourcesCached(options, {
|
|
27
|
+
cacheKey: options.cacheKey,
|
|
28
|
+
ttlMs: options.cacheTtlMs,
|
|
29
|
+
forceRefresh: options.forceRefresh ?? options.bundledOnly === true
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
ok: loaded.direct.size > 0 && loaded.openrouter.size > 0,
|
|
33
|
+
directCount: loaded.meta.directCount,
|
|
34
|
+
openRouterCount: loaded.meta.openRouterCount,
|
|
35
|
+
directSource: loaded.meta.directSource,
|
|
36
|
+
openRouterSource: loaded.meta.openRouterSource,
|
|
37
|
+
directUrl: options.directCatalogUrl ?? DEFAULT_DIRECT_CATALOG_URL,
|
|
38
|
+
openRouterUrl: options.openRouterCatalogUrl ?? DEFAULT_OPENROUTER_CATALOG_URL
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
refreshAiModelsCatalog,
|
|
44
|
+
verifyAiModelsCatalog
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=chunk-AB5GNXJ4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/catalog/catalogMaintenance.ts"],"sourcesContent":["import {\n DEFAULT_DIRECT_CATALOG_URL,\n DEFAULT_OPENROUTER_CATALOG_URL,\n type LoadCatalogOptions,\n} from \"./loadCatalogSources.js\";\nimport { loadCatalogSourcesCached } from \"./catalogLoadCache.js\";\nimport { AiModelsCatalogClient } from \"./AiModelsCatalogClient.js\";\n\nexport type CatalogRefreshOptions = LoadCatalogOptions & {\n cacheKey?: string;\n cacheTtlMs?: number;\n};\n\nexport type CatalogRefreshResult = {\n ok: true;\n directCount: number;\n openRouterCount: number;\n directSource: \"remote\" | \"bundled\";\n openRouterSource: \"remote\" | \"bundled\";\n};\n\n/** Fetch remote catalogs and warm the in-memory cache (forces a network load). */\nexport async function refreshAiModelsCatalog(\n options: CatalogRefreshOptions = {},\n): Promise<CatalogRefreshResult> {\n const client = new AiModelsCatalogClient(options);\n await client.refresh();\n const loaded = await loadCatalogSourcesCached(options, {\n cacheKey: options.cacheKey,\n ttlMs: options.cacheTtlMs,\n forceRefresh: false,\n });\n return {\n ok: true,\n directCount: loaded.meta.directCount,\n openRouterCount: loaded.meta.openRouterCount,\n directSource: loaded.meta.directSource,\n openRouterSource: loaded.meta.openRouterSource,\n };\n}\n\nexport type CatalogVerifyOptions = LoadCatalogOptions & {\n cacheKey?: string;\n cacheTtlMs?: number;\n};\n\nexport type CatalogVerifyReport = {\n ok: boolean;\n directCount: number;\n openRouterCount: number;\n directSource: \"remote\" | \"bundled\";\n openRouterSource: \"remote\" | \"bundled\";\n directUrl: string;\n openRouterUrl: string;\n};\n\n/** Load and validate both catalogs (uses cache unless `forceRefresh`). */\nexport async function verifyAiModelsCatalog(\n options: CatalogVerifyOptions & { forceRefresh?: boolean } = {},\n): Promise<CatalogVerifyReport> {\n const loaded = await loadCatalogSourcesCached(options, {\n cacheKey: options.cacheKey,\n ttlMs: options.cacheTtlMs,\n forceRefresh: options.forceRefresh ?? options.bundledOnly === true,\n });\n return {\n ok: loaded.direct.size > 0 && loaded.openrouter.size > 0,\n directCount: loaded.meta.directCount,\n openRouterCount: loaded.meta.openRouterCount,\n directSource: loaded.meta.directSource,\n openRouterSource: loaded.meta.openRouterSource,\n directUrl: options.directCatalogUrl ?? DEFAULT_DIRECT_CATALOG_URL,\n openRouterUrl: options.openRouterCatalogUrl ?? DEFAULT_OPENROUTER_CATALOG_URL,\n };\n}\n"],"mappings":";;;;;;;;AAsBA,eAAsB,uBACpB,UAAiC,CAAC,GACH;AAC/B,QAAM,SAAS,IAAI,sBAAsB,OAAO;AAChD,QAAM,OAAO,QAAQ;AACrB,QAAM,SAAS,MAAM,yBAAyB,SAAS;AAAA,IACrD,UAAU,QAAQ;AAAA,IAClB,OAAO,QAAQ;AAAA,IACf,cAAc;AAAA,EAChB,CAAC;AACD,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,aAAa,OAAO,KAAK;AAAA,IACzB,iBAAiB,OAAO,KAAK;AAAA,IAC7B,cAAc,OAAO,KAAK;AAAA,IAC1B,kBAAkB,OAAO,KAAK;AAAA,EAChC;AACF;AAkBA,eAAsB,sBACpB,UAA6D,CAAC,GAChC;AAC9B,QAAM,SAAS,MAAM,yBAAyB,SAAS;AAAA,IACrD,UAAU,QAAQ;AAAA,IAClB,OAAO,QAAQ;AAAA,IACf,cAAc,QAAQ,gBAAgB,QAAQ,gBAAgB;AAAA,EAChE,CAAC;AACD,SAAO;AAAA,IACL,IAAI,OAAO,OAAO,OAAO,KAAK,OAAO,WAAW,OAAO;AAAA,IACvD,aAAa,OAAO,KAAK;AAAA,IACzB,iBAAiB,OAAO,KAAK;AAAA,IAC7B,cAAc,OAAO,KAAK;AAAA,IAC1B,kBAAkB,OAAO,KAAK;AAAA,IAC9B,WAAW,QAAQ,oBAAoB;AAAA,IACvC,eAAe,QAAQ,wBAAwB;AAAA,EACjD;AACF;","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
AliasFileWriteError,
|
|
5
5
|
AliasInvalidNameError,
|
|
6
6
|
AliasNotFoundError
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2PTCWPHV.js";
|
|
8
8
|
|
|
9
9
|
// src/aliases/AliasRegistry.ts
|
|
10
10
|
import fs from "fs";
|
|
@@ -237,4 +237,4 @@ export {
|
|
|
237
237
|
AliasRegistry,
|
|
238
238
|
AliasResolver
|
|
239
239
|
};
|
|
240
|
-
//# sourceMappingURL=chunk-
|
|
240
|
+
//# sourceMappingURL=chunk-ANVONYJF.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/aliases/AliasRegistry.ts","../src/aliases/AliasResolver.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport {\n AliasConflictError,\n AliasFileParseError,\n AliasFileWriteError,\n AliasInvalidNameError,\n AliasNotFoundError,\n} from \"../errors.js\";\nimport type { AliasEntry, AliasFileSchema } from \"./types.js\";\n\nconst ALIAS_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;\n\nconst aliasEntrySchema = z.object({\n modelId: z.string().min(1),\n provider: z.string().min(1),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n addedAt: z.string(),\n updatedAt: z.string(),\n});\n\nconst aliasFileSchema = z.object({\n $schema: z.string().optional(),\n version: z.literal(1),\n updatedAt: z.string(),\n aliases: z.record(aliasEntrySchema),\n});\n\nexport type AliasRegistryOptions = {\n aliasesPath?: string;\n};\n\nfunction defaultAliasesPath(): string {\n if (process.env.AI_TOOLS_ALIASES_PATH) {\n return path.resolve(process.env.AI_TOOLS_ALIASES_PATH);\n }\n return path.resolve(process.cwd(), \"ai-tools/aliases.json\");\n}\n\nfunction emptySchema(): AliasFileSchema {\n const now = new Date().toISOString();\n return {\n $schema: \"https://unpkg.com/@x12i/ai-tools/schemas/aliases.json\",\n version: 1,\n updatedAt: now,\n aliases: {},\n };\n}\n\nexport class AliasRegistry {\n private readonly aliasesPath: string;\n\n constructor(options: AliasRegistryOptions = {}) {\n this.aliasesPath = options.aliasesPath ?? defaultAliasesPath();\n }\n\n get path(): string {\n return this.aliasesPath;\n }\n\n exists(): boolean {\n return fs.existsSync(this.aliasesPath);\n }\n\n init(): void {\n if (this.exists()) return;\n fs.mkdirSync(path.dirname(this.aliasesPath), { recursive: true });\n this.writeFile(emptySchema());\n }\n\n load(): AliasFileSchema {\n if (!this.exists()) return emptySchema();\n\n let raw: string;\n try {\n raw = fs.readFileSync(this.aliasesPath, \"utf8\");\n } catch (cause) {\n throw new AliasFileParseError(this.aliasesPath, cause);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (cause) {\n throw new AliasFileParseError(this.aliasesPath, cause);\n }\n\n const result = aliasFileSchema.safeParse(parsed);\n if (!result.success) {\n throw new AliasFileParseError(this.aliasesPath, result.error);\n }\n\n return result.data;\n }\n\n get(aliasName: string): AliasEntry | null {\n const schema = this.load();\n return schema.aliases[aliasName] ?? null;\n }\n\n list(filter?: { tag?: string }): Array<{ name: string } & AliasEntry> {\n const schema = this.load();\n return Object.entries(schema.aliases)\n .filter(([, entry]) => !filter?.tag || (entry.tags ?? []).includes(filter.tag))\n .map(([name, entry]) => ({ name, ...entry }));\n }\n\n set(\n aliasName: string,\n entry: Omit<AliasEntry, \"addedAt\" | \"updatedAt\">,\n ): AliasEntry {\n if (!ALIAS_NAME_RE.test(aliasName)) {\n throw new AliasInvalidNameError(aliasName);\n }\n\n if (!this.exists()) this.init();\n\n const schema = this.load();\n const now = new Date().toISOString();\n const existing = schema.aliases[aliasName];\n\n const full: AliasEntry = {\n ...entry,\n addedAt: existing?.addedAt ?? now,\n updatedAt: now,\n };\n\n schema.aliases[aliasName] = full;\n schema.updatedAt = now;\n this.writeFile(schema);\n return full;\n }\n\n remove(aliasName: string): boolean {\n if (!this.exists()) return false;\n const schema = this.load();\n if (!schema.aliases[aliasName]) return false;\n delete schema.aliases[aliasName];\n schema.updatedAt = new Date().toISOString();\n this.writeFile(schema);\n return true;\n }\n\n rename(from: string, to: string, options?: { force?: boolean }): void {\n if (!ALIAS_NAME_RE.test(to)) {\n throw new AliasInvalidNameError(to);\n }\n\n const schema = this.load();\n const entry = schema.aliases[from];\n if (!entry) {\n throw new AliasNotFoundError(from);\n }\n if (schema.aliases[to] && !options?.force) {\n throw new AliasConflictError(to);\n }\n\n delete schema.aliases[from];\n entry.updatedAt = new Date().toISOString();\n schema.aliases[to] = entry;\n schema.updatedAt = entry.updatedAt;\n this.writeFile(schema);\n }\n\n private writeFile(schema: AliasFileSchema): void {\n const tmp = `${this.aliasesPath}.tmp`;\n try {\n fs.mkdirSync(path.dirname(this.aliasesPath), { recursive: true });\n fs.writeFileSync(tmp, JSON.stringify(schema, null, 2), \"utf8\");\n fs.renameSync(tmp, this.aliasesPath);\n } catch (cause) {\n throw new AliasFileWriteError(this.aliasesPath, cause);\n }\n }\n}\n","import { AliasNotFoundError } from \"../errors.js\";\nimport type { AiModelsCatalogClient } from \"../catalox/AiModelsCatalogClient.js\";\nimport type { AliasRegistry } from \"./AliasRegistry.js\";\nimport type { AliasValidationReport, ResolvedModelRef } from \"./types.js\";\n\nconst ALIAS_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;\n\nexport type AliasResolverOptions = {\n registry: AliasRegistry;\n catalogClient: AiModelsCatalogClient;\n};\n\nexport class AliasResolver {\n private readonly registry: AliasRegistry;\n private readonly catalogClient: AiModelsCatalogClient;\n\n constructor(options: AliasResolverOptions) {\n this.registry = options.registry;\n this.catalogClient = options.catalogClient;\n }\n\n async getModel(aliasName: string): Promise<ResolvedModelRef> {\n const entry = this.registry.get(aliasName);\n if (!entry) {\n throw new AliasNotFoundError(aliasName);\n }\n return this.resolveEntry(aliasName, entry);\n }\n\n async getModels(aliasNames: string[]): Promise<ResolvedModelRef[]> {\n const results: ResolvedModelRef[] = [];\n for (const name of aliasNames) {\n const entry = this.registry.get(name);\n if (!entry) {\n console.warn(`[ai-tools] Unknown alias \"${name}\" — skipped.`);\n continue;\n }\n results.push(await this.resolveEntry(name, entry));\n }\n return results;\n }\n\n async getAllResolved(): Promise<ResolvedModelRef[]> {\n const list = this.registry.list();\n return Promise.all(list.map(({ name, ...entry }) => this.resolveEntry(name, entry)));\n }\n\n async validate(): Promise<AliasValidationReport> {\n const list = this.registry.list();\n const entries: AliasValidationReport[\"entries\"] = [];\n let ok = 0;\n let unknown = 0;\n let broken = 0;\n\n for (const { name, modelId } of list) {\n if (!ALIAS_NAME_RE.test(name) || !modelId) {\n broken++;\n entries.push({\n name,\n status: \"broken\",\n modelId: modelId ?? \"\",\n issue: \"Invalid alias name or empty modelId\",\n });\n continue;\n }\n\n const ref = await this.resolveEntry(name, this.registry.get(name)!);\n if (ref.modelRecord) {\n ok++;\n entries.push({\n name,\n status: \"ok\",\n modelId: ref.modelId,\n resolvedName: ref.name,\n });\n } else {\n unknown++;\n entries.push({\n name,\n status: \"unknown\",\n modelId: ref.modelId,\n issue: \"Model not found in catalog\",\n });\n }\n }\n\n return {\n total: list.length,\n ok,\n unknown,\n broken,\n entries,\n };\n }\n\n private async resolveEntry(\n alias: string,\n entry: import(\"./types.js\").AliasEntry,\n ): Promise<ResolvedModelRef> {\n const result = await this.catalogClient.resolveModel({\n model: entry.modelId,\n provider: entry.provider,\n });\n\n return {\n alias,\n entry,\n modelRecord: result.found ? result.record : null,\n modelId: result.found ? result.modelId : entry.modelId,\n provider: entry.provider,\n name: result.record?.name ?? entry.modelId,\n };\n }\n}\n"],"mappings":"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","names":["ALIAS_NAME_RE"]}
|
|
1
|
+
{"version":3,"sources":["../src/aliases/AliasRegistry.ts","../src/aliases/AliasResolver.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport {\n AliasConflictError,\n AliasFileParseError,\n AliasFileWriteError,\n AliasInvalidNameError,\n AliasNotFoundError,\n} from \"../errors.js\";\nimport type { AliasEntry, AliasFileSchema } from \"./types.js\";\n\nconst ALIAS_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;\n\nconst aliasEntrySchema = z.object({\n modelId: z.string().min(1),\n provider: z.string().min(1),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n addedAt: z.string(),\n updatedAt: z.string(),\n});\n\nconst aliasFileSchema = z.object({\n $schema: z.string().optional(),\n version: z.literal(1),\n updatedAt: z.string(),\n aliases: z.record(aliasEntrySchema),\n});\n\nexport type AliasRegistryOptions = {\n aliasesPath?: string;\n};\n\nfunction defaultAliasesPath(): string {\n if (process.env.AI_TOOLS_ALIASES_PATH) {\n return path.resolve(process.env.AI_TOOLS_ALIASES_PATH);\n }\n return path.resolve(process.cwd(), \"ai-tools/aliases.json\");\n}\n\nfunction emptySchema(): AliasFileSchema {\n const now = new Date().toISOString();\n return {\n $schema: \"https://unpkg.com/@x12i/ai-tools/schemas/aliases.json\",\n version: 1,\n updatedAt: now,\n aliases: {},\n };\n}\n\nexport class AliasRegistry {\n private readonly aliasesPath: string;\n\n constructor(options: AliasRegistryOptions = {}) {\n this.aliasesPath = options.aliasesPath ?? defaultAliasesPath();\n }\n\n get path(): string {\n return this.aliasesPath;\n }\n\n exists(): boolean {\n return fs.existsSync(this.aliasesPath);\n }\n\n init(): void {\n if (this.exists()) return;\n fs.mkdirSync(path.dirname(this.aliasesPath), { recursive: true });\n this.writeFile(emptySchema());\n }\n\n load(): AliasFileSchema {\n if (!this.exists()) return emptySchema();\n\n let raw: string;\n try {\n raw = fs.readFileSync(this.aliasesPath, \"utf8\");\n } catch (cause) {\n throw new AliasFileParseError(this.aliasesPath, cause);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (cause) {\n throw new AliasFileParseError(this.aliasesPath, cause);\n }\n\n const result = aliasFileSchema.safeParse(parsed);\n if (!result.success) {\n throw new AliasFileParseError(this.aliasesPath, result.error);\n }\n\n return result.data;\n }\n\n get(aliasName: string): AliasEntry | null {\n const schema = this.load();\n return schema.aliases[aliasName] ?? null;\n }\n\n list(filter?: { tag?: string }): Array<{ name: string } & AliasEntry> {\n const schema = this.load();\n return Object.entries(schema.aliases)\n .filter(([, entry]) => !filter?.tag || (entry.tags ?? []).includes(filter.tag))\n .map(([name, entry]) => ({ name, ...entry }));\n }\n\n set(\n aliasName: string,\n entry: Omit<AliasEntry, \"addedAt\" | \"updatedAt\">,\n ): AliasEntry {\n if (!ALIAS_NAME_RE.test(aliasName)) {\n throw new AliasInvalidNameError(aliasName);\n }\n\n if (!this.exists()) this.init();\n\n const schema = this.load();\n const now = new Date().toISOString();\n const existing = schema.aliases[aliasName];\n\n const full: AliasEntry = {\n ...entry,\n addedAt: existing?.addedAt ?? now,\n updatedAt: now,\n };\n\n schema.aliases[aliasName] = full;\n schema.updatedAt = now;\n this.writeFile(schema);\n return full;\n }\n\n remove(aliasName: string): boolean {\n if (!this.exists()) return false;\n const schema = this.load();\n if (!schema.aliases[aliasName]) return false;\n delete schema.aliases[aliasName];\n schema.updatedAt = new Date().toISOString();\n this.writeFile(schema);\n return true;\n }\n\n rename(from: string, to: string, options?: { force?: boolean }): void {\n if (!ALIAS_NAME_RE.test(to)) {\n throw new AliasInvalidNameError(to);\n }\n\n const schema = this.load();\n const entry = schema.aliases[from];\n if (!entry) {\n throw new AliasNotFoundError(from);\n }\n if (schema.aliases[to] && !options?.force) {\n throw new AliasConflictError(to);\n }\n\n delete schema.aliases[from];\n entry.updatedAt = new Date().toISOString();\n schema.aliases[to] = entry;\n schema.updatedAt = entry.updatedAt;\n this.writeFile(schema);\n }\n\n private writeFile(schema: AliasFileSchema): void {\n const tmp = `${this.aliasesPath}.tmp`;\n try {\n fs.mkdirSync(path.dirname(this.aliasesPath), { recursive: true });\n fs.writeFileSync(tmp, JSON.stringify(schema, null, 2), \"utf8\");\n fs.renameSync(tmp, this.aliasesPath);\n } catch (cause) {\n throw new AliasFileWriteError(this.aliasesPath, cause);\n }\n }\n}\n","import { AliasNotFoundError } from \"../errors.js\";\nimport type { AiModelsCatalogClient } from \"../catalog/AiModelsCatalogClient.js\";\nimport type { AliasRegistry } from \"./AliasRegistry.js\";\nimport type { AliasValidationReport, ResolvedModelRef } from \"./types.js\";\n\nconst ALIAS_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;\n\nexport type AliasResolverOptions = {\n registry: AliasRegistry;\n catalogClient: AiModelsCatalogClient;\n};\n\nexport class AliasResolver {\n private readonly registry: AliasRegistry;\n private readonly catalogClient: AiModelsCatalogClient;\n\n constructor(options: AliasResolverOptions) {\n this.registry = options.registry;\n this.catalogClient = options.catalogClient;\n }\n\n async getModel(aliasName: string): Promise<ResolvedModelRef> {\n const entry = this.registry.get(aliasName);\n if (!entry) {\n throw new AliasNotFoundError(aliasName);\n }\n return this.resolveEntry(aliasName, entry);\n }\n\n async getModels(aliasNames: string[]): Promise<ResolvedModelRef[]> {\n const results: ResolvedModelRef[] = [];\n for (const name of aliasNames) {\n const entry = this.registry.get(name);\n if (!entry) {\n console.warn(`[ai-tools] Unknown alias \"${name}\" — skipped.`);\n continue;\n }\n results.push(await this.resolveEntry(name, entry));\n }\n return results;\n }\n\n async getAllResolved(): Promise<ResolvedModelRef[]> {\n const list = this.registry.list();\n return Promise.all(list.map(({ name, ...entry }) => this.resolveEntry(name, entry)));\n }\n\n async validate(): Promise<AliasValidationReport> {\n const list = this.registry.list();\n const entries: AliasValidationReport[\"entries\"] = [];\n let ok = 0;\n let unknown = 0;\n let broken = 0;\n\n for (const { name, modelId } of list) {\n if (!ALIAS_NAME_RE.test(name) || !modelId) {\n broken++;\n entries.push({\n name,\n status: \"broken\",\n modelId: modelId ?? \"\",\n issue: \"Invalid alias name or empty modelId\",\n });\n continue;\n }\n\n const ref = await this.resolveEntry(name, this.registry.get(name)!);\n if (ref.modelRecord) {\n ok++;\n entries.push({\n name,\n status: \"ok\",\n modelId: ref.modelId,\n resolvedName: ref.name,\n });\n } else {\n unknown++;\n entries.push({\n name,\n status: \"unknown\",\n modelId: ref.modelId,\n issue: \"Model not found in catalog\",\n });\n }\n }\n\n return {\n total: list.length,\n ok,\n unknown,\n broken,\n entries,\n };\n }\n\n private async resolveEntry(\n alias: string,\n entry: import(\"./types.js\").AliasEntry,\n ): Promise<ResolvedModelRef> {\n const result = await this.catalogClient.resolveModel({\n model: entry.modelId,\n provider: entry.provider,\n });\n\n return {\n alias,\n entry,\n modelRecord: result.found ? result.record : null,\n modelId: result.found ? result.modelId : entry.modelId,\n provider: entry.provider,\n name: result.record?.name ?? entry.modelId,\n };\n }\n}\n"],"mappings":"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","names":["ALIAS_NAME_RE"]}
|