@blockrun/clawrouter 0.12.94 → 0.12.96

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 (282) hide show
  1. package/dist/auth.d.ts +82 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/auth.js +388 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/balance.d.ts +97 -0
  6. package/dist/balance.d.ts.map +1 -0
  7. package/dist/balance.js +157 -0
  8. package/dist/balance.js.map +1 -0
  9. package/dist/cli.d.ts +15 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +256 -54991
  12. package/dist/cli.js.map +1 -1
  13. package/dist/compression/codebook.d.ts +24 -0
  14. package/dist/compression/codebook.d.ts.map +1 -0
  15. package/dist/compression/codebook.js +119 -0
  16. package/dist/compression/codebook.js.map +1 -0
  17. package/dist/compression/index.d.ts +33 -0
  18. package/dist/compression/index.d.ts.map +1 -0
  19. package/dist/compression/index.js +246 -0
  20. package/dist/compression/index.js.map +1 -0
  21. package/dist/compression/layers/deduplication.d.ts +28 -0
  22. package/dist/compression/layers/deduplication.d.ts.map +1 -0
  23. package/dist/compression/layers/deduplication.js +101 -0
  24. package/dist/compression/layers/deduplication.js.map +1 -0
  25. package/dist/compression/layers/dictionary.d.ts +21 -0
  26. package/dist/compression/layers/dictionary.d.ts.map +1 -0
  27. package/dist/compression/layers/dictionary.js +73 -0
  28. package/dist/compression/layers/dictionary.js.map +1 -0
  29. package/dist/compression/layers/dynamic-codebook.d.ts +26 -0
  30. package/dist/compression/layers/dynamic-codebook.d.ts.map +1 -0
  31. package/dist/compression/layers/dynamic-codebook.js +149 -0
  32. package/dist/compression/layers/dynamic-codebook.js.map +1 -0
  33. package/dist/compression/layers/json-compact.d.ts +23 -0
  34. package/dist/compression/layers/json-compact.d.ts.map +1 -0
  35. package/dist/compression/layers/json-compact.js +79 -0
  36. package/dist/compression/layers/json-compact.js.map +1 -0
  37. package/dist/compression/layers/observation.d.ts +21 -0
  38. package/dist/compression/layers/observation.d.ts.map +1 -0
  39. package/dist/compression/layers/observation.js +130 -0
  40. package/dist/compression/layers/observation.js.map +1 -0
  41. package/dist/compression/layers/paths.d.ts +24 -0
  42. package/dist/compression/layers/paths.d.ts.map +1 -0
  43. package/dist/compression/layers/paths.js +110 -0
  44. package/dist/compression/layers/paths.js.map +1 -0
  45. package/dist/compression/layers/whitespace.d.ts +27 -0
  46. package/dist/compression/layers/whitespace.d.ts.map +1 -0
  47. package/dist/compression/layers/whitespace.js +60 -0
  48. package/dist/compression/layers/whitespace.js.map +1 -0
  49. package/dist/compression/types.d.ts +84 -0
  50. package/dist/compression/types.d.ts.map +1 -0
  51. package/dist/compression/types.js +27 -0
  52. package/dist/compression/types.js.map +1 -0
  53. package/dist/config.d.ts +12 -0
  54. package/dist/config.d.ts.map +1 -0
  55. package/dist/config.js +22 -0
  56. package/dist/config.js.map +1 -0
  57. package/dist/dedup.d.ts +34 -0
  58. package/dist/dedup.d.ts.map +1 -0
  59. package/dist/dedup.js +150 -0
  60. package/dist/dedup.js.map +1 -0
  61. package/dist/doctor.d.ts +8 -0
  62. package/dist/doctor.d.ts.map +1 -0
  63. package/dist/doctor.js +375 -0
  64. package/dist/doctor.js.map +1 -0
  65. package/dist/error-classification.test.d.ts +2 -0
  66. package/dist/error-classification.test.d.ts.map +1 -0
  67. package/dist/error-classification.test.js +59 -0
  68. package/dist/error-classification.test.js.map +1 -0
  69. package/dist/errors.d.ts +54 -0
  70. package/dist/errors.d.ts.map +1 -0
  71. package/dist/errors.js +85 -0
  72. package/dist/errors.js.map +1 -0
  73. package/dist/exclude-models.d.ts +28 -0
  74. package/dist/exclude-models.d.ts.map +1 -0
  75. package/dist/exclude-models.integration.test.d.ts +2 -0
  76. package/dist/exclude-models.integration.test.d.ts.map +1 -0
  77. package/dist/exclude-models.integration.test.js +46 -0
  78. package/dist/exclude-models.integration.test.js.map +1 -0
  79. package/dist/exclude-models.js +70 -0
  80. package/dist/exclude-models.js.map +1 -0
  81. package/dist/exclude-models.test.d.ts +5 -0
  82. package/dist/exclude-models.test.d.ts.map +1 -0
  83. package/dist/exclude-models.test.js +95 -0
  84. package/dist/exclude-models.test.js.map +1 -0
  85. package/dist/fs-read.d.ts +11 -0
  86. package/dist/fs-read.d.ts.map +1 -0
  87. package/dist/fs-read.js +47 -0
  88. package/dist/fs-read.js.map +1 -0
  89. package/dist/index.d.ts +34 -1368
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +1071 -56191
  92. package/dist/index.js.map +1 -1
  93. package/dist/journal.d.ts +67 -0
  94. package/dist/journal.d.ts.map +1 -0
  95. package/dist/journal.js +184 -0
  96. package/dist/journal.js.map +1 -0
  97. package/dist/journal.test.d.ts +2 -0
  98. package/dist/journal.test.d.ts.map +1 -0
  99. package/dist/journal.test.js +201 -0
  100. package/dist/journal.test.js.map +1 -0
  101. package/dist/logger.d.ts +33 -0
  102. package/dist/logger.d.ts.map +1 -0
  103. package/dist/logger.js +35 -0
  104. package/dist/logger.js.map +1 -0
  105. package/dist/models.d.ts +107 -0
  106. package/dist/models.d.ts.map +1 -0
  107. package/dist/models.js +941 -0
  108. package/dist/models.js.map +1 -0
  109. package/dist/models.test.d.ts +2 -0
  110. package/dist/models.test.d.ts.map +1 -0
  111. package/dist/models.test.js +38 -0
  112. package/dist/models.test.js.map +1 -0
  113. package/dist/partners/index.d.ts +8 -0
  114. package/dist/partners/index.d.ts.map +1 -0
  115. package/dist/partners/index.js +6 -0
  116. package/dist/partners/index.js.map +1 -0
  117. package/dist/partners/registry.d.ts +51 -0
  118. package/dist/partners/registry.d.ts.map +1 -0
  119. package/dist/partners/registry.js +256 -0
  120. package/dist/partners/registry.js.map +1 -0
  121. package/dist/partners/tools.d.ts +24 -0
  122. package/dist/partners/tools.d.ts.map +1 -0
  123. package/dist/partners/tools.js +97 -0
  124. package/dist/partners/tools.js.map +1 -0
  125. package/dist/payment-preauth.d.ts +17 -0
  126. package/dist/payment-preauth.d.ts.map +1 -0
  127. package/dist/payment-preauth.js +102 -0
  128. package/dist/payment-preauth.js.map +1 -0
  129. package/dist/provider.d.ts +19 -0
  130. package/dist/provider.d.ts.map +1 -0
  131. package/dist/provider.js +45 -0
  132. package/dist/provider.js.map +1 -0
  133. package/dist/proxy.d.ts +210 -0
  134. package/dist/proxy.d.ts.map +1 -0
  135. package/dist/proxy.debrand.test.d.ts +2 -0
  136. package/dist/proxy.debrand.test.d.ts.map +1 -0
  137. package/dist/proxy.debrand.test.js +101 -0
  138. package/dist/proxy.debrand.test.js.map +1 -0
  139. package/dist/proxy.degraded-response.test.d.ts +2 -0
  140. package/dist/proxy.degraded-response.test.d.ts.map +1 -0
  141. package/dist/proxy.degraded-response.test.js +105 -0
  142. package/dist/proxy.degraded-response.test.js.map +1 -0
  143. package/dist/proxy.image-download.test.d.ts +2 -0
  144. package/dist/proxy.image-download.test.d.ts.map +1 -0
  145. package/dist/proxy.image-download.test.js +92 -0
  146. package/dist/proxy.image-download.test.js.map +1 -0
  147. package/dist/proxy.js +3810 -0
  148. package/dist/proxy.js.map +1 -0
  149. package/dist/proxy.models-endpoint.test.d.ts +2 -0
  150. package/dist/proxy.models-endpoint.test.d.ts.map +1 -0
  151. package/dist/proxy.models-endpoint.test.js +19 -0
  152. package/dist/proxy.models-endpoint.test.js.map +1 -0
  153. package/dist/proxy.multiturn-thinking.test.d.ts +2 -0
  154. package/dist/proxy.multiturn-thinking.test.d.ts.map +1 -0
  155. package/dist/proxy.multiturn-thinking.test.js +82 -0
  156. package/dist/proxy.multiturn-thinking.test.js.map +1 -0
  157. package/dist/proxy.payment-chain-reuse.test.d.ts +2 -0
  158. package/dist/proxy.payment-chain-reuse.test.d.ts.map +1 -0
  159. package/dist/proxy.payment-chain-reuse.test.js +30 -0
  160. package/dist/proxy.payment-chain-reuse.test.js.map +1 -0
  161. package/dist/proxy.solana-resilience.test.d.ts +12 -0
  162. package/dist/proxy.solana-resilience.test.d.ts.map +1 -0
  163. package/dist/proxy.solana-resilience.test.js +39 -0
  164. package/dist/proxy.solana-resilience.test.js.map +1 -0
  165. package/dist/report.d.ts +6 -0
  166. package/dist/report.d.ts.map +1 -0
  167. package/dist/report.js +44 -0
  168. package/dist/report.js.map +1 -0
  169. package/dist/response-cache.advanced.test.d.ts +2 -0
  170. package/dist/response-cache.advanced.test.d.ts.map +1 -0
  171. package/dist/response-cache.advanced.test.js +566 -0
  172. package/dist/response-cache.advanced.test.js.map +1 -0
  173. package/dist/response-cache.d.ts +85 -0
  174. package/dist/response-cache.d.ts.map +1 -0
  175. package/dist/response-cache.edge-cases.test.d.ts +2 -0
  176. package/dist/response-cache.edge-cases.test.d.ts.map +1 -0
  177. package/dist/response-cache.edge-cases.test.js +488 -0
  178. package/dist/response-cache.edge-cases.test.js.map +1 -0
  179. package/dist/response-cache.extreme.test.d.ts +2 -0
  180. package/dist/response-cache.extreme.test.d.ts.map +1 -0
  181. package/dist/response-cache.extreme.test.js +561 -0
  182. package/dist/response-cache.extreme.test.js.map +1 -0
  183. package/dist/response-cache.js +240 -0
  184. package/dist/response-cache.js.map +1 -0
  185. package/dist/response-cache.test.d.ts +2 -0
  186. package/dist/response-cache.test.d.ts.map +1 -0
  187. package/dist/response-cache.test.js +242 -0
  188. package/dist/response-cache.test.js.map +1 -0
  189. package/dist/retry.d.ts +42 -0
  190. package/dist/retry.d.ts.map +1 -0
  191. package/dist/retry.js +99 -0
  192. package/dist/retry.js.map +1 -0
  193. package/dist/router/config.d.ts +11 -0
  194. package/dist/router/config.d.ts.map +1 -0
  195. package/dist/router/config.js +1215 -0
  196. package/dist/router/config.js.map +1 -0
  197. package/dist/router/index.d.ts +18 -0
  198. package/dist/router/index.d.ts.map +1 -0
  199. package/dist/router/index.js +19 -0
  200. package/dist/router/index.js.map +1 -0
  201. package/dist/router/llm-classifier.d.ts +29 -0
  202. package/dist/router/llm-classifier.d.ts.map +1 -0
  203. package/dist/router/llm-classifier.js +99 -0
  204. package/dist/router/llm-classifier.js.map +1 -0
  205. package/dist/router/rules.d.ts +12 -0
  206. package/dist/router/rules.d.ts.map +1 -0
  207. package/dist/router/rules.js +202 -0
  208. package/dist/router/rules.js.map +1 -0
  209. package/dist/router/selector.d.ts +58 -0
  210. package/dist/router/selector.d.ts.map +1 -0
  211. package/dist/router/selector.js +165 -0
  212. package/dist/router/selector.js.map +1 -0
  213. package/dist/router/selector.test.d.ts +2 -0
  214. package/dist/router/selector.test.d.ts.map +1 -0
  215. package/dist/router/selector.test.js +67 -0
  216. package/dist/router/selector.test.js.map +1 -0
  217. package/dist/router/strategy.d.ts +19 -0
  218. package/dist/router/strategy.d.ts.map +1 -0
  219. package/dist/router/strategy.js +138 -0
  220. package/dist/router/strategy.js.map +1 -0
  221. package/dist/router/strategy.test.d.ts +2 -0
  222. package/dist/router/strategy.test.d.ts.map +1 -0
  223. package/dist/router/strategy.test.js +131 -0
  224. package/dist/router/strategy.test.js.map +1 -0
  225. package/dist/router/types.d.ts +127 -0
  226. package/dist/router/types.d.ts.map +1 -0
  227. package/dist/router/types.js +11 -0
  228. package/dist/router/types.js.map +1 -0
  229. package/dist/session.d.ts +124 -0
  230. package/dist/session.d.ts.map +1 -0
  231. package/dist/session.js +256 -0
  232. package/dist/session.js.map +1 -0
  233. package/dist/session.test.d.ts +2 -0
  234. package/dist/session.test.d.ts.map +1 -0
  235. package/dist/session.test.js +163 -0
  236. package/dist/session.test.js.map +1 -0
  237. package/dist/solana-balance.d.ts +48 -0
  238. package/dist/solana-balance.d.ts.map +1 -0
  239. package/dist/solana-balance.js +142 -0
  240. package/dist/solana-balance.js.map +1 -0
  241. package/dist/spend-control.d.ts +112 -0
  242. package/dist/spend-control.d.ts.map +1 -0
  243. package/dist/spend-control.js +278 -0
  244. package/dist/spend-control.js.map +1 -0
  245. package/dist/spend-control.test.d.ts +5 -0
  246. package/dist/spend-control.test.d.ts.map +1 -0
  247. package/dist/spend-control.test.js +210 -0
  248. package/dist/spend-control.test.js.map +1 -0
  249. package/dist/stats.d.ts +64 -0
  250. package/dist/stats.d.ts.map +1 -0
  251. package/dist/stats.js +295 -0
  252. package/dist/stats.js.map +1 -0
  253. package/dist/types.d.ts +150 -0
  254. package/dist/types.d.ts.map +1 -0
  255. package/dist/types.js +9 -0
  256. package/dist/types.js.map +1 -0
  257. package/dist/update-hint.test.d.ts +9 -0
  258. package/dist/update-hint.test.d.ts.map +1 -0
  259. package/dist/update-hint.test.js +156 -0
  260. package/dist/update-hint.test.js.map +1 -0
  261. package/dist/updater.d.ts +10 -0
  262. package/dist/updater.d.ts.map +1 -0
  263. package/dist/updater.js +55 -0
  264. package/dist/updater.js.map +1 -0
  265. package/dist/version.d.ts +3 -0
  266. package/dist/version.d.ts.map +1 -0
  267. package/dist/version.js +16 -0
  268. package/dist/version.js.map +1 -0
  269. package/dist/wallet.d.ts +52 -0
  270. package/dist/wallet.d.ts.map +1 -0
  271. package/dist/wallet.js +93 -0
  272. package/dist/wallet.js.map +1 -0
  273. package/dist/wallet.test.d.ts +6 -0
  274. package/dist/wallet.test.d.ts.map +1 -0
  275. package/dist/wallet.test.js +117 -0
  276. package/dist/wallet.test.js.map +1 -0
  277. package/dist/x402-sdk.test.d.ts +6 -0
  278. package/dist/x402-sdk.test.d.ts.map +1 -0
  279. package/dist/x402-sdk.test.js +161 -0
  280. package/dist/x402-sdk.test.js.map +1 -0
  281. package/package.json +2 -2
  282. package/scripts/e2e-multiturn.mjs +4 -1
package/dist/models.js ADDED
@@ -0,0 +1,941 @@
1
+ /**
2
+ * BlockRun Model Definitions for OpenClaw
3
+ *
4
+ * Maps BlockRun's 55+ AI models to OpenClaw's ModelDefinitionConfig format.
5
+ * All models use the "openai-completions" API since BlockRun is OpenAI-compatible.
6
+ *
7
+ * Pricing is in USD per 1M tokens. Operators pay these rates via x402;
8
+ * they set their own markup when reselling to end users (Phase 2).
9
+ */
10
+ /**
11
+ * Model aliases for convenient shorthand access.
12
+ * Users can type `/model claude` instead of `/model blockrun/anthropic/claude-sonnet-4-6`.
13
+ */
14
+ export const MODEL_ALIASES = {
15
+ // Claude - use newest versions (4.6)
16
+ claude: "anthropic/claude-sonnet-4.6",
17
+ sonnet: "anthropic/claude-sonnet-4.6",
18
+ "sonnet-4": "anthropic/claude-sonnet-4.6",
19
+ "sonnet-4.6": "anthropic/claude-sonnet-4.6",
20
+ "sonnet-4-6": "anthropic/claude-sonnet-4.6",
21
+ opus: "anthropic/claude-opus-4.6",
22
+ "opus-4": "anthropic/claude-opus-4.6",
23
+ "opus-4.6": "anthropic/claude-opus-4.6",
24
+ "opus-4-6": "anthropic/claude-opus-4.6",
25
+ haiku: "anthropic/claude-haiku-4.5",
26
+ // Claude - provider/shortname patterns (common in agent frameworks)
27
+ "anthropic/sonnet": "anthropic/claude-sonnet-4.6",
28
+ "anthropic/opus": "anthropic/claude-opus-4.6",
29
+ "anthropic/haiku": "anthropic/claude-haiku-4.5",
30
+ "anthropic/claude": "anthropic/claude-sonnet-4.6",
31
+ // Backward compatibility - map all variants to 4.6
32
+ "anthropic/claude-sonnet-4": "anthropic/claude-sonnet-4.6",
33
+ "anthropic/claude-sonnet-4-6": "anthropic/claude-sonnet-4.6",
34
+ "anthropic/claude-opus-4": "anthropic/claude-opus-4.6",
35
+ "anthropic/claude-opus-4-6": "anthropic/claude-opus-4.6",
36
+ "anthropic/claude-opus-4.5": "anthropic/claude-opus-4.6",
37
+ "anthropic/claude-haiku-4": "anthropic/claude-haiku-4.5",
38
+ "anthropic/claude-haiku-4-5": "anthropic/claude-haiku-4.5",
39
+ // OpenAI
40
+ gpt: "openai/gpt-4o",
41
+ gpt4: "openai/gpt-4o",
42
+ gpt5: "openai/gpt-5.4",
43
+ "gpt-5.4": "openai/gpt-5.4",
44
+ "gpt-5.4-pro": "openai/gpt-5.4-pro",
45
+ "gpt-5.4-nano": "openai/gpt-5.4-nano",
46
+ nano: "openai/gpt-5.4-nano",
47
+ "gpt-5-nano": "openai/gpt-5.4-nano",
48
+ codex: "openai/gpt-5.3-codex",
49
+ mini: "openai/gpt-4o-mini",
50
+ o1: "openai/o1",
51
+ o3: "openai/o3",
52
+ // DeepSeek
53
+ deepseek: "deepseek/deepseek-chat",
54
+ "deepseek-chat": "deepseek/deepseek-chat",
55
+ reasoner: "deepseek/deepseek-reasoner",
56
+ // Kimi / Moonshot
57
+ kimi: "moonshot/kimi-k2.5",
58
+ moonshot: "moonshot/kimi-k2.5",
59
+ "kimi-k2.5": "moonshot/kimi-k2.5",
60
+ // Google
61
+ gemini: "google/gemini-2.5-pro",
62
+ flash: "google/gemini-2.5-flash",
63
+ "gemini-3.1-pro-preview": "google/gemini-3.1-pro",
64
+ "google/gemini-3.1-pro-preview": "google/gemini-3.1-pro",
65
+ "gemini-3.1-flash-lite": "google/gemini-3.1-flash-lite",
66
+ // xAI
67
+ grok: "xai/grok-3",
68
+ "grok-fast": "xai/grok-4-fast-reasoning",
69
+ "grok-code": "deepseek/deepseek-chat", // was grok-code-fast-1, delisted due to poor retention
70
+ // Delisted model redirects — full model IDs that were previously valid but removed
71
+ "grok-code-fast-1": "deepseek/deepseek-chat", // bare alias
72
+ "xai/grok-code-fast-1": "deepseek/deepseek-chat", // delisted 2026-03-12
73
+ "xai/grok-3-fast": "xai/grok-4-fast-reasoning", // delisted (too expensive)
74
+ // NVIDIA — backward compat aliases (nvidia/xxx → free/xxx)
75
+ nvidia: "free/gpt-oss-120b",
76
+ "gpt-120b": "free/gpt-oss-120b",
77
+ "gpt-20b": "free/gpt-oss-20b",
78
+ "nvidia/gpt-oss-120b": "free/gpt-oss-120b",
79
+ "nvidia/gpt-oss-20b": "free/gpt-oss-20b",
80
+ "nvidia/nemotron-ultra-253b": "free/nemotron-ultra-253b",
81
+ "nvidia/nemotron-3-super-120b": "free/nemotron-3-super-120b",
82
+ "nvidia/nemotron-super-49b": "free/nemotron-super-49b",
83
+ "nvidia/deepseek-v3.2": "free/deepseek-v3.2",
84
+ "nvidia/mistral-large-3-675b": "free/mistral-large-3-675b",
85
+ "nvidia/qwen3-coder-480b": "free/qwen3-coder-480b",
86
+ "nvidia/devstral-2-123b": "free/devstral-2-123b",
87
+ "nvidia/glm-4.7": "free/glm-4.7",
88
+ "nvidia/llama-4-maverick": "free/llama-4-maverick",
89
+ // Free model shorthand aliases
90
+ "deepseek-free": "free/deepseek-v3.2",
91
+ "mistral-free": "free/mistral-large-3-675b",
92
+ "glm-free": "free/glm-4.7",
93
+ "llama-free": "free/llama-4-maverick",
94
+ nemotron: "free/nemotron-ultra-253b",
95
+ "nemotron-ultra": "free/nemotron-ultra-253b",
96
+ "nemotron-253b": "free/nemotron-ultra-253b",
97
+ "nemotron-super": "free/nemotron-super-49b",
98
+ "nemotron-49b": "free/nemotron-super-49b",
99
+ "nemotron-120b": "free/nemotron-3-super-120b",
100
+ devstral: "free/devstral-2-123b",
101
+ "devstral-2": "free/devstral-2-123b",
102
+ "qwen-coder": "free/qwen3-coder-480b",
103
+ "qwen-coder-free": "free/qwen3-coder-480b",
104
+ maverick: "free/llama-4-maverick",
105
+ free: "free/nemotron-ultra-253b",
106
+ // MiniMax
107
+ minimax: "minimax/minimax-m2.7",
108
+ "minimax-m2.7": "minimax/minimax-m2.7",
109
+ "minimax-m2.5": "minimax/minimax-m2.5",
110
+ // Z.AI GLM-5
111
+ glm: "zai/glm-5",
112
+ "glm-5": "zai/glm-5",
113
+ "glm-5-turbo": "zai/glm-5-turbo",
114
+ // Routing profile aliases (common variations)
115
+ "auto-router": "auto",
116
+ router: "auto",
117
+ // Note: auto, eco, premium are virtual routing profiles registered in BLOCKRUN_MODELS
118
+ // They don't need aliases since they're already top-level model IDs
119
+ };
120
+ /**
121
+ * Resolve a model alias to its full model ID.
122
+ * Also strips "blockrun/" prefix for direct model paths.
123
+ * Examples:
124
+ * - "claude" -> "anthropic/claude-sonnet-4-6" (alias)
125
+ * - "blockrun/claude" -> "anthropic/claude-sonnet-4-6" (alias with prefix)
126
+ * - "blockrun/anthropic/claude-sonnet-4-6" -> "anthropic/claude-sonnet-4-6" (prefix stripped)
127
+ * - "openai/gpt-4o" -> "openai/gpt-4o" (unchanged)
128
+ */
129
+ export function resolveModelAlias(model) {
130
+ const normalized = model.trim().toLowerCase();
131
+ const resolved = MODEL_ALIASES[normalized];
132
+ if (resolved)
133
+ return resolved;
134
+ // Check with "blockrun/" prefix stripped
135
+ if (normalized.startsWith("blockrun/")) {
136
+ const withoutPrefix = normalized.slice("blockrun/".length);
137
+ const resolvedWithoutPrefix = MODEL_ALIASES[withoutPrefix];
138
+ if (resolvedWithoutPrefix)
139
+ return resolvedWithoutPrefix;
140
+ // Even if not an alias, strip the prefix for direct model paths
141
+ // e.g., "blockrun/anthropic/claude-sonnet-4-6" -> "anthropic/claude-sonnet-4-6"
142
+ return withoutPrefix;
143
+ }
144
+ // Strip "openai/" prefix when it wraps a virtual routing profile or alias.
145
+ // OpenClaw sends virtual models as "openai/eco", "openai/auto", etc. because
146
+ // the provider uses the openai-completions API type.
147
+ if (normalized.startsWith("openai/")) {
148
+ const withoutPrefix = normalized.slice("openai/".length);
149
+ const resolvedWithoutPrefix = MODEL_ALIASES[withoutPrefix];
150
+ if (resolvedWithoutPrefix)
151
+ return resolvedWithoutPrefix;
152
+ // If it's a known BlockRun virtual profile (eco, auto, premium), return bare id
153
+ const isVirtualProfile = BLOCKRUN_MODELS.some((m) => m.id === withoutPrefix);
154
+ if (isVirtualProfile)
155
+ return withoutPrefix;
156
+ }
157
+ return model;
158
+ }
159
+ export const BLOCKRUN_MODELS = [
160
+ // Smart routing meta-models — proxy replaces with actual model
161
+ // NOTE: Model IDs are WITHOUT provider prefix (OpenClaw adds "blockrun/" automatically)
162
+ {
163
+ id: "auto",
164
+ name: "Auto (Smart Router - Balanced)",
165
+ inputPrice: 0,
166
+ outputPrice: 0,
167
+ contextWindow: 1_050_000,
168
+ maxOutput: 128_000,
169
+ },
170
+ {
171
+ id: "free",
172
+ name: "Free → Nemotron Ultra 253B",
173
+ inputPrice: 0,
174
+ outputPrice: 0,
175
+ contextWindow: 131_072,
176
+ maxOutput: 16_384,
177
+ reasoning: true,
178
+ },
179
+ {
180
+ id: "eco",
181
+ name: "Eco (Smart Router - Cost Optimized)",
182
+ inputPrice: 0,
183
+ outputPrice: 0,
184
+ contextWindow: 1_050_000,
185
+ maxOutput: 128_000,
186
+ },
187
+ {
188
+ id: "premium",
189
+ name: "Premium (Smart Router - Best Quality)",
190
+ inputPrice: 0,
191
+ outputPrice: 0,
192
+ contextWindow: 2_000_000,
193
+ maxOutput: 200_000,
194
+ },
195
+ // OpenAI GPT-5 Family
196
+ {
197
+ id: "openai/gpt-5.2",
198
+ name: "GPT-5.2",
199
+ version: "5.2",
200
+ inputPrice: 1.75,
201
+ outputPrice: 14.0,
202
+ contextWindow: 400000,
203
+ maxOutput: 128000,
204
+ reasoning: true,
205
+ vision: true,
206
+ agentic: true,
207
+ toolCalling: true,
208
+ },
209
+ {
210
+ id: "openai/gpt-5-mini",
211
+ name: "GPT-5 Mini",
212
+ version: "5.0",
213
+ inputPrice: 0.25,
214
+ outputPrice: 2.0,
215
+ contextWindow: 200000,
216
+ maxOutput: 65536,
217
+ toolCalling: true,
218
+ },
219
+ {
220
+ id: "openai/gpt-5-nano",
221
+ name: "GPT-5 Nano",
222
+ version: "5.0",
223
+ inputPrice: 0.05,
224
+ outputPrice: 0.4,
225
+ contextWindow: 128000,
226
+ maxOutput: 32768,
227
+ toolCalling: true,
228
+ deprecated: true,
229
+ fallbackModel: "openai/gpt-5.4-nano",
230
+ },
231
+ {
232
+ id: "openai/gpt-5.2-pro",
233
+ name: "GPT-5.2 Pro",
234
+ version: "5.2",
235
+ inputPrice: 21.0,
236
+ outputPrice: 168.0,
237
+ contextWindow: 400000,
238
+ maxOutput: 128000,
239
+ reasoning: true,
240
+ toolCalling: true,
241
+ },
242
+ // GPT-5.4 — newest flagship, same input price as 4o but much more capable
243
+ {
244
+ id: "openai/gpt-5.4",
245
+ name: "GPT-5.4",
246
+ version: "5.4",
247
+ inputPrice: 2.5,
248
+ outputPrice: 15.0,
249
+ contextWindow: 400000,
250
+ maxOutput: 128000,
251
+ reasoning: true,
252
+ vision: true,
253
+ agentic: true,
254
+ toolCalling: true,
255
+ },
256
+ {
257
+ id: "openai/gpt-5.4-pro",
258
+ name: "GPT-5.4 Pro",
259
+ version: "5.4",
260
+ inputPrice: 30.0,
261
+ outputPrice: 180.0,
262
+ contextWindow: 400000,
263
+ maxOutput: 128000,
264
+ reasoning: true,
265
+ toolCalling: true,
266
+ },
267
+ {
268
+ id: "openai/gpt-5.4-nano",
269
+ name: "GPT-5.4 Nano",
270
+ version: "5.4",
271
+ inputPrice: 0.2,
272
+ outputPrice: 1.25,
273
+ contextWindow: 1050000,
274
+ maxOutput: 32768,
275
+ toolCalling: true,
276
+ },
277
+ // OpenAI GPT-5.3 Family
278
+ {
279
+ id: "openai/gpt-5.3",
280
+ name: "GPT-5.3",
281
+ version: "5.3",
282
+ inputPrice: 1.75,
283
+ outputPrice: 14.0,
284
+ contextWindow: 128000,
285
+ maxOutput: 16000,
286
+ reasoning: true,
287
+ vision: true,
288
+ agentic: true,
289
+ toolCalling: true,
290
+ },
291
+ // OpenAI Codex Family
292
+ {
293
+ id: "openai/gpt-5.3-codex",
294
+ name: "GPT-5.3 Codex",
295
+ version: "5.3",
296
+ inputPrice: 1.75,
297
+ outputPrice: 14.0,
298
+ contextWindow: 400000,
299
+ maxOutput: 128000,
300
+ agentic: true,
301
+ toolCalling: true,
302
+ },
303
+ // OpenAI GPT-4 Family
304
+ {
305
+ id: "openai/gpt-4.1",
306
+ name: "GPT-4.1",
307
+ version: "4.1",
308
+ inputPrice: 2.0,
309
+ outputPrice: 8.0,
310
+ contextWindow: 128000,
311
+ maxOutput: 16384,
312
+ vision: true,
313
+ toolCalling: true,
314
+ },
315
+ {
316
+ id: "openai/gpt-4.1-mini",
317
+ name: "GPT-4.1 Mini",
318
+ version: "4.1",
319
+ inputPrice: 0.4,
320
+ outputPrice: 1.6,
321
+ contextWindow: 128000,
322
+ maxOutput: 16384,
323
+ toolCalling: true,
324
+ },
325
+ {
326
+ id: "openai/gpt-4.1-nano",
327
+ name: "GPT-4.1 Nano",
328
+ version: "4.1",
329
+ inputPrice: 0.1,
330
+ outputPrice: 0.4,
331
+ contextWindow: 128000,
332
+ maxOutput: 16384,
333
+ toolCalling: true,
334
+ },
335
+ {
336
+ id: "openai/gpt-4o",
337
+ name: "GPT-4o",
338
+ version: "4o",
339
+ inputPrice: 2.5,
340
+ outputPrice: 10.0,
341
+ contextWindow: 128000,
342
+ maxOutput: 16384,
343
+ vision: true,
344
+ agentic: true,
345
+ toolCalling: true,
346
+ },
347
+ {
348
+ id: "openai/gpt-4o-mini",
349
+ name: "GPT-4o Mini",
350
+ version: "4o-mini",
351
+ inputPrice: 0.15,
352
+ outputPrice: 0.6,
353
+ contextWindow: 128000,
354
+ maxOutput: 16384,
355
+ toolCalling: true,
356
+ },
357
+ // OpenAI O-series (Reasoning)
358
+ {
359
+ id: "openai/o1",
360
+ name: "o1",
361
+ version: "1",
362
+ inputPrice: 15.0,
363
+ outputPrice: 60.0,
364
+ contextWindow: 200000,
365
+ maxOutput: 100000,
366
+ reasoning: true,
367
+ toolCalling: true,
368
+ },
369
+ {
370
+ id: "openai/o1-mini",
371
+ name: "o1-mini",
372
+ version: "1-mini",
373
+ inputPrice: 1.1,
374
+ outputPrice: 4.4,
375
+ contextWindow: 128000,
376
+ maxOutput: 65536,
377
+ reasoning: true,
378
+ toolCalling: true,
379
+ },
380
+ {
381
+ id: "openai/o3",
382
+ name: "o3",
383
+ version: "3",
384
+ inputPrice: 2.0,
385
+ outputPrice: 8.0,
386
+ contextWindow: 200000,
387
+ maxOutput: 100000,
388
+ reasoning: true,
389
+ toolCalling: true,
390
+ },
391
+ {
392
+ id: "openai/o3-mini",
393
+ name: "o3-mini",
394
+ version: "3-mini",
395
+ inputPrice: 1.1,
396
+ outputPrice: 4.4,
397
+ contextWindow: 128000,
398
+ maxOutput: 65536,
399
+ reasoning: true,
400
+ toolCalling: true,
401
+ },
402
+ {
403
+ id: "openai/o4-mini",
404
+ name: "o4-mini",
405
+ version: "4-mini",
406
+ inputPrice: 1.1,
407
+ outputPrice: 4.4,
408
+ contextWindow: 128000,
409
+ maxOutput: 65536,
410
+ reasoning: true,
411
+ toolCalling: true,
412
+ },
413
+ // Anthropic - all Claude models excel at agentic workflows
414
+ // Use newest versions (4.6) with full provider prefix
415
+ {
416
+ id: "anthropic/claude-haiku-4.5",
417
+ name: "Claude Haiku 4.5",
418
+ version: "4.5",
419
+ inputPrice: 1.0,
420
+ outputPrice: 5.0,
421
+ contextWindow: 200000,
422
+ maxOutput: 8192,
423
+ vision: true,
424
+ agentic: true,
425
+ toolCalling: true,
426
+ },
427
+ {
428
+ id: "anthropic/claude-sonnet-4.6",
429
+ name: "Claude Sonnet 4.6",
430
+ version: "4.6",
431
+ inputPrice: 3.0,
432
+ outputPrice: 15.0,
433
+ contextWindow: 200000,
434
+ maxOutput: 64000,
435
+ reasoning: true,
436
+ vision: true,
437
+ agentic: true,
438
+ toolCalling: true,
439
+ },
440
+ {
441
+ id: "anthropic/claude-opus-4.6",
442
+ name: "Claude Opus 4.6",
443
+ version: "4.6",
444
+ inputPrice: 5.0,
445
+ outputPrice: 25.0,
446
+ contextWindow: 200000,
447
+ maxOutput: 32000,
448
+ reasoning: true,
449
+ vision: true,
450
+ agentic: true,
451
+ toolCalling: true,
452
+ },
453
+ // Google
454
+ {
455
+ id: "google/gemini-3.1-pro",
456
+ name: "Gemini 3.1 Pro",
457
+ version: "3.1",
458
+ inputPrice: 2.0,
459
+ outputPrice: 12.0,
460
+ contextWindow: 1050000,
461
+ maxOutput: 65536,
462
+ reasoning: true,
463
+ vision: true,
464
+ toolCalling: true,
465
+ },
466
+ {
467
+ id: "google/gemini-3-pro-preview",
468
+ name: "Gemini 3 Pro Preview",
469
+ version: "3.0",
470
+ inputPrice: 2.0,
471
+ outputPrice: 12.0,
472
+ contextWindow: 1050000,
473
+ maxOutput: 65536,
474
+ reasoning: true,
475
+ vision: true,
476
+ toolCalling: true,
477
+ },
478
+ {
479
+ id: "google/gemini-3-flash-preview",
480
+ name: "Gemini 3 Flash Preview",
481
+ version: "3.0",
482
+ inputPrice: 0.5,
483
+ outputPrice: 3.0,
484
+ contextWindow: 1000000,
485
+ maxOutput: 65536,
486
+ vision: true,
487
+ },
488
+ {
489
+ id: "google/gemini-2.5-pro",
490
+ name: "Gemini 2.5 Pro",
491
+ version: "2.5",
492
+ inputPrice: 1.25,
493
+ outputPrice: 10.0,
494
+ contextWindow: 1050000,
495
+ maxOutput: 65536,
496
+ reasoning: true,
497
+ vision: true,
498
+ toolCalling: true,
499
+ },
500
+ {
501
+ id: "google/gemini-2.5-flash",
502
+ name: "Gemini 2.5 Flash",
503
+ version: "2.5",
504
+ inputPrice: 0.3,
505
+ outputPrice: 2.5,
506
+ contextWindow: 1000000,
507
+ maxOutput: 65536,
508
+ vision: true,
509
+ toolCalling: true,
510
+ },
511
+ {
512
+ id: "google/gemini-2.5-flash-lite",
513
+ name: "Gemini 2.5 Flash Lite",
514
+ version: "2.5",
515
+ inputPrice: 0.1,
516
+ outputPrice: 0.4,
517
+ contextWindow: 1000000,
518
+ maxOutput: 65536,
519
+ toolCalling: true,
520
+ },
521
+ {
522
+ id: "google/gemini-3.1-flash-lite",
523
+ name: "Gemini 3.1 Flash Lite",
524
+ version: "3.1",
525
+ inputPrice: 0.25,
526
+ outputPrice: 1.5,
527
+ contextWindow: 1000000,
528
+ maxOutput: 8192,
529
+ toolCalling: true,
530
+ },
531
+ // DeepSeek
532
+ {
533
+ id: "deepseek/deepseek-chat",
534
+ name: "DeepSeek V3.2 Chat",
535
+ version: "3.2",
536
+ inputPrice: 0.28,
537
+ outputPrice: 0.42,
538
+ contextWindow: 128000,
539
+ maxOutput: 8192,
540
+ toolCalling: true,
541
+ },
542
+ {
543
+ id: "deepseek/deepseek-reasoner",
544
+ name: "DeepSeek V3.2 Reasoner",
545
+ version: "3.2",
546
+ inputPrice: 0.28,
547
+ outputPrice: 0.42,
548
+ contextWindow: 128000,
549
+ maxOutput: 8192,
550
+ reasoning: true,
551
+ toolCalling: true,
552
+ },
553
+ // Moonshot / Kimi - optimized for agentic workflows
554
+ {
555
+ id: "moonshot/kimi-k2.5",
556
+ name: "Kimi K2.5",
557
+ version: "k2.5",
558
+ inputPrice: 0.6,
559
+ outputPrice: 3.0,
560
+ contextWindow: 262144,
561
+ maxOutput: 8192,
562
+ reasoning: true,
563
+ vision: true,
564
+ agentic: true,
565
+ toolCalling: true,
566
+ },
567
+ // xAI / Grok
568
+ {
569
+ id: "xai/grok-3",
570
+ name: "Grok 3",
571
+ version: "3",
572
+ inputPrice: 3.0,
573
+ outputPrice: 15.0,
574
+ contextWindow: 131072,
575
+ maxOutput: 16384,
576
+ reasoning: true,
577
+ toolCalling: true,
578
+ },
579
+ // grok-3-fast removed - too expensive ($5/$25), use grok-4-fast instead
580
+ {
581
+ id: "xai/grok-3-mini",
582
+ name: "Grok 3 Mini",
583
+ version: "3-mini",
584
+ inputPrice: 0.3,
585
+ outputPrice: 0.5,
586
+ contextWindow: 131072,
587
+ maxOutput: 16384,
588
+ toolCalling: true,
589
+ },
590
+ // xAI Grok 4 Family - Ultra-cheap fast models
591
+ {
592
+ id: "xai/grok-4-fast-reasoning",
593
+ name: "Grok 4 Fast Reasoning",
594
+ version: "4",
595
+ inputPrice: 0.2,
596
+ outputPrice: 0.5,
597
+ contextWindow: 131072,
598
+ maxOutput: 16384,
599
+ reasoning: true,
600
+ toolCalling: true,
601
+ },
602
+ {
603
+ id: "xai/grok-4-fast-non-reasoning",
604
+ name: "Grok 4 Fast",
605
+ version: "4",
606
+ inputPrice: 0.2,
607
+ outputPrice: 0.5,
608
+ contextWindow: 131072,
609
+ maxOutput: 16384,
610
+ toolCalling: true,
611
+ },
612
+ {
613
+ id: "xai/grok-4-1-fast-reasoning",
614
+ name: "Grok 4.1 Fast Reasoning",
615
+ version: "4.1",
616
+ inputPrice: 0.2,
617
+ outputPrice: 0.5,
618
+ contextWindow: 131072,
619
+ maxOutput: 16384,
620
+ reasoning: true,
621
+ toolCalling: true,
622
+ },
623
+ {
624
+ id: "xai/grok-4-1-fast-non-reasoning",
625
+ name: "Grok 4.1 Fast",
626
+ version: "4.1",
627
+ inputPrice: 0.2,
628
+ outputPrice: 0.5,
629
+ contextWindow: 131072,
630
+ maxOutput: 16384,
631
+ toolCalling: true,
632
+ },
633
+ // xai/grok-code-fast-1 delisted 2026-03-12: poor retention (coding users churn),
634
+ // no structured tool calling, alias "grok-code" redirected to deepseek-chat
635
+ {
636
+ id: "xai/grok-4-0709",
637
+ name: "Grok 4 (0709)",
638
+ version: "4-0709",
639
+ inputPrice: 3.0,
640
+ outputPrice: 15.0,
641
+ contextWindow: 131072,
642
+ maxOutput: 16384,
643
+ reasoning: true,
644
+ toolCalling: true,
645
+ },
646
+ {
647
+ id: "xai/grok-2-vision",
648
+ name: "Grok 2 Vision",
649
+ version: "2",
650
+ inputPrice: 2.0,
651
+ outputPrice: 10.0,
652
+ contextWindow: 131072,
653
+ maxOutput: 16384,
654
+ vision: true,
655
+ toolCalling: true,
656
+ },
657
+ // MiniMax
658
+ {
659
+ id: "minimax/minimax-m2.7",
660
+ name: "MiniMax M2.7",
661
+ version: "m2.7",
662
+ inputPrice: 0.3,
663
+ outputPrice: 1.2,
664
+ contextWindow: 204800,
665
+ maxOutput: 16384,
666
+ reasoning: true,
667
+ agentic: true,
668
+ toolCalling: true,
669
+ },
670
+ {
671
+ id: "minimax/minimax-m2.5",
672
+ name: "MiniMax M2.5",
673
+ version: "m2.5",
674
+ inputPrice: 0.3,
675
+ outputPrice: 1.2,
676
+ contextWindow: 204800,
677
+ maxOutput: 16384,
678
+ reasoning: true,
679
+ agentic: true,
680
+ toolCalling: true,
681
+ },
682
+ // Free models (hosted by NVIDIA, billingMode: "free" on server)
683
+ // IDs use "free/" prefix so users see them as free in the /model picker.
684
+ // ClawRouter maps free/xxx → nvidia/xxx before sending to BlockRun upstream.
685
+ // toolCalling intentionally omitted: structured function calling unverified.
686
+ {
687
+ id: "free/gpt-oss-120b",
688
+ name: "[Free] GPT-OSS 120B",
689
+ version: "120b",
690
+ inputPrice: 0,
691
+ outputPrice: 0,
692
+ contextWindow: 128000,
693
+ maxOutput: 16384,
694
+ },
695
+ {
696
+ id: "free/gpt-oss-20b",
697
+ name: "[Free] GPT-OSS 20B",
698
+ version: "20b",
699
+ inputPrice: 0,
700
+ outputPrice: 0,
701
+ contextWindow: 128000,
702
+ maxOutput: 16384,
703
+ },
704
+ {
705
+ id: "free/nemotron-ultra-253b",
706
+ name: "[Free] Nemotron Ultra 253B",
707
+ version: "253b",
708
+ inputPrice: 0,
709
+ outputPrice: 0,
710
+ contextWindow: 131072,
711
+ maxOutput: 16384,
712
+ reasoning: true,
713
+ },
714
+ {
715
+ id: "free/nemotron-3-super-120b",
716
+ name: "[Free] Nemotron 3 Super 120B",
717
+ version: "3-super-120b",
718
+ inputPrice: 0,
719
+ outputPrice: 0,
720
+ contextWindow: 131072,
721
+ maxOutput: 16384,
722
+ reasoning: true,
723
+ },
724
+ {
725
+ id: "free/nemotron-super-49b",
726
+ name: "[Free] Nemotron Super 49B",
727
+ version: "super-49b",
728
+ inputPrice: 0,
729
+ outputPrice: 0,
730
+ contextWindow: 131072,
731
+ maxOutput: 16384,
732
+ reasoning: true,
733
+ },
734
+ {
735
+ id: "free/deepseek-v3.2",
736
+ name: "[Free] DeepSeek V3.2",
737
+ version: "v3.2",
738
+ inputPrice: 0,
739
+ outputPrice: 0,
740
+ contextWindow: 131072,
741
+ maxOutput: 16384,
742
+ reasoning: true,
743
+ },
744
+ {
745
+ id: "free/mistral-large-3-675b",
746
+ name: "[Free] Mistral Large 675B",
747
+ version: "3-675b",
748
+ inputPrice: 0,
749
+ outputPrice: 0,
750
+ contextWindow: 131072,
751
+ maxOutput: 16384,
752
+ reasoning: true,
753
+ },
754
+ {
755
+ id: "free/qwen3-coder-480b",
756
+ name: "[Free] Qwen3 Coder 480B",
757
+ version: "480b",
758
+ inputPrice: 0,
759
+ outputPrice: 0,
760
+ contextWindow: 131072,
761
+ maxOutput: 16384,
762
+ },
763
+ {
764
+ id: "free/devstral-2-123b",
765
+ name: "[Free] Devstral 2 123B",
766
+ version: "2-123b",
767
+ inputPrice: 0,
768
+ outputPrice: 0,
769
+ contextWindow: 131072,
770
+ maxOutput: 16384,
771
+ },
772
+ {
773
+ id: "free/glm-4.7",
774
+ name: "[Free] GLM-4.7",
775
+ version: "4.7",
776
+ inputPrice: 0,
777
+ outputPrice: 0,
778
+ contextWindow: 131072,
779
+ maxOutput: 16384,
780
+ reasoning: true,
781
+ },
782
+ {
783
+ id: "free/llama-4-maverick",
784
+ name: "[Free] Llama 4 Maverick",
785
+ version: "4-maverick",
786
+ inputPrice: 0,
787
+ outputPrice: 0,
788
+ contextWindow: 131072,
789
+ maxOutput: 16384,
790
+ reasoning: true,
791
+ },
792
+ // NVIDIA - Paid models
793
+ {
794
+ id: "nvidia/kimi-k2.5",
795
+ name: "NVIDIA Kimi K2.5",
796
+ version: "k2.5",
797
+ inputPrice: 0.6,
798
+ outputPrice: 3.0,
799
+ contextWindow: 262144,
800
+ maxOutput: 16384,
801
+ toolCalling: true,
802
+ },
803
+ // Z.AI GLM-5 Models
804
+ {
805
+ id: "zai/glm-5",
806
+ name: "GLM-5",
807
+ version: "5",
808
+ inputPrice: 1.0,
809
+ outputPrice: 3.2,
810
+ contextWindow: 200000,
811
+ maxOutput: 128000,
812
+ toolCalling: true,
813
+ promo: { flatPrice: 0.001, startDate: "2026-04-01", endDate: "2026-04-15" },
814
+ },
815
+ {
816
+ id: "zai/glm-5-turbo",
817
+ name: "GLM-5 Turbo",
818
+ version: "5-turbo",
819
+ inputPrice: 1.2,
820
+ outputPrice: 4.0,
821
+ contextWindow: 200000,
822
+ maxOutput: 128000,
823
+ toolCalling: true,
824
+ },
825
+ ];
826
+ /**
827
+ * Get the active flat promo price for a model, or undefined if no promo / expired.
828
+ */
829
+ export function getActivePromoPrice(model, now = new Date()) {
830
+ if (!model.promo)
831
+ return undefined;
832
+ const start = new Date(model.promo.startDate);
833
+ const end = new Date(model.promo.endDate);
834
+ if (now >= start && now < end)
835
+ return model.promo.flatPrice;
836
+ return undefined;
837
+ }
838
+ /**
839
+ * Convert BlockRun model definitions to OpenClaw ModelDefinitionConfig format.
840
+ */
841
+ function toOpenClawModel(m) {
842
+ return {
843
+ id: m.id,
844
+ name: m.name,
845
+ api: "openai-completions",
846
+ reasoning: m.reasoning ?? false,
847
+ input: m.vision ? ["text", "image"] : ["text"],
848
+ cost: {
849
+ input: m.inputPrice,
850
+ output: m.outputPrice,
851
+ cacheRead: 0,
852
+ cacheWrite: 0,
853
+ },
854
+ contextWindow: m.contextWindow,
855
+ maxTokens: m.maxOutput,
856
+ };
857
+ }
858
+ /**
859
+ * Alias models that map to real models.
860
+ * These allow users to use friendly names like "free" or "gpt-120b".
861
+ */
862
+ const ALIAS_MODELS = Object.entries(MODEL_ALIASES)
863
+ .map(([alias, targetId]) => {
864
+ const target = BLOCKRUN_MODELS.find((m) => m.id === targetId);
865
+ if (!target)
866
+ return null;
867
+ return toOpenClawModel({ ...target, id: alias, name: `${alias} → ${target.name}` });
868
+ })
869
+ .filter((m) => m !== null);
870
+ /**
871
+ * All BlockRun models in OpenClaw format (including aliases).
872
+ */
873
+ export const OPENCLAW_MODELS = [
874
+ ...BLOCKRUN_MODELS.map(toOpenClawModel),
875
+ ...ALIAS_MODELS,
876
+ ];
877
+ /**
878
+ * Build a ModelProviderConfig for BlockRun.
879
+ *
880
+ * @param baseUrl - The proxy's local base URL (e.g., "http://127.0.0.1:12345")
881
+ */
882
+ export function buildProviderModels(baseUrl) {
883
+ return {
884
+ baseUrl: `${baseUrl}/v1`,
885
+ api: "openai-completions",
886
+ models: OPENCLAW_MODELS,
887
+ };
888
+ }
889
+ /**
890
+ * Check if a model is optimized for agentic workflows.
891
+ * Agentic models continue autonomously with multi-step tasks
892
+ * instead of stopping and waiting for user input.
893
+ */
894
+ export function isAgenticModel(modelId) {
895
+ const model = BLOCKRUN_MODELS.find((m) => m.id === modelId || m.id === modelId.replace("blockrun/", ""));
896
+ return model?.agentic ?? false;
897
+ }
898
+ /**
899
+ * Get all agentic-capable models.
900
+ */
901
+ export function getAgenticModels() {
902
+ return BLOCKRUN_MODELS.filter((m) => m.agentic).map((m) => m.id);
903
+ }
904
+ /**
905
+ * Check if a model supports OpenAI-compatible structured tool/function calling.
906
+ * Models without this flag (e.g. grok-code-fast-1) output tool invocations as
907
+ * plain text JSON, which leaks {"command":"..."} into visible chat messages.
908
+ */
909
+ export function supportsToolCalling(modelId) {
910
+ const normalized = modelId.replace("blockrun/", "");
911
+ const model = BLOCKRUN_MODELS.find((m) => m.id === normalized);
912
+ return model?.toolCalling ?? false;
913
+ }
914
+ /**
915
+ * Check if a model supports vision (image inputs).
916
+ * Models without this flag cannot process image_url content parts.
917
+ */
918
+ export function supportsVision(modelId) {
919
+ const normalized = modelId.replace("blockrun/", "");
920
+ const model = BLOCKRUN_MODELS.find((m) => m.id === normalized);
921
+ return model?.vision ?? false;
922
+ }
923
+ /**
924
+ * Get context window size for a model.
925
+ * Returns undefined if model not found.
926
+ */
927
+ export function getModelContextWindow(modelId) {
928
+ const normalized = modelId.replace("blockrun/", "");
929
+ const model = BLOCKRUN_MODELS.find((m) => m.id === normalized);
930
+ return model?.contextWindow;
931
+ }
932
+ /**
933
+ * Check if a model has reasoning/thinking capabilities.
934
+ * Reasoning models may require reasoning_content in assistant tool_call messages.
935
+ */
936
+ export function isReasoningModel(modelId) {
937
+ const normalized = modelId.replace("blockrun/", "");
938
+ const model = BLOCKRUN_MODELS.find((m) => m.id === normalized);
939
+ return model?.reasoning ?? false;
940
+ }
941
+ //# sourceMappingURL=models.js.map