@x12i/ai-tools 1.0.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +146 -204
  3. package/dist/AiModelsCatalogClient-B5FMI9gj.d.cts +58 -0
  4. package/dist/AiModelsCatalogClient-CPPNI6Ry.d.ts +58 -0
  5. package/dist/aliases/index.cjs +4 -3
  6. package/dist/aliases/index.cjs.map +1 -1
  7. package/dist/aliases/index.d.cts +3 -5
  8. package/dist/aliases/index.d.ts +3 -5
  9. package/dist/aliases/index.js +2 -2
  10. package/dist/catalog/index.cjs +18 -9
  11. package/dist/catalog/index.cjs.map +1 -1
  12. package/dist/catalog/index.d.cts +13 -100
  13. package/dist/catalog/index.d.ts +13 -100
  14. package/dist/catalog/index.js +31 -23
  15. package/dist/{chunk-AJEKEWWB.js → chunk-2PTCWPHV.js} +17 -3
  16. package/dist/chunk-2PTCWPHV.js.map +1 -0
  17. package/dist/chunk-56R4XA2S.js +1 -0
  18. package/dist/chunk-5GUKLOEK.cjs +1 -0
  19. package/dist/chunk-5GUKLOEK.cjs.map +1 -0
  20. package/dist/chunk-5XAAMBDO.cjs +1988 -0
  21. package/dist/chunk-5XAAMBDO.cjs.map +1 -0
  22. package/dist/chunk-6BQBKROR.js +95 -0
  23. package/dist/chunk-6BQBKROR.js.map +1 -0
  24. package/dist/chunk-AB5GNXJ4.js +46 -0
  25. package/dist/chunk-AB5GNXJ4.js.map +1 -0
  26. package/dist/{chunk-O2A6OVEH.js → chunk-ANVONYJF.js} +2 -2
  27. package/dist/{chunk-O2A6OVEH.js.map → chunk-ANVONYJF.js.map} +1 -1
  28. package/dist/chunk-B3V2EHRY.js +225 -0
  29. package/dist/chunk-B3V2EHRY.js.map +1 -0
  30. package/dist/{chunk-QWAX7VQO.cjs → chunk-BAHBDADJ.cjs} +11 -11
  31. package/dist/{chunk-QWAX7VQO.cjs.map → chunk-BAHBDADJ.cjs.map} +1 -1
  32. package/dist/{chunk-TF4L2NEC.cjs → chunk-DXZOL3VN.cjs} +62 -313
  33. package/dist/chunk-DXZOL3VN.cjs.map +1 -0
  34. package/dist/chunk-EDMCKHO6.cjs +225 -0
  35. package/dist/chunk-EDMCKHO6.cjs.map +1 -0
  36. package/dist/{chunk-DJ5SWJDY.js → chunk-EYHMQVAL.js} +48 -299
  37. package/dist/chunk-EYHMQVAL.js.map +1 -0
  38. package/dist/chunk-GS7T56RP.cjs +8 -0
  39. package/dist/chunk-GS7T56RP.cjs.map +1 -0
  40. package/dist/chunk-NF2SKQR7.cjs +973 -0
  41. package/dist/chunk-NF2SKQR7.cjs.map +1 -0
  42. package/dist/chunk-OPN6BGNH.js +1985 -0
  43. package/dist/chunk-OPN6BGNH.js.map +1 -0
  44. package/dist/{chunk-7Q742NI3.cjs → chunk-PADNCGZB.cjs} +17 -3
  45. package/dist/chunk-PADNCGZB.cjs.map +1 -0
  46. package/dist/chunk-PRCICORG.cjs +95 -0
  47. package/dist/chunk-PRCICORG.cjs.map +1 -0
  48. package/dist/{chunk-6QGDZTGH.js → chunk-SIH4GPV4.js} +4 -29
  49. package/dist/chunk-SIH4GPV4.js.map +1 -0
  50. package/dist/chunk-U2YDDUVP.js +970 -0
  51. package/dist/chunk-U2YDDUVP.js.map +1 -0
  52. package/dist/{chunk-4NAY6HRP.js → chunk-VJHLO2R3.js} +7 -58
  53. package/dist/chunk-VJHLO2R3.js.map +1 -0
  54. package/dist/chunk-XAWBTX3N.cjs +46 -0
  55. package/dist/chunk-XAWBTX3N.cjs.map +1 -0
  56. package/dist/{chunk-AV6OE2YQ.cjs → chunk-XOKUDUUI.cjs} +14 -39
  57. package/dist/chunk-XOKUDUUI.cjs.map +1 -0
  58. package/dist/chunk-YQDSN6R6.cjs +86 -0
  59. package/dist/chunk-YQDSN6R6.cjs.map +1 -0
  60. package/dist/cli/index.cjs +59 -201
  61. package/dist/cli/index.cjs.map +1 -1
  62. package/dist/cli/index.js +53 -198
  63. package/dist/cli/index.js.map +1 -1
  64. package/dist/cost/index.cjs +19 -3
  65. package/dist/cost/index.cjs.map +1 -1
  66. package/dist/cost/index.d.cts +10 -50
  67. package/dist/cost/index.d.ts +10 -50
  68. package/dist/cost/index.js +18 -3
  69. package/dist/index.cjs +24 -16
  70. package/dist/index.cjs.map +1 -1
  71. package/dist/index.d.cts +13 -13
  72. package/dist/index.d.ts +13 -13
  73. package/dist/index.js +44 -37
  74. package/dist/modelCache-BzRn6t_C.d.ts +113 -0
  75. package/dist/modelCache-CJftI-Ko.d.cts +113 -0
  76. package/dist/{modelNameResolver-DqFt7g6W.d.ts → modelNameResolver-5XkBMctP.d.ts} +2 -6
  77. package/dist/{modelNameResolver-D9V_GfUK.d.cts → modelNameResolver-C5CSTGFF.d.cts} +2 -6
  78. package/dist/models/index.cjs +9 -6
  79. package/dist/models/index.cjs.map +1 -1
  80. package/dist/models/index.d.cts +9 -31
  81. package/dist/models/index.d.ts +9 -31
  82. package/dist/models/index.js +9 -7
  83. package/dist/resolveUsageModel-BFwf80Hz.d.ts +140 -0
  84. package/dist/resolveUsageModel-C_YmGR1M.d.cts +140 -0
  85. package/dist/sync/index.cjs +7 -9
  86. package/dist/sync/index.cjs.map +1 -1
  87. package/dist/sync/index.d.cts +3 -8
  88. package/dist/sync/index.d.ts +3 -8
  89. package/dist/sync/index.js +8 -11
  90. package/dist/toolbox/index.cjs +1 -0
  91. package/dist/toolbox/index.cjs.map +1 -1
  92. package/dist/types-BrzJWsTU.d.cts +277 -0
  93. package/dist/types-BrzJWsTU.d.ts +277 -0
  94. package/package.json +9 -20
  95. package/src/data/models-catalog.json +670 -0
  96. package/src/data/openrouter-models-catalog.json +857 -0
  97. package/dist/AiModelsCatalogClient-4RF5BCDL.cjs +0 -9
  98. package/dist/AiModelsCatalogClient-4RF5BCDL.cjs.map +0 -1
  99. package/dist/AiModelsCatalogClient-CNeqFiFs.d.cts +0 -30
  100. package/dist/AiModelsCatalogClient-NUF3CBLW.js +0 -9
  101. package/dist/AiModelsCatalogClient-nwFoEaqL.d.ts +0 -30
  102. package/dist/catalox/index.cjs +0 -21
  103. package/dist/catalox/index.cjs.map +0 -1
  104. package/dist/catalox/index.d.cts +0 -11
  105. package/dist/catalox/index.d.ts +0 -11
  106. package/dist/catalox/index.js +0 -21
  107. package/dist/catalox/index.js.map +0 -1
  108. package/dist/chunk-4NAY6HRP.js.map +0 -1
  109. package/dist/chunk-6QGDZTGH.js.map +0 -1
  110. package/dist/chunk-7Q742NI3.cjs.map +0 -1
  111. package/dist/chunk-AJEKEWWB.js.map +0 -1
  112. package/dist/chunk-AV6OE2YQ.cjs.map +0 -1
  113. package/dist/chunk-C3H7RTFR.cjs +0 -1
  114. package/dist/chunk-C3H7RTFR.cjs.map +0 -1
  115. package/dist/chunk-DJ5SWJDY.js.map +0 -1
  116. package/dist/chunk-DKHGWHXP.cjs +0 -169
  117. package/dist/chunk-DKHGWHXP.cjs.map +0 -1
  118. package/dist/chunk-F2F4UEFD.cjs +0 -75
  119. package/dist/chunk-F2F4UEFD.cjs.map +0 -1
  120. package/dist/chunk-FGP3QXWL.cjs +0 -163
  121. package/dist/chunk-FGP3QXWL.cjs.map +0 -1
  122. package/dist/chunk-G2G4KSC5.js +0 -30
  123. package/dist/chunk-G2G4KSC5.js.map +0 -1
  124. package/dist/chunk-HN6UAQAE.cjs +0 -83
  125. package/dist/chunk-HN6UAQAE.cjs.map +0 -1
  126. package/dist/chunk-HS74X2OJ.cjs +0 -172
  127. package/dist/chunk-HS74X2OJ.cjs.map +0 -1
  128. package/dist/chunk-HYGXZY25.js +0 -163
  129. package/dist/chunk-HYGXZY25.js.map +0 -1
  130. package/dist/chunk-KQOALKKX.js +0 -75
  131. package/dist/chunk-KQOALKKX.js.map +0 -1
  132. package/dist/chunk-LYOU7CA2.cjs +0 -30
  133. package/dist/chunk-LYOU7CA2.cjs.map +0 -1
  134. package/dist/chunk-M5TMA73F.js +0 -1
  135. package/dist/chunk-M5TMA73F.js.map +0 -1
  136. package/dist/chunk-MX3AMQFC.js +0 -172
  137. package/dist/chunk-MX3AMQFC.js.map +0 -1
  138. package/dist/chunk-QCRLKVB3.cjs +0 -137
  139. package/dist/chunk-QCRLKVB3.cjs.map +0 -1
  140. package/dist/chunk-TF4L2NEC.cjs.map +0 -1
  141. package/dist/chunk-VRFVF5RH.js +0 -169
  142. package/dist/chunk-VRFVF5RH.js.map +0 -1
  143. package/dist/chunk-YHO57D2V.js +0 -83
  144. package/dist/chunk-YHO57D2V.js.map +0 -1
  145. package/dist/syncAiModelsCatalog-CnXRLm2c.d.cts +0 -32
  146. package/dist/syncAiModelsCatalog-DpkN_w7S.d.ts +0 -32
  147. package/dist/types-BYXnCvKx.d.cts +0 -137
  148. package/dist/types-BYXnCvKx.d.ts +0 -137
  149. package/dist/types-CX6QFNNy.d.cts +0 -144
  150. package/dist/types-CuiPDcVs.d.ts +0 -144
  151. package/dist/upsertAiModelRecord-C831wOIF.d.ts +0 -35
  152. package/dist/upsertAiModelRecord-CjY-sny0.d.cts +0 -35
  153. /package/dist/{AiModelsCatalogClient-NUF3CBLW.js.map → chunk-56R4XA2S.js.map} +0 -0
@@ -0,0 +1,1988 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;
2
+
3
+
4
+ var _chunkDXZOL3VNcjs = require('./chunk-DXZOL3VN.cjs');
5
+
6
+
7
+
8
+ var _chunkEDMCKHO6cjs = require('./chunk-EDMCKHO6.cjs');
9
+
10
+
11
+ var _chunkGS7T56RPcjs = require('./chunk-GS7T56RP.cjs');
12
+
13
+ // src/cache/modelCache.ts
14
+ var _nxcache = require('nx-cache');
15
+ var cache = _nxcache.createNxCache.call(void 0, );
16
+ var DEFAULT_CATALOG_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
17
+ function resolveCatalogCacheTtlMs(override) {
18
+ if (override !== void 0) return override;
19
+ const raw = process.env.AI_TOOLS_CACHE_TTL_MS;
20
+ if (!raw) return DEFAULT_CATALOG_CACHE_TTL_MS;
21
+ const n = Number.parseInt(raw, 10);
22
+ return Number.isFinite(n) && n > 0 ? n : DEFAULT_CATALOG_CACHE_TTL_MS;
23
+ }
24
+ function writeCachedModels(scopeKey, models, ttlMs = DEFAULT_CATALOG_CACHE_TTL_MS) {
25
+ cache.write("ai-models", models, {
26
+ scope: { appId: scopeKey },
27
+ ttlMs,
28
+ metadata: { cachedAt: (/* @__PURE__ */ new Date()).toISOString(), count: models.size }
29
+ });
30
+ }
31
+
32
+ // src/catalog/catalogSources.ts
33
+ var DEFAULT_DIRECT_CATALOG_URL = "https://open-assets.x12i.com/models-catalog.json";
34
+ var DEFAULT_OPENROUTER_CATALOG_URL = "https://open-assets.x12i.com/openrouter-models-catalog.json";
35
+
36
+ // src/catalog/normalizeX12iCatalogModel.ts
37
+ var TOKENS_PER_UNIT = 1e6;
38
+ function usdPerToken(perMillion) {
39
+ if (perMillion == null || !Number.isFinite(perMillion)) return 0;
40
+ return perMillion / TOKENS_PER_UNIT;
41
+ }
42
+ function firstRate(raw, ...keys) {
43
+ for (const key of keys) {
44
+ const v = raw[key];
45
+ if (typeof v === "number" && Number.isFinite(v)) return v;
46
+ }
47
+ return void 0;
48
+ }
49
+ function canonicalCatalogModelId(provider, modelId) {
50
+ const m = _chunkEDMCKHO6cjs.normalizeString.call(void 0, modelId);
51
+ if (m.includes("/")) return m;
52
+ const p = _nullishCoalesce(_chunkEDMCKHO6cjs.normalizeProvider.call(void 0, provider), () => ( _chunkEDMCKHO6cjs.normalizeString.call(void 0, provider)));
53
+ return `${p}/${m}`;
54
+ }
55
+ function mapStatus(status) {
56
+ if (!status) return "active";
57
+ const s = status.toLowerCase();
58
+ if (s === "deprecated" || s === "legacy") return "deprecated";
59
+ if (s === "active" || s === "preview" || s === "announced") return "active";
60
+ return "unknown";
61
+ }
62
+ function mapModalities(modalities) {
63
+ if (Array.isArray(modalities)) {
64
+ return {
65
+ input: modalities,
66
+ output: modalities.includes("text") ? ["text"] : modalities.slice(0, 1),
67
+ modality: modalities.join("+")
68
+ };
69
+ }
70
+ if (modalities && typeof modalities === "object") {
71
+ const input = _nullishCoalesce(modalities.input, () => ( ["text"]));
72
+ const output = _nullishCoalesce(modalities.output, () => ( ["text"]));
73
+ return { input, output, modality: `${input.join("+")}->${output.join("+")}` };
74
+ }
75
+ return { input: ["text"], output: ["text"], modality: "text->text" };
76
+ }
77
+ function pricingToOpenRouterApi(raw, perMillion = true) {
78
+ const scale = perMillion ? (n) => (_nullishCoalesce(n, () => ( 0))) / TOKENS_PER_UNIT : (n) => _nullishCoalesce(n, () => ( 0));
79
+ return {
80
+ prompt: String(scale(firstRate(raw, "input", "textInput"))),
81
+ completion: String(scale(firstRate(raw, "output", "textOutput"))),
82
+ request: "0",
83
+ image: String(scale(firstRate(raw, "imageInput"))),
84
+ input_cache_read: raw.cachedInput != null ? String(scale(raw.cachedInput)) : void 0,
85
+ input_cache_write: raw.cacheWrite != null ? String(scale(raw.cacheWrite)) : void 0,
86
+ internal_reasoning: raw.internalReasoning != null ? String(scale(raw.internalReasoning)) : void 0,
87
+ web_search: raw.webSearchPerRequest != null ? String(raw.webSearchPerRequest) : void 0
88
+ };
89
+ }
90
+ function pricingFromX12i(raw, pricedAt, source) {
91
+ return {
92
+ promptUsdPerToken: usdPerToken(firstRate(raw, "input", "textInput")),
93
+ completionUsdPerToken: usdPerToken(firstRate(raw, "output", "textOutput")),
94
+ imageUsdPerUnit: usdPerToken(firstRate(raw, "imageInput")),
95
+ requestUsdPerRequest: usdPerToken(
96
+ typeof raw.webSearchPerRequest === "number" ? raw.webSearchPerRequest * 1e3 : 0
97
+ ),
98
+ cacheReadUsdPerToken: usdPerToken(
99
+ firstRate(raw, "cachedInput", "cacheHit")
100
+ ),
101
+ cacheWriteUsdPerToken: usdPerToken(
102
+ firstRate(raw, "cacheWrite", "cacheWrite5m", "cacheWrite1h")
103
+ ),
104
+ reasoningUsdPerToken: usdPerToken(raw.internalReasoning),
105
+ webSearchUsdPerRequest: typeof raw.webSearchPerRequest === "number" ? raw.webSearchPerRequest : void 0,
106
+ pricedAt,
107
+ source
108
+ };
109
+ }
110
+ function stubOpenRouterApi(modelId, entry, modalities, pricing) {
111
+ return {
112
+ id: modelId,
113
+ canonical_slug: _nullishCoalesce(entry.canonicalSlug, () => ( modelId)),
114
+ name: _nullishCoalesce(entry.displayName, () => ( modelId)),
115
+ created: 0,
116
+ description: _nullishCoalesce(entry.displayName, () => ( "")),
117
+ context_length: _nullishCoalesce(entry.contextWindow, () => ( 0)),
118
+ architecture: {
119
+ modality: modalities.modality,
120
+ input_modalities: modalities.input,
121
+ output_modalities: modalities.output,
122
+ tokenizer: "",
123
+ instruct_type: null
124
+ },
125
+ pricing,
126
+ top_provider: {
127
+ context_length: _nullishCoalesce(entry.contextWindow, () => ( 0)),
128
+ max_completion_tokens: _nullishCoalesce(entry.maxCompletionTokens, () => ( null)),
129
+ is_moderated: false
130
+ },
131
+ per_request_limits: null,
132
+ supported_parameters: _optionalChain([entry, 'access', _ => _.capabilities, 'optionalAccess', _2 => _2.toolCalling]) ? ["tools"] : [],
133
+ default_parameters: null
134
+ };
135
+ }
136
+ function normalizeX12iCatalogModel(entry, kind, verifiedAt) {
137
+ const pricingRaw = entry.pricing;
138
+ if (!pricingRaw) return null;
139
+ const inputRate = firstRate(pricingRaw, "input", "textInput", "inputBelow200k");
140
+ const outputRate = firstRate(pricingRaw, "output", "textOutput", "outputBelow200k");
141
+ if (inputRate == null && outputRate == null) return null;
142
+ const modelId = canonicalCatalogModelId(entry.provider, entry.modelId);
143
+ const providerId = kind === "openrouter" && modelId.includes("/") ? modelId.split("/")[0] : _nullishCoalesce(_chunkEDMCKHO6cjs.normalizeProvider.call(void 0, entry.provider), () => ( entry.provider));
144
+ const modalities = mapModalities(entry.modalities);
145
+ const pricedAt = verifiedAt || (/* @__PURE__ */ new Date()).toISOString();
146
+ const pricingSource = kind === "openrouter" ? "openrouter" : "direct";
147
+ const pricing = pricingFromX12i(pricingRaw, pricedAt, pricingSource);
148
+ const openRouterPricing = pricingToOpenRouterApi(pricingRaw, true);
149
+ const openRouter = stubOpenRouterApi(modelId, entry, modalities, openRouterPricing);
150
+ const supportedParameters = _nullishCoalesce(openRouter.supported_parameters, () => ( []));
151
+ const supportsReasoning = _optionalChain([entry, 'access', _3 => _3.capabilities, 'optionalAccess', _4 => _4.reasoning]) === true || _chunkDXZOL3VNcjs.computeSupportsReasoning.call(void 0, {
152
+ supportedParameters,
153
+ pricing,
154
+ openRouterPricing
155
+ });
156
+ const aliases = new Set(_nullishCoalesce(entry.aliases, () => ( [])));
157
+ aliases.add(entry.modelId);
158
+ if (entry.displayName) aliases.add(entry.displayName);
159
+ const slash = modelId.indexOf("/");
160
+ if (slash > 0) aliases.add(modelId.slice(slash + 1));
161
+ return {
162
+ modelId,
163
+ name: _nullishCoalesce(entry.displayName, () => ( modelId)),
164
+ providerId,
165
+ canonicalSlug: _nullishCoalesce(entry.canonicalSlug, () => ( modelId)),
166
+ status: mapStatus(entry.status),
167
+ description: _nullishCoalesce(entry.displayName, () => ( "")),
168
+ created: 0,
169
+ expirationDate: null,
170
+ contextLength: _nullishCoalesce(entry.contextWindow, () => ( 0)),
171
+ maxCompletionTokens: _nullishCoalesce(entry.maxCompletionTokens, () => ( null)),
172
+ isModerated: false,
173
+ modality: modalities.modality,
174
+ inputModalities: modalities.input,
175
+ outputModalities: modalities.output,
176
+ tokenizer: "",
177
+ instructType: null,
178
+ supportedParameters,
179
+ defaultParameters: null,
180
+ perRequestLimits: null,
181
+ pricing,
182
+ openRouterPricing,
183
+ architecture: openRouter.architecture,
184
+ topProvider: openRouter.top_provider,
185
+ openRouter,
186
+ aliases: [...aliases],
187
+ availableOnOpenRouter: kind === "openrouter",
188
+ supportsStreaming: modalities.output.includes("text"),
189
+ supportsTools: _optionalChain([entry, 'access', _5 => _5.capabilities, 'optionalAccess', _6 => _6.toolCalling]) === true,
190
+ supportsReasoning,
191
+ primaryOutputModality: _nullishCoalesce(modalities.output[0], () => ( "text")),
192
+ syncedAt: pricedAt,
193
+ syncSource: kind === "openrouter" ? "openrouter" : "manual"
194
+ };
195
+ }
196
+ function modelsFromX12iCatalogFile(file, kind) {
197
+ const map = /* @__PURE__ */ new Map();
198
+ const verifiedAt = _nullishCoalesce(file.verifiedAt, () => ( (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)));
199
+ for (const entry of file.models) {
200
+ const record = normalizeX12iCatalogModel(entry, kind, verifiedAt);
201
+ if (record) map.set(record.modelId, record);
202
+ }
203
+ return map;
204
+ }
205
+
206
+ // src/catalog/loadCatalogSources.ts
207
+ var _promises = require('fs/promises');
208
+ var _path = require('path');
209
+ var _url = require('url');
210
+
211
+ // src/data/models-catalog.json
212
+ var models_catalog_default = {
213
+ schema: "x12i.ai-models.catalog",
214
+ version: "0.1.0",
215
+ currency: "USD",
216
+ pricingUnit: "1M_tokens",
217
+ verifiedAt: "2026-05-27",
218
+ notes: [
219
+ "All token prices are listed per 1M tokens unless otherwise stated.",
220
+ "Null means pricing was not found or not public in the checked official source.",
221
+ "Some providers price audio, image, video, search, batch, cache, and regional processing separately.",
222
+ "This catalog intentionally does not include OpenRouter pricing."
223
+ ],
224
+ models: [
225
+ {
226
+ provider: "openai",
227
+ modelId: "gpt-5.5",
228
+ displayName: "GPT-5.5",
229
+ family: "gpt",
230
+ status: "active",
231
+ modalities: ["text", "vision"],
232
+ contextWindow: 1e6,
233
+ pricing: {
234
+ input: 5,
235
+ cachedInput: 0.5,
236
+ output: 30,
237
+ batchDiscount: "50%",
238
+ priorityMultiplier: 2.5,
239
+ dataResidencyMultiplier: 1.1
240
+ },
241
+ sourceUrl: "https://openai.com/api/pricing/"
242
+ },
243
+ {
244
+ provider: "openai",
245
+ modelId: "gpt-5.5-pro",
246
+ displayName: "GPT-5.5 Pro",
247
+ family: "gpt",
248
+ status: "announced",
249
+ modalities: ["text", "vision"],
250
+ contextWindow: 1e6,
251
+ pricing: {
252
+ input: 30,
253
+ output: 180
254
+ },
255
+ sourceUrl: "https://openai.com/index/introducing-gpt-5-5/"
256
+ },
257
+ {
258
+ provider: "openai",
259
+ modelId: "gpt-5.4",
260
+ displayName: "GPT-5.4",
261
+ family: "gpt",
262
+ status: "active",
263
+ modalities: ["text", "vision"],
264
+ pricing: {
265
+ input: 2.5,
266
+ cachedInput: 0.25,
267
+ output: 15,
268
+ batchDiscount: "50%",
269
+ dataResidencyMultiplier: 1.1
270
+ },
271
+ sourceUrl: "https://openai.com/api/pricing/"
272
+ },
273
+ {
274
+ provider: "openai",
275
+ modelId: "gpt-5.4-mini",
276
+ displayName: "GPT-5.4 Mini",
277
+ family: "gpt",
278
+ status: "active",
279
+ modalities: ["text", "vision"],
280
+ pricing: {
281
+ input: 0.75,
282
+ cachedInput: 0.075,
283
+ output: 4.5,
284
+ batchDiscount: "50%",
285
+ dataResidencyMultiplier: 1.1
286
+ },
287
+ sourceUrl: "https://openai.com/api/pricing/"
288
+ },
289
+ {
290
+ provider: "openai",
291
+ modelId: "gpt-realtime-2",
292
+ displayName: "GPT Realtime 2",
293
+ family: "gpt-realtime",
294
+ status: "active",
295
+ modalities: ["text", "audio", "image"],
296
+ pricing: {
297
+ textInput: 4,
298
+ textCachedInput: 0.4,
299
+ textOutput: 24,
300
+ audioInput: 32,
301
+ audioCachedInput: 0.4,
302
+ audioOutput: 64,
303
+ imageInput: 5,
304
+ imageCachedInput: 0.5
305
+ },
306
+ sourceUrl: "https://openai.com/api/pricing/"
307
+ },
308
+ {
309
+ provider: "openai",
310
+ modelId: "gpt-image-2",
311
+ displayName: "GPT Image 2",
312
+ family: "gpt-image",
313
+ status: "active",
314
+ modalities: ["image", "text"],
315
+ pricing: {
316
+ imageInput: 8,
317
+ imageCachedInput: 2,
318
+ imageOutput: 30,
319
+ textInput: 5,
320
+ textCachedInput: 1.25
321
+ },
322
+ sourceUrl: "https://openai.com/api/pricing/"
323
+ },
324
+ {
325
+ provider: "anthropic",
326
+ modelId: "claude-opus-4-7",
327
+ displayName: "Claude Opus 4.7",
328
+ family: "claude",
329
+ status: "active",
330
+ modalities: ["text", "vision"],
331
+ contextWindow: 1e6,
332
+ pricing: {
333
+ input: 5,
334
+ cacheWrite5m: 6.25,
335
+ cacheWrite1h: 10,
336
+ cacheHit: 0.5,
337
+ output: 25,
338
+ batchInput: 2.5,
339
+ batchOutput: 12.5,
340
+ fastModeInput: 30,
341
+ fastModeOutput: 150
342
+ },
343
+ sourceUrl: "https://platform.claude.com/docs/en/about-claude/pricing"
344
+ },
345
+ {
346
+ provider: "anthropic",
347
+ modelId: "claude-opus-4-6",
348
+ displayName: "Claude Opus 4.6",
349
+ family: "claude",
350
+ status: "active",
351
+ modalities: ["text", "vision"],
352
+ contextWindow: 1e6,
353
+ pricing: {
354
+ input: 5,
355
+ cacheWrite5m: 6.25,
356
+ cacheWrite1h: 10,
357
+ cacheHit: 0.5,
358
+ output: 25,
359
+ batchInput: 2.5,
360
+ batchOutput: 12.5,
361
+ fastModeInput: 30,
362
+ fastModeOutput: 150
363
+ },
364
+ sourceUrl: "https://platform.claude.com/docs/en/about-claude/pricing"
365
+ },
366
+ {
367
+ provider: "anthropic",
368
+ modelId: "claude-opus-4-5",
369
+ displayName: "Claude Opus 4.5",
370
+ family: "claude",
371
+ status: "active",
372
+ modalities: ["text", "vision"],
373
+ pricing: {
374
+ input: 5,
375
+ cacheWrite5m: 6.25,
376
+ cacheWrite1h: 10,
377
+ cacheHit: 0.5,
378
+ output: 25,
379
+ batchInput: 2.5,
380
+ batchOutput: 12.5
381
+ },
382
+ sourceUrl: "https://platform.claude.com/docs/en/about-claude/pricing"
383
+ },
384
+ {
385
+ provider: "anthropic",
386
+ modelId: "claude-sonnet-4-6",
387
+ displayName: "Claude Sonnet 4.6",
388
+ family: "claude",
389
+ status: "active",
390
+ modalities: ["text", "vision"],
391
+ contextWindow: 1e6,
392
+ pricing: {
393
+ input: 3,
394
+ cacheWrite5m: 3.75,
395
+ cacheWrite1h: 6,
396
+ cacheHit: 0.3,
397
+ output: 15,
398
+ batchInput: 1.5,
399
+ batchOutput: 7.5
400
+ },
401
+ sourceUrl: "https://platform.claude.com/docs/en/about-claude/pricing"
402
+ },
403
+ {
404
+ provider: "anthropic",
405
+ modelId: "claude-sonnet-4-5",
406
+ displayName: "Claude Sonnet 4.5",
407
+ family: "claude",
408
+ status: "active",
409
+ modalities: ["text", "vision"],
410
+ pricing: {
411
+ input: 3,
412
+ cacheWrite5m: 3.75,
413
+ cacheWrite1h: 6,
414
+ cacheHit: 0.3,
415
+ output: 15,
416
+ batchInput: 1.5,
417
+ batchOutput: 7.5
418
+ },
419
+ sourceUrl: "https://platform.claude.com/docs/en/about-claude/pricing"
420
+ },
421
+ {
422
+ provider: "anthropic",
423
+ modelId: "claude-haiku-4-5",
424
+ displayName: "Claude Haiku 4.5",
425
+ family: "claude",
426
+ status: "active",
427
+ modalities: ["text", "vision"],
428
+ pricing: {
429
+ input: 1,
430
+ cacheWrite5m: 1.25,
431
+ cacheWrite1h: 2,
432
+ cacheHit: 0.1,
433
+ output: 5,
434
+ batchInput: 0.5,
435
+ batchOutput: 2.5
436
+ },
437
+ sourceUrl: "https://platform.claude.com/docs/en/about-claude/pricing"
438
+ },
439
+ {
440
+ provider: "google",
441
+ modelId: "gemini-3.5-flash",
442
+ displayName: "Gemini 3.5 Flash",
443
+ family: "gemini",
444
+ status: "active",
445
+ modalities: ["text", "image", "video", "audio"],
446
+ pricing: {
447
+ input: 0.25,
448
+ audioInput: 0.5,
449
+ output: 1.5,
450
+ cachedInput: 0.025,
451
+ audioCachedInput: 0.05,
452
+ cacheStoragePerHour: 1,
453
+ batchInput: 0.125,
454
+ batchAudioInput: 0.25,
455
+ batchOutput: 0.75,
456
+ googleSearchAfterFreePer1kQueries: 14,
457
+ googleMapsAfterFreePer1kQueries: 14
458
+ },
459
+ sourceUrl: "https://ai.google.dev/gemini-api/docs/pricing"
460
+ },
461
+ {
462
+ provider: "google",
463
+ modelId: "gemini-3.1-pro-preview",
464
+ displayName: "Gemini 3.1 Pro Preview",
465
+ family: "gemini",
466
+ status: "preview",
467
+ modalities: ["text", "image", "video", "audio"],
468
+ pricing: {
469
+ input: 0.45,
470
+ audioInput: 0.9,
471
+ output: 2.7,
472
+ cachedInput: 0.045,
473
+ audioCachedInput: 0.09,
474
+ cacheStoragePerHour: 1.8,
475
+ googleSearchAfterFreePer1kQueries: 14,
476
+ googleMapsAfterFreePer1kQueries: 14
477
+ },
478
+ sourceUrl: "https://ai.google.dev/gemini-api/docs/pricing"
479
+ },
480
+ {
481
+ provider: "google",
482
+ modelId: "gemini-3.1-flash-lite-preview",
483
+ displayName: "Gemini 3.1 Flash-Lite Preview",
484
+ family: "gemini",
485
+ status: "preview",
486
+ modalities: ["text", "image", "video", "audio"],
487
+ pricing: {
488
+ input: 0.25,
489
+ audioInput: 0.5,
490
+ output: 1.5,
491
+ cachedInput: 0.025,
492
+ audioCachedInput: 0.05,
493
+ cacheStoragePerHour: 1,
494
+ batchInput: 0.125,
495
+ batchAudioInput: 0.25,
496
+ batchOutput: 0.75,
497
+ googleSearchAfterFreePer1kQueries: 14
498
+ },
499
+ sourceUrl: "https://ai.google.dev/gemini-api/docs/pricing"
500
+ },
501
+ {
502
+ provider: "google",
503
+ modelId: "gemini-2.5-flash",
504
+ displayName: "Gemini 2.5 Flash",
505
+ family: "gemini",
506
+ status: "active",
507
+ modalities: ["text", "image", "video", "audio"],
508
+ pricing: {
509
+ input: 0.1,
510
+ audioInput: 0.7,
511
+ output: 0.4,
512
+ cachedInput: 0.025,
513
+ audioCachedInput: 0.175,
514
+ cacheStoragePerHour: 1
515
+ },
516
+ sourceUrl: "https://ai.google.dev/gemini-api/docs/pricing"
517
+ },
518
+ {
519
+ provider: "google",
520
+ modelId: "gemini-2.5-flash-lite",
521
+ displayName: "Gemini 2.5 Flash-Lite",
522
+ family: "gemini",
523
+ status: "active",
524
+ modalities: ["text", "image", "video", "audio"],
525
+ pricing: {
526
+ input: 0.05,
527
+ audioInput: 0.35,
528
+ output: 0.2,
529
+ cachedInput: 0.025,
530
+ audioCachedInput: 0.175,
531
+ cacheStoragePerHour: 1
532
+ },
533
+ sourceUrl: "https://ai.google.dev/gemini-api/docs/pricing"
534
+ },
535
+ {
536
+ provider: "google",
537
+ modelId: "gemini-2.5-computer-use-preview-10-2025",
538
+ displayName: "Gemini 2.5 Computer Use Preview",
539
+ family: "gemini",
540
+ status: "preview",
541
+ modalities: ["text", "image", "browser-control"],
542
+ pricing: {
543
+ inputBelow200k: 1.25,
544
+ inputAbove200k: 2.5,
545
+ outputBelow200k: 10,
546
+ outputAbove200k: 15
547
+ },
548
+ sourceUrl: "https://ai.google.dev/gemini-api/docs/pricing"
549
+ },
550
+ {
551
+ provider: "google",
552
+ modelId: "gemini-embedding-2",
553
+ displayName: "Gemini Embedding 2",
554
+ family: "gemini-embedding",
555
+ status: "active",
556
+ modalities: ["text", "image", "video", "audio", "pdf"],
557
+ pricing: {
558
+ textInput: 0.2,
559
+ imageInput: 0.45,
560
+ audioInput: 6.5,
561
+ videoInput: 12
562
+ },
563
+ sourceUrl: "https://ai.google.dev/gemini-api/docs/pricing"
564
+ },
565
+ {
566
+ provider: "google",
567
+ modelId: "gemini-embedding-001",
568
+ displayName: "Gemini Embedding",
569
+ family: "gemini-embedding",
570
+ status: "active",
571
+ modalities: ["text"],
572
+ pricing: {
573
+ input: 0.15,
574
+ batchInput: 0.075
575
+ },
576
+ sourceUrl: "https://ai.google.dev/gemini-api/docs/pricing"
577
+ },
578
+ {
579
+ provider: "deepseek",
580
+ modelId: "deepseek-v4-flash",
581
+ displayName: "DeepSeek V4 Flash",
582
+ family: "deepseek-v4",
583
+ status: "active",
584
+ modalities: ["text"],
585
+ contextWindow: 1e6,
586
+ maxOutputTokens: 384e3,
587
+ pricing: {
588
+ inputCacheHit: 28e-4,
589
+ inputCacheMiss: 0.14,
590
+ output: 0.28
591
+ },
592
+ capabilities: {
593
+ thinkingMode: true,
594
+ jsonOutput: true,
595
+ toolCalls: true,
596
+ fimCompletion: true
597
+ },
598
+ sourceUrl: "https://api-docs.deepseek.com/quick_start/pricing"
599
+ },
600
+ {
601
+ provider: "deepseek",
602
+ modelId: "deepseek-v4-pro",
603
+ displayName: "DeepSeek V4 Pro",
604
+ family: "deepseek-v4",
605
+ status: "active",
606
+ modalities: ["text"],
607
+ contextWindow: 1e6,
608
+ maxOutputTokens: 384e3,
609
+ pricing: {
610
+ inputCacheHit: 3625e-6,
611
+ inputCacheMiss: 0.435,
612
+ output: 0.87,
613
+ note: "DeepSeek states the 75% reduction becomes official pricing after the promotion ends on 2026-05-31 15:59 UTC."
614
+ },
615
+ capabilities: {
616
+ thinkingMode: true,
617
+ jsonOutput: true,
618
+ toolCalls: true,
619
+ fimCompletion: true
620
+ },
621
+ sourceUrl: "https://api-docs.deepseek.com/quick_start/pricing"
622
+ },
623
+ {
624
+ provider: "xai",
625
+ modelId: "grok-4.3",
626
+ displayName: "Grok 4.3",
627
+ family: "grok",
628
+ status: "active",
629
+ modalities: ["text"],
630
+ contextWindow: 1e6,
631
+ pricing: {
632
+ input: 1.25,
633
+ cachedInput: 0.2,
634
+ output: 2.5
635
+ },
636
+ capabilities: {
637
+ reasoning: "configurable",
638
+ toolCalling: true
639
+ },
640
+ sourceUrl: "https://docs.x.ai/developers/pricing"
641
+ },
642
+ {
643
+ provider: "xai",
644
+ modelId: "grok-build-0.1",
645
+ displayName: "Grok Build 0.1",
646
+ family: "grok-build",
647
+ status: "active",
648
+ modalities: ["text", "code"],
649
+ contextWindow: 256e3,
650
+ pricing: {
651
+ input: 1,
652
+ cachedInput: 0.2,
653
+ output: 2
654
+ },
655
+ sourceUrl: "https://docs.x.ai/developers/pricing"
656
+ },
657
+ {
658
+ provider: "xai",
659
+ modelId: "grok-4.20-multi-agent-0309",
660
+ displayName: "Grok 4.20 Multi-Agent",
661
+ family: "grok",
662
+ status: "active",
663
+ modalities: ["text"],
664
+ contextWindow: 1e6,
665
+ pricing: {
666
+ input: 1.25,
667
+ cachedInput: 0.2,
668
+ output: 2.5
669
+ },
670
+ sourceUrl: "https://docs.x.ai/developers/pricing"
671
+ },
672
+ {
673
+ provider: "xai",
674
+ modelId: "grok-4.20-0309-reasoning",
675
+ displayName: "Grok 4.20 Reasoning",
676
+ family: "grok",
677
+ status: "active",
678
+ modalities: ["text"],
679
+ contextWindow: 1e6,
680
+ pricing: {
681
+ input: 1.25,
682
+ cachedInput: 0.2,
683
+ output: 2.5
684
+ },
685
+ sourceUrl: "https://docs.x.ai/developers/pricing"
686
+ },
687
+ {
688
+ provider: "xai",
689
+ modelId: "grok-4.20-0309-non-reasoning",
690
+ displayName: "Grok 4.20 Non-Reasoning",
691
+ family: "grok",
692
+ status: "active",
693
+ modalities: ["text"],
694
+ contextWindow: 1e6,
695
+ pricing: {
696
+ input: 1.25,
697
+ cachedInput: 0.2,
698
+ output: 2.5
699
+ },
700
+ sourceUrl: "https://docs.x.ai/developers/pricing"
701
+ },
702
+ {
703
+ provider: "cohere",
704
+ modelId: "command-a",
705
+ displayName: "Command A",
706
+ family: "command",
707
+ status: "active",
708
+ modalities: ["text"],
709
+ pricing: {
710
+ input: 1,
711
+ output: 2
712
+ },
713
+ sourceUrl: "https://cohere.com/pricing"
714
+ },
715
+ {
716
+ provider: "cohere",
717
+ modelId: "command",
718
+ displayName: "Command",
719
+ family: "command",
720
+ status: "legacy",
721
+ modalities: ["text"],
722
+ pricing: {
723
+ input: 1,
724
+ output: 2
725
+ },
726
+ sourceUrl: "https://cohere.com/pricing"
727
+ },
728
+ {
729
+ provider: "cohere",
730
+ modelId: "command-light",
731
+ displayName: "Command Light",
732
+ family: "command",
733
+ status: "legacy",
734
+ modalities: ["text"],
735
+ pricing: {
736
+ input: 0.3,
737
+ output: 0.6
738
+ },
739
+ sourceUrl: "https://cohere.com/pricing"
740
+ },
741
+ {
742
+ provider: "cohere",
743
+ modelId: "command-r-03-2024",
744
+ displayName: "Command R 03-2024",
745
+ family: "command-r",
746
+ status: "legacy",
747
+ modalities: ["text"],
748
+ pricing: {
749
+ input: 0.5,
750
+ output: 1.5
751
+ },
752
+ sourceUrl: "https://cohere.com/pricing"
753
+ },
754
+ {
755
+ provider: "cohere",
756
+ modelId: "command-r-plus-08-2024",
757
+ displayName: "Command R+ 08-2024",
758
+ family: "command-r",
759
+ status: "legacy",
760
+ modalities: ["text"],
761
+ pricing: {
762
+ input: 2.5,
763
+ output: 10
764
+ },
765
+ sourceUrl: "https://cohere.com/pricing"
766
+ },
767
+ {
768
+ provider: "perplexity",
769
+ modelId: "sonar-pro",
770
+ displayName: "Sonar Pro",
771
+ family: "sonar",
772
+ status: "active",
773
+ modalities: ["text", "search"],
774
+ pricing: {
775
+ input: 3,
776
+ output: 15,
777
+ searchRequestFeePer1k: {
778
+ fastLow: 6,
779
+ fastMedium: 10,
780
+ fastHigh: 14,
781
+ proLow: 14,
782
+ proMedium: 18,
783
+ proHigh: 22
784
+ }
785
+ },
786
+ sourceUrl: "https://docs.perplexity.ai/docs/getting-started/pricing"
787
+ },
788
+ {
789
+ provider: "groq",
790
+ modelId: "openai/gpt-oss-20b",
791
+ displayName: "GPT OSS 20B 128k",
792
+ family: "gpt-oss",
793
+ status: "active",
794
+ modalities: ["text"],
795
+ contextWindow: 128e3,
796
+ pricing: {
797
+ input: 0.075,
798
+ output: 0.3
799
+ },
800
+ sourceUrl: "https://groq.com/pricing"
801
+ },
802
+ {
803
+ provider: "groq",
804
+ modelId: "openai/gpt-oss-120b",
805
+ displayName: "GPT OSS 120B 128k",
806
+ family: "gpt-oss",
807
+ status: "active",
808
+ modalities: ["text"],
809
+ contextWindow: 128e3,
810
+ pricing: {
811
+ input: 0.15,
812
+ output: 0.6
813
+ },
814
+ sourceUrl: "https://groq.com/pricing"
815
+ },
816
+ {
817
+ provider: "groq",
818
+ modelId: "meta-llama/llama-4-scout-17b-16e-instruct",
819
+ displayName: "Llama 4 Scout 17Bx16E 128k",
820
+ family: "llama",
821
+ status: "active",
822
+ modalities: ["text"],
823
+ contextWindow: 128e3,
824
+ pricing: {
825
+ input: 0.11,
826
+ output: 0.34
827
+ },
828
+ sourceUrl: "https://groq.com/pricing"
829
+ },
830
+ {
831
+ provider: "groq",
832
+ modelId: "qwen/qwen3-32b",
833
+ displayName: "Qwen3 32B 131k",
834
+ family: "qwen",
835
+ status: "active",
836
+ modalities: ["text"],
837
+ contextWindow: 131e3,
838
+ pricing: {
839
+ input: 0.29,
840
+ output: 0.59
841
+ },
842
+ sourceUrl: "https://groq.com/pricing"
843
+ },
844
+ {
845
+ provider: "mistral",
846
+ modelId: "mistral-medium-3",
847
+ displayName: "Mistral Medium 3",
848
+ family: "mistral",
849
+ status: "active",
850
+ modalities: ["text", "vision", "tools"],
851
+ pricing: {
852
+ input: 0.4,
853
+ output: 2
854
+ },
855
+ sourceUrl: "https://mistral.ai/news/mistral-medium-3"
856
+ },
857
+ {
858
+ provider: "ai21",
859
+ modelId: "jamba-large-1.7",
860
+ displayName: "Jamba Large 1.7",
861
+ family: "jamba",
862
+ status: "needs_verification",
863
+ modalities: ["text"],
864
+ pricing: {
865
+ input: null,
866
+ output: null
867
+ },
868
+ 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.",
869
+ sourceUrl: "https://docs.ai21.com/docs/usage-cost"
870
+ }
871
+ ]
872
+ };
873
+
874
+ // src/data/openrouter-models-catalog.json
875
+ var openrouter_models_catalog_default = {
876
+ schema: "x12i.openrouter-models.catalog",
877
+ version: "0.1.0",
878
+ currency: "USD",
879
+ pricingUnit: "1M_tokens",
880
+ source: {
881
+ provider: "openrouter",
882
+ catalogUrl: "https://openrouter.ai/api/v1/models",
883
+ pricingUrl: "https://openrouter.ai/pricing",
884
+ verifiedAt: "2026-05-27",
885
+ normalization: "OpenRouter pricing fields are per-token decimal strings. Values below are normalized to USD per 1M tokens."
886
+ },
887
+ notes: [
888
+ "This catalog is OpenRouter-specific and should not be merged with direct-provider pricing.",
889
+ "Router models beginning with ~ are dynamic aliases that redirect to latest model families.",
890
+ "Models ending with :free are free OpenRouter variants and may have rate limits or availability limits.",
891
+ "webSearch is kept as a separate field because OpenRouter exposes it separately from token pricing.",
892
+ "This is a seed catalog. In production, generate the full file from https://openrouter.ai/api/v1/models."
893
+ ],
894
+ models: [
895
+ {
896
+ provider: "openrouter",
897
+ modelId: "qwen/qwen3.7-max",
898
+ canonicalSlug: "qwen/qwen3.7-max-20260520",
899
+ displayName: "Qwen: Qwen3.7 Max",
900
+ family: "qwen",
901
+ status: "active",
902
+ modalities: {
903
+ input: ["text"],
904
+ output: ["text"]
905
+ },
906
+ contextWindow: 1e6,
907
+ maxCompletionTokens: 65536,
908
+ pricing: {
909
+ input: 1.25,
910
+ output: 3.75,
911
+ cachedInput: 0.25,
912
+ cacheWrite: 1.5625
913
+ },
914
+ capabilities: {
915
+ reasoning: true,
916
+ toolCalling: true,
917
+ structuredOutputs: true
918
+ }
919
+ },
920
+ {
921
+ provider: "openrouter",
922
+ modelId: "x-ai/grok-build-0.1",
923
+ canonicalSlug: "x-ai/grok-build-0.1-20260520",
924
+ displayName: "xAI: Grok Build 0.1",
925
+ family: "grok",
926
+ status: "active",
927
+ modalities: {
928
+ input: ["text", "image"],
929
+ output: ["text"]
930
+ },
931
+ contextWindow: 256e3,
932
+ pricing: {
933
+ input: 1,
934
+ output: 2,
935
+ cachedInput: 0.2,
936
+ webSearchPerRequest: 5e-3
937
+ },
938
+ capabilities: {
939
+ reasoning: true,
940
+ toolCalling: true,
941
+ structuredOutputs: true
942
+ }
943
+ },
944
+ {
945
+ provider: "openrouter",
946
+ modelId: "google/gemini-3.5-flash",
947
+ canonicalSlug: "google/gemini-3.5-flash-20260519",
948
+ displayName: "Google: Gemini 3.5 Flash",
949
+ family: "gemini",
950
+ status: "active",
951
+ modalities: {
952
+ input: ["text", "image", "video", "file", "audio"],
953
+ output: ["text"]
954
+ },
955
+ contextWindow: 1048576,
956
+ maxCompletionTokens: 65536,
957
+ knowledgeCutoff: "2025-01-01",
958
+ pricing: {
959
+ input: 1.5,
960
+ output: 9,
961
+ imageInput: 1.5,
962
+ audioInput: 3,
963
+ cachedInput: 0.15,
964
+ cacheWrite: 0.08333333333333334,
965
+ internalReasoning: 9,
966
+ webSearchPerRequest: 0.014
967
+ },
968
+ capabilities: {
969
+ reasoning: true,
970
+ toolCalling: true,
971
+ structuredOutputs: true
972
+ }
973
+ },
974
+ {
975
+ provider: "openrouter",
976
+ modelId: "anthropic/claude-opus-4.7-fast",
977
+ canonicalSlug: "anthropic/claude-4.7-opus-fast-20260512",
978
+ displayName: "Anthropic: Claude Opus 4.7 Fast",
979
+ family: "claude",
980
+ status: "active",
981
+ modalities: {
982
+ input: ["text", "image", "file"],
983
+ output: ["text"]
984
+ },
985
+ contextWindow: 1e6,
986
+ maxCompletionTokens: 128e3,
987
+ pricing: {
988
+ input: 30,
989
+ output: 150,
990
+ cachedInput: 3,
991
+ cacheWrite: 37.5,
992
+ webSearchPerRequest: 0.01
993
+ },
994
+ capabilities: {
995
+ reasoning: true,
996
+ toolCalling: true,
997
+ structuredOutputs: true
998
+ }
999
+ },
1000
+ {
1001
+ provider: "openrouter",
1002
+ modelId: "perceptron/perceptron-mk1",
1003
+ canonicalSlug: "perceptron/perceptron-mk1-20260512",
1004
+ displayName: "Perceptron: Perceptron Mk1",
1005
+ family: "perceptron",
1006
+ status: "active",
1007
+ modalities: {
1008
+ input: ["text", "image", "video"],
1009
+ output: ["text"]
1010
+ },
1011
+ contextWindow: 32768,
1012
+ maxCompletionTokens: 8192,
1013
+ pricing: {
1014
+ input: 0.15,
1015
+ output: 1.5
1016
+ },
1017
+ capabilities: {
1018
+ reasoning: true,
1019
+ structuredOutputs: true
1020
+ }
1021
+ },
1022
+ {
1023
+ provider: "openrouter",
1024
+ modelId: "inclusionai/ring-2.6-1t",
1025
+ canonicalSlug: "inclusionai/ring-2.6-1t-20260508",
1026
+ displayName: "inclusionAI: Ring-2.6-1T",
1027
+ family: "ring",
1028
+ status: "active",
1029
+ modalities: {
1030
+ input: ["text"],
1031
+ output: ["text"]
1032
+ },
1033
+ contextWindow: 262144,
1034
+ maxCompletionTokens: 65536,
1035
+ pricing: {
1036
+ input: 0.075,
1037
+ output: 0.625,
1038
+ cachedInput: 0.015
1039
+ },
1040
+ capabilities: {
1041
+ reasoning: true,
1042
+ toolCalling: true,
1043
+ structuredOutputs: true
1044
+ }
1045
+ },
1046
+ {
1047
+ provider: "openrouter",
1048
+ modelId: "google/gemini-3.1-flash-lite",
1049
+ canonicalSlug: "google/gemini-3.1-flash-lite-20260507",
1050
+ displayName: "Google: Gemini 3.1 Flash Lite",
1051
+ family: "gemini",
1052
+ status: "active",
1053
+ modalities: {
1054
+ input: ["text", "image", "video", "file", "audio"],
1055
+ output: ["text"]
1056
+ },
1057
+ contextWindow: 1048576,
1058
+ maxCompletionTokens: 65536,
1059
+ pricing: {
1060
+ input: 0.25,
1061
+ output: 1.5,
1062
+ imageInput: 0.25,
1063
+ audioInput: 0.5,
1064
+ cachedInput: 0.025,
1065
+ cacheWrite: 0.08333333333333334,
1066
+ internalReasoning: 1.5,
1067
+ webSearchPerRequest: 0.014
1068
+ },
1069
+ capabilities: {
1070
+ reasoning: true,
1071
+ toolCalling: true,
1072
+ structuredOutputs: true
1073
+ }
1074
+ },
1075
+ {
1076
+ provider: "openrouter",
1077
+ modelId: "openai/gpt-chat-latest",
1078
+ canonicalSlug: "openai/gpt-chat-latest-20260505",
1079
+ displayName: "OpenAI: GPT Chat Latest",
1080
+ family: "gpt",
1081
+ status: "active",
1082
+ modalities: {
1083
+ input: ["text", "image", "file"],
1084
+ output: ["text"]
1085
+ },
1086
+ contextWindow: 4e5,
1087
+ maxCompletionTokens: 128e3,
1088
+ pricing: {
1089
+ input: 5,
1090
+ output: 30,
1091
+ cachedInput: 0.5,
1092
+ webSearchPerRequest: 0.01
1093
+ },
1094
+ capabilities: {
1095
+ toolCalling: true,
1096
+ structuredOutputs: true
1097
+ }
1098
+ },
1099
+ {
1100
+ provider: "openrouter",
1101
+ modelId: "x-ai/grok-4.3",
1102
+ canonicalSlug: "x-ai/grok-4.3-20260430",
1103
+ displayName: "xAI: Grok 4.3",
1104
+ family: "grok",
1105
+ status: "active",
1106
+ modalities: {
1107
+ input: ["text", "image"],
1108
+ output: ["text"]
1109
+ },
1110
+ contextWindow: 1e6,
1111
+ pricing: {
1112
+ input: 1.25,
1113
+ output: 2.5,
1114
+ cachedInput: 0.2,
1115
+ webSearchPerRequest: 5e-3
1116
+ },
1117
+ capabilities: {
1118
+ reasoning: true,
1119
+ toolCalling: true,
1120
+ structuredOutputs: true
1121
+ }
1122
+ },
1123
+ {
1124
+ provider: "openrouter",
1125
+ modelId: "ibm-granite/granite-4.1-8b",
1126
+ canonicalSlug: "ibm-granite/granite-4.1-8b-20260429",
1127
+ displayName: "IBM: Granite 4.1 8B",
1128
+ family: "granite",
1129
+ status: "active",
1130
+ modalities: {
1131
+ input: ["text"],
1132
+ output: ["text"]
1133
+ },
1134
+ contextWindow: 131072,
1135
+ maxCompletionTokens: 131072,
1136
+ pricing: {
1137
+ input: 0.05,
1138
+ output: 0.1,
1139
+ cachedInput: 0.05
1140
+ },
1141
+ capabilities: {
1142
+ toolCalling: true,
1143
+ structuredOutputs: true
1144
+ }
1145
+ },
1146
+ {
1147
+ provider: "openrouter",
1148
+ modelId: "mistralai/mistral-medium-3-5",
1149
+ canonicalSlug: "mistralai/mistral-medium-3.5-20260430",
1150
+ displayName: "Mistral: Mistral Medium 3.5",
1151
+ family: "mistral",
1152
+ status: "active",
1153
+ modalities: {
1154
+ input: ["text", "image", "file"],
1155
+ output: ["text"]
1156
+ },
1157
+ contextWindow: 262144,
1158
+ pricing: {
1159
+ input: 1.5,
1160
+ output: 7.5
1161
+ },
1162
+ capabilities: {
1163
+ reasoning: true,
1164
+ toolCalling: true,
1165
+ structuredOutputs: true
1166
+ }
1167
+ },
1168
+ {
1169
+ provider: "openrouter",
1170
+ modelId: "openrouter/owl-alpha",
1171
+ canonicalSlug: "openrouter/owl-alpha",
1172
+ displayName: "Owl Alpha",
1173
+ family: "owl",
1174
+ status: "active",
1175
+ modalities: {
1176
+ input: ["text"],
1177
+ output: ["text"]
1178
+ },
1179
+ contextWindow: 1048756,
1180
+ maxCompletionTokens: 262144,
1181
+ pricing: {
1182
+ input: 0,
1183
+ output: 0
1184
+ },
1185
+ capabilities: {
1186
+ toolCalling: true,
1187
+ structuredOutputs: true
1188
+ }
1189
+ },
1190
+ {
1191
+ provider: "openrouter",
1192
+ modelId: "~anthropic/claude-haiku-latest",
1193
+ canonicalSlug: "~anthropic/claude-haiku-latest",
1194
+ displayName: "Anthropic Claude Haiku Latest",
1195
+ family: "claude-router",
1196
+ status: "router",
1197
+ modalities: {
1198
+ input: ["text", "image", "file"],
1199
+ output: ["text"]
1200
+ },
1201
+ contextWindow: 2e5,
1202
+ maxCompletionTokens: 64e3,
1203
+ pricing: {
1204
+ input: 1,
1205
+ output: 5,
1206
+ cachedInput: 0.1,
1207
+ cacheWrite: 1.25,
1208
+ webSearchPerRequest: 0.01
1209
+ },
1210
+ capabilities: {
1211
+ reasoning: true,
1212
+ toolCalling: true,
1213
+ structuredOutputs: true
1214
+ }
1215
+ },
1216
+ {
1217
+ provider: "openrouter",
1218
+ modelId: "~openai/gpt-mini-latest",
1219
+ canonicalSlug: "~openai/gpt-mini-latest",
1220
+ displayName: "OpenAI GPT Mini Latest",
1221
+ family: "gpt-router",
1222
+ status: "router",
1223
+ modalities: {
1224
+ input: ["text", "image", "file"],
1225
+ output: ["text"]
1226
+ },
1227
+ contextWindow: 4e5,
1228
+ maxCompletionTokens: 128e3,
1229
+ knowledgeCutoff: "2025-08-31",
1230
+ pricing: {
1231
+ input: 0.75,
1232
+ output: 4.5,
1233
+ cachedInput: 0.075,
1234
+ webSearchPerRequest: 0.01
1235
+ },
1236
+ capabilities: {
1237
+ reasoning: true,
1238
+ toolCalling: true,
1239
+ structuredOutputs: true
1240
+ }
1241
+ },
1242
+ {
1243
+ provider: "openrouter",
1244
+ modelId: "~google/gemini-pro-latest",
1245
+ canonicalSlug: "~google/gemini-pro-latest",
1246
+ displayName: "Google Gemini Pro Latest",
1247
+ family: "gemini-router",
1248
+ status: "router",
1249
+ modalities: {
1250
+ input: ["text", "image", "file", "audio", "video"],
1251
+ output: ["text"]
1252
+ },
1253
+ contextWindow: 1048576,
1254
+ maxCompletionTokens: 65536,
1255
+ pricing: {
1256
+ input: 2,
1257
+ output: 12,
1258
+ imageInput: 2,
1259
+ audioInput: 2,
1260
+ cachedInput: 0.2,
1261
+ cacheWrite: 0.375,
1262
+ internalReasoning: 12,
1263
+ webSearchPerRequest: 0.014
1264
+ },
1265
+ capabilities: {
1266
+ reasoning: true,
1267
+ toolCalling: true,
1268
+ structuredOutputs: true
1269
+ }
1270
+ },
1271
+ {
1272
+ provider: "openrouter",
1273
+ modelId: "~moonshotai/kimi-latest",
1274
+ canonicalSlug: "~moonshotai/kimi-latest",
1275
+ displayName: "MoonshotAI Kimi Latest",
1276
+ family: "kimi-router",
1277
+ status: "router",
1278
+ modalities: {
1279
+ input: ["text", "image"],
1280
+ output: ["text"]
1281
+ },
1282
+ contextWindow: 262144,
1283
+ maxCompletionTokens: 262142,
1284
+ pricing: {
1285
+ input: 0.73,
1286
+ output: 3.49,
1287
+ cachedInput: 0.25
1288
+ },
1289
+ capabilities: {
1290
+ reasoning: true,
1291
+ toolCalling: true,
1292
+ structuredOutputs: true
1293
+ }
1294
+ },
1295
+ {
1296
+ provider: "openrouter",
1297
+ modelId: "~google/gemini-flash-latest",
1298
+ canonicalSlug: "~google/gemini-flash-latest",
1299
+ displayName: "Google Gemini Flash Latest",
1300
+ family: "gemini-router",
1301
+ status: "router",
1302
+ modalities: {
1303
+ input: ["text", "image", "video", "file", "audio"],
1304
+ output: ["text"]
1305
+ },
1306
+ contextWindow: 1048576,
1307
+ maxCompletionTokens: 65536,
1308
+ knowledgeCutoff: "2025-01-01",
1309
+ pricing: {
1310
+ input: 1.5,
1311
+ output: 9,
1312
+ imageInput: 1.5,
1313
+ audioInput: 3,
1314
+ cachedInput: 0.15,
1315
+ cacheWrite: 0.08333333333333334,
1316
+ internalReasoning: 9,
1317
+ webSearchPerRequest: 0.014
1318
+ },
1319
+ capabilities: {
1320
+ reasoning: true,
1321
+ toolCalling: true,
1322
+ structuredOutputs: true
1323
+ }
1324
+ },
1325
+ {
1326
+ provider: "openrouter",
1327
+ modelId: "~anthropic/claude-sonnet-latest",
1328
+ canonicalSlug: "~anthropic/claude-sonnet-latest",
1329
+ displayName: "Anthropic Claude Sonnet Latest",
1330
+ family: "claude-router",
1331
+ status: "router",
1332
+ modalities: {
1333
+ input: ["text", "image", "file"],
1334
+ output: ["text"]
1335
+ },
1336
+ contextWindow: 1e6,
1337
+ maxCompletionTokens: 128e3,
1338
+ pricing: {
1339
+ input: 3,
1340
+ output: 15,
1341
+ cachedInput: 0.3,
1342
+ cacheWrite: 3.75,
1343
+ webSearchPerRequest: 0.01
1344
+ },
1345
+ capabilities: {
1346
+ reasoning: true,
1347
+ toolCalling: true,
1348
+ structuredOutputs: true
1349
+ }
1350
+ },
1351
+ {
1352
+ provider: "openrouter",
1353
+ modelId: "~openai/gpt-latest",
1354
+ canonicalSlug: "~openai/gpt-latest",
1355
+ displayName: "OpenAI GPT Latest",
1356
+ family: "gpt-router",
1357
+ status: "router",
1358
+ modalities: {
1359
+ input: ["text", "image", "file"],
1360
+ output: ["text"]
1361
+ },
1362
+ contextWindow: 105e4,
1363
+ maxCompletionTokens: 128e3,
1364
+ knowledgeCutoff: "2025-12-01",
1365
+ pricing: {
1366
+ input: 5,
1367
+ output: 30,
1368
+ cachedInput: 0.5,
1369
+ webSearchPerRequest: 0.01
1370
+ },
1371
+ capabilities: {
1372
+ reasoning: true,
1373
+ toolCalling: true,
1374
+ structuredOutputs: true
1375
+ }
1376
+ },
1377
+ {
1378
+ provider: "openrouter",
1379
+ modelId: "qwen/qwen3.5-plus-20260420",
1380
+ canonicalSlug: "qwen/qwen3.5-plus-20260420",
1381
+ displayName: "Qwen: Qwen3.5 Plus 2026-04-20",
1382
+ family: "qwen",
1383
+ status: "active",
1384
+ modalities: {
1385
+ input: ["text", "image", "video"],
1386
+ output: ["text"]
1387
+ },
1388
+ contextWindow: 1e6,
1389
+ maxCompletionTokens: 65536,
1390
+ pricing: {
1391
+ input: 0.3,
1392
+ output: 1.8,
1393
+ cacheWrite: 0.375
1394
+ },
1395
+ capabilities: {
1396
+ reasoning: true,
1397
+ toolCalling: true,
1398
+ structuredOutputs: true
1399
+ }
1400
+ },
1401
+ {
1402
+ provider: "openrouter",
1403
+ modelId: "qwen/qwen3.6-flash",
1404
+ canonicalSlug: "qwen/qwen3.6-flash",
1405
+ displayName: "Qwen: Qwen3.6 Flash",
1406
+ family: "qwen",
1407
+ status: "active",
1408
+ modalities: {
1409
+ input: ["text", "image", "video"],
1410
+ output: ["text"]
1411
+ },
1412
+ contextWindow: 1e6,
1413
+ maxCompletionTokens: 65536,
1414
+ pricing: {
1415
+ input: 0.1875,
1416
+ output: 1.125,
1417
+ cacheWrite: 0.234375
1418
+ },
1419
+ capabilities: {
1420
+ reasoning: true,
1421
+ toolCalling: true,
1422
+ structuredOutputs: true
1423
+ }
1424
+ },
1425
+ {
1426
+ provider: "openrouter",
1427
+ modelId: "qwen/qwen3.6-35b-a3b",
1428
+ canonicalSlug: "qwen/qwen3.6-35b-a3b-20260415",
1429
+ displayName: "Qwen: Qwen3.6 35B A3B",
1430
+ family: "qwen",
1431
+ status: "active",
1432
+ modalities: {
1433
+ input: ["text", "image", "video"],
1434
+ output: ["text"]
1435
+ },
1436
+ contextWindow: 262144,
1437
+ maxCompletionTokens: 262140,
1438
+ pricing: {
1439
+ input: 0.14,
1440
+ output: 1
1441
+ },
1442
+ capabilities: {
1443
+ reasoning: true,
1444
+ toolCalling: true,
1445
+ structuredOutputs: true
1446
+ }
1447
+ },
1448
+ {
1449
+ provider: "openrouter",
1450
+ modelId: "qwen/qwen3.6-max-preview",
1451
+ canonicalSlug: "qwen/qwen3.6-max-preview-20260420",
1452
+ displayName: "Qwen: Qwen3.6 Max Preview",
1453
+ family: "qwen",
1454
+ status: "preview",
1455
+ modalities: {
1456
+ input: ["text"],
1457
+ output: ["text"]
1458
+ },
1459
+ contextWindow: 262144,
1460
+ maxCompletionTokens: 65536,
1461
+ pricing: {
1462
+ input: 1.04,
1463
+ output: 6.24,
1464
+ cacheWrite: 1.3
1465
+ },
1466
+ capabilities: {
1467
+ reasoning: true,
1468
+ toolCalling: true,
1469
+ structuredOutputs: true
1470
+ }
1471
+ },
1472
+ {
1473
+ provider: "openrouter",
1474
+ modelId: "qwen/qwen3.6-27b",
1475
+ canonicalSlug: "qwen/qwen3.6-27b-20260422",
1476
+ displayName: "Qwen: Qwen3.6 27B",
1477
+ family: "qwen",
1478
+ status: "active",
1479
+ modalities: {
1480
+ input: ["text", "image", "video"],
1481
+ output: ["text"]
1482
+ },
1483
+ contextWindow: 262144,
1484
+ maxCompletionTokens: 262140,
1485
+ pricing: {
1486
+ input: 0.29,
1487
+ output: 3.2
1488
+ },
1489
+ capabilities: {
1490
+ reasoning: true,
1491
+ toolCalling: true,
1492
+ structuredOutputs: true
1493
+ }
1494
+ },
1495
+ {
1496
+ provider: "openrouter",
1497
+ modelId: "openai/gpt-5.5-pro",
1498
+ canonicalSlug: "openai/gpt-5.5-pro-20260423",
1499
+ displayName: "OpenAI: GPT-5.5 Pro",
1500
+ family: "gpt",
1501
+ status: "active",
1502
+ modalities: {
1503
+ input: ["text", "image", "file"],
1504
+ output: ["text"]
1505
+ },
1506
+ contextWindow: 105e4,
1507
+ maxCompletionTokens: 128e3,
1508
+ knowledgeCutoff: "2025-12-01",
1509
+ pricing: {
1510
+ input: 30,
1511
+ output: 180,
1512
+ webSearchPerRequest: 0.01
1513
+ },
1514
+ capabilities: {
1515
+ reasoning: true,
1516
+ toolCalling: true,
1517
+ structuredOutputs: true
1518
+ }
1519
+ },
1520
+ {
1521
+ provider: "openrouter",
1522
+ modelId: "openai/gpt-5.5",
1523
+ canonicalSlug: "openai/gpt-5.5-20260423",
1524
+ displayName: "OpenAI: GPT-5.5",
1525
+ family: "gpt",
1526
+ status: "active",
1527
+ modalities: {
1528
+ input: ["text", "image", "file"],
1529
+ output: ["text"]
1530
+ },
1531
+ contextWindow: 105e4,
1532
+ maxCompletionTokens: 128e3,
1533
+ knowledgeCutoff: "2025-12-01",
1534
+ pricing: {
1535
+ input: 5,
1536
+ output: 30,
1537
+ cachedInput: 0.5,
1538
+ webSearchPerRequest: 0.01
1539
+ },
1540
+ capabilities: {
1541
+ reasoning: true,
1542
+ toolCalling: true,
1543
+ structuredOutputs: true
1544
+ }
1545
+ },
1546
+ {
1547
+ provider: "openrouter",
1548
+ modelId: "deepseek/deepseek-v4-pro",
1549
+ canonicalSlug: "deepseek/deepseek-v4-pro-20260423",
1550
+ displayName: "DeepSeek: DeepSeek V4 Pro",
1551
+ family: "deepseek",
1552
+ status: "active",
1553
+ modalities: {
1554
+ input: ["text"],
1555
+ output: ["text"]
1556
+ },
1557
+ contextWindow: 1048576,
1558
+ maxCompletionTokens: 384e3,
1559
+ pricing: {
1560
+ input: 0.435,
1561
+ output: 0.87,
1562
+ cachedInput: 3625e-6
1563
+ },
1564
+ capabilities: {
1565
+ reasoning: true,
1566
+ toolCalling: true,
1567
+ structuredOutputs: true
1568
+ }
1569
+ },
1570
+ {
1571
+ provider: "openrouter",
1572
+ modelId: "deepseek/deepseek-v4-flash",
1573
+ canonicalSlug: "deepseek/deepseek-v4-flash-20260423",
1574
+ displayName: "DeepSeek: DeepSeek V4 Flash",
1575
+ family: "deepseek",
1576
+ status: "active",
1577
+ modalities: {
1578
+ input: ["text"],
1579
+ output: ["text"]
1580
+ },
1581
+ contextWindow: 1048576,
1582
+ maxCompletionTokens: 16384,
1583
+ pricing: {
1584
+ input: 0.1,
1585
+ output: 0.2,
1586
+ cachedInput: 0.02
1587
+ },
1588
+ capabilities: {
1589
+ reasoning: true,
1590
+ toolCalling: true,
1591
+ structuredOutputs: true
1592
+ }
1593
+ },
1594
+ {
1595
+ provider: "openrouter",
1596
+ modelId: "deepseek/deepseek-v4-flash:free",
1597
+ canonicalSlug: "deepseek/deepseek-v4-flash-20260423",
1598
+ displayName: "DeepSeek: DeepSeek V4 Flash Free",
1599
+ family: "deepseek",
1600
+ status: "free",
1601
+ modalities: {
1602
+ input: ["text"],
1603
+ output: ["text"]
1604
+ },
1605
+ contextWindow: 1048576,
1606
+ maxCompletionTokens: 384e3,
1607
+ pricing: {
1608
+ input: 0,
1609
+ output: 0
1610
+ },
1611
+ capabilities: {
1612
+ reasoning: true,
1613
+ toolCalling: true
1614
+ }
1615
+ },
1616
+ {
1617
+ provider: "openrouter",
1618
+ modelId: "inclusionai/ling-2.6-1t",
1619
+ canonicalSlug: "inclusionai/ling-2.6-1t-20260423",
1620
+ displayName: "inclusionAI: Ling-2.6-1T",
1621
+ family: "ling",
1622
+ status: "active",
1623
+ modalities: {
1624
+ input: ["text"],
1625
+ output: ["text"]
1626
+ },
1627
+ contextWindow: 262144,
1628
+ maxCompletionTokens: 32768,
1629
+ pricing: {
1630
+ input: 0.075,
1631
+ output: 0.625,
1632
+ cachedInput: 0.015
1633
+ },
1634
+ capabilities: {
1635
+ toolCalling: true,
1636
+ structuredOutputs: true
1637
+ }
1638
+ },
1639
+ {
1640
+ provider: "openrouter",
1641
+ modelId: "tencent/hy3-preview",
1642
+ canonicalSlug: "tencent/hy3-preview-20260421",
1643
+ displayName: "Tencent: Hy3 Preview",
1644
+ family: "hy3",
1645
+ status: "preview",
1646
+ modalities: {
1647
+ input: ["text"],
1648
+ output: ["text"]
1649
+ },
1650
+ contextWindow: 262144,
1651
+ maxCompletionTokens: 262144,
1652
+ pricing: {
1653
+ input: 0.066,
1654
+ output: 0.26,
1655
+ cachedInput: 0.029
1656
+ },
1657
+ capabilities: {
1658
+ reasoning: true,
1659
+ toolCalling: true
1660
+ }
1661
+ },
1662
+ {
1663
+ provider: "openrouter",
1664
+ modelId: "xiaomi/mimo-v2.5-pro",
1665
+ canonicalSlug: "xiaomi/mimo-v2.5-pro-20260422",
1666
+ displayName: "Xiaomi: MiMo-V2.5-Pro",
1667
+ family: "mimo",
1668
+ status: "active",
1669
+ modalities: {
1670
+ input: ["text"],
1671
+ output: ["text"]
1672
+ },
1673
+ contextWindow: 1048576,
1674
+ maxCompletionTokens: 131072,
1675
+ pricing: {
1676
+ input: 0.435,
1677
+ output: 0.87,
1678
+ cachedInput: 36e-4
1679
+ },
1680
+ capabilities: {
1681
+ reasoning: true,
1682
+ toolCalling: true,
1683
+ structuredOutputs: true
1684
+ }
1685
+ },
1686
+ {
1687
+ provider: "openrouter",
1688
+ modelId: "xiaomi/mimo-v2.5",
1689
+ canonicalSlug: "xiaomi/mimo-v2.5-20260422",
1690
+ displayName: "Xiaomi: MiMo-V2.5",
1691
+ family: "mimo",
1692
+ status: "active",
1693
+ modalities: {
1694
+ input: ["text", "image", "audio", "video"],
1695
+ output: ["text"]
1696
+ },
1697
+ contextWindow: 1048576,
1698
+ maxCompletionTokens: 131072,
1699
+ pricing: {
1700
+ input: 0.14,
1701
+ output: 0.28,
1702
+ cachedInput: 28e-4
1703
+ },
1704
+ capabilities: {
1705
+ reasoning: true,
1706
+ toolCalling: true
1707
+ }
1708
+ },
1709
+ {
1710
+ provider: "openrouter",
1711
+ modelId: "openai/gpt-5.4-image-2",
1712
+ canonicalSlug: "openai/gpt-5.4-image-2-20260421",
1713
+ displayName: "OpenAI: GPT-5.4 Image 2",
1714
+ family: "gpt-image",
1715
+ status: "active",
1716
+ modalities: {
1717
+ input: ["text", "image", "file"],
1718
+ output: ["text", "image"]
1719
+ },
1720
+ contextWindow: 272e3,
1721
+ pricing: {
1722
+ input: 8,
1723
+ output: 15
1724
+ },
1725
+ capabilities: {
1726
+ imageGeneration: true,
1727
+ structuredOutputs: true
1728
+ }
1729
+ }
1730
+ ]
1731
+ };
1732
+
1733
+ // src/catalog/loadCatalogSources.ts
1734
+ var dataDir = _path.dirname.call(void 0, _url.fileURLToPath.call(void 0, _chunkGS7T56RPcjs.importMetaUrl));
1735
+ async function fetchCatalogJson(url, timeoutMs) {
1736
+ const res = await fetch(url, {
1737
+ signal: AbortSignal.timeout(timeoutMs),
1738
+ headers: { accept: "application/json" }
1739
+ });
1740
+ if (!res.ok) {
1741
+ throw new Error(`HTTP ${res.status} fetching ${url}`);
1742
+ }
1743
+ return await res.json();
1744
+ }
1745
+ async function loadOneSource(source, options) {
1746
+ if (options.bundledOnly) {
1747
+ return { file: source.bundled, from: "bundled" };
1748
+ }
1749
+ try {
1750
+ const file = await fetchCatalogJson(source.url, _nullishCoalesce(options.fetchTimeoutMs, () => ( 3e4)));
1751
+ return { file, from: "remote" };
1752
+ } catch (err) {
1753
+ console.warn(
1754
+ `[ai-tools] Failed to load ${source.kind} catalog from ${source.url} (${err instanceof Error ? err.message : err}); using bundled fallback.`
1755
+ );
1756
+ return { file: source.bundled, from: "bundled" };
1757
+ }
1758
+ }
1759
+ async function loadCatalogSources(options = {}) {
1760
+ const directUrl = _nullishCoalesce(options.directCatalogUrl, () => ( DEFAULT_DIRECT_CATALOG_URL));
1761
+ const openRouterUrl = _nullishCoalesce(options.openRouterCatalogUrl, () => ( DEFAULT_OPENROUTER_CATALOG_URL));
1762
+ const sources = [
1763
+ {
1764
+ kind: "direct",
1765
+ url: directUrl,
1766
+ bundled: models_catalog_default
1767
+ },
1768
+ {
1769
+ kind: "openrouter",
1770
+ url: openRouterUrl,
1771
+ bundled: openrouter_models_catalog_default
1772
+ }
1773
+ ];
1774
+ const [directLoad, orLoad] = await Promise.all(
1775
+ sources.map((s) => loadOneSource(s, options))
1776
+ );
1777
+ const direct = modelsFromX12iCatalogFile(directLoad.file, "direct");
1778
+ const openrouter = modelsFromX12iCatalogFile(orLoad.file, "openrouter");
1779
+ return {
1780
+ direct,
1781
+ openrouter,
1782
+ meta: {
1783
+ directSource: directLoad.from,
1784
+ openRouterSource: orLoad.from,
1785
+ directUrl,
1786
+ openRouterUrl,
1787
+ directCount: direct.size,
1788
+ openRouterCount: openrouter.size
1789
+ }
1790
+ };
1791
+ }
1792
+ async function readBundledCatalogFiles() {
1793
+ const directPath = _path.join.call(void 0, dataDir, "../data/models-catalog.json");
1794
+ const orPath = _path.join.call(void 0, dataDir, "../data/openrouter-models-catalog.json");
1795
+ const [directRaw, orRaw] = await Promise.all([
1796
+ _promises.readFile.call(void 0, directPath, "utf8"),
1797
+ _promises.readFile.call(void 0, orPath, "utf8")
1798
+ ]);
1799
+ const directFile = JSON.parse(directRaw);
1800
+ const orFile = JSON.parse(orRaw);
1801
+ return {
1802
+ direct: modelsFromX12iCatalogFile(directFile, "direct"),
1803
+ openrouter: modelsFromX12iCatalogFile(orFile, "openrouter"),
1804
+ meta: {
1805
+ directSource: "bundled",
1806
+ openRouterSource: "bundled",
1807
+ directUrl: DEFAULT_DIRECT_CATALOG_URL,
1808
+ openRouterUrl: DEFAULT_OPENROUTER_CATALOG_URL,
1809
+ directCount: directFile.models.length,
1810
+ openRouterCount: orFile.models.length
1811
+ }
1812
+ };
1813
+ }
1814
+
1815
+ // src/catalog/catalogLoadCache.ts
1816
+ var slots = /* @__PURE__ */ new Map();
1817
+ var inflight = /* @__PURE__ */ new Map();
1818
+ function slotKey(options, cacheKey) {
1819
+ return [
1820
+ cacheKey,
1821
+ options.bundledOnly ? "bundled" : "remote",
1822
+ _nullishCoalesce(options.directCatalogUrl, () => ( "")),
1823
+ _nullishCoalesce(options.openRouterCatalogUrl, () => ( ""))
1824
+ ].join("\0");
1825
+ }
1826
+ function invalidateCatalogLoadCache(cacheKey = "default") {
1827
+ for (const key of [...slots.keys()]) {
1828
+ if (key.startsWith(`${cacheKey}\0`)) slots.delete(key);
1829
+ }
1830
+ for (const key of [...inflight.keys()]) {
1831
+ if (key.startsWith(`${cacheKey}\0`)) inflight.delete(key);
1832
+ }
1833
+ }
1834
+ async function loadCatalogSourcesCached(options = {}, cacheOptions = {}) {
1835
+ if (options.bundledOnly) {
1836
+ return loadCatalogSources(options);
1837
+ }
1838
+ const ttlMs = resolveCatalogCacheTtlMs(cacheOptions.ttlMs);
1839
+ const key = slotKey(options, _nullishCoalesce(cacheOptions.cacheKey, () => ( "default")));
1840
+ if (!cacheOptions.forceRefresh) {
1841
+ const slot = slots.get(key);
1842
+ if (slot && Date.now() - slot.loadedAt < ttlMs) {
1843
+ return slot.data;
1844
+ }
1845
+ } else {
1846
+ slots.delete(key);
1847
+ inflight.delete(key);
1848
+ }
1849
+ const pending = inflight.get(key);
1850
+ if (pending) return pending;
1851
+ const promise = loadCatalogSources(options).then((data) => {
1852
+ slots.set(key, { loadedAt: Date.now(), data });
1853
+ inflight.delete(key);
1854
+ return data;
1855
+ }).catch((err) => {
1856
+ inflight.delete(key);
1857
+ throw err;
1858
+ });
1859
+ inflight.set(key, promise);
1860
+ return promise;
1861
+ }
1862
+
1863
+ // src/catalog/AiModelsCatalogClient.ts
1864
+ function isOpenRouterProvider(provider) {
1865
+ return _chunkEDMCKHO6cjs.normalizeProvider.call(void 0, provider) === "openrouter";
1866
+ }
1867
+ var AiModelsCatalogClient = (_class = class {
1868
+
1869
+
1870
+
1871
+
1872
+ __init() {this.directModels = null}
1873
+ __init2() {this.openRouterModels = null}
1874
+ __init3() {this.loadedAt = 0}
1875
+ __init4() {this.loadPromise = null}
1876
+ constructor(options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);
1877
+ this.cacheTtlMs = resolveCatalogCacheTtlMs(options.cacheTtlMs);
1878
+ this.cacheKey = _nullishCoalesce(options.cacheKey, () => ( "default"));
1879
+ this.loadOptions = {
1880
+ directCatalogUrl: options.directCatalogUrl,
1881
+ openRouterCatalogUrl: options.openRouterCatalogUrl,
1882
+ bundledOnly: options.bundledOnly,
1883
+ fetchTimeoutMs: options.fetchTimeoutMs
1884
+ };
1885
+ this.resolverOptions = options.resolverOptions;
1886
+ }
1887
+ isInstanceCacheValid() {
1888
+ return this.directModels !== null && this.openRouterModels !== null && Date.now() - this.loadedAt < this.cacheTtlMs;
1889
+ }
1890
+ applyLoaded(direct, openrouter) {
1891
+ this.directModels = direct;
1892
+ this.openRouterModels = openrouter;
1893
+ this.loadedAt = Date.now();
1894
+ writeCachedModels(`${this.cacheKey}:direct`, direct, this.cacheTtlMs);
1895
+ writeCachedModels(`${this.cacheKey}:openrouter`, openrouter, this.cacheTtlMs);
1896
+ }
1897
+ async ensureLoaded(forceRefresh = false) {
1898
+ if (!forceRefresh && this.isInstanceCacheValid()) return;
1899
+ if (this.loadPromise) return this.loadPromise;
1900
+ this.loadPromise = (async () => {
1901
+ const loaded = await loadCatalogSourcesCached(this.loadOptions, {
1902
+ cacheKey: this.cacheKey,
1903
+ ttlMs: this.cacheTtlMs,
1904
+ forceRefresh
1905
+ });
1906
+ this.applyLoaded(loaded.direct, loaded.openrouter);
1907
+ })().finally(() => {
1908
+ this.loadPromise = null;
1909
+ });
1910
+ await this.loadPromise;
1911
+ }
1912
+ mergedModels() {
1913
+ const map = /* @__PURE__ */ new Map();
1914
+ for (const r of _nullishCoalesce(_optionalChain([this, 'access', _7 => _7.directModels, 'optionalAccess', _8 => _8.values, 'call', _9 => _9()]), () => ( []))) {
1915
+ map.set(r.modelId, r);
1916
+ }
1917
+ for (const r of _nullishCoalesce(_optionalChain([this, 'access', _10 => _10.openRouterModels, 'optionalAccess', _11 => _11.values, 'call', _12 => _12()]), () => ( []))) {
1918
+ map.set(r.modelId, r);
1919
+ }
1920
+ return map;
1921
+ }
1922
+ catalogForProvider(provider) {
1923
+ if (isOpenRouterProvider(provider)) {
1924
+ return _nullishCoalesce(this.openRouterModels, () => ( /* @__PURE__ */ new Map()));
1925
+ }
1926
+ return _nullishCoalesce(this.directModels, () => ( /* @__PURE__ */ new Map()));
1927
+ }
1928
+ resolver(models, options) {
1929
+ return new (0, _chunkDXZOL3VNcjs.ModelNameResolver)(models, { ...this.resolverOptions, ...options });
1930
+ }
1931
+ async getAllModels() {
1932
+ await this.ensureLoaded();
1933
+ return this.mergedModels();
1934
+ }
1935
+ async getDirectModels() {
1936
+ await this.ensureLoaded();
1937
+ return new Map(this.directModels);
1938
+ }
1939
+ async getOpenRouterModels() {
1940
+ await this.ensureLoaded();
1941
+ return new Map(this.openRouterModels);
1942
+ }
1943
+ async resolveModel(input, options) {
1944
+ await this.ensureLoaded();
1945
+ const primary = this.catalogForProvider(input.provider);
1946
+ const secondary = isOpenRouterProvider(input.provider) ? _nullishCoalesce(this.directModels, () => ( /* @__PURE__ */ new Map())) : _nullishCoalesce(this.openRouterModels, () => ( /* @__PURE__ */ new Map()));
1947
+ let result = this.resolver(primary, options).resolve(input);
1948
+ if (result.found && result.record) return result;
1949
+ if (secondary.size > 0) {
1950
+ const fallback = this.resolver(secondary, options).resolve(input);
1951
+ if (fallback.found && fallback.record) return fallback;
1952
+ if (!result.found && fallback.found) result = fallback;
1953
+ }
1954
+ if (!result.found) {
1955
+ result = this.resolver(this.mergedModels(), options).resolve(input);
1956
+ }
1957
+ return result;
1958
+ }
1959
+ async getModel(modelId, provider, options) {
1960
+ const result = await this.resolveModel({ model: modelId, provider }, options);
1961
+ return result.found ? result.record : null;
1962
+ }
1963
+ /** Clear caches and fetch catalogs again immediately. */
1964
+ async refresh() {
1965
+ invalidateCatalogLoadCache(this.cacheKey);
1966
+ this.directModels = null;
1967
+ this.openRouterModels = null;
1968
+ this.loadedAt = 0;
1969
+ this.loadPromise = null;
1970
+ await this.ensureLoaded(true);
1971
+ }
1972
+ }, _class);
1973
+
1974
+
1975
+
1976
+
1977
+
1978
+
1979
+
1980
+
1981
+
1982
+
1983
+
1984
+
1985
+
1986
+
1987
+ exports.DEFAULT_CATALOG_CACHE_TTL_MS = DEFAULT_CATALOG_CACHE_TTL_MS; exports.resolveCatalogCacheTtlMs = resolveCatalogCacheTtlMs; exports.DEFAULT_DIRECT_CATALOG_URL = DEFAULT_DIRECT_CATALOG_URL; exports.DEFAULT_OPENROUTER_CATALOG_URL = DEFAULT_OPENROUTER_CATALOG_URL; exports.canonicalCatalogModelId = canonicalCatalogModelId; exports.normalizeX12iCatalogModel = normalizeX12iCatalogModel; exports.modelsFromX12iCatalogFile = modelsFromX12iCatalogFile; exports.loadCatalogSources = loadCatalogSources; exports.readBundledCatalogFiles = readBundledCatalogFiles; exports.invalidateCatalogLoadCache = invalidateCatalogLoadCache; exports.loadCatalogSourcesCached = loadCatalogSourcesCached; exports.AiModelsCatalogClient = AiModelsCatalogClient;
1988
+ //# sourceMappingURL=chunk-5XAAMBDO.cjs.map