@slkiser/opencode-quota 4.0.1 → 4.2.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 (358) hide show
  1. package/README.md +94 -28
  2. package/dist/bin/opencode-quota.d.ts.map +1 -1
  3. package/dist/bin/opencode-quota.js +8 -0
  4. package/dist/bin/opencode-quota.js.map +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/lib/anthropic.d.ts.map +1 -1
  8. package/dist/lib/anthropic.js +78 -72
  9. package/dist/lib/anthropic.js.map +1 -1
  10. package/dist/lib/api-key-resolver.d.ts +73 -22
  11. package/dist/lib/api-key-resolver.d.ts.map +1 -1
  12. package/dist/lib/api-key-resolver.js +116 -39
  13. package/dist/lib/api-key-resolver.js.map +1 -1
  14. package/dist/lib/atomic-json.d.ts +3 -1
  15. package/dist/lib/atomic-json.d.ts.map +1 -1
  16. package/dist/lib/atomic-json.js +23 -9
  17. package/dist/lib/atomic-json.js.map +1 -1
  18. package/dist/lib/chutes-config.d.ts.map +1 -1
  19. package/dist/lib/chutes-config.js +2 -4
  20. package/dist/lib/chutes-config.js.map +1 -1
  21. package/dist/lib/chutes.d.ts.map +1 -1
  22. package/dist/lib/chutes.js +28 -23
  23. package/dist/lib/chutes.js.map +1 -1
  24. package/dist/lib/cli-show.d.ts +9 -0
  25. package/dist/lib/cli-show.d.ts.map +1 -1
  26. package/dist/lib/cli-show.js +34 -5
  27. package/dist/lib/cli-show.js.map +1 -1
  28. package/dist/lib/cli-status.d.ts +8 -0
  29. package/dist/lib/cli-status.d.ts.map +1 -0
  30. package/dist/lib/cli-status.js +125 -0
  31. package/dist/lib/cli-status.js.map +1 -0
  32. package/dist/lib/config.d.ts +1 -1
  33. package/dist/lib/config.d.ts.map +1 -1
  34. package/dist/lib/config.js +47 -12
  35. package/dist/lib/config.js.map +1 -1
  36. package/dist/lib/copilot.d.ts +11 -5
  37. package/dist/lib/copilot.d.ts.map +1 -1
  38. package/dist/lib/copilot.js +378 -79
  39. package/dist/lib/copilot.js.map +1 -1
  40. package/dist/lib/deepseek-auth.d.ts.map +1 -1
  41. package/dist/lib/deepseek-auth.js +3 -7
  42. package/dist/lib/deepseek-auth.js.map +1 -1
  43. package/dist/lib/deepseek.d.ts.map +1 -1
  44. package/dist/lib/deepseek.js +22 -17
  45. package/dist/lib/deepseek.js.map +1 -1
  46. package/dist/lib/display-sanitize.d.ts.map +1 -1
  47. package/dist/lib/display-sanitize.js +8 -0
  48. package/dist/lib/display-sanitize.js.map +1 -1
  49. package/dist/lib/entries.d.ts +14 -0
  50. package/dist/lib/entries.d.ts.map +1 -1
  51. package/dist/lib/entries.js.map +1 -1
  52. package/dist/lib/format-utils.d.ts +7 -0
  53. package/dist/lib/format-utils.d.ts.map +1 -1
  54. package/dist/lib/format-utils.js +18 -0
  55. package/dist/lib/format-utils.js.map +1 -1
  56. package/dist/lib/format.d.ts +1 -0
  57. package/dist/lib/format.d.ts.map +1 -1
  58. package/dist/lib/format.js +22 -7
  59. package/dist/lib/format.js.map +1 -1
  60. package/dist/lib/glm-coding-plan.d.ts +18 -0
  61. package/dist/lib/glm-coding-plan.d.ts.map +1 -0
  62. package/dist/lib/glm-coding-plan.js +68 -0
  63. package/dist/lib/glm-coding-plan.js.map +1 -0
  64. package/dist/lib/google-agy-companion.d.ts +4 -25
  65. package/dist/lib/google-agy-companion.d.ts.map +1 -1
  66. package/dist/lib/google-agy-companion.js +47 -272
  67. package/dist/lib/google-agy-companion.js.map +1 -1
  68. package/dist/lib/google-agy.d.ts.map +1 -1
  69. package/dist/lib/google-agy.js +204 -111
  70. package/dist/lib/google-agy.js.map +1 -1
  71. package/dist/lib/google-antigravity-companion.d.ts +4 -25
  72. package/dist/lib/google-antigravity-companion.d.ts.map +1 -1
  73. package/dist/lib/google-antigravity-companion.js +44 -283
  74. package/dist/lib/google-antigravity-companion.js.map +1 -1
  75. package/dist/lib/google-companion-credentials.d.ts +70 -0
  76. package/dist/lib/google-companion-credentials.d.ts.map +1 -0
  77. package/dist/lib/google-companion-credentials.js +265 -0
  78. package/dist/lib/google-companion-credentials.js.map +1 -0
  79. package/dist/lib/google-gemini-cli-companion.d.ts +4 -25
  80. package/dist/lib/google-gemini-cli-companion.d.ts.map +1 -1
  81. package/dist/lib/google-gemini-cli-companion.js +47 -258
  82. package/dist/lib/google-gemini-cli-companion.js.map +1 -1
  83. package/dist/lib/google-gemini-cli.d.ts.map +1 -1
  84. package/dist/lib/google-gemini-cli.js +55 -61
  85. package/dist/lib/google-gemini-cli.js.map +1 -1
  86. package/dist/lib/google-token-cache.d.ts.map +1 -1
  87. package/dist/lib/google-token-cache.js +87 -34
  88. package/dist/lib/google-token-cache.js.map +1 -1
  89. package/dist/lib/google.d.ts.map +1 -1
  90. package/dist/lib/google.js +80 -84
  91. package/dist/lib/google.js.map +1 -1
  92. package/dist/lib/grouped-entry-normalization.d.ts.map +1 -1
  93. package/dist/lib/grouped-entry-normalization.js +7 -1
  94. package/dist/lib/grouped-entry-normalization.js.map +1 -1
  95. package/dist/lib/http.d.ts +12 -7
  96. package/dist/lib/http.d.ts.map +1 -1
  97. package/dist/lib/http.js +28 -15
  98. package/dist/lib/http.js.map +1 -1
  99. package/dist/lib/init-installer.d.ts +2 -1
  100. package/dist/lib/init-installer.d.ts.map +1 -1
  101. package/dist/lib/init-installer.js +29 -2
  102. package/dist/lib/init-installer.js.map +1 -1
  103. package/dist/lib/kimi-auth.d.ts +3 -26
  104. package/dist/lib/kimi-auth.d.ts.map +1 -1
  105. package/dist/lib/kimi-auth.js +24 -91
  106. package/dist/lib/kimi-auth.js.map +1 -1
  107. package/dist/lib/kimi.d.ts.map +1 -1
  108. package/dist/lib/kimi.js +20 -15
  109. package/dist/lib/kimi.js.map +1 -1
  110. package/dist/lib/maintainer-announcements.d.ts.map +1 -1
  111. package/dist/lib/maintainer-announcements.js +5 -0
  112. package/dist/lib/maintainer-announcements.js.map +1 -1
  113. package/dist/lib/map-with-concurrency.d.ts +2 -0
  114. package/dist/lib/map-with-concurrency.d.ts.map +1 -0
  115. package/dist/lib/map-with-concurrency.js +17 -0
  116. package/dist/lib/map-with-concurrency.js.map +1 -0
  117. package/dist/lib/mimo-config.d.ts +29 -0
  118. package/dist/lib/mimo-config.d.ts.map +1 -0
  119. package/dist/lib/mimo-config.js +147 -0
  120. package/dist/lib/mimo-config.js.map +1 -0
  121. package/dist/lib/mimo.d.ts +35 -0
  122. package/dist/lib/mimo.d.ts.map +1 -0
  123. package/dist/lib/mimo.js +236 -0
  124. package/dist/lib/mimo.js.map +1 -0
  125. package/dist/lib/modelsdev-pricing.d.ts.map +1 -1
  126. package/dist/lib/modelsdev-pricing.js +39 -27
  127. package/dist/lib/modelsdev-pricing.js.map +1 -1
  128. package/dist/lib/nanogpt-config.d.ts.map +1 -1
  129. package/dist/lib/nanogpt-config.js +2 -4
  130. package/dist/lib/nanogpt-config.js.map +1 -1
  131. package/dist/lib/nanogpt.d.ts.map +1 -1
  132. package/dist/lib/nanogpt.js +40 -30
  133. package/dist/lib/nanogpt.js.map +1 -1
  134. package/dist/lib/ollama-cloud.d.ts +1 -1
  135. package/dist/lib/ollama-cloud.d.ts.map +1 -1
  136. package/dist/lib/ollama-cloud.js +73 -68
  137. package/dist/lib/ollama-cloud.js.map +1 -1
  138. package/dist/lib/openai.d.ts.map +1 -1
  139. package/dist/lib/openai.js +53 -48
  140. package/dist/lib/openai.js.map +1 -1
  141. package/dist/lib/opencode-config-providers.d.ts.map +1 -1
  142. package/dist/lib/opencode-config-providers.js +13 -16
  143. package/dist/lib/opencode-config-providers.js.map +1 -1
  144. package/dist/lib/opencode-config-read.d.ts +23 -0
  145. package/dist/lib/opencode-config-read.d.ts.map +1 -0
  146. package/dist/lib/opencode-config-read.js +30 -0
  147. package/dist/lib/opencode-config-read.js.map +1 -0
  148. package/dist/lib/opencode-go.d.ts.map +1 -1
  149. package/dist/lib/opencode-go.js +44 -39
  150. package/dist/lib/opencode-go.js.map +1 -1
  151. package/dist/lib/opencode-zen-config.d.ts +34 -0
  152. package/dist/lib/opencode-zen-config.d.ts.map +1 -0
  153. package/dist/lib/opencode-zen-config.js +103 -0
  154. package/dist/lib/opencode-zen-config.js.map +1 -0
  155. package/dist/lib/opencode-zen.d.ts +27 -0
  156. package/dist/lib/opencode-zen.d.ts.map +1 -0
  157. package/dist/lib/opencode-zen.js +143 -0
  158. package/dist/lib/opencode-zen.js.map +1 -0
  159. package/dist/lib/openrouter.d.ts +13 -0
  160. package/dist/lib/openrouter.d.ts.map +1 -0
  161. package/dist/lib/openrouter.js +41 -0
  162. package/dist/lib/openrouter.js.map +1 -0
  163. package/dist/lib/provider-add-command.d.ts.map +1 -1
  164. package/dist/lib/provider-add-command.js +4 -12
  165. package/dist/lib/provider-add-command.js.map +1 -1
  166. package/dist/lib/provider-add-json-v1-questionnaire.d.ts +32 -0
  167. package/dist/lib/provider-add-json-v1-questionnaire.d.ts.map +1 -0
  168. package/dist/lib/provider-add-json-v1-questionnaire.js +336 -0
  169. package/dist/lib/provider-add-json-v1-questionnaire.js.map +1 -0
  170. package/dist/lib/provider-availability.d.ts +2 -2
  171. package/dist/lib/provider-availability.d.ts.map +1 -1
  172. package/dist/lib/provider-availability.js +2 -3
  173. package/dist/lib/provider-availability.js.map +1 -1
  174. package/dist/lib/provider-metadata.d.ts +300 -1
  175. package/dist/lib/provider-metadata.d.ts.map +1 -1
  176. package/dist/lib/provider-metadata.js +332 -227
  177. package/dist/lib/provider-metadata.js.map +1 -1
  178. package/dist/lib/quota-command-format.d.ts.map +1 -1
  179. package/dist/lib/quota-command-format.js +12 -16
  180. package/dist/lib/quota-command-format.js.map +1 -1
  181. package/dist/lib/quota-dialog-commands.d.ts +59 -2
  182. package/dist/lib/quota-dialog-commands.d.ts.map +1 -1
  183. package/dist/lib/quota-dialog-commands.js +73 -39
  184. package/dist/lib/quota-dialog-commands.js.map +1 -1
  185. package/dist/lib/quota-entry-display.d.ts +2 -0
  186. package/dist/lib/quota-entry-display.d.ts.map +1 -1
  187. package/dist/lib/quota-entry-display.js +27 -13
  188. package/dist/lib/quota-entry-display.js.map +1 -1
  189. package/dist/lib/quota-providers-remote.d.ts +0 -1
  190. package/dist/lib/quota-providers-remote.d.ts.map +1 -1
  191. package/dist/lib/quota-providers-remote.js +3 -16
  192. package/dist/lib/quota-providers-remote.js.map +1 -1
  193. package/dist/lib/quota-render-data.d.ts +4 -0
  194. package/dist/lib/quota-render-data.d.ts.map +1 -1
  195. package/dist/lib/quota-render-data.js +118 -127
  196. package/dist/lib/quota-render-data.js.map +1 -1
  197. package/dist/lib/quota-runtime-context.d.ts +9 -1
  198. package/dist/lib/quota-runtime-context.d.ts.map +1 -1
  199. package/dist/lib/quota-runtime-context.js +5 -0
  200. package/dist/lib/quota-runtime-context.js.map +1 -1
  201. package/dist/lib/quota-state.d.ts.map +1 -1
  202. package/dist/lib/quota-state.js +25 -1
  203. package/dist/lib/quota-state.js.map +1 -1
  204. package/dist/lib/quota-stats.d.ts +1 -0
  205. package/dist/lib/quota-stats.d.ts.map +1 -1
  206. package/dist/lib/quota-stats.js +14 -4
  207. package/dist/lib/quota-stats.js.map +1 -1
  208. package/dist/lib/quota-status.d.ts +7 -17
  209. package/dist/lib/quota-status.d.ts.map +1 -1
  210. package/dist/lib/quota-status.js +123 -948
  211. package/dist/lib/quota-status.js.map +1 -1
  212. package/dist/lib/runtime-provider-ids.d.ts +4 -0
  213. package/dist/lib/runtime-provider-ids.d.ts.map +1 -0
  214. package/dist/lib/runtime-provider-ids.js +10 -0
  215. package/dist/lib/runtime-provider-ids.js.map +1 -0
  216. package/dist/lib/session-tokens.d.ts +2 -0
  217. package/dist/lib/session-tokens.d.ts.map +1 -1
  218. package/dist/lib/session-tokens.js +4 -2
  219. package/dist/lib/session-tokens.js.map +1 -1
  220. package/dist/lib/synthetic-config.d.ts.map +1 -1
  221. package/dist/lib/synthetic-config.js +2 -4
  222. package/dist/lib/synthetic-config.js.map +1 -1
  223. package/dist/lib/synthetic.d.ts.map +1 -1
  224. package/dist/lib/synthetic.js +37 -32
  225. package/dist/lib/synthetic.js.map +1 -1
  226. package/dist/lib/toast-format-grouped.d.ts +1 -0
  227. package/dist/lib/toast-format-grouped.d.ts.map +1 -1
  228. package/dist/lib/toast-format-grouped.js +33 -29
  229. package/dist/lib/toast-format-grouped.js.map +1 -1
  230. package/dist/lib/tui-refresh-lifecycle.d.ts +17 -0
  231. package/dist/lib/tui-refresh-lifecycle.d.ts.map +1 -0
  232. package/dist/lib/tui-refresh-lifecycle.js +83 -0
  233. package/dist/lib/tui-refresh-lifecycle.js.map +1 -0
  234. package/dist/lib/tui-runtime.d.ts +0 -5
  235. package/dist/lib/tui-runtime.d.ts.map +1 -1
  236. package/dist/lib/tui-runtime.js +1 -6
  237. package/dist/lib/tui-runtime.js.map +1 -1
  238. package/dist/lib/tui-sidebar-format.d.ts +1 -1
  239. package/dist/lib/tui-sidebar-format.d.ts.map +1 -1
  240. package/dist/lib/tui-sidebar-format.js +1 -0
  241. package/dist/lib/tui-sidebar-format.js.map +1 -1
  242. package/dist/lib/types.d.ts +72 -8
  243. package/dist/lib/types.d.ts.map +1 -1
  244. package/dist/lib/types.js +2 -0
  245. package/dist/lib/types.js.map +1 -1
  246. package/dist/lib/xai.d.ts +39 -0
  247. package/dist/lib/xai.d.ts.map +1 -0
  248. package/dist/lib/xai.js +153 -0
  249. package/dist/lib/xai.js.map +1 -0
  250. package/dist/lib/zai-auth.d.ts +3 -26
  251. package/dist/lib/zai-auth.d.ts.map +1 -1
  252. package/dist/lib/zai-auth.js +24 -94
  253. package/dist/lib/zai-auth.js.map +1 -1
  254. package/dist/lib/zai.d.ts +1 -8
  255. package/dist/lib/zai.d.ts.map +1 -1
  256. package/dist/lib/zai.js +11 -91
  257. package/dist/lib/zai.js.map +1 -1
  258. package/dist/lib/zhipu-auth.d.ts +3 -26
  259. package/dist/lib/zhipu-auth.d.ts.map +1 -1
  260. package/dist/lib/zhipu-auth.js +24 -94
  261. package/dist/lib/zhipu-auth.js.map +1 -1
  262. package/dist/lib/zhipu.d.ts +1 -8
  263. package/dist/lib/zhipu.d.ts.map +1 -1
  264. package/dist/lib/zhipu.js +10 -84
  265. package/dist/lib/zhipu.js.map +1 -1
  266. package/dist/plugin.d.ts.map +1 -1
  267. package/dist/plugin.js +20 -145
  268. package/dist/plugin.js.map +1 -1
  269. package/dist/providers/alibaba-coding-plan.d.ts.map +1 -1
  270. package/dist/providers/alibaba-coding-plan.js +33 -6
  271. package/dist/providers/alibaba-coding-plan.js.map +1 -1
  272. package/dist/providers/anthropic.d.ts.map +1 -1
  273. package/dist/providers/anthropic.js +35 -7
  274. package/dist/providers/anthropic.js.map +1 -1
  275. package/dist/providers/chutes.d.ts.map +1 -1
  276. package/dist/providers/chutes.js +10 -3
  277. package/dist/providers/chutes.js.map +1 -1
  278. package/dist/providers/copilot.d.ts.map +1 -1
  279. package/dist/providers/copilot.js +102 -31
  280. package/dist/providers/copilot.js.map +1 -1
  281. package/dist/providers/cursor.d.ts.map +1 -1
  282. package/dist/providers/cursor.js +34 -6
  283. package/dist/providers/cursor.js.map +1 -1
  284. package/dist/providers/deepseek.d.ts.map +1 -1
  285. package/dist/providers/deepseek.js +10 -3
  286. package/dist/providers/deepseek.js.map +1 -1
  287. package/dist/providers/glm-coding-plan-provider.d.ts +44 -0
  288. package/dist/providers/glm-coding-plan-provider.d.ts.map +1 -0
  289. package/dist/providers/glm-coding-plan-provider.js +62 -0
  290. package/dist/providers/glm-coding-plan-provider.js.map +1 -0
  291. package/dist/providers/google-agy.d.ts.map +1 -1
  292. package/dist/providers/google-agy.js +83 -42
  293. package/dist/providers/google-agy.js.map +1 -1
  294. package/dist/providers/google-antigravity.d.ts.map +1 -1
  295. package/dist/providers/google-antigravity.js +31 -6
  296. package/dist/providers/google-antigravity.js.map +1 -1
  297. package/dist/providers/google-gemini-cli.d.ts.map +1 -1
  298. package/dist/providers/google-gemini-cli.js +24 -6
  299. package/dist/providers/google-gemini-cli.js.map +1 -1
  300. package/dist/providers/kimi-code.d.ts.map +1 -1
  301. package/dist/providers/kimi-code.js +27 -8
  302. package/dist/providers/kimi-code.js.map +1 -1
  303. package/dist/providers/mimo.d.ts +3 -0
  304. package/dist/providers/mimo.d.ts.map +1 -0
  305. package/dist/providers/mimo.js +127 -0
  306. package/dist/providers/mimo.js.map +1 -0
  307. package/dist/providers/minimax-coding-plan.d.ts.map +1 -1
  308. package/dist/providers/minimax-coding-plan.js +68 -32
  309. package/dist/providers/minimax-coding-plan.js.map +1 -1
  310. package/dist/providers/nanogpt.d.ts.map +1 -1
  311. package/dist/providers/nanogpt.js +41 -4
  312. package/dist/providers/nanogpt.js.map +1 -1
  313. package/dist/providers/openai.d.ts.map +1 -1
  314. package/dist/providers/openai.js +20 -3
  315. package/dist/providers/openai.js.map +1 -1
  316. package/dist/providers/opencode-go.d.ts.map +1 -1
  317. package/dist/providers/opencode-go.js +33 -15
  318. package/dist/providers/opencode-go.js.map +1 -1
  319. package/dist/providers/opencode-zen.d.ts +3 -0
  320. package/dist/providers/opencode-zen.d.ts.map +1 -0
  321. package/dist/providers/opencode-zen.js +99 -0
  322. package/dist/providers/opencode-zen.js.map +1 -0
  323. package/dist/providers/openrouter.d.ts +6 -0
  324. package/dist/providers/openrouter.d.ts.map +1 -0
  325. package/dist/providers/openrouter.js +25 -0
  326. package/dist/providers/openrouter.js.map +1 -0
  327. package/dist/providers/quota-providers.d.ts.map +1 -1
  328. package/dist/providers/quota-providers.js +3 -3
  329. package/dist/providers/quota-providers.js.map +1 -1
  330. package/dist/providers/qwen-code.d.ts.map +1 -1
  331. package/dist/providers/qwen-code.js +19 -5
  332. package/dist/providers/qwen-code.js.map +1 -1
  333. package/dist/providers/registry.d.ts.map +1 -1
  334. package/dist/providers/registry.js +8 -0
  335. package/dist/providers/registry.js.map +1 -1
  336. package/dist/providers/result-helpers.d.ts +29 -1
  337. package/dist/providers/result-helpers.d.ts.map +1 -1
  338. package/dist/providers/result-helpers.js +69 -0
  339. package/dist/providers/result-helpers.js.map +1 -1
  340. package/dist/providers/synthetic.d.ts.map +1 -1
  341. package/dist/providers/synthetic.js +10 -3
  342. package/dist/providers/synthetic.js.map +1 -1
  343. package/dist/providers/xai.d.ts +6 -0
  344. package/dist/providers/xai.d.ts.map +1 -0
  345. package/dist/providers/xai.js +51 -0
  346. package/dist/providers/xai.js.map +1 -0
  347. package/dist/providers/zai.d.ts +1 -7
  348. package/dist/providers/zai.d.ts.map +1 -1
  349. package/dist/providers/zai.js +11 -46
  350. package/dist/providers/zai.js.map +1 -1
  351. package/dist/providers/zhipu.d.ts +1 -7
  352. package/dist/providers/zhipu.d.ts.map +1 -1
  353. package/dist/providers/zhipu.js +11 -46
  354. package/dist/providers/zhipu.js.map +1 -1
  355. package/dist/tui.d.ts.map +1 -1
  356. package/dist/tui.js +47 -136
  357. package/dist/tui.tsx +62 -179
  358. package/package.json +1 -1
@@ -1,51 +1,18 @@
1
- import { readFile, stat } from "fs/promises";
2
- import { getAuthPath, getAuthPaths, readAuthFileCached } from "./opencode-auth.js";
1
+ import { stat } from "fs/promises";
2
+ import { getAuthPath, getAuthPaths } from "./opencode-auth.js";
3
3
  import { getOpencodeRuntimeDirs } from "./opencode-runtime-paths.js";
4
- import { getGoogleTokenCachePath } from "./google-token-cache.js";
5
- import { inspectAntigravityCompanionPresence } from "./google-antigravity-companion.js";
6
- import { inspectGeminiCliCompanionPresence } from "./google-gemini-cli-companion.js";
7
- import { inspectGeminiCliAuthPresence } from "./google-gemini-cli.js";
8
- import { inspectAntigravityAccountsPresence } from "./google.js";
9
- import { inspectAgyCompanionPresence } from "./google-agy-companion.js";
10
- import { inspectAgyAuthPresence } from "./google-agy.js";
11
- import { getAnthropicDiagnostics } from "./anthropic.js";
12
- import { getChutesKeyDiagnostics } from "./chutes.js";
13
- import { getNanoGptKeyDiagnostics, queryNanoGptQuota } from "./nanogpt.js";
14
- import { getDeepSeekKeyDiagnostics } from "./deepseek.js";
15
- import { getSyntheticKeyDiagnostics } from "./synthetic.js";
16
- import { getCopilotQuotaAuthDiagnostics } from "./copilot.js";
17
- import { ALIBABA_CODING_PLAN_STATE_VERSION, QWEN_LOCAL_QUOTA_STATE_VERSION, getAlibabaCodingPlanQuotaPath, getQwenLocalQuotaPath, } from "./qwen-local-quota.js";
18
- import { DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS, getAlibabaCodingPlanAuthDiagnostics, resolveAlibabaCodingPlanAuthCached, } from "./alibaba-auth.js";
19
- import { hasQwenOAuthAuth, resolveQwenLocalPlan } from "./qwen-auth.js";
20
- import { resolveOpenAIOAuth } from "./openai.js";
21
- import { DEFAULT_MINIMAX_AUTH_CACHE_MAX_AGE_MS, getMiniMaxAuthDiagnostics, getMiniMaxChinaAuthDiagnostics, resolveMiniMaxAuthCached, resolveMiniMaxChinaAuthCached, } from "./minimax-auth.js";
22
- import { getMiniMaxQuotaEndpoint } from "./minimax-endpoints.js";
23
- import { DEFAULT_ZAI_AUTH_CACHE_MAX_AGE_MS, getZaiAuthDiagnostics } from "./zai-auth.js";
24
- import { DEFAULT_ZHIPU_AUTH_CACHE_MAX_AGE_MS, getZhipuAuthDiagnostics } from "./zhipu-auth.js";
25
- import { DEFAULT_KIMI_AUTH_CACHE_MAX_AGE_MS, getKimiAuthDiagnostics, } from "./kimi-auth.js";
26
- import { queryKimiQuota } from "./kimi.js";
27
4
  import { getPricingSnapshotHealth, getPricingRefreshPolicy, getPricingSnapshotMeta, getPricingSnapshotSource, getRuntimePricingRefreshStatePath, getRuntimePricingSnapshotPath, listProviders, getProviderModelCount, hasProvider as snapshotHasProvider, readPricingRefreshState, } from "./modelsdev-pricing.js";
28
5
  import { getProviders } from "../providers/registry.js";
29
6
  import { getPackageVersion } from "./version.js";
30
7
  import { getOpenCodeDbPath, getOpenCodeDbPathCandidates, getOpenCodeDbStats, } from "./opencode-storage.js";
31
8
  import { aggregateUsage } from "./quota-stats.js";
32
- import { fmtUsdAmount } from "./format-utils.js";
33
9
  import { renderPlainTextReport } from "./report-document.js";
34
10
  import { totalTokenBuckets } from "./token-buckets.js";
35
- import { CURSOR_CANONICAL_PLUGIN_PACKAGE, inspectCursorAuthPresence, inspectCursorOpenCodeIntegration, } from "./cursor-detection.js";
36
- import { getCurrentCursorUsageSummary } from "./cursor-usage.js";
37
- import { sanitizeSingleLineDisplaySnippet, sanitizeSingleLineDisplayText, sanitizeDisplayText, sanitizeQuotaProviderResult, } from "./display-sanitize.js";
11
+ import { sanitizeSingleLineDisplaySnippet, sanitizeSingleLineDisplayText, sanitizeQuotaProviderResult, } from "./display-sanitize.js";
38
12
  import { QUOTA_TOAST_SETTING_SOURCE_KEYS, } from "./config.js";
39
- import { getCursorPlanDisplayName, getEffectiveCursorIncludedApiUsd } from "./cursor-pricing.js";
40
13
  import { getQuotaProviderDisplayLabel } from "./provider-metadata.js";
41
14
  import { isMaintainedQuotaProviderTuning } from "./quota-providers.js";
42
- import { inspectLocalQuotaProviderState } from "./quota-providers-local.js";
43
15
  import { isValueEntry } from "./entries.js";
44
- import { queryMiniMaxQuota } from "../providers/minimax-coding-plan.js";
45
- import { queryZaiQuota } from "./zai.js";
46
- import { queryZhipuQuota } from "./zhipu.js";
47
- import { getOpenCodeGoConfigDiagnostics, resolveOpenCodeGoConfigCached, DEFAULT_OPENCODE_GO_CONFIG_CACHE_MAX_AGE_MS, } from "./opencode-go-config.js";
48
- import { queryOpenCodeGoQuota } from "./opencode-go.js";
49
16
  async function pathExists(path) {
50
17
  try {
51
18
  await stat(path);
@@ -55,37 +22,6 @@ async function pathExists(path) {
55
22
  return false;
56
23
  }
57
24
  }
58
- async function inspectGeneratedCounterFile(path, expectedVersion) {
59
- try {
60
- const parsed = JSON.parse(await readFile(path, "utf8"));
61
- const record = parsed && typeof parsed === "object" && !Array.isArray(parsed)
62
- ? parsed
63
- : null;
64
- const version = typeof record?.version === "number" ? record.version : null;
65
- const updatedAt = typeof record?.updatedAt === "number" && Number.isFinite(record.updatedAt)
66
- ? record.updatedAt
67
- : null;
68
- return {
69
- exists: true,
70
- health: !record || version === null || updatedAt === null
71
- ? "malformed"
72
- : version === expectedVersion
73
- ? "healthy"
74
- : "version_mismatch",
75
- version,
76
- lastUpdatedAt: updatedAt,
77
- };
78
- }
79
- catch (error) {
80
- if (error &&
81
- typeof error === "object" &&
82
- "code" in error &&
83
- String(error.code) === "ENOENT") {
84
- return { exists: false, health: "missing", version: null, lastUpdatedAt: null };
85
- }
86
- return { exists: true, health: "malformed", version: null, lastUpdatedAt: null };
87
- }
88
- }
89
25
  function fmtInt(n) {
90
26
  return Math.trunc(n).toLocaleString("en-US");
91
27
  }
@@ -93,31 +29,9 @@ const STATUS_SAMPLE_LIMIT = 5;
93
29
  const STATUS_LIVE_ENTRY_LIMIT = 2;
94
30
  const STATUS_LIVE_ERROR_LIMIT = 2;
95
31
  const STATUS_LIVE_ROW_MAX_LENGTH = 120;
96
- const OPENCODE_GO_STATUS_WINDOW_ORDER = ["rolling", "weekly", "monthly"];
97
- const OPENCODE_GO_STATUS_WINDOW_FIELDS = {
98
- rolling: "rollingUsage",
99
- weekly: "weeklyUsage",
100
- monthly: "monthlyUsage",
101
- };
102
32
  function joinOrNone(values) {
103
33
  return values.length > 0 ? values.join(" | ") : "(none)";
104
34
  }
105
- function formatOpenCodeGoWindowSelection(windows) {
106
- return windows.join(",");
107
- }
108
- function isDefaultOpenCodeGoStatusWindowSelection(windows) {
109
- const selected = new Set(windows);
110
- return (selected.size === OPENCODE_GO_STATUS_WINDOW_ORDER.length &&
111
- OPENCODE_GO_STATUS_WINDOW_ORDER.every((window) => selected.has(window)));
112
- }
113
- function formatOpenCodeGoMissingWindows(windows) {
114
- return windows
115
- .map((window) => `${window} (${OPENCODE_GO_STATUS_WINDOW_FIELDS[window]})`)
116
- .join(", ");
117
- }
118
- function formatOpenCodeGoUsage(window) {
119
- return `percent_used=${window.usagePercent} percent_remaining=${window.percentRemaining} reset_in_sec=${window.resetInSec} reset_at=${window.resetTimeIso}`;
120
- }
121
35
  function formatSettingSources(sources) {
122
36
  if (!sources)
123
37
  return "(none)";
@@ -136,24 +50,6 @@ function getConfigPrecedenceLabel(configSource) {
136
50
  return configSource;
137
51
  }
138
52
  }
139
- function getDefaultBasicApiKeyDiagnostics() {
140
- return {
141
- configured: false,
142
- source: null,
143
- checkedPaths: [],
144
- };
145
- }
146
- async function readBasicApiKeyDiagnostics(read) {
147
- try {
148
- return await read();
149
- }
150
- catch {
151
- return getDefaultBasicApiKeyDiagnostics();
152
- }
153
- }
154
- function formatInlineApiKeyDiagnosticsValue(diagnostics) {
155
- return `configured=${diagnostics.configured ? "true" : "false"}${diagnostics.source ? ` source=${diagnostics.source}` : ""}${diagnostics.checkedPaths.length > 0 ? ` checked=${diagnostics.checkedPaths.join(" | ")}` : ""}`;
156
- }
157
53
  function createKvSection(id, title, rows) {
158
54
  return {
159
55
  id,
@@ -183,6 +79,20 @@ function isRedundantLiveProbeDescriptor(providerId, value) {
183
79
  function findProviderLiveProbe(providerId, probes) {
184
80
  return probes?.find((probe) => probe.providerId === providerId);
185
81
  }
82
+ function getProviderStatusDetails(providerId, probes) {
83
+ const probe = findProviderLiveProbe(providerId, probes);
84
+ return probe ? sanitizeQuotaProviderResult(probe.result).statusDetails : undefined;
85
+ }
86
+ function appendProviderStatusDetailRows(rows, providerId, probes, keys) {
87
+ for (const detail of getProviderStatusDetails(providerId, probes) ?? []) {
88
+ if (!keys || keys.has(detail.key)) {
89
+ rows.push({ key: detail.key, value: detail.value });
90
+ }
91
+ }
92
+ }
93
+ function findProviderStatusDetail(providerId, key, probes) {
94
+ return getProviderStatusDetails(providerId, probes)?.find((detail) => detail.key === key)?.value;
95
+ }
186
96
  function getLiveProbeState(probe) {
187
97
  if (!probe)
188
98
  return "unavailable";
@@ -194,10 +104,16 @@ function getLiveProbeState(probe) {
194
104
  return "error";
195
105
  return "no_data";
196
106
  }
197
- function appendProviderCompactLiveProbeRows(rows, providerId, probes) {
107
+ function appendProviderCompactLiveProbeRows(rows, providerId, probes, availability) {
108
+ const provider = availability.find((item) => item.id === providerId);
109
+ if (!provider?.enabled || !provider.available)
110
+ return;
198
111
  appendCompactLiveProbeRows(rows, providerId, findProviderLiveProbe(providerId, probes));
199
112
  }
200
113
  function createCompactLiveProbeOnlySection(params) {
114
+ const provider = params.availability.find((item) => item.id === params.providerId);
115
+ if (!provider?.enabled || !provider.available)
116
+ return null;
201
117
  const probe = findProviderLiveProbe(params.providerId, params.probes);
202
118
  if (!probe) {
203
119
  return null;
@@ -206,6 +122,14 @@ function createCompactLiveProbeOnlySection(params) {
206
122
  appendCompactLiveProbeRows(rows, params.providerId, probe);
207
123
  return createKvSection(params.id, params.title, rows);
208
124
  }
125
+ function createProviderStatusSection(params) {
126
+ const rows = [];
127
+ if (params.includeDetails !== false) {
128
+ appendProviderStatusDetailRows(rows, params.providerId, params.probes);
129
+ }
130
+ appendProviderCompactLiveProbeRows(rows, params.providerId, params.probes, params.availability);
131
+ return createKvSection(params.id, params.title, rows);
132
+ }
209
133
  function getCompactLiveProbeDescriptor(providerId, entry) {
210
134
  const candidates = [entry.label, entry.name, entry.group];
211
135
  for (const candidate of candidates) {
@@ -262,7 +186,7 @@ function getQuotaProviderCredentialCategory(source) {
262
186
  return "none";
263
187
  }
264
188
  }
265
- async function createQuotaProvidersSection(params) {
189
+ function createQuotaProvidersSection(params) {
266
190
  if (params.definitions.length === 0)
267
191
  return null;
268
192
  const diagnostics = findProviderLiveProbe("quota-providers", params.probes)?.result.diagnostics ?? [];
@@ -272,17 +196,12 @@ async function createQuotaProvidersSection(params) {
272
196
  const diagnostic = diagnosticsBySource.get(definition.id);
273
197
  const coverage = definition.modelIds ? definition.modelIds.join(",") : "all_models";
274
198
  if (definition.mode === "local-estimate" && isMaintainedQuotaProviderTuning(definition)) {
275
- const maintained = definition.id === "qwen-code"
276
- ? {
277
- path: getQwenLocalQuotaPath(),
278
- version: QWEN_LOCAL_QUOTA_STATE_VERSION,
279
- }
280
- : {
281
- path: getAlibabaCodingPlanQuotaPath(),
282
- version: ALIBABA_CODING_PLAN_STATE_VERSION,
283
- };
284
- const state = await inspectGeneratedCounterFile(maintained.path, maintained.version);
285
199
  const probe = findProviderLiveProbe(definition.id, params.probes);
200
+ const statePath = findProviderStatusDetail(definition.id, "local_state_path", params.probes);
201
+ const stateExists = findProviderStatusDetail(definition.id, "local_state_exists", params.probes);
202
+ const stateHealth = findProviderStatusDetail(definition.id, "local_state_health", params.probes);
203
+ const stateVersion = findProviderStatusDetail(definition.id, "local_state_version", params.probes);
204
+ const stateLastUpdate = findProviderStatusDetail(definition.id, "local_state_last_update", params.probes);
286
205
  rows.push({
287
206
  key: `provider_${definition.id}`,
288
207
  value: [
@@ -291,11 +210,11 @@ async function createQuotaProvidersSection(params) {
291
210
  `coverage=${coverage}`,
292
211
  `outcome=${getLiveProbeState(probe)}`,
293
212
  `limits=${definition.windows.map((window) => `${window.id}:${window.requestLimit}`).join(",")}`,
294
- `state_path=${maintained.path}`,
295
- `state_exists=${state.exists ? "true" : "false"}`,
296
- `state_health=${state.health}`,
297
- `state_version=${state.version ?? "(none)"}`,
298
- `state_last_update=${state.lastUpdatedAt === null ? "(none)" : new Date(state.lastUpdatedAt).toISOString()}`,
213
+ `state_path=${statePath ?? "(none)"}`,
214
+ `state_exists=${stateExists ?? "false"}`,
215
+ `state_health=${stateHealth ?? "missing"}`,
216
+ `state_version=${stateVersion ?? "(none)"}`,
217
+ `state_last_update=${stateLastUpdate ?? "(none)"}`,
299
218
  ]
300
219
  .map((part) => sanitizeSingleLineDisplayText(part))
301
220
  .join(" "),
@@ -303,7 +222,7 @@ async function createQuotaProvidersSection(params) {
303
222
  continue;
304
223
  }
305
224
  if (definition.mode === "local-estimate") {
306
- const state = await inspectLocalQuotaProviderState(definition);
225
+ const stateHealth = diagnostic?.stateHealth ?? "missing";
307
226
  rows.push({
308
227
  key: `provider_${definition.id}`,
309
228
  value: [
@@ -311,11 +230,11 @@ async function createQuotaProvidersSection(params) {
311
230
  "mode=local-estimate",
312
231
  `coverage=${coverage}`,
313
232
  `outcome=${diagnostic?.outcome ?? "unavailable"}`,
314
- `state_path=${state.path}`,
315
- `state_exists=${state.exists ? "true" : "false"}`,
316
- `state_health=${state.health}`,
317
- `state_version=${state.version ?? "(none)"}`,
318
- `state_last_update=${state.lastUpdatedAt === null ? "(none)" : new Date(state.lastUpdatedAt).toISOString()}`,
233
+ `state_path=${diagnostic?.statePath ?? "(none)"}`,
234
+ `state_exists=${diagnostic?.statePath && stateHealth !== "missing" ? "true" : "false"}`,
235
+ `state_health=${stateHealth}`,
236
+ `state_version=${diagnostic?.stateVersion ?? "(none)"}`,
237
+ `state_last_update=${diagnostic?.stateLastUpdatedAt == null ? "(none)" : new Date(diagnostic.stateLastUpdatedAt).toISOString()}`,
319
238
  ]
320
239
  .map((part) => sanitizeSingleLineDisplayText(part))
321
240
  .join(" "),
@@ -378,27 +297,6 @@ function appendCompactLiveProbeRows(rows, providerId, probe) {
378
297
  });
379
298
  }
380
299
  }
381
- function getDefaultApiKeyDiagnosticsWithAuthPaths() {
382
- return {
383
- ...getDefaultBasicApiKeyDiagnostics(),
384
- authPaths: [],
385
- };
386
- }
387
- async function readApiKeyDiagnosticsWithAuthPaths(read) {
388
- try {
389
- return await read();
390
- }
391
- catch {
392
- return getDefaultApiKeyDiagnosticsWithAuthPaths();
393
- }
394
- }
395
- function fmtNanoGptMetric(value) {
396
- if (!Number.isFinite(value))
397
- return "0";
398
- if (Number.isInteger(value))
399
- return String(Math.trunc(value));
400
- return value.toFixed(2).replace(/\.?0+$/, "");
401
- }
402
300
  function computePricingCoverageFromAgg(agg) {
403
301
  const byProvider = new Map();
404
302
  let pricedKeysSeen = 0;
@@ -495,6 +393,13 @@ function supportedProviderPricingRow(params) {
495
393
  notes: "subscription percentage quota via dashboard scraping (not token-priced)",
496
394
  };
497
395
  }
396
+ if (id === "xiaomi") {
397
+ return {
398
+ id,
399
+ pricing: "no",
400
+ notes: "dashboard monthly token quota and balances; per-key costs unsupported",
401
+ };
402
+ }
498
403
  if (id === "kimi-for-coding" || id === "kimi-code") {
499
404
  return {
500
405
  id,
@@ -599,7 +504,7 @@ export async function buildQuotaStatusReport(params) {
599
504
  toastLines.push(` - ${p.id}: ${bits.join(" ")}`);
600
505
  }
601
506
  sections.push(createLinesSection("toast", "toast:", toastLines));
602
- const quotaProvidersSection = await createQuotaProvidersSection({
507
+ const quotaProvidersSection = createQuotaProvidersSection({
603
508
  definitions: params.quotaProviders ?? [],
604
509
  probes: params.providerLiveProbes,
605
510
  });
@@ -641,247 +546,41 @@ export async function buildQuotaStatusReport(params) {
641
546
  key: "auth.json",
642
547
  value: `preferred=${getAuthPath()} present=${joinOrNone(authPresent)} candidates=${joinOrNone(authCandidates)}`,
643
548
  });
644
- const authData = await readAuthFileCached({ maxAgeMs: 5_000 });
645
- const qwenAuthConfigured = hasQwenOAuthAuth(authData);
646
- const qwenLocalPlan = resolveQwenLocalPlan(authData);
647
- const openaiAuth = resolveOpenAIOAuth(authData);
648
- const alibabaAuthDiagnostics = await getAlibabaCodingPlanAuthDiagnostics({
649
- maxAgeMs: DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS,
650
- fallbackTier: "lite",
651
- });
652
- const alibabaCodingPlanAuth = await resolveAlibabaCodingPlanAuthCached({
653
- maxAgeMs: DEFAULT_ALIBABA_AUTH_CACHE_MAX_AGE_MS,
654
- fallbackTier: "lite",
655
- });
656
- pathsRows.push({
657
- key: "qwen oauth auth configured",
658
- value: qwenAuthConfigured ? "true" : "false",
659
- });
660
- pathsRows.push({
661
- key: "qwen_oauth_source",
662
- value: qwenLocalPlan.state === "qwen_free" ? qwenLocalPlan.sourceKey : "(none)",
663
- });
664
- pathsRows.push({
665
- key: "qwen_local_plan",
666
- value: qwenLocalPlan.state === "qwen_free" ? "qwen-code/free" : "(none)",
667
- });
668
- pathsRows.push({
669
- key: "alibaba auth configured",
670
- value: alibabaAuthDiagnostics.state === "none" ? "false" : "true",
671
- });
672
- pathsRows.push({
673
- key: "alibaba_api_key_source",
674
- value: alibabaAuthDiagnostics.source ?? "(none)",
675
- });
676
- pathsRows.push({
677
- key: "alibaba_api_key_checked_paths",
678
- value: joinOrNone(alibabaAuthDiagnostics.checkedPaths),
679
- });
680
- pathsRows.push({
681
- key: "alibaba_api_key_auth_paths",
682
- value: joinOrNone(alibabaAuthDiagnostics.authPaths),
683
- });
684
- pathsRows.push({
685
- key: "alibaba_coding_plan",
686
- value: alibabaAuthDiagnostics.state === "configured"
687
- ? alibabaAuthDiagnostics.tier
688
- : alibabaAuthDiagnostics.state === "invalid"
689
- ? "invalid"
690
- : "(none)",
691
- });
692
- if (alibabaAuthDiagnostics.state === "invalid") {
693
- pathsRows.push({
694
- key: "alibaba_auth_error",
695
- value: sanitizeDisplayText(alibabaAuthDiagnostics.error),
696
- });
697
- }
549
+ appendProviderStatusDetailRows(pathsRows, "qwen-code", params.providerLiveProbes, new Set(["qwen oauth auth configured", "qwen_oauth_source", "qwen_local_plan"]));
550
+ appendProviderStatusDetailRows(pathsRows, "alibaba-coding-plan", params.providerLiveProbes, new Set([
551
+ "alibaba auth configured",
552
+ "alibaba_api_key_source",
553
+ "alibaba_api_key_checked_paths",
554
+ "alibaba_api_key_auth_paths",
555
+ "alibaba_coding_plan",
556
+ "alibaba_auth_error",
557
+ ]));
698
558
  sections.push(createKvSection("paths", "paths:", pathsRows));
699
- // === openai ===
700
- const openaiRows = [
701
- { key: "auth_configured", value: openaiAuth.state === "configured" ? "true" : "false" },
702
- {
703
- key: "auth_source",
704
- value: openaiAuth.state === "configured" ? openaiAuth.sourceKey : "(none)",
705
- },
706
- ];
707
- const openaiTokenStatus = openaiAuth.state !== "configured"
708
- ? "(none)"
709
- : openaiAuth.expiresAt && openaiAuth.expiresAt < Date.now()
710
- ? "expired"
711
- : "valid";
712
- openaiRows.push({ key: "token_status", value: openaiTokenStatus });
713
- openaiRows.push({
714
- key: "token_expires_at",
715
- value: openaiAuth.state === "configured" && openaiAuth.expiresAt
716
- ? new Date(openaiAuth.expiresAt).toISOString()
717
- : "(none)",
718
- });
719
- openaiRows.push({
720
- key: "account_email",
721
- value: openaiAuth.state === "configured" && openaiAuth.email
722
- ? sanitizeDisplayText(openaiAuth.email)
723
- : "(none)",
724
- });
725
- openaiRows.push({
726
- key: "account_id",
727
- value: openaiAuth.state === "configured" && openaiAuth.accountId
728
- ? sanitizeDisplayText(openaiAuth.accountId)
729
- : "(none)",
730
- });
731
- appendProviderCompactLiveProbeRows(openaiRows, "openai", params.providerLiveProbes);
732
- sections.push(createKvSection("openai", "openai:", openaiRows));
733
- // === anthropic ===
734
- const anthropicRows = [];
735
- try {
736
- const anthropicDiagnostics = await getAnthropicDiagnostics({
737
- binaryPath: params.anthropicBinaryPath,
738
- });
739
- anthropicRows.push({
740
- key: "cli_installed",
741
- value: anthropicDiagnostics.installed ? "true" : "false",
742
- });
743
- anthropicRows.push({ key: "cli_version", value: anthropicDiagnostics.version ?? "(none)" });
744
- anthropicRows.push({ key: "auth_status", value: anthropicDiagnostics.authStatus });
745
- anthropicRows.push({
746
- key: "quota_supported",
747
- value: anthropicDiagnostics.quotaSupported ? "true" : "false",
748
- });
749
- anthropicRows.push({
750
- key: "quota_source",
751
- value: anthropicDiagnostics.quotaSource === "none" ? "(none)" : anthropicDiagnostics.quotaSource,
752
- });
753
- anthropicRows.push({
754
- key: "checked_commands",
755
- value: anthropicDiagnostics.checkedCommands.length > 0
756
- ? anthropicDiagnostics.checkedCommands.join(" | ")
757
- : "(none)",
758
- });
759
- if (anthropicDiagnostics.message) {
760
- anthropicRows.push({ key: "message", value: anthropicDiagnostics.message });
761
- }
762
- if (anthropicDiagnostics.quotaSupported && anthropicDiagnostics.quota) {
763
- anthropicRows.push({
764
- key: "five_hour_remaining",
765
- value: `${anthropicDiagnostics.quota.five_hour.percentRemaining}% reset_at=${anthropicDiagnostics.quota.five_hour.resetTimeIso ?? "(none)"}`,
766
- });
767
- anthropicRows.push({
768
- key: "seven_day_remaining",
769
- value: `${anthropicDiagnostics.quota.seven_day.percentRemaining}% reset_at=${anthropicDiagnostics.quota.seven_day.resetTimeIso ?? "(none)"}`,
770
- });
771
- }
772
- }
773
- catch (err) {
774
- anthropicRows.push({ key: "cli_installed", value: "false" });
775
- anthropicRows.push({
776
- key: "message",
777
- value: `failed to probe Claude CLI${err ? `: ${sanitizeDisplayText(err instanceof Error ? err.message : String(err))}` : ""}`,
778
- });
559
+ for (const [id, providerId] of [
560
+ ["openai", "openai"],
561
+ ["anthropic", "anthropic"],
562
+ ]) {
563
+ sections.push(createProviderStatusSection({
564
+ id,
565
+ title: `${id}:`,
566
+ providerId,
567
+ probes: params.providerLiveProbes,
568
+ availability: params.providerAvailability,
569
+ }));
779
570
  }
780
- appendProviderCompactLiveProbeRows(anthropicRows, "anthropic", params.providerLiveProbes);
781
- sections.push(createKvSection("anthropic", "anthropic:", anthropicRows));
782
571
  // === cursor ===
783
- const cursorPlanLabel = getCursorPlanDisplayName(params.cursorPlan);
784
- const cursorIncludedApiUsd = getEffectiveCursorIncludedApiUsd({
785
- plan: params.cursorPlan,
786
- overrideUsd: params.cursorIncludedApiUsd,
787
- });
788
- const cursorAuth = await inspectCursorAuthPresence();
789
- const cursorIntegration = await inspectCursorOpenCodeIntegration();
790
- const cursorRows = [
791
- { key: "plan", value: cursorPlanLabel ?? "none" },
792
- {
793
- key: "included_api_usd",
794
- value: typeof cursorIncludedApiUsd === "number" ? fmtUsdAmount(cursorIncludedApiUsd) : "(none)",
795
- },
796
- {
797
- key: "billing_cycle_start_day",
798
- value: typeof params.cursorBillingCycleStartDay === "number"
799
- ? String(params.cursorBillingCycleStartDay)
800
- : "(calendar month)",
801
- },
802
- { key: "auth_state", value: cursorAuth.state },
803
- { key: "auth_selected_path", value: cursorAuth.selectedPath ?? "(none)" },
804
- { key: "auth_present_paths", value: joinOrNone(cursorAuth.presentPaths) },
805
- { key: "auth_candidate_paths", value: joinOrNone(cursorAuth.candidatePaths) },
806
- ];
807
- if (cursorAuth.error) {
808
- cursorRows.push({ key: "auth_error", value: cursorAuth.error });
809
- }
810
- cursorRows.push({
811
- key: "plugin_enabled",
812
- value: cursorIntegration.pluginEnabled ? "true" : "false",
813
- });
814
- cursorRows.push({ key: "canonical_plugin_package", value: CURSOR_CANONICAL_PLUGIN_PACKAGE });
815
- cursorRows.push({
816
- key: "provider_configured",
817
- value: cursorIntegration.providerConfigured ? "true" : "false",
818
- });
819
- cursorRows.push({ key: "config_matches", value: joinOrNone(cursorIntegration.matchedPaths) });
820
- cursorRows.push({
821
- key: "config_checked_paths",
822
- value: joinOrNone(cursorIntegration.checkedPaths),
823
- });
824
- try {
825
- const cursorUsage = await getCurrentCursorUsageSummary({
826
- billingCycleStartDay: params.cursorBillingCycleStartDay,
827
- });
828
- cursorRows.push({ key: "cycle_source", value: cursorUsage.window.source });
829
- cursorRows.push({ key: "cycle_reset_at", value: cursorUsage.window.resetTimeIso });
830
- cursorRows.push({
831
- key: "api_usage",
832
- value: `${fmtUsdAmount(cursorUsage.api.costUsd)} across ${fmtInt(cursorUsage.api.messageCount)} messages`,
833
- });
834
- cursorRows.push({
835
- key: "auto_composer_usage",
836
- value: `${fmtUsdAmount(cursorUsage.autoComposer.costUsd)} across ${fmtInt(cursorUsage.autoComposer.messageCount)} messages`,
837
- });
838
- cursorRows.push({
839
- key: "total_cursor_usage",
840
- value: `${fmtUsdAmount(cursorUsage.total.costUsd)} across ${fmtInt(cursorUsage.total.messageCount)} messages`,
841
- });
842
- cursorRows.push({
843
- key: "unknown_cursor_models",
844
- value: fmtInt(cursorUsage.unknownModels.length),
845
- });
846
- }
847
- catch (err) {
848
- const msg = err instanceof Error ? err.message : String(err);
849
- cursorRows.push({ key: "usage_error", value: msg });
850
- }
851
- const qwenLocalQuotaPath = getQwenLocalQuotaPath();
852
- const qwenCounter = await inspectGeneratedCounterFile(qwenLocalQuotaPath, QWEN_LOCAL_QUOTA_STATE_VERSION);
853
- cursorRows.push({
854
- key: "qwen free local quota",
855
- value: [
856
- `path=${qwenLocalQuotaPath}`,
857
- `exists=${qwenCounter.exists ? "true" : "false"}`,
858
- `health=${qwenCounter.health}`,
859
- `version=${qwenCounter.version ?? "(none)"}`,
860
- `last_update=${qwenCounter.lastUpdatedAt === null ? "(none)" : new Date(qwenCounter.lastUpdatedAt).toISOString()}`,
861
- ].join(" "),
862
- });
863
- const alibabaLocalQuotaPath = getAlibabaCodingPlanQuotaPath();
864
- const alibabaCounter = await inspectGeneratedCounterFile(alibabaLocalQuotaPath, ALIBABA_CODING_PLAN_STATE_VERSION);
865
- cursorRows.push({
866
- key: "alibaba coding plan local quota",
867
- value: [
868
- `path=${alibabaLocalQuotaPath}`,
869
- `exists=${alibabaCounter.exists ? "true" : "false"}`,
870
- `health=${alibabaCounter.health}`,
871
- `version=${alibabaCounter.version ?? "(none)"}`,
872
- `last_update=${alibabaCounter.lastUpdatedAt === null ? "(none)" : new Date(alibabaCounter.lastUpdatedAt).toISOString()}`,
873
- ].join(" "),
874
- });
875
- if (alibabaCodingPlanAuth.state === "invalid") {
876
- cursorRows.push({ key: "alibaba coding plan error", value: alibabaCodingPlanAuth.error });
877
- }
878
- appendProviderCompactLiveProbeRows(cursorRows, "cursor", params.providerLiveProbes);
572
+ const cursorRows = [];
573
+ appendProviderStatusDetailRows(cursorRows, "cursor", params.providerLiveProbes);
574
+ appendProviderStatusDetailRows(cursorRows, "qwen-code", params.providerLiveProbes, new Set(["qwen free local quota"]));
575
+ appendProviderStatusDetailRows(cursorRows, "alibaba-coding-plan", params.providerLiveProbes, new Set(["alibaba coding plan local quota", "alibaba coding plan error"]));
576
+ appendProviderCompactLiveProbeRows(cursorRows, "cursor", params.providerLiveProbes, params.providerAvailability);
879
577
  sections.push(createKvSection("cursor", "cursor:", cursorRows));
880
578
  const qwenCodeLiveProbeSection = createCompactLiveProbeOnlySection({
881
579
  id: "qwen_code",
882
580
  title: "qwen_code:",
883
581
  providerId: "qwen-code",
884
582
  probes: params.providerLiveProbes,
583
+ availability: params.providerAvailability,
885
584
  });
886
585
  if (qwenCodeLiveProbeSection) {
887
586
  sections.push(qwenCodeLiveProbeSection);
@@ -891,494 +590,42 @@ export async function buildQuotaStatusReport(params) {
891
590
  title: "alibaba_coding_plan:",
892
591
  providerId: "alibaba-coding-plan",
893
592
  probes: params.providerLiveProbes,
593
+ availability: params.providerAvailability,
894
594
  });
895
595
  if (alibabaCodingPlanLiveProbeSection) {
896
596
  sections.push(alibabaCodingPlanLiveProbeSection);
897
597
  }
898
- async function appendMiniMaxSection(section) {
899
- const minimaxRows = [];
900
- const minimaxAuth = await section.getDiagnostics({
901
- maxAgeMs: DEFAULT_MINIMAX_AUTH_CACHE_MAX_AGE_MS,
902
- });
903
- minimaxRows.push({ key: "auth_state", value: minimaxAuth.state });
904
- minimaxRows.push({
905
- key: "api_key_configured",
906
- value: minimaxAuth.state === "configured" ? "true" : "false",
907
- });
908
- minimaxRows.push({ key: "api_key_source", value: minimaxAuth.source ?? "(none)" });
909
- if (minimaxAuth.state === "configured") {
910
- const endpoint = getMiniMaxQuotaEndpoint(minimaxAuth.endpoint);
911
- minimaxRows.push({ key: "api_endpoint", value: endpoint.id });
912
- minimaxRows.push({ key: "api_base_url", value: endpoint.apiBaseUrl });
913
- }
914
- minimaxRows.push({ key: "api_key_checked_paths", value: joinOrNone(minimaxAuth.checkedPaths) });
915
- minimaxRows.push({ key: "api_key_auth_paths", value: joinOrNone(minimaxAuth.authPaths) });
916
- if (minimaxAuth.state === "invalid") {
917
- minimaxRows.push({ key: "auth_error", value: sanitizeDisplayText(minimaxAuth.error) });
918
- }
919
- if (minimaxAuth.state === "configured") {
920
- const resolvedMiniMaxAuth = await section.resolveAuth({
921
- maxAgeMs: DEFAULT_MINIMAX_AUTH_CACHE_MAX_AGE_MS,
922
- });
923
- if (resolvedMiniMaxAuth.state !== "configured") {
924
- minimaxRows.push({
925
- key: "live_fetch_error",
926
- value: `${section.label} API key became unavailable before fetch`,
927
- });
928
- }
929
- else {
930
- const minimaxQuota = await queryMiniMaxQuota(resolvedMiniMaxAuth.apiKey, {
931
- endpoint: resolvedMiniMaxAuth.endpoint,
932
- label: section.label,
933
- });
934
- if (!minimaxQuota.success) {
935
- minimaxRows.push({ key: "live_fetch_error", value: minimaxQuota.error });
936
- }
937
- else {
938
- const fiveHourEntry = minimaxQuota.entries.find((entry) => entry.window === "five_hour");
939
- const weeklyEntry = minimaxQuota.entries.find((entry) => entry.window === "weekly");
940
- if (fiveHourEntry) {
941
- minimaxRows.push({
942
- key: "five_hour_usage",
943
- value: `${fiveHourEntry.right ?? "(none)"} percent_remaining=${fiveHourEntry.percentRemaining} reset_at=${fiveHourEntry.resetTimeIso ?? "(none)"}`,
944
- });
945
- }
946
- if (weeklyEntry) {
947
- minimaxRows.push({
948
- key: "weekly_usage",
949
- value: `${weeklyEntry.right ?? "(none)"} percent_remaining=${weeklyEntry.percentRemaining} reset_at=${weeklyEntry.resetTimeIso ?? "(none)"}`,
950
- });
951
- }
952
- if (!fiveHourEntry && !weeklyEntry) {
953
- minimaxRows.push({ key: "live_state", value: `no reportable ${section.label} quota` });
954
- }
955
- }
956
- }
957
- }
958
- appendProviderCompactLiveProbeRows(minimaxRows, section.providerId, params.providerLiveProbes);
959
- sections.push(createKvSection(section.id, section.title, minimaxRows));
960
- }
961
- // === minimax ===
962
- await appendMiniMaxSection({
963
- id: "minimax",
964
- title: "minimax:",
965
- providerId: "minimax-coding-plan",
966
- label: "MiniMax Coding Plan",
967
- getDiagnostics: getMiniMaxAuthDiagnostics,
968
- resolveAuth: resolveMiniMaxAuthCached,
969
- });
970
- await appendMiniMaxSection({
971
- id: "minimax_china",
972
- title: "minimax_china:",
973
- providerId: "minimax-china-coding-plan",
974
- label: "MiniMax Coding Plan (CN)",
975
- getDiagnostics: getMiniMaxChinaAuthDiagnostics,
976
- resolveAuth: resolveMiniMaxChinaAuthCached,
977
- });
978
- // === kimi ===
979
- const kimiRows = [];
980
- const kimiAuth = await getKimiAuthDiagnostics({
981
- maxAgeMs: DEFAULT_KIMI_AUTH_CACHE_MAX_AGE_MS,
982
- });
983
- kimiRows.push({ key: "auth_state", value: kimiAuth.state });
984
- kimiRows.push({
985
- key: "api_key_configured",
986
- value: kimiAuth.state === "configured" ? "true" : "false",
987
- });
988
- kimiRows.push({ key: "api_key_source", value: kimiAuth.source ?? "(none)" });
989
- kimiRows.push({ key: "api_key_checked_paths", value: joinOrNone(kimiAuth.checkedPaths) });
990
- kimiRows.push({ key: "api_key_auth_paths", value: joinOrNone(kimiAuth.authPaths) });
991
- if (kimiAuth.state === "invalid") {
992
- kimiRows.push({ key: "auth_error", value: sanitizeDisplayText(kimiAuth.error) });
993
- }
994
- if (kimiAuth.state === "configured") {
995
- const kimiQuota = await queryKimiQuota();
996
- if (!kimiQuota) {
997
- kimiRows.push({
998
- key: "live_fetch_error",
999
- value: "Kimi API key became unavailable before fetch",
1000
- });
1001
- }
1002
- else if (!kimiQuota.success) {
1003
- kimiRows.push({ key: "live_fetch_error", value: kimiQuota.error });
1004
- }
1005
- else {
1006
- for (const window of kimiQuota.windows) {
1007
- kimiRows.push({
1008
- key: window.label.toLowerCase().replace(/\s+/g, "_"),
1009
- value: `used=${window.used}/${window.limit} percent_remaining=${window.percentRemaining} reset_at=${window.resetTimeIso ?? "(none)"}`,
1010
- });
1011
- }
1012
- if (kimiQuota.windows.length === 0) {
1013
- kimiRows.push({ key: "live_state", value: "no reportable Kimi quota" });
1014
- }
1015
- }
1016
- }
1017
- appendProviderCompactLiveProbeRows(kimiRows, "kimi-for-coding", params.providerLiveProbes);
1018
- sections.push(createKvSection("kimi", "kimi:", kimiRows));
1019
- // === opencode_go ===
1020
- const openCodeGoRows = [];
1021
- const openCodeGoDiag = await getOpenCodeGoConfigDiagnostics();
1022
- openCodeGoRows.push({ key: "config_state", value: openCodeGoDiag.state });
1023
- openCodeGoRows.push({ key: "config_source", value: openCodeGoDiag.source ?? "(none)" });
1024
- if (openCodeGoDiag.missing) {
1025
- openCodeGoRows.push({ key: "config_missing", value: openCodeGoDiag.missing });
1026
- }
1027
- if (openCodeGoDiag.error) {
1028
- openCodeGoRows.push({ key: "config_error", value: sanitizeDisplayText(openCodeGoDiag.error) });
1029
- }
1030
- openCodeGoRows.push({
1031
- key: "config_checked_paths",
1032
- value: joinOrNone(openCodeGoDiag.checkedPaths),
1033
- });
1034
- const openCodeGoSelectedWindows = params.opencodeGoWindows ?? OPENCODE_GO_STATUS_WINDOW_ORDER;
1035
- openCodeGoRows.push({
1036
- key: "selected_windows",
1037
- value: formatOpenCodeGoWindowSelection(openCodeGoSelectedWindows),
1038
- });
1039
- if (openCodeGoDiag.state === "configured") {
1040
- const openCodeGoConfig = await resolveOpenCodeGoConfigCached({
1041
- maxAgeMs: DEFAULT_OPENCODE_GO_CONFIG_CACHE_MAX_AGE_MS,
1042
- });
1043
- if (openCodeGoConfig.state !== "configured") {
1044
- openCodeGoRows.push({
1045
- key: "live_fetch_error",
1046
- value: "OpenCode Go config became unavailable before fetch",
1047
- });
1048
- }
1049
- else {
1050
- const openCodeGoQuota = await queryOpenCodeGoQuota(openCodeGoConfig.config.workspaceId, openCodeGoConfig.config.authCookie);
1051
- if (!openCodeGoQuota) {
1052
- openCodeGoRows.push({ key: "live_fetch_error", value: "OpenCode Go returned null" });
1053
- }
1054
- else if (!openCodeGoQuota.success) {
1055
- openCodeGoRows.push({ key: "live_fetch_error", value: openCodeGoQuota.error });
1056
- }
1057
- else {
1058
- for (const window of OPENCODE_GO_STATUS_WINDOW_ORDER) {
1059
- const usage = openCodeGoQuota[window];
1060
- if (!usage)
1061
- continue;
1062
- openCodeGoRows.push({
1063
- key: `${window}_usage`,
1064
- value: formatOpenCodeGoUsage(usage),
1065
- });
1066
- }
1067
- const missingSelectedWindows = openCodeGoSelectedWindows.filter((window) => !openCodeGoQuota[window]);
1068
- if (missingSelectedWindows.length > 0 &&
1069
- !isDefaultOpenCodeGoStatusWindowSelection(openCodeGoSelectedWindows)) {
1070
- openCodeGoRows.push({
1071
- key: "live_fetch_error",
1072
- value: `Selected OpenCode Go dashboard window(s) missing: ${formatOpenCodeGoMissingWindows(missingSelectedWindows)}`,
1073
- });
1074
- }
1075
- }
1076
- }
1077
- }
1078
- appendProviderCompactLiveProbeRows(openCodeGoRows, "opencode-go", params.providerLiveProbes);
1079
- sections.push(createKvSection("opencode_go", "opencode_go:", openCodeGoRows));
1080
- // === zai ===
1081
- const zaiRows = [];
1082
- const zaiAuth = await getZaiAuthDiagnostics({
1083
- maxAgeMs: DEFAULT_ZAI_AUTH_CACHE_MAX_AGE_MS,
1084
- });
1085
- zaiRows.push({ key: "auth_state", value: zaiAuth.state });
1086
- zaiRows.push({
1087
- key: "api_key_configured",
1088
- value: zaiAuth.state === "configured" ? "true" : "false",
1089
- });
1090
- zaiRows.push({ key: "api_key_source", value: zaiAuth.source ?? "(none)" });
1091
- zaiRows.push({ key: "api_key_checked_paths", value: joinOrNone(zaiAuth.checkedPaths) });
1092
- zaiRows.push({ key: "api_key_auth_paths", value: joinOrNone(zaiAuth.authPaths) });
1093
- if (zaiAuth.state === "invalid") {
1094
- zaiRows.push({ key: "auth_error", value: sanitizeDisplayText(zaiAuth.error) });
1095
- }
1096
- if (zaiAuth.state === "configured") {
1097
- const zaiQuota = await queryZaiQuota();
1098
- if (!zaiQuota) {
1099
- zaiRows.push({
1100
- key: "live_fetch_error",
1101
- value: "Z.ai API key became unavailable before fetch",
1102
- });
1103
- }
1104
- else if (!zaiQuota.success) {
1105
- zaiRows.push({ key: "live_fetch_error", value: zaiQuota.error });
1106
- }
1107
- else {
1108
- if (zaiQuota.windows.fiveHour) {
1109
- zaiRows.push({
1110
- key: "five_hour_remaining",
1111
- value: `${zaiQuota.windows.fiveHour.percentRemaining}% reset_at=${zaiQuota.windows.fiveHour.resetTimeIso ?? "(none)"}`,
1112
- });
1113
- }
1114
- if (zaiQuota.windows.weekly) {
1115
- zaiRows.push({
1116
- key: "weekly_remaining",
1117
- value: `${zaiQuota.windows.weekly.percentRemaining}% reset_at=${zaiQuota.windows.weekly.resetTimeIso ?? "(none)"}`,
1118
- });
1119
- }
1120
- if (zaiQuota.windows.mcp) {
1121
- zaiRows.push({
1122
- key: "mcp_remaining",
1123
- value: `${zaiQuota.windows.mcp.percentRemaining}% reset_at=${zaiQuota.windows.mcp.resetTimeIso ?? "(none)"}`,
1124
- });
1125
- }
1126
- if (!zaiQuota.windows.fiveHour && !zaiQuota.windows.weekly && !zaiQuota.windows.mcp) {
1127
- zaiRows.push({ key: "live_state", value: "no reportable Z.ai quota windows" });
1128
- }
1129
- }
1130
- }
1131
- appendProviderCompactLiveProbeRows(zaiRows, "zai", params.providerLiveProbes);
1132
- sections.push(createKvSection("zai", "zai:", zaiRows));
1133
- // === zhipu ===
1134
- const zhipuRows = [];
1135
- const zhipuAuth = await getZhipuAuthDiagnostics({
1136
- maxAgeMs: DEFAULT_ZHIPU_AUTH_CACHE_MAX_AGE_MS,
1137
- });
1138
- zhipuRows.push({ key: "auth_state", value: zhipuAuth.state });
1139
- zhipuRows.push({
1140
- key: "api_key_configured",
1141
- value: zhipuAuth.state === "configured" ? "true" : "false",
1142
- });
1143
- zhipuRows.push({ key: "api_key_source", value: zhipuAuth.source ?? "(none)" });
1144
- zhipuRows.push({ key: "api_key_checked_paths", value: joinOrNone(zhipuAuth.checkedPaths) });
1145
- zhipuRows.push({ key: "api_key_auth_paths", value: joinOrNone(zhipuAuth.authPaths) });
1146
- if (zhipuAuth.state === "invalid") {
1147
- zhipuRows.push({ key: "auth_error", value: sanitizeDisplayText(zhipuAuth.error) });
1148
- }
1149
- if (zhipuAuth.state === "configured") {
1150
- const zhipuQuota = await queryZhipuQuota();
1151
- if (!zhipuQuota) {
1152
- zhipuRows.push({
1153
- key: "live_fetch_error",
1154
- value: "Zhipu API key became unavailable before fetch",
1155
- });
1156
- }
1157
- else if (!zhipuQuota.success) {
1158
- zhipuRows.push({ key: "live_fetch_error", value: zhipuQuota.error });
1159
- }
1160
- else {
1161
- if (zhipuQuota.windows.fiveHour) {
1162
- zhipuRows.push({
1163
- key: "five_hour_remaining",
1164
- value: `${zhipuQuota.windows.fiveHour.percentRemaining}% reset_at=${zhipuQuota.windows.fiveHour.resetTimeIso ?? "(none)"}`,
1165
- });
1166
- }
1167
- if (zhipuQuota.windows.weekly) {
1168
- zhipuRows.push({
1169
- key: "weekly_remaining",
1170
- value: `${zhipuQuota.windows.weekly.percentRemaining}% reset_at=${zhipuQuota.windows.weekly.resetTimeIso ?? "(none)"}`,
1171
- });
1172
- }
1173
- if (zhipuQuota.windows.mcp) {
1174
- zhipuRows.push({
1175
- key: "mcp_remaining",
1176
- value: `${zhipuQuota.windows.mcp.percentRemaining}% reset_at=${zhipuQuota.windows.mcp.resetTimeIso ?? "(none)"}`,
1177
- });
1178
- }
1179
- if (!zhipuQuota.windows.fiveHour && !zhipuQuota.windows.weekly && !zhipuQuota.windows.mcp) {
1180
- zhipuRows.push({ key: "live_state", value: "no reportable Zhipu quota windows" });
1181
- }
1182
- }
1183
- }
1184
- appendProviderCompactLiveProbeRows(zhipuRows, "zhipu", params.providerLiveProbes);
1185
- sections.push(createKvSection("zhipu", "zhipu:", zhipuRows));
1186
- // === simple API key sections ===
1187
- const syntheticDiag = await readBasicApiKeyDiagnostics(getSyntheticKeyDiagnostics);
1188
- const syntheticRows = [
598
+ for (const section of [
599
+ { id: "minimax", title: "minimax:", providerId: "minimax-coding-plan" },
1189
600
  {
1190
- key: "synthetic api key",
1191
- value: formatInlineApiKeyDiagnosticsValue(syntheticDiag),
601
+ id: "minimax_china",
602
+ title: "minimax_china:",
603
+ providerId: "minimax-china-coding-plan",
1192
604
  },
1193
- ];
1194
- appendProviderCompactLiveProbeRows(syntheticRows, "synthetic", params.providerLiveProbes);
1195
- sections.push(createKvSection("synthetic", "synthetic:", syntheticRows));
1196
- const chutesDiag = await readBasicApiKeyDiagnostics(getChutesKeyDiagnostics);
1197
- const chutesRows = [
605
+ { id: "kimi", title: "kimi:", providerId: "kimi-for-coding" },
606
+ { id: "opencode_go", title: "opencode_go:", providerId: "opencode-go" },
607
+ { id: "opencode_zen", title: "opencode_zen:", providerId: "opencode" },
608
+ { id: "xiaomi", title: "xiaomi:", providerId: "xiaomi" },
609
+ { id: "zai", title: "zai:", providerId: "zai" },
610
+ { id: "zhipu", title: "zhipu:", providerId: "zhipu" },
611
+ { id: "synthetic", title: "synthetic:", providerId: "synthetic" },
612
+ { id: "chutes", title: "chutes:", providerId: "chutes" },
613
+ { id: "deepseek", title: "deepseek:", providerId: "deepseek" },
614
+ { id: "xai", title: "xai:", providerId: "xai", includeDetails: false },
615
+ { id: "nanogpt", title: "nanogpt:", providerId: "nanogpt" },
1198
616
  {
1199
- key: "chutes api key",
1200
- value: formatInlineApiKeyDiagnosticsValue(chutesDiag),
617
+ id: "copilot_quota_auth",
618
+ title: "copilot_quota_auth:",
619
+ providerId: "copilot",
1201
620
  },
1202
- ];
1203
- appendProviderCompactLiveProbeRows(chutesRows, "chutes", params.providerLiveProbes);
1204
- sections.push(createKvSection("chutes", "chutes:", chutesRows));
1205
- const deepSeekDiag = await readApiKeyDiagnosticsWithAuthPaths(getDeepSeekKeyDiagnostics);
1206
- const deepSeekRows = [
1207
- { key: "api_key_configured", value: deepSeekDiag.configured ? "true" : "false" },
1208
- { key: "api_key_source", value: deepSeekDiag.source ?? "(none)" },
1209
- { key: "api_key_checked_paths", value: joinOrNone(deepSeekDiag.checkedPaths) },
1210
- { key: "api_key_auth_paths", value: joinOrNone(deepSeekDiag.authPaths) },
1211
- ];
1212
- appendProviderCompactLiveProbeRows(deepSeekRows, "deepseek", params.providerLiveProbes);
1213
- sections.push(createKvSection("deepseek", "deepseek:", deepSeekRows));
1214
- // === nanogpt ===
1215
- const nanoGptDiag = await readApiKeyDiagnosticsWithAuthPaths(getNanoGptKeyDiagnostics);
1216
- const nanoGptRows = [
1217
- { key: "api_key_configured", value: nanoGptDiag.configured ? "true" : "false" },
1218
- { key: "api_key_source", value: nanoGptDiag.source ?? "(none)" },
1219
- { key: "api_key_checked_paths", value: joinOrNone(nanoGptDiag.checkedPaths) },
1220
- { key: "api_key_auth_paths", value: joinOrNone(nanoGptDiag.authPaths) },
1221
- ];
1222
- if (nanoGptDiag.configured) {
1223
- try {
1224
- const nanoGptQuota = await queryNanoGptQuota();
1225
- if (!nanoGptQuota) {
1226
- nanoGptRows.push({
1227
- key: "live_fetch_error",
1228
- value: "NanoGPT API key became unavailable before fetch",
1229
- });
1230
- }
1231
- else if (!nanoGptQuota.success) {
1232
- nanoGptRows.push({ key: "live_fetch_error", value: nanoGptQuota.error });
1233
- }
1234
- else {
1235
- if (nanoGptQuota.subscription) {
1236
- nanoGptRows.push({
1237
- key: "subscription_active",
1238
- value: nanoGptQuota.subscription.active ? "true" : "false",
1239
- });
1240
- nanoGptRows.push({ key: "subscription_state", value: nanoGptQuota.subscription.state });
1241
- nanoGptRows.push({
1242
- key: "enforce_daily_limit",
1243
- value: nanoGptQuota.subscription.enforceDailyLimit ? "true" : "false",
1244
- });
1245
- if (nanoGptQuota.subscription.daily) {
1246
- const daily = nanoGptQuota.subscription.daily;
1247
- nanoGptRows.push({
1248
- key: "daily_usage",
1249
- value: `${fmtNanoGptMetric(daily.used)}/${fmtNanoGptMetric(daily.limit)} remaining=${fmtNanoGptMetric(daily.remaining)} percent_remaining=${daily.percentRemaining} reset_at=${daily.resetTimeIso ?? "(none)"}`,
1250
- });
1251
- }
1252
- if (nanoGptQuota.subscription.monthly) {
1253
- const monthly = nanoGptQuota.subscription.monthly;
1254
- nanoGptRows.push({
1255
- key: "monthly_usage",
1256
- value: `${fmtNanoGptMetric(monthly.used)}/${fmtNanoGptMetric(monthly.limit)} remaining=${fmtNanoGptMetric(monthly.remaining)} percent_remaining=${monthly.percentRemaining} reset_at=${monthly.resetTimeIso ?? "(none)"}`,
1257
- });
1258
- }
1259
- nanoGptRows.push({
1260
- key: "billing_period_end",
1261
- value: nanoGptQuota.subscription.currentPeriodEndIso ?? "(none)",
1262
- });
1263
- if (nanoGptQuota.subscription.graceUntilIso) {
1264
- nanoGptRows.push({
1265
- key: "grace_until",
1266
- value: nanoGptQuota.subscription.graceUntilIso,
1267
- });
1268
- }
1269
- }
1270
- nanoGptRows.push({
1271
- key: "balance_usd",
1272
- value: typeof nanoGptQuota.balance?.usdBalance === "number"
1273
- ? fmtUsdAmount(nanoGptQuota.balance.usdBalance)
1274
- : "(none)",
1275
- });
1276
- nanoGptRows.push({
1277
- key: "balance_nano",
1278
- value: nanoGptQuota.balance?.nanoBalanceRaw ?? "(none)",
1279
- });
1280
- for (const entry of nanoGptQuota.endpointErrors ?? []) {
1281
- nanoGptRows.push({ key: `live_error_${entry.endpoint}`, value: entry.message });
1282
- }
1283
- }
1284
- }
1285
- catch (err) {
1286
- const msg = err instanceof Error ? err.message : String(err);
1287
- nanoGptRows.push({ key: "live_fetch_error", value: msg });
1288
- }
1289
- }
1290
- appendProviderCompactLiveProbeRows(nanoGptRows, "nanogpt", params.providerLiveProbes);
1291
- sections.push(createKvSection("nanogpt", "nanogpt:", nanoGptRows));
1292
- // === copilot auth ===
1293
- const copilotDiag = getCopilotQuotaAuthDiagnostics(authData);
1294
- const copilotRows = [{ key: "pat_state", value: copilotDiag.pat.state }];
1295
- if (copilotDiag.pat.selectedPath) {
1296
- copilotRows.push({ key: "pat_path", value: copilotDiag.pat.selectedPath });
1297
- }
1298
- if (copilotDiag.pat.tokenKind) {
1299
- copilotRows.push({ key: "pat_token_kind", value: copilotDiag.pat.tokenKind });
1300
- }
1301
- if (copilotDiag.pat.config?.tier) {
1302
- copilotRows.push({ key: "pat_tier", value: copilotDiag.pat.config.tier });
1303
- }
1304
- if (copilotDiag.billingModel) {
1305
- copilotRows.push({ key: "billing_model", value: copilotDiag.billingModel });
1306
- }
1307
- if (copilotDiag.pat.config?.organization) {
1308
- copilotRows.push({ key: "pat_organization", value: copilotDiag.pat.config.organization });
1309
- }
1310
- if (copilotDiag.pat.config?.enterprise) {
1311
- copilotRows.push({ key: "pat_enterprise", value: copilotDiag.pat.config.enterprise });
1312
- }
1313
- copilotRows.push({ key: "billing_mode", value: copilotDiag.billingMode });
1314
- copilotRows.push({ key: "billing_scope", value: copilotDiag.billingScope });
1315
- copilotRows.push({ key: "quota_api", value: copilotDiag.quotaApi });
1316
- copilotRows.push({ key: "budget_api", value: copilotDiag.budgetApi });
1317
- copilotRows.push({
1318
- key: "billing_api_access_likely",
1319
- value: copilotDiag.billingApiAccessLikely ? "true" : "false",
1320
- });
1321
- copilotRows.push({ key: "remaining_totals_state", value: copilotDiag.remainingTotalsState });
1322
- if (copilotDiag.queryPeriod) {
1323
- copilotRows.push({
1324
- key: "billing_period",
1325
- value: `${copilotDiag.queryPeriod.year}-${String(copilotDiag.queryPeriod.month).padStart(2, "0")}`,
1326
- });
1327
- }
1328
- if (copilotDiag.usernameFilter) {
1329
- copilotRows.push({ key: "username_filter", value: copilotDiag.usernameFilter });
1330
- }
1331
- if (copilotDiag.billingMode === "organization_usage") {
1332
- copilotRows.push({
1333
- key: "billing_usage_note",
1334
- value: "organization AI Credit usage for the current UTC calendar month",
1335
- });
1336
- copilotRows.push({
1337
- key: "remaining_quota_note",
1338
- value: "the usage report exposes included-pool consumption and billed usage, but no included-pool denominator; percentages require a real budget",
1339
- });
1340
- }
1341
- if (copilotDiag.billingMode === "enterprise_usage") {
1342
- copilotRows.push({
1343
- key: "billing_usage_note",
1344
- value: "enterprise AI Credit usage for the current UTC calendar month",
1345
- });
1346
- copilotRows.push({
1347
- key: "remaining_quota_note",
1348
- value: "the usage report exposes included-pool consumption and billed usage, but no included-pool denominator; percentages require a real budget",
1349
- });
1350
- }
1351
- if (copilotDiag.billingTargetError) {
1352
- copilotRows.push({ key: "billing_target_error", value: copilotDiag.billingTargetError });
1353
- }
1354
- if (copilotDiag.tokenCompatibilityError) {
1355
- copilotRows.push({
1356
- key: "token_compatibility_error",
1357
- value: copilotDiag.tokenCompatibilityError,
1358
- });
1359
- }
1360
- if (copilotDiag.pat.error) {
1361
- copilotRows.push({ key: "pat_error", value: copilotDiag.pat.error });
621
+ ]) {
622
+ sections.push(createProviderStatusSection({
623
+ ...section,
624
+ probes: params.providerLiveProbes,
625
+ availability: params.providerAvailability,
626
+ }));
1362
627
  }
1363
- copilotRows.push({
1364
- key: "pat_checked_paths",
1365
- value: copilotDiag.pat.checkedPaths.length
1366
- ? copilotDiag.pat.checkedPaths.join(" | ")
1367
- : "(none)",
1368
- });
1369
- copilotRows.push({
1370
- key: "oauth_configured",
1371
- value: `${copilotDiag.oauth.configured ? "true" : "false"} key=${copilotDiag.oauth.keyName ?? "(none)"} refresh=${copilotDiag.oauth.hasRefreshToken ? "true" : "false"} access=${copilotDiag.oauth.hasAccessToken ? "true" : "false"}`,
1372
- });
1373
- copilotRows.push({ key: "effective_source", value: copilotDiag.effectiveSource });
1374
- copilotRows.push({ key: "oauth_accounting_state", value: copilotDiag.oauthAccountingState });
1375
- copilotRows.push({ key: "override", value: copilotDiag.override });
1376
- appendProviderCompactLiveProbeRows(copilotRows, "copilot", params.providerLiveProbes);
1377
- sections.push(createKvSection("copilot_quota_auth", "copilot_quota_auth:", copilotRows));
1378
628
  // === google antigravity + db path ===
1379
- const googleTokenCachePath = getGoogleTokenCachePath();
1380
- const googleAuthPresence = await inspectAntigravityAccountsPresence();
1381
- const googleCompanionPresence = await inspectAntigravityCompanionPresence();
1382
629
  const dbCandidates = getOpenCodeDbPathCandidates();
1383
630
  const dbSelected = getOpenCodeDbPath();
1384
631
  const dbPresent = [];
@@ -1386,98 +633,26 @@ export async function buildQuotaStatusReport(params) {
1386
633
  if (await pathExists(p))
1387
634
  dbPresent.push(p);
1388
635
  }));
1389
- const googleRows = [
1390
- { key: "auth_state", value: googleAuthPresence.state },
1391
- { key: "selected_accounts_path", value: googleAuthPresence.selectedPath ?? "(none)" },
1392
- { key: "present_accounts_paths", value: joinOrNone(googleAuthPresence.presentPaths) },
1393
- { key: "candidate_accounts_paths", value: joinOrNone(googleAuthPresence.candidatePaths) },
1394
- { key: "account_count", value: String(googleAuthPresence.accountCount) },
1395
- { key: "valid_account_count", value: String(googleAuthPresence.validAccountCount) },
1396
- { key: "companion_package_state", value: googleCompanionPresence.state },
1397
- {
1398
- key: "companion_package_path",
1399
- value: googleCompanionPresence.state === "present" || googleCompanionPresence.state === "invalid"
1400
- ? (googleCompanionPresence.resolvedPath ?? "(none)")
1401
- : "(none)",
1402
- },
1403
- ];
1404
- if (googleCompanionPresence.state !== "present") {
1405
- googleRows.push({
1406
- key: "companion_error",
1407
- value: sanitizeDisplayText(googleCompanionPresence.error),
1408
- });
1409
- }
1410
- googleRows.push({
1411
- key: "token_cache_path",
1412
- value: `${googleTokenCachePath} exists=${(await pathExists(googleTokenCachePath)) ? "true" : "false"}`,
1413
- });
1414
- if (googleAuthPresence.state === "invalid" && googleAuthPresence.error) {
1415
- googleRows.push({ key: "auth_error", value: sanitizeDisplayText(googleAuthPresence.error) });
1416
- }
636
+ const googleRows = [];
637
+ appendProviderStatusDetailRows(googleRows, "google-antigravity", params.providerLiveProbes);
1417
638
  googleRows.push({
1418
639
  key: "opencode db",
1419
640
  value: `preferred=${dbSelected} present=${joinOrNone(dbPresent)} candidates=${joinOrNone(dbCandidates)}`,
1420
641
  });
1421
- appendProviderCompactLiveProbeRows(googleRows, "google-antigravity", params.providerLiveProbes);
642
+ appendProviderCompactLiveProbeRows(googleRows, "google-antigravity", params.providerLiveProbes, params.providerAvailability);
1422
643
  sections.push(createKvSection("google_antigravity", "google_antigravity:", googleRows));
1423
- // === google gemini cli ===
1424
- const geminiCliAuthPresence = await inspectGeminiCliAuthPresence(params.geminiCliClient);
1425
- const geminiCliCompanionPresence = await inspectGeminiCliCompanionPresence();
1426
- const geminiCliRows = [
1427
- { key: "auth_state", value: geminiCliAuthPresence.state },
1428
- { key: "auth_source", value: geminiCliAuthPresence.sourceKey ?? "(none)" },
1429
- { key: "account_count", value: String(geminiCliAuthPresence.accountCount) },
1430
- { key: "valid_account_count", value: String(geminiCliAuthPresence.validAccountCount) },
1431
- { key: "companion_package_state", value: geminiCliCompanionPresence.state },
1432
- {
1433
- key: "companion_package_path",
1434
- value: geminiCliCompanionPresence.state === "present" ||
1435
- geminiCliCompanionPresence.state === "invalid"
1436
- ? (geminiCliCompanionPresence.resolvedPath ?? "(none)")
1437
- : "(none)",
1438
- },
1439
- ];
1440
- if (geminiCliAuthPresence.state === "invalid") {
1441
- geminiCliRows.push({
1442
- key: "auth_error",
1443
- value: sanitizeDisplayText(geminiCliAuthPresence.error),
1444
- });
1445
- }
1446
- if (geminiCliCompanionPresence.state !== "present") {
1447
- geminiCliRows.push({
1448
- key: "companion_error",
1449
- value: sanitizeDisplayText(geminiCliCompanionPresence.error),
1450
- });
1451
- }
1452
- appendProviderCompactLiveProbeRows(geminiCliRows, "google-gemini-cli", params.providerLiveProbes);
1453
- sections.push(createKvSection("google_gemini_cli", "google_gemini_cli:", geminiCliRows));
1454
- // Google AGY
1455
- const agyAuthPresence = await inspectAgyAuthPresence(params.agyClient);
1456
- const agyCompanionPresence = await inspectAgyCompanionPresence();
1457
- const agyRows = [
1458
- { key: "auth_state", value: agyAuthPresence.state },
1459
- { key: "auth_source", value: agyAuthPresence.sourceKey ?? "(none)" },
1460
- { key: "account_count", value: String(agyAuthPresence.accountCount) },
1461
- { key: "valid_account_count", value: String(agyAuthPresence.validAccountCount) },
1462
- { key: "companion_package_state", value: agyCompanionPresence.state },
1463
- {
1464
- key: "companion_package_path",
1465
- value: agyCompanionPresence.state === "present" || agyCompanionPresence.state === "invalid"
1466
- ? (agyCompanionPresence.resolvedPath ?? "(none)")
1467
- : "(none)",
1468
- },
1469
- ];
1470
- if (agyAuthPresence.state === "invalid") {
1471
- agyRows.push({ key: "auth_error", value: sanitizeDisplayText(agyAuthPresence.error) });
1472
- }
1473
- if (agyCompanionPresence.state !== "present") {
1474
- agyRows.push({
1475
- key: "companion_error",
1476
- value: sanitizeDisplayText(agyCompanionPresence.error),
1477
- });
644
+ for (const [id, providerId] of [
645
+ ["google_gemini_cli", "google-gemini-cli"],
646
+ ["google_agy", "google-agy"],
647
+ ]) {
648
+ sections.push(createProviderStatusSection({
649
+ id,
650
+ title: `${id}:`,
651
+ providerId,
652
+ probes: params.providerLiveProbes,
653
+ availability: params.providerAvailability,
654
+ }));
1478
655
  }
1479
- appendProviderCompactLiveProbeRows(agyRows, "google-agy", params.providerLiveProbes);
1480
- sections.push(createKvSection("google_agy", "google_agy:", agyRows));
1481
656
  if (params.googleRefresh?.attempted) {
1482
657
  const googleRefreshRows = [];
1483
658
  if (typeof params.googleRefresh.total === "number" &&