@hashimkarim/usagestat-linux-x64-gnu 2.0.0-alpha.1 → 2.0.0-alpha.4

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 (384) hide show
  1. package/LICENSE +0 -0
  2. package/native-manifest.json +1088 -134
  3. package/package.json +160 -1
  4. package/plugins/UPSTREAM-LICENSES.md +113 -0
  5. package/plugins/_provider-icons/LICENSE +21 -0
  6. package/plugins/_provider-icons/NOTICE +12 -0
  7. package/plugins/_provider-icons/licenses/CodexBar-MIT.txt +21 -0
  8. package/plugins/_provider-icons/licenses/LobeHub-MIT.txt +21 -0
  9. package/plugins/_provider-icons/licenses/UsageStat-Bar-MIT.txt +21 -0
  10. package/plugins/_provider-icons/manifest.json +1219 -0
  11. package/plugins/_provider-icons/provenance.json +269 -0
  12. package/plugins/_provider-icons/source.json +4 -0
  13. package/plugins/abacus-ai/icon-color.svg +18 -0
  14. package/plugins/abacus-ai/icon.svg +0 -0
  15. package/plugins/abacus-ai/plugin.js +0 -0
  16. package/plugins/abacus-ai/plugin.json +0 -0
  17. package/plugins/aiand/icon.svg +6 -0
  18. package/plugins/aiand/plugin.js +108 -0
  19. package/plugins/aiand/plugin.json +22 -0
  20. package/plugins/aixy/LICENSE +21 -0
  21. package/plugins/aixy/plugin.js +261 -0
  22. package/plugins/aixy/plugin.json +24 -0
  23. package/plugins/alibaba/icon-color.svg +0 -0
  24. package/plugins/alibaba/icon.svg +0 -0
  25. package/plugins/alibaba/plugin.js +0 -0
  26. package/plugins/alibaba/plugin.json +0 -0
  27. package/plugins/alibaba-token-plan/icon-color.svg +0 -0
  28. package/plugins/alibaba-token-plan/icon.svg +0 -0
  29. package/plugins/alibaba-token-plan/plugin.js +0 -0
  30. package/plugins/alibaba-token-plan/plugin.json +0 -0
  31. package/plugins/amp/icon-color.svg +0 -0
  32. package/plugins/amp/icon-conflict.svg +0 -0
  33. package/plugins/amp/icon.svg +0 -0
  34. package/plugins/amp/plugin.js +0 -0
  35. package/plugins/amp/plugin.json +0 -0
  36. package/plugins/antigravity/icon-color.svg +0 -0
  37. package/plugins/antigravity/icon-conflict.svg +0 -0
  38. package/plugins/antigravity/icon.svg +0 -0
  39. package/plugins/antigravity/plugin.js +136 -46
  40. package/plugins/antigravity/plugin.json +0 -0
  41. package/plugins/antigravity-cli/icon-color.svg +1 -0
  42. package/plugins/antigravity-cli/icon.svg +1 -3
  43. package/plugins/antigravity-cli/plugin.js +11 -15
  44. package/plugins/antigravity-cli/plugin.json +0 -0
  45. package/plugins/antigravity-ide/icon-color.svg +1 -0
  46. package/plugins/antigravity-ide/icon.svg +1 -3
  47. package/plugins/antigravity-ide/plugin.js +0 -0
  48. package/plugins/antigravity-ide/plugin.json +0 -0
  49. package/plugins/atlascloud/LICENSE +21 -0
  50. package/plugins/atlascloud/icon-color.svg +1 -0
  51. package/plugins/atlascloud/icon.svg +1 -0
  52. package/plugins/atlascloud/plugin.js +49 -0
  53. package/plugins/atlascloud/plugin.json +23 -0
  54. package/plugins/augment/icon-color.svg +14 -0
  55. package/plugins/augment/icon.svg +0 -0
  56. package/plugins/augment/plugin.js +0 -0
  57. package/plugins/augment/plugin.json +0 -0
  58. package/plugins/aws-bedrock/icon-color.svg +0 -0
  59. package/plugins/aws-bedrock/icon.svg +0 -0
  60. package/plugins/aws-bedrock/plugin.js +0 -0
  61. package/plugins/aws-bedrock/plugin.json +0 -0
  62. package/plugins/azure-openai/icon-color.svg +0 -0
  63. package/plugins/azure-openai/icon.svg +0 -0
  64. package/plugins/azure-openai/plugin.js +0 -0
  65. package/plugins/azure-openai/plugin.json +0 -0
  66. package/plugins/bifrost/LICENSE +21 -0
  67. package/plugins/bifrost/plugin.js +361 -0
  68. package/plugins/bifrost/plugin.json +23 -0
  69. package/plugins/chutes/icon.svg +0 -0
  70. package/plugins/chutes/plugin.js +0 -0
  71. package/plugins/chutes/plugin.json +0 -0
  72. package/plugins/claude/icon-color.svg +0 -0
  73. package/plugins/claude/icon.svg +0 -0
  74. package/plugins/claude/plugin.js +358 -161
  75. package/plugins/claude/plugin.json +1 -1
  76. package/plugins/clawrouter/icon.svg +7 -0
  77. package/plugins/clawrouter/plugin.js +45 -0
  78. package/plugins/clawrouter/plugin.json +22 -0
  79. package/plugins/clinepass/icon.svg +4 -0
  80. package/plugins/clinepass/plugin.js +87 -0
  81. package/plugins/clinepass/plugin.json +23 -0
  82. package/plugins/codebuddy/plugin.js +331 -0
  83. package/plugins/codebuddy/plugin.json +30 -0
  84. package/plugins/codebuff/icon-color.svg +92 -0
  85. package/plugins/codebuff/icon.svg +0 -0
  86. package/plugins/codebuff/plugin.js +0 -0
  87. package/plugins/codebuff/plugin.json +0 -0
  88. package/plugins/coderabbit/plugin.js +25 -0
  89. package/plugins/coderabbit/plugin.json +12 -0
  90. package/plugins/codex/icon-color.svg +0 -0
  91. package/plugins/codex/icon.svg +0 -0
  92. package/plugins/codex/plugin.js +8 -2
  93. package/plugins/codex/plugin.json +0 -0
  94. package/plugins/command-code/icon-color.svg +3 -0
  95. package/plugins/command-code/icon.svg +0 -0
  96. package/plugins/command-code/plugin.js +14 -3
  97. package/plugins/command-code/plugin.json +0 -0
  98. package/plugins/copilot/icon-color.svg +0 -0
  99. package/plugins/copilot/icon.svg +1 -1
  100. package/plugins/copilot/plugin.js +61 -9
  101. package/plugins/copilot/plugin.json +4 -1
  102. package/plugins/crof/icon-color.svg +3 -0
  103. package/plugins/crof/icon.svg +0 -0
  104. package/plugins/crof/plugin.js +0 -0
  105. package/plugins/crof/plugin.json +0 -0
  106. package/plugins/crofai/icon-color.svg +3 -0
  107. package/plugins/crofai/icon.svg +2 -15
  108. package/plugins/crofai/plugin.js +0 -0
  109. package/plugins/crofai/plugin.json +0 -0
  110. package/plugins/cursor/icon-color.svg +1 -0
  111. package/plugins/cursor/icon-conflict.svg +0 -0
  112. package/plugins/cursor/icon.svg +0 -0
  113. package/plugins/cursor/plugin.js +46 -9
  114. package/plugins/cursor/plugin.json +3 -2
  115. package/plugins/cursor-nightly/icon.png +0 -0
  116. package/plugins/cursor-nightly/plugin.js +45 -8
  117. package/plugins/cursor-nightly/plugin.json +3 -2
  118. package/plugins/deepgram/icon.svg +0 -0
  119. package/plugins/deepgram/plugin.js +0 -0
  120. package/plugins/deepgram/plugin.json +0 -0
  121. package/plugins/deepinfra/icon-color.svg +1 -0
  122. package/plugins/deepinfra/icon.svg +1 -0
  123. package/plugins/deepinfra/plugin.js +97 -0
  124. package/plugins/deepinfra/plugin.json +28 -0
  125. package/plugins/deepseek/icon-color.svg +0 -0
  126. package/plugins/deepseek/icon.svg +0 -0
  127. package/plugins/deepseek/plugin.js +150 -59
  128. package/plugins/deepseek/plugin.json +3 -1
  129. package/plugins/devin/icon.svg +0 -0
  130. package/plugins/devin/plugin.js +114 -0
  131. package/plugins/devin/plugin.json +2 -1
  132. package/plugins/devpass/LICENSE +21 -0
  133. package/plugins/devpass/plugin.js +115 -0
  134. package/plugins/devpass/plugin.json +23 -0
  135. package/plugins/doubao/icon-color.svg +0 -0
  136. package/plugins/doubao/icon.svg +0 -0
  137. package/plugins/doubao/plugin.js +0 -0
  138. package/plugins/doubao/plugin.json +0 -0
  139. package/plugins/droid/icon.svg +0 -0
  140. package/plugins/droid/plugin.json +2 -1
  141. package/plugins/elevenlabs/icon-color.svg +4 -0
  142. package/plugins/elevenlabs/icon.svg +0 -0
  143. package/plugins/elevenlabs/plugin.js +17 -2
  144. package/plugins/elevenlabs/plugin.json +0 -0
  145. package/plugins/factory/icon-color.svg +1 -0
  146. package/plugins/factory/icon-conflict.svg +0 -0
  147. package/plugins/factory/icon.svg +0 -0
  148. package/plugins/factory/plugin.js +38 -14
  149. package/plugins/factory/plugin.json +2 -1
  150. package/plugins/fireworks-ai/icon-color.svg +1 -0
  151. package/plugins/fireworks-ai/icon.svg +1 -6
  152. package/plugins/fireworks-ai/plugin.js +0 -0
  153. package/plugins/fireworks-ai/plugin.json +0 -0
  154. package/plugins/gemini/icon-color.svg +0 -0
  155. package/plugins/gemini/icon.svg +0 -0
  156. package/plugins/gemini/plugin.js +0 -0
  157. package/plugins/gemini/plugin.json +0 -0
  158. package/plugins/gemini-apps/LICENSE +22 -0
  159. package/plugins/gemini-apps/icon-color.svg +1 -0
  160. package/plugins/gemini-apps/icon.svg +1 -0
  161. package/plugins/gemini-apps/plugin.js +470 -0
  162. package/plugins/gemini-apps/plugin.json +19 -0
  163. package/plugins/gitkraken/LICENSE +21 -0
  164. package/plugins/gitkraken/plugin.js +153 -0
  165. package/plugins/gitkraken/plugin.json +24 -0
  166. package/plugins/grok/icon-color.svg +1 -0
  167. package/plugins/grok/icon.svg +0 -0
  168. package/plugins/grok/plugin.js +30 -5
  169. package/plugins/grok/plugin.json +3 -1
  170. package/plugins/groqcloud/icon-color.svg +1 -0
  171. package/plugins/groqcloud/icon.svg +0 -0
  172. package/plugins/groqcloud/plugin.js +0 -0
  173. package/plugins/groqcloud/plugin.json +0 -0
  174. package/plugins/helmcode/LICENSE +21 -0
  175. package/plugins/helmcode/plugin.js +188 -0
  176. package/plugins/helmcode/plugin.json +24 -0
  177. package/plugins/huggingface/LICENSE +21 -0
  178. package/plugins/huggingface/icon-color.svg +1 -0
  179. package/plugins/huggingface/icon.svg +1 -0
  180. package/plugins/huggingface/plugin.js +293 -0
  181. package/plugins/huggingface/plugin.json +25 -0
  182. package/plugins/hyper/LICENSE +21 -0
  183. package/plugins/hyper/plugin.js +131 -0
  184. package/plugins/hyper/plugin.json +26 -0
  185. package/plugins/ibmbob/icon.svg +23 -0
  186. package/plugins/ibmbob/plugin.js +61 -0
  187. package/plugins/ibmbob/plugin.json +22 -0
  188. package/plugins/jetbrains-ai-assistant/icon-color.svg +0 -0
  189. package/plugins/jetbrains-ai-assistant/icon-conflict.svg +0 -0
  190. package/plugins/jetbrains-ai-assistant/icon.svg +0 -0
  191. package/plugins/jetbrains-ai-assistant/plugin.js +0 -0
  192. package/plugins/jetbrains-ai-assistant/plugin.json +0 -0
  193. package/plugins/kilo/icon-color.svg +1 -0
  194. package/plugins/kilo/icon.svg +0 -0
  195. package/plugins/kilo/plugin.js +0 -0
  196. package/plugins/kilo/plugin.json +0 -0
  197. package/plugins/kimi/icon-color.svg +0 -0
  198. package/plugins/kimi/icon-conflict.svg +0 -0
  199. package/plugins/kimi/icon.svg +0 -0
  200. package/plugins/kimi/plugin.js +122 -141
  201. package/plugins/kimi/plugin.json +5 -2
  202. package/plugins/kimi-k2/icon-color.svg +0 -0
  203. package/plugins/kimi-k2/icon.svg +0 -0
  204. package/plugins/kimi-k2/plugin.js +0 -0
  205. package/plugins/kimi-k2/plugin.json +0 -0
  206. package/plugins/kiro/icon-color.svg +0 -0
  207. package/plugins/kiro/icon-conflict.svg +0 -0
  208. package/plugins/kiro/icon.svg +0 -0
  209. package/plugins/kiro/plugin.js +49 -10
  210. package/plugins/kiro/plugin.json +3 -1
  211. package/plugins/litellm/icon.svg +0 -0
  212. package/plugins/litellm/plugin.js +54 -3
  213. package/plugins/litellm/plugin.json +0 -0
  214. package/plugins/llm-proxy/icon.svg +0 -0
  215. package/plugins/llm-proxy/plugin.js +0 -0
  216. package/plugins/llm-proxy/plugin.json +0 -0
  217. package/plugins/llmman/LICENSE +21 -0
  218. package/plugins/llmman/plugin.js +133 -0
  219. package/plugins/llmman/plugin.json +23 -0
  220. package/plugins/longcat/icon-color.svg +1 -0
  221. package/plugins/longcat/icon.svg +1 -0
  222. package/plugins/longcat/plugin.js +182 -0
  223. package/plugins/longcat/plugin.json +23 -0
  224. package/plugins/manus/icon-color.svg +6 -0
  225. package/plugins/manus/icon.svg +0 -0
  226. package/plugins/manus/plugin.js +0 -0
  227. package/plugins/manus/plugin.json +0 -0
  228. package/plugins/mimo/icon-color.svg +4 -0
  229. package/plugins/mimo/icon.svg +4 -1
  230. package/plugins/mimo/plugin.js +0 -0
  231. package/plugins/mimo/plugin.json +0 -0
  232. package/plugins/minimax/icon-color.svg +0 -0
  233. package/plugins/minimax/icon-conflict.svg +0 -0
  234. package/plugins/minimax/icon.svg +0 -0
  235. package/plugins/minimax/plugin.js +25 -31
  236. package/plugins/minimax/plugin.json +0 -0
  237. package/plugins/mistral/icon-color.svg +0 -0
  238. package/plugins/mistral/icon.svg +0 -0
  239. package/plugins/mistral/plugin.js +110 -5
  240. package/plugins/mistral/plugin.json +0 -0
  241. package/plugins/moonshot/icon-color.svg +1 -0
  242. package/plugins/moonshot/icon.svg +0 -0
  243. package/plugins/moonshot/plugin.js +8 -6
  244. package/plugins/moonshot/plugin.json +0 -0
  245. package/plugins/muse/LICENSE +21 -0
  246. package/plugins/muse/plugin.js +319 -0
  247. package/plugins/muse/plugin.json +26 -0
  248. package/plugins/nanogpt/icon-color.svg +0 -0
  249. package/plugins/nanogpt/icon.svg +0 -0
  250. package/plugins/nanogpt/plugin.js +0 -0
  251. package/plugins/nanogpt/plugin.json +0 -0
  252. package/plugins/neuralwatt/icon.svg +0 -0
  253. package/plugins/neuralwatt/plugin.js +0 -0
  254. package/plugins/neuralwatt/plugin.json +0 -0
  255. package/plugins/notion/icon.svg +1 -0
  256. package/plugins/notion/plugin.js +282 -0
  257. package/plugins/notion/plugin.json +29 -0
  258. package/plugins/nous/LICENSE +21 -0
  259. package/plugins/nous/icon-color.svg +1 -0
  260. package/plugins/nous/icon.svg +1 -0
  261. package/plugins/nous/plugin.js +124 -0
  262. package/plugins/nous/plugin.json +24 -0
  263. package/plugins/ollama/icon-color.svg +1 -0
  264. package/plugins/ollama/icon.svg +0 -0
  265. package/plugins/ollama/plugin.js +257 -56
  266. package/plugins/ollama/plugin.json +6 -3
  267. package/plugins/openai-api/icon-color.svg +1 -0
  268. package/plugins/openai-api/icon.svg +0 -0
  269. package/plugins/openai-api/plugin.js +0 -0
  270. package/plugins/openai-api/plugin.json +0 -0
  271. package/plugins/opencode/icon-color.svg +1 -0
  272. package/plugins/opencode/icon.svg +0 -0
  273. package/plugins/opencode/plugin.js +0 -0
  274. package/plugins/opencode/plugin.json +0 -0
  275. package/plugins/opencode-go/icon-color.svg +1 -0
  276. package/plugins/opencode-go/icon-conflict.svg +0 -0
  277. package/plugins/opencode-go/icon.svg +0 -0
  278. package/plugins/opencode-go/plugin.js +103 -17
  279. package/plugins/opencode-go/plugin.json +5 -2
  280. package/plugins/openrouter/icon-color.svg +1 -0
  281. package/plugins/openrouter/icon.svg +0 -0
  282. package/plugins/openrouter/plugin.js +371 -114
  283. package/plugins/openrouter/plugin.json +6 -0
  284. package/plugins/perplexity/icon-color.svg +0 -0
  285. package/plugins/perplexity/icon-conflict.svg +0 -0
  286. package/plugins/perplexity/icon.svg +0 -0
  287. package/plugins/perplexity/plugin.js +0 -0
  288. package/plugins/perplexity/plugin.json +0 -0
  289. package/plugins/pi/plugin.js +113 -0
  290. package/plugins/pi/plugin.json +11 -0
  291. package/plugins/poe/icon.svg +0 -0
  292. package/plugins/poe/plugin.js +24 -18
  293. package/plugins/poe/plugin.json +2 -0
  294. package/plugins/qoder/icon.svg +3 -0
  295. package/plugins/qoder/plugin.js +227 -0
  296. package/plugins/qoder/plugin.json +23 -0
  297. package/plugins/qwencloud/icon-color.svg +1 -0
  298. package/plugins/qwencloud/icon.svg +1 -0
  299. package/plugins/qwencloud/plugin.js +677 -0
  300. package/plugins/qwencloud/plugin.json +29 -0
  301. package/plugins/raycast/LICENSE +21 -0
  302. package/plugins/raycast/plugin.js +174 -0
  303. package/plugins/raycast/plugin.json +24 -0
  304. package/plugins/replicate/LICENSE +21 -0
  305. package/plugins/replicate/icon-color.svg +1 -0
  306. package/plugins/replicate/icon.svg +1 -0
  307. package/plugins/replicate/plugin.js +165 -0
  308. package/plugins/replicate/plugin.json +24 -0
  309. package/plugins/sakana/icon.svg +5 -0
  310. package/plugins/sakana/plugin.js +156 -0
  311. package/plugins/sakana/plugin.json +23 -0
  312. package/plugins/stepfun/icon-color.svg +0 -0
  313. package/plugins/stepfun/icon.svg +0 -0
  314. package/plugins/stepfun/plugin.js +0 -0
  315. package/plugins/stepfun/plugin.json +0 -0
  316. package/plugins/sub2api/icon.svg +4 -0
  317. package/plugins/sub2api/plugin.js +191 -0
  318. package/plugins/sub2api/plugin.json +16 -0
  319. package/plugins/synthetic/icon-color.svg +14 -0
  320. package/plugins/synthetic/icon-conflict.svg +0 -0
  321. package/plugins/synthetic/icon.svg +0 -0
  322. package/plugins/synthetic/plugin.js +0 -0
  323. package/plugins/synthetic/plugin.json +0 -0
  324. package/plugins/t3chat/icon-color.svg +0 -0
  325. package/plugins/t3chat/icon.svg +0 -0
  326. package/plugins/t3chat/plugin.js +0 -0
  327. package/plugins/t3chat/plugin.json +0 -0
  328. package/plugins/typesafe/LICENSE +21 -0
  329. package/plugins/typesafe/plugin.js +225 -0
  330. package/plugins/typesafe/plugin.json +24 -0
  331. package/plugins/v0/LICENSE +21 -0
  332. package/plugins/v0/icon-color.svg +1 -0
  333. package/plugins/v0/icon.svg +1 -0
  334. package/plugins/v0/plugin.js +214 -0
  335. package/plugins/v0/plugin.json +24 -0
  336. package/plugins/venice/icon-color.svg +0 -0
  337. package/plugins/venice/icon.svg +0 -0
  338. package/plugins/venice/plugin.js +50 -1
  339. package/plugins/venice/plugin.json +2 -1
  340. package/plugins/vercel/LICENSE +21 -0
  341. package/plugins/vercel/icon-color.svg +1 -0
  342. package/plugins/vercel/icon.svg +1 -0
  343. package/plugins/vercel/plugin.js +55 -0
  344. package/plugins/vercel/plugin.json +23 -0
  345. package/plugins/vertex-ai/icon-color.svg +0 -0
  346. package/plugins/vertex-ai/icon.svg +0 -0
  347. package/plugins/vertex-ai/plugin.js +0 -0
  348. package/plugins/vertex-ai/plugin.json +0 -0
  349. package/plugins/warp/icon-color.svg +0 -0
  350. package/plugins/warp/icon.svg +0 -0
  351. package/plugins/warp/plugin.js +0 -0
  352. package/plugins/warp/plugin.json +0 -0
  353. package/plugins/wayfinder/icon.svg +5 -0
  354. package/plugins/wayfinder/plugin.js +47 -0
  355. package/plugins/wayfinder/plugin.json +16 -0
  356. package/plugins/windsurf/icon-color.svg +1 -0
  357. package/plugins/windsurf/icon-conflict.svg +0 -0
  358. package/plugins/windsurf/icon.svg +0 -0
  359. package/plugins/windsurf/plugin.js +0 -0
  360. package/plugins/windsurf/plugin.json +0 -0
  361. package/plugins/xai/icon-color.svg +1 -0
  362. package/plugins/xai/icon.svg +1 -0
  363. package/plugins/xai/plugin.js +162 -0
  364. package/plugins/xai/plugin.json +28 -0
  365. package/plugins/xkiro/LICENSE +21 -0
  366. package/plugins/xkiro/plugin.js +99 -0
  367. package/plugins/xkiro/plugin.json +23 -0
  368. package/plugins/zai/icon-color.svg +1 -0
  369. package/plugins/zai/icon-conflict.svg +0 -0
  370. package/plugins/zai/icon.svg +0 -0
  371. package/plugins/zai/plugin.js +111 -161
  372. package/plugins/zai/plugin.json +4 -1
  373. package/plugins/zed/icon.svg +0 -0
  374. package/plugins/zed/plugin.js +0 -0
  375. package/plugins/zed/plugin.json +0 -0
  376. package/plugins/zenmux/icon-color.svg +1 -0
  377. package/plugins/zenmux/icon.svg +1 -0
  378. package/plugins/zenmux/plugin.js +102 -0
  379. package/plugins/zenmux/plugin.json +23 -0
  380. package/plugins/zoommate/icon.svg +1 -0
  381. package/plugins/zoommate/plugin.js +244 -0
  382. package/plugins/zoommate/plugin.json +29 -0
  383. package/usagestat +0 -0
  384. package/usagestatd +0 -0
@@ -3,7 +3,9 @@
3
3
  var USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36"
4
4
 
5
5
  function getCookieHeader(ctx) {
6
- var raw = ctx.host.env.get("MISTRAL_COOKIE")
6
+ var provider = ctx.provider || {}
7
+ var raw = Object.prototype.hasOwnProperty.call(provider, 'cookieHeader') ? provider.cookieHeader :
8
+ provider.instanceId && provider.instanceId !== 'mistral' ? null : ctx.host.env.get("MISTRAL_COOKIE")
7
9
  if (!raw || !raw.trim()) {
8
10
  throw "Set MISTRAL_COOKIE to your cookie header from admin.mistral.ai. Include csrftoken if present."
9
11
  }
@@ -62,8 +64,9 @@
62
64
  var total = 0
63
65
  for (var i = 0; i < entries.length; i++) {
64
66
  var e = entries[i]
65
- total += e.value_paid != null ? e.value_paid : (e.value || 0)
67
+ total += Number(e.value != null ? e.value : (e.value_paid || 0))
66
68
  }
69
+ if (!Number.isSafeInteger(total) || total < 0) throw new Error('Invalid Mistral token total.')
67
70
  return total
68
71
  }
69
72
 
@@ -80,6 +83,104 @@
80
83
  return index
81
84
  }
82
85
 
86
+ function subscriptionBudgets(html) {
87
+ if (typeof html !== 'string' || html.length > 2 * 1024 * 1024) throw new Error('Invalid subscription page.')
88
+ var chunks = [], marker = 'self.__next_f.push(', cursor = 0
89
+ while ((cursor = html.indexOf(marker, cursor)) >= 0) {
90
+ cursor += marker.length
91
+ var start = cursor, stack = [], quoted = false, escaped = false
92
+ while (/\s/.test(html[start] || '') && start < html.length) start++
93
+ if (html[start] !== '[') continue
94
+ for (var end = start; end < html.length; end++) {
95
+ var ch = html[end]
96
+ if (quoted) { if (escaped) escaped = false; else if (ch === '\\') escaped = true; else if (ch === '"') quoted = false }
97
+ else if (ch === '"') quoted = true
98
+ else if (ch === '[' || ch === '{') stack.push(ch === '[' ? ']' : '}')
99
+ else if (ch === ']' || ch === '}') {
100
+ if (stack.pop() !== ch) throw new Error('Invalid subscription record.')
101
+ if (!stack.length) {
102
+ var value = JSON.parse(html.slice(start,end+1))
103
+ if (value[0] === 1 && typeof value[1] === 'string') chunks.push(value[1])
104
+ cursor = end+1; break
105
+ }
106
+ }
107
+ }
108
+ }
109
+ // Flight's text/binary records are byte-counted and may contain fake JSON rows.
110
+ var stream = encodeURIComponent(chunks.join('')).replace(/%([0-9A-F]{2})/g, function(_,hex){return String.fromCharCode(parseInt(hex,16))})
111
+ var found = new Map()
112
+ function budget(raw) {
113
+ if (!raw || typeof raw.usage_percentage !== 'number' || !Number.isFinite(raw.usage_percentage) || raw.usage_percentage < 0 ||
114
+ typeof raw.initial_budget !== 'number' || !Number.isFinite(raw.initial_budget) || raw.initial_budget <= 0 ||
115
+ !/^[A-Za-z]{3}$/.test(raw.currency || '')) return null
116
+ return {percent:raw.usage_percentage,limit:raw.initial_budget,currency:raw.currency.toUpperCase(),reset:raw.reset_at || null}
117
+ }
118
+ function collect(value, depth) {
119
+ if (depth > 64) throw new Error('Subscription record too deep.')
120
+ if (!value || typeof value !== 'object') return
121
+ if (value.budget) {
122
+ var pair = [budget(value.budget.api_budget),budget(value.budget.vibe_budget)]
123
+ if (pair.some(Boolean)) found.set(JSON.stringify(pair),pair)
124
+ }
125
+ for (var child of Object.values(value)) collect(child,depth+1)
126
+ }
127
+ cursor = 0
128
+ while (cursor < stream.length) {
129
+ var newline = stream.indexOf('\n',cursor); if (newline < 0) newline = stream.length
130
+ var row = stream.slice(cursor,newline), match = /^[0-9a-f]+:/i.exec(row)
131
+ if (!match) { cursor = newline+1; continue }
132
+ var body = row.slice(match[0].length)
133
+ if (/^[TAOoUSsLlGgMmV]/.test(body)) {
134
+ var length = /^[TAOoUSsLlGgMmV]([0-9a-f]+),/i.exec(body)
135
+ if (!length) throw new Error('Invalid Flight length.')
136
+ cursor += match[0].length+length[0].length+parseInt(length[1],16)
137
+ if (cursor > stream.length) throw new Error('Incomplete Flight record.')
138
+ continue
139
+ }
140
+ if (/^[\[{]/.test(body)) {
141
+ var text = decodeURIComponent(Array.from(body,function(c){return '%'+c.charCodeAt(0).toString(16).padStart(2,'0')}).join(''))
142
+ collect(JSON.parse(text),0)
143
+ }
144
+ cursor = newline+1
145
+ }
146
+ if (found.size !== 1) throw new Error('Subscription budgets absent or ambiguous.')
147
+ return found.values().next().value
148
+ }
149
+
150
+ function optionalAllowances(ctx, headers, cookie, csrf, lines) {
151
+ var hasVibe = false
152
+ try {
153
+ var page = ctx.host.http.request({method:'GET',url:BASE_URL+'/subscription',headers:headers,timeoutMs:3000})
154
+ if (page.status === 200) subscriptionBudgets(page.bodyText).forEach(function(b,index){
155
+ if (!b) return
156
+ var used = b.limit*b.percent/100
157
+ if (!Number.isFinite(used)) return
158
+ var reset = ctx.util.toIso(b.reset)
159
+ lines.push(ctx.line.progress({label:index?'Monthly Plan':'Included API',used:b.percent,limit:100,
160
+ format:{kind:'percent'},resetsAt:reset || undefined,
161
+ detail:b.currency+' '+used.toFixed(2)+' / '+b.limit.toFixed(2)}))
162
+ if (index) hasVibe = true
163
+ })
164
+ } catch (_) {}
165
+ if (!hasVibe && csrf) try {
166
+ var minimal = cookie.split(';').map(function(p){return p.trim()}).filter(function(p){return /^(csrftoken|ory_session_[^=]+)=/.test(p)}).join('; ')
167
+ var url = 'https://console.mistral.ai/api-ui/trpc/billing.vibeUsage?batch=1&input='+encodeURIComponent(JSON.stringify({'0':{json:null,meta:{values:['undefined'],v:1}}}))
168
+ var resp = ctx.host.http.request({method:'GET',url:url,headers:{Cookie:minimal,'X-CSRFTOKEN':csrf,Accept:'application/json'},timeoutMs:2000})
169
+ var vibe = resp.status===200 ? ctx.util.tryParseJson(resp.bodyText)?.[0]?.result?.data?.json : null
170
+ if (typeof vibe?.usage_percentage==='number' && vibe.usage_percentage>=0 && vibe.usage_percentage<=100)
171
+ lines.push(ctx.line.progress({label:'Monthly Plan',used:vibe.usage_percentage,limit:100,format:{kind:'percent'},resetsAt:ctx.util.toIso(vibe.reset_at) || undefined}))
172
+ } catch (_) {}
173
+ try {
174
+ var credits = ctx.util.requestJson({method:'GET',url:BASE_URL+'/api/billing/credits',headers:headers,timeoutMs:2000})
175
+ var data = credits.json
176
+ if (credits.resp.status!==200 || typeof data?.wallet_amount!=='number' || !/^[A-Za-z]{3}$/.test(data.currency || '')) return
177
+ var values = [data.wallet_amount,data.credit_notes_amount ?? 0,data.ongoing_usage_balance ?? 0]
178
+ if (!values.every(function(n){return typeof n==='number'&&Number.isFinite(n)})) return
179
+ var amount = values[0]+values[1]-values[2]
180
+ if (Number.isFinite(amount)) lines.push(ctx.line.text({label:'Credit balance',value:data.currency.toUpperCase()+' '+amount.toFixed(2)}))
181
+ } catch (_) {}
182
+ }
183
+
83
184
  function probe(ctx) {
84
185
  var cookieHeader = getCookieHeader(ctx)
85
186
  var csrf = extractCsrf(cookieHeader)
@@ -119,8 +220,10 @@
119
220
  var totalInput = 0
120
221
  var totalOutput = 0
121
222
 
122
- if (billing.completion && billing.completion.models) {
123
- var r = aggregateModels(billing.completion.models, prices)
223
+ var completions = [billing.completion, billing.chat, billing.vibe_code && billing.vibe_code.completion]
224
+ for (var c = 0; c < completions.length; c++) {
225
+ if (!completions[c] || !completions[c].models) continue
226
+ var r = aggregateModels(completions[c].models, prices)
124
227
  totalCost += r.cost; totalInput += r.inputTokens; totalOutput += r.outputTokens
125
228
  }
126
229
 
@@ -145,7 +248,9 @@
145
248
  ctx.line.text({ label: "Tokens", value: tokenDetail }),
146
249
  ]
147
250
 
148
- return { lines: lines }
251
+ optionalAllowances(ctx,headers,cookieHeader,csrf,lines)
252
+
253
+ return { source:'web', lines: lines }
149
254
  }
150
255
 
151
256
  globalThis.__openusage_plugin = { id: "mistral", probe: probe }
File without changes
@@ -0,0 +1 @@
1
+ <svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>MoonshotAI</title><path d="M1.052 16.916l9.539 2.552a21.007 21.007 0 00.06 2.033l5.956 1.593a11.997 11.997 0 01-5.586.865l-.18-.016-.044-.004-.084-.009-.094-.01a11.605 11.605 0 01-.157-.02l-.107-.014-.11-.016a11.962 11.962 0 01-.32-.051l-.042-.008-.075-.013-.107-.02-.07-.015-.093-.019-.075-.016-.095-.02-.097-.023-.094-.022-.068-.017-.088-.022-.09-.024-.095-.025-.082-.023-.109-.03-.062-.02-.084-.025-.093-.028-.105-.034-.058-.019-.08-.026-.09-.031-.066-.024a6.293 6.293 0 01-.044-.015l-.068-.025-.101-.037-.057-.022-.08-.03-.087-.035-.088-.035-.079-.032-.095-.04-.063-.028-.063-.027a5.655 5.655 0 01-.041-.018l-.066-.03-.103-.047-.052-.024-.096-.046-.062-.03-.084-.04-.086-.044-.093-.047-.052-.027-.103-.055-.057-.03-.058-.032a6.49 6.49 0 01-.046-.026l-.094-.053-.06-.034-.051-.03-.072-.041-.082-.05-.093-.056-.052-.032-.084-.053-.061-.039-.079-.05-.07-.047-.053-.035a7.785 7.785 0 01-.054-.036l-.044-.03-.044-.03a6.066 6.066 0 01-.04-.028l-.057-.04-.076-.054-.069-.05-.074-.054-.056-.042-.076-.057-.076-.059-.086-.067-.045-.035-.064-.052-.074-.06-.089-.073-.046-.039-.046-.039a7.516 7.516 0 01-.043-.037l-.045-.04-.061-.053-.07-.062-.068-.06-.062-.058-.067-.062-.053-.05-.088-.084a13.28 13.28 0 01-.099-.097l-.029-.028-.041-.042-.069-.07-.05-.051-.05-.053a6.457 6.457 0 01-.168-.179l-.08-.088-.062-.07-.071-.08-.042-.049-.053-.062-.058-.068-.046-.056a7.175 7.175 0 01-.027-.033l-.045-.055-.066-.082-.041-.052-.05-.064-.02-.025a11.99 11.99 0 01-1.44-2.402zm-1.02-5.794l11.353 3.037a20.468 20.468 0 00-.469 2.011l10.817 2.894a12.076 12.076 0 01-1.845 2.005L.657 15.923l-.016-.046-.035-.104a11.965 11.965 0 01-.05-.153l-.007-.023a11.896 11.896 0 01-.207-.741l-.03-.126-.018-.08-.021-.097-.018-.081-.018-.09-.017-.084-.018-.094c-.026-.141-.05-.283-.071-.426l-.017-.118-.011-.083-.013-.102a12.01 12.01 0 01-.019-.161l-.005-.047a12.12 12.12 0 01-.034-2.145zm1.593-5.15l11.948 3.196c-.368.605-.705 1.231-1.01 1.875l11.295 3.022c-.142.82-.368 1.612-.668 2.365l-11.55-3.09L.124 10.26l.015-.1.008-.049.01-.067.015-.087.018-.098c.026-.148.056-.295.088-.442l.028-.124.02-.085.024-.097c.022-.09.045-.18.07-.268l.028-.102.023-.083.03-.1.025-.082.03-.096.026-.082.031-.095a11.896 11.896 0 011.01-2.232zm4.442-4.4L17.352 4.59a20.77 20.77 0 00-1.688 1.721l7.823 2.093c.267.852.442 1.744.513 2.665L2.106 5.213l.045-.065.027-.04.04-.055.046-.065.055-.076.054-.072.064-.086.05-.065.057-.073.055-.07.06-.074.055-.069.065-.077.054-.066.066-.077.053-.06.072-.082.053-.06.067-.074.054-.058.073-.078.058-.06.063-.067.168-.17.1-.098.059-.056.076-.071a12.084 12.084 0 012.272-1.677zM12.017 0h.097l.082.001.069.001.054.002.068.002.046.001.076.003.047.002.06.003.054.002.087.005.105.007.144.011.088.007.044.004.077.008.082.008.047.005.102.012.05.006.108.014.081.01.042.006.065.01.207.032.07.012.065.011.14.026.092.018.11.022.046.01.075.016.041.01L14.7.3l.042.01.065.015.049.012.071.017.096.024.112.03.113.03.113.032.05.015.07.02.078.024.073.023.05.016.05.016.076.025.099.033.102.036.048.017.064.023.093.034.11.041.116.045.1.04.047.02.06.024.041.018.063.026.04.018.057.025.11.048.1.046.074.035.075.036.06.028.092.046.091.045.102.052.053.028.049.026.046.024.06.033.041.022.052.029.088.05.106.06.087.051.057.034.053.032.096.059.088.055.098.062.036.024.064.041.084.056.04.027.062.042.062.043.023.017c.054.037.108.075.161.114l.083.06.065.048.056.043.086.065.082.064.04.03.05.041.086.069.079.065.085.071c.712.6 1.353 1.283 1.909 2.031L7.222.994l.062-.027.065-.028.081-.034.086-.035c.113-.045.227-.09.341-.131l.096-.035.093-.033.084-.03.096-.031c.087-.03.176-.058.264-.085l.091-.027.086-.025.102-.03.085-.023.1-.026L9.04.37l.09-.023.091-.022.095-.022.09-.02.098-.021.091-.02.095-.018.092-.018.1-.018.091-.016.098-.017.092-.014.097-.015.092-.013.102-.013.091-.012.105-.012.09-.01.105-.01c.093-.01.186-.018.28-.024l.106-.008.09-.005.11-.006.093-.004.1-.004.097-.002.099-.002.197-.002z"></path></svg>
File without changes
@@ -1,10 +1,10 @@
1
1
  (function () {
2
2
  function apiKey(ctx) {
3
- return ctx.host.env.get("MOONSHOT_API_KEY") || ctx.host.env.get("MOONSHOT_KEY");
3
+ return (ctx.provider && ctx.provider.apiKey) || ctx.host.env.get("MOONSHOT_API_KEY") || ctx.host.env.get("MOONSHOT_KEY");
4
4
  }
5
5
 
6
6
  function baseUrl(ctx) {
7
- var region = String(ctx.host.env.get("MOONSHOT_REGION") || "").toLowerCase();
7
+ var region = String((ctx.provider && ctx.provider.region) || ctx.host.env.get("MOONSHOT_REGION") || "").toLowerCase();
8
8
  var explicit = ctx.host.env.get("MOONSHOT_API_URL");
9
9
  if (explicit) return explicit.replace(/\/$/, "");
10
10
  return region === "cn" || region === "china" ? "https://api.moonshot.cn" : "https://api.moonshot.ai";
@@ -13,8 +13,8 @@
13
13
  function pick(obj, names) {
14
14
  for (var i = 0; i < names.length; i++) {
15
15
  var v = obj && obj[names[i]];
16
- if (typeof v === "number") return v;
17
- if (typeof v === "string" && v.trim() !== "" && !isNaN(Number(v))) return Number(v);
16
+ if (typeof v === "number" && Number.isFinite(v)) return v;
17
+ if (typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v))) return Number(v);
18
18
  }
19
19
  return null;
20
20
  }
@@ -23,9 +23,10 @@
23
23
  var key = apiKey(ctx);
24
24
  if (!key) throw "Moonshot API key not found. Set MOONSHOT_API_KEY or MOONSHOT_KEY.";
25
25
 
26
+ var base = baseUrl(ctx);
26
27
  var result = ctx.util.requestJson({
27
28
  method: "GET",
28
- url: baseUrl(ctx) + "/v1/users/me/balance",
29
+ url: base + "/v1/users/me/balance",
29
30
  headers: { Authorization: "Bearer " + key, Accept: "application/json" },
30
31
  timeoutMs: 15000,
31
32
  });
@@ -36,7 +37,8 @@
36
37
  var data = json.data || json;
37
38
  var available = pick(data, ["available_balance", "availableBalance", "balance", "cash_balance"]);
38
39
  if (available === null) throw "Moonshot response did not include a recognizable balance.";
39
- return { lines: [ctx.line.text({ label: "Balance", value: String(available) })] };
40
+ var currency = /^https:\/\/api\.moonshot\.cn(?::443)?(?:\/|$)/i.test(base) ? "CNY" : "USD";
41
+ return { source: "api", lines: [ctx.line.text({ label: "Balance", value: currency + " " + available.toFixed(2) })] };
40
42
  }
41
43
 
42
44
  globalThis.__openusage_plugin = { id: "moonshot", probe: probe };
File without changes
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Peter Steinberger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,319 @@
1
+ // Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
2
+ globalThis.__usagestat_bundled_options = {"labels":["Session","Weekly","Additional"],"defaults":{},"autoMode":"api"};
3
+ function _nullishCoalesce(lhs, rhsFn) {
4
+ if (lhs != null) {
5
+ return lhs;
6
+ } else {
7
+ return rhsFn();
8
+ }
9
+ }
10
+ function _optionalChain(ops) {
11
+ let lastAccessLHS = undefined;
12
+ let value = ops[0];
13
+ let i = 1;
14
+ while (i < ops.length) {
15
+ const op = ops[i];
16
+ const fn = ops[i + 1];
17
+ i += 2;
18
+ if ((op === "optionalAccess" || op === "optionalCall") && value == null) {
19
+ return undefined;
20
+ }
21
+ if (op === "access" || op === "optionalAccess") {
22
+ lastAccessLHS = value;
23
+ value = fn(value);
24
+ } else if (op === "call" || op === "optionalCall") {
25
+ value = fn((...args) => value.call(lastAccessLHS, ...args));
26
+ lastAccessLHS = undefined;
27
+ }
28
+ }
29
+ return value;
30
+ }
31
+ async function _asyncOptionalChain(ops) {
32
+ let lastAccessLHS = undefined;
33
+ let value = ops[0];
34
+ let i = 1;
35
+ while (i < ops.length) {
36
+ const op = ops[i];
37
+ const fn = ops[i + 1];
38
+ i += 2;
39
+ if ((op === "optionalAccess" || op === "optionalCall") && value == null) {
40
+ return undefined;
41
+ }
42
+ if (op === "access" || op === "optionalAccess") {
43
+ lastAccessLHS = value;
44
+ value = await fn(value);
45
+ } else if (op === "call" || op === "optionalCall") {
46
+ value = await fn((...args) => value.call(lastAccessLHS, ...args));
47
+ lastAccessLHS = undefined;
48
+ }
49
+ }
50
+ return value;
51
+ }
52
+ defineProvider({
53
+ id: "muse",
54
+ name: "Muse Code",
55
+ endpoints: ["https://api.meta.ai", "https://dev.meta.ai"],
56
+ settings: [
57
+ { key: "MUSE_DEVICE_TOKEN", title: "Muse login", type: "secure" },
58
+ { key: "MUSE_WEB_TEAM_ID", title: "Browser team ID", type: "plain" },
59
+ ],
60
+ capabilities: ["browser-cookies", "http-status"],
61
+ cookieDomains: ["dev.meta.ai"],
62
+ async fetchUsage(ctx) {
63
+ const token = ctx.settings.getSecret("MUSE_DEVICE_TOKEN");
64
+ if (!_optionalChain([token, "optionalAccess", (_) => _.startsWith, "call", (_2) => _2("dca:")])) {
65
+ throw ctx.fail.authenticationExpired("Muse Code requires a device-code login. Run `muse login` again.");
66
+ }
67
+ // Keep the device credential off dev.meta.ai requests, which authenticate with the browser session.
68
+ const response = await ctx.http.post("https://api.meta.ai/muse-code/key", {
69
+ body: {},
70
+ headers: { Authorization: `Bearer ${token}`, "x-api-version": "1.0.0", "User-Agent": "CodexBar" },
71
+ timeoutSeconds: 15,
72
+ });
73
+ if (response.status === 401 || response.status === 403) {
74
+ throw ctx.fail.authenticationExpired("Muse Code login was rejected. Run `muse login` again.");
75
+ }
76
+ if (response.status === 429) throw ctx.fail.rateLimited("Muse Code usage requests are rate limited.");
77
+ if (response.status >= 500) throw ctx.fail.providerUnavailable(`Muse Code API returned HTTP ${response.status}.`);
78
+ if (response.status !== 200) throw ctx.fail.apiFailure(`Muse Code API returned HTTP ${response.status}.`);
79
+ const fail = (field) => {
80
+ throw ctx.fail.parseFailure(`Could not parse Muse Code subscription usage: ${field}`);
81
+ };
82
+ const object = (value, field) => {
83
+ if (!value || typeof value !== "object" || Array.isArray(value)) return fail(field);
84
+ return value;
85
+ };
86
+ const number = (value, field) => {
87
+ if (typeof value !== "number" || !Number.isFinite(value)) return fail(field);
88
+ return value;
89
+ };
90
+ const text = (value, field) => {
91
+ if (value === undefined || value === null) return undefined;
92
+ if (typeof value !== "string") return fail(field);
93
+ return value.trim() || undefined;
94
+ };
95
+ const reset = (value) => {
96
+ if (value === undefined || value === null) return undefined;
97
+ const seconds = number(value, "resets_at");
98
+ // Match the native countdown boundary; oversized dates must not discard useful quota data.
99
+ if (seconds <= 0 || seconds > 64092211200) return undefined;
100
+ return ctx.date.unixSeconds(seconds);
101
+ };
102
+ let decoded;
103
+ try {
104
+ decoded = JSON.parse(response.bodyText);
105
+ } catch (error) {
106
+ void error;
107
+ return fail("expected JSON");
108
+ }
109
+ const root = object(decoded, "expected a response object");
110
+ for (const key of ["require_payment", "is_subs_active"]) {
111
+ if (root[key] !== undefined && root[key] !== null && typeof root[key] !== "boolean") return fail(key);
112
+ }
113
+ if (root.require_payment === true) {
114
+ throw ctx.fail.permissionDenied("Muse Code requires a payment method. Finish billing at https://dev.meta.ai");
115
+ }
116
+ if (root.is_subs_active !== true) {
117
+ throw ctx.fail.permissionDenied("No Muse Code subscription is active on this login.");
118
+ }
119
+ const plan = text(root.subs_tier_name, "subs_tier_name");
120
+ const rows = [];
121
+ if (plan) rows.push({ label: "Plan", value: plan });
122
+ const snapshot = {
123
+ details: [{ title: "Muse Code subscription", rows }],
124
+ identity: { email: text(root.user_email, "user_email"), loginMethod: _nullishCoalesce(plan, () => "Muse login") },
125
+ dataConfidence: "unknown",
126
+ };
127
+ const percentLabel = (value) => `${ctx.format.number(value, { maximumFractionDigits: 0 })}%`;
128
+
129
+ // The browser quota belongs to one dev.meta.ai team, which the user must choose explicitly: a session can
130
+ // see several teams, and list order says nothing about which one holds the CLI login's subscription.
131
+ async function webQuota() {
132
+ if (ctx.browser.availability("dev.meta.ai") === "off") return undefined;
133
+ try {
134
+ let requestsLeft = 5;
135
+ for await (const session of ctx.browser.sessions("dev.meta.ai")) {
136
+ if (requestsLeft <= 0) break;
137
+ let rejected = false;
138
+ const headers = { Cookie: session.header, "User-Agent": "CodexBar" };
139
+ const get = async (path) => {
140
+ if (requestsLeft-- <= 0) throw new Error("Muse browser request budget exhausted");
141
+ const response = await ctx.http.get(`https://dev.meta.ai${path}`, { headers, timeoutSeconds: 8 });
142
+ if (response.status === 401 || response.status === 403) {
143
+ rejected = true;
144
+ ctx.browser.rejectCookie("dev.meta.ai", session);
145
+ return undefined;
146
+ }
147
+ if (response.status !== 200) return undefined;
148
+ const value = JSON.parse(response.bodyText);
149
+ return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
150
+ };
151
+ // The browser session must belong to the same Meta account as the CLI login.
152
+ const loginEmail = _optionalChain([
153
+ text,
154
+ "call",
155
+ (_3) => _3(root.user_email, "user_email"),
156
+ "optionalAccess",
157
+ (_4) => _4.toLowerCase,
158
+ "call",
159
+ (_5) => _5(),
160
+ ]);
161
+ const me = await get("/api/auth/me");
162
+ const webEmail =
163
+ typeof _optionalChain([me, "optionalAccess", (_6) => _6.email]) === "string"
164
+ ? me.email.trim().toLowerCase()
165
+ : undefined;
166
+ if (!loginEmail || !webEmail || loginEmail !== webEmail) continue;
167
+ const listed = await _asyncOptionalChain([
168
+ await get("/api/portal/teams"),
169
+ "optionalAccess",
170
+ async (_7) => _7.teams,
171
+ ]);
172
+ if (rejected) continue;
173
+ if (!Array.isArray(listed)) return undefined;
174
+ const teams = [];
175
+ for (const entry of listed) {
176
+ const item = entry && typeof entry === "object" ? entry : {};
177
+ const id =
178
+ typeof item.team_id === "string"
179
+ ? item.team_id
180
+ : Number.isSafeInteger(item.team_id)
181
+ ? String(item.team_id)
182
+ : "";
183
+ if (!/^[0-9]+$/.test(id)) continue;
184
+ const name = typeof item.team_name === "string" && item.team_name.trim() ? item.team_name.trim() : id;
185
+ teams.push({ id, name });
186
+ }
187
+ const selected = _nullishCoalesce(
188
+ _optionalChain([
189
+ ctx,
190
+ "access",
191
+ (_8) => _8.settings,
192
+ "access",
193
+ (_9) => _9.get,
194
+ "call",
195
+ (_10) => _10("MUSE_WEB_TEAM_ID"),
196
+ "optionalAccess",
197
+ (_11) => _11.trim,
198
+ "call",
199
+ (_12) => _12(),
200
+ ]),
201
+ () => "",
202
+ );
203
+ const team = teams.find((candidate) => candidate.id === selected);
204
+ if (!selected) return { teams, note: "Choose a browser team in Muse Code settings" };
205
+ if (!team) return { teams, note: "The selected browser team is not visible to this session" };
206
+ const quota = await _asyncOptionalChain([
207
+ await get(`/api/portal/teams/${team.id}/subscription-quota`),
208
+ "optionalAccess",
209
+ async (_13) => _13.subscription_quota,
210
+ ]);
211
+ if (rejected) continue;
212
+ if (!quota || typeof quota !== "object")
213
+ return { teams, note: "No subscription quota for the selected team" };
214
+ const record = quota;
215
+ // The team's quota must be for the same plan the CLI login reports.
216
+ if (!plan || typeof record.tier !== "string" || record.tier.trim() !== plan) {
217
+ return { teams, note: "The selected team's plan differs from the Muse login" };
218
+ }
219
+ const parsed = parseWebQuota(record);
220
+ return parsed ? { teams, quota: { team, ...parsed } } : { teams };
221
+ }
222
+ } catch (error) {
223
+ void error;
224
+ }
225
+ return undefined;
226
+ }
227
+ function parseWebQuota(quota) {
228
+ // Limits and usage are weighted token counts encoded as decimal strings.
229
+ const amount = (value) => {
230
+ const parsed = typeof value === "string" && /^[0-9]+$/.test(value) ? Number(value) : value;
231
+ return typeof parsed === "number" && Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
232
+ };
233
+ const percent = (used, limit) => {
234
+ const u = amount(used);
235
+ const l = amount(limit);
236
+ return u === null || l === null || l <= 0 ? null : Math.min(100, (u / l) * 100);
237
+ };
238
+ const resetAt = (value) => {
239
+ const parsed = amount(value);
240
+ return parsed === null || parsed <= 0 || parsed > 64092211200 ? undefined : ctx.date.unixSeconds(parsed);
241
+ };
242
+ const now = ctx.date.now().getTime();
243
+ const weeklyReset = resetAt(quota.weekly_resets_at);
244
+ const weeklyPercent = percent(quota.weekly_weighted_used, quota.weekly_weighted_limit);
245
+ const seconds = amount(quota.window_duration_secs);
246
+ // A weekly quota without a future reset is stale; show nothing rather than an old reading.
247
+ if (weeklyPercent === null || !weeklyReset || weeklyReset.getTime() <= now) return null;
248
+ if (seconds === null || !Number.isSafeInteger(seconds) || seconds < 60) return null;
249
+ const windowReset = resetAt(quota.window_resets_at);
250
+ let primaryPercent = percent(quota.window_weighted_used, quota.window_weighted_limit);
251
+ if (primaryPercent === null) return null;
252
+ const noWindowReset = quota.window_resets_at === undefined || quota.window_resets_at === null;
253
+ if ((!noWindowReset && !windowReset) || (noWindowReset && primaryPercent !== 0)) return null;
254
+ // An idle 5-hour window has no reset time; one whose reset has passed carries no usage into the next window.
255
+ const windowActive = windowReset !== undefined && windowReset.getTime() > now;
256
+ if (!windowActive) primaryPercent = 0;
257
+ return {
258
+ primary: {
259
+ usedPercent: primaryPercent,
260
+ windowMinutes: Math.round(seconds / 60),
261
+ resetsAt: windowActive ? windowReset : undefined,
262
+ },
263
+ secondary: { usedPercent: weeklyPercent, windowMinutes: 10080, resetsAt: weeklyReset },
264
+ };
265
+ }
266
+ if (root.subs_usage === undefined || root.subs_usage === null) {
267
+ // The login response omits quotas while the 5-hour window is idle, even when the weekly limit has usage.
268
+ // The dev.meta.ai usage page reads the same subscription quota with the browser session.
269
+ const web = await webQuota();
270
+ if (!_optionalChain([web, "optionalAccess", (_14) => _14.quota]))
271
+ rows.push({ label: "Quota", value: "Not included in this login response" });
272
+ if (!web) return snapshot;
273
+ const teamRows = _nullishCoalesce(web.teams, () => []).map((team) => ({ label: team.name, value: team.id }));
274
+ if (web.note) teamRows.unshift({ label: "Status", value: web.note });
275
+ _optionalChain([
276
+ snapshot,
277
+ "access",
278
+ (_15) => _15.details,
279
+ "optionalAccess",
280
+ (_16) => _16.push,
281
+ "call",
282
+ (_17) => _17({ title: "Browser teams", rows: teamRows }),
283
+ ]);
284
+ if (!web.quota) return snapshot;
285
+ const { team, primary, secondary } = web.quota;
286
+ const webRows = [
287
+ { label: "Team", value: team.name },
288
+ { label: "5 hours", value: percentLabel(primary.usedPercent) },
289
+ { label: "Weekly", value: percentLabel(secondary.usedPercent) },
290
+ ];
291
+ _optionalChain([
292
+ snapshot,
293
+ "access",
294
+ (_18) => _18.details,
295
+ "optionalAccess",
296
+ (_19) => _19.push,
297
+ "call",
298
+ (_20) => _20({ title: "Browser team quota (dev.meta.ai)", rows: webRows }),
299
+ ]);
300
+ // Weighted usage reported for a user-selected team, not by the CLI login itself.
301
+ return { usage: { ...snapshot, primary, secondary, dataConfidence: "estimated" }, sourceLabel: "oauth+web" };
302
+ }
303
+ const usage = object(root.subs_usage, "subs_usage");
304
+ const window = object(usage.window, "missing subscription window");
305
+ const weekly = object(usage.weekly, "missing weekly window");
306
+ const minutes = Math.round(number(window.window_duration_mins, "window_duration_mins"));
307
+ if (!Number.isSafeInteger(minutes) || minutes <= 0) return fail("window_duration_mins");
308
+ const primaryPercent = Math.min(100, Math.max(0, number(window.used_percent, "window.used_percent")));
309
+ const weeklyPercent = Math.min(100, Math.max(0, number(weekly.used_percent, "weekly.used_percent")));
310
+ rows.push({ label: "5 hours", value: percentLabel(primaryPercent) });
311
+ rows.push({ label: "Weekly", value: percentLabel(weeklyPercent) });
312
+ return {
313
+ ...snapshot,
314
+ primary: { usedPercent: primaryPercent, windowMinutes: minutes, resetsAt: reset(window.resets_at) },
315
+ secondary: { usedPercent: weeklyPercent, windowMinutes: 10080, resetsAt: reset(weekly.resets_at) },
316
+ dataConfidence: "exact",
317
+ };
318
+ },
319
+ });
@@ -0,0 +1,26 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "muse",
4
+ "name": "Muse Code",
5
+ "version": "0.1.0",
6
+ "entry": "plugin.js",
7
+ "enabledByDefault": false,
8
+ "supportedModes": [
9
+ "api"
10
+ ],
11
+ "autoMode": "api",
12
+ "usageDashboardUrl": "https://dev.meta.ai",
13
+ "webUrl": "https://dev.meta.ai",
14
+ "envVars": [
15
+ "MUSE_DEVICE_TOKEN",
16
+ "MUSE_WEB_TEAM_ID",
17
+ "MUSE_COOKIE"
18
+ ],
19
+ "upstream": {
20
+ "repository": "https://github.com/steipete/CodexBar",
21
+ "revision": "78ba5a1e65e6859da59a21b799df95ab91bc0b89",
22
+ "path": "Sources/CodexBarCore/Resources/Plugins/muse.js",
23
+ "sha256": "80ddeae2d6f2fb90b22b3a978dfdd5f8904a1766687a19bc93c8108fd5a7dc41",
24
+ "license": "MIT"
25
+ }
26
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1 @@
1
+ <svg fill="currentColor" fill-rule="evenodd" height="512" style="flex:none;line-height:1" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg"><title>Notion</title><path clip-rule="evenodd" d="M15.257.055l-13.31.98C.874 1.128.5 1.83.5 2.667v14.559c0 .654.233 1.213.794 1.96l3.129 4.06c.513.653.98.794 1.962.745l15.457-.932c1.307-.093 1.681-.7 1.681-1.727V4.954c0-.53-.21-.684-.829-1.135l-.106-.078L18.34.755c-1.027-.746-1.45-.84-3.083-.7zm-8.521 4.63c-1.263.086-1.549.105-2.266-.477L2.647 2.76c-.186-.187-.092-.42.375-.466l12.796-.933c1.074-.094 1.634.28 2.054.606l2.195 1.587c.093.047.326.326.047.326l-13.216.794-.162.01zM5.263 21.193V7.287c0-.606.187-.886.748-.933l15.176-.886c.515-.047.748.28.748.886v13.81c0 .609-.093 1.122-.934 1.168l-14.523.84c-.842.047-1.215-.232-1.215-.98zm14.338-13.16c.093.422 0 .842-.422.89l-.699.139v10.264c-.608.327-1.168.513-1.635.513-.747 0-.934-.232-1.495-.932l-4.576-7.185v6.952l1.448.327s0 .84-1.169.84l-3.221.186c-.094-.187 0-.654.327-.747l.84-.232V9.853L7.832 9.76c-.093-.42.14-1.026.794-1.073l3.456-.232 4.763 7.279v-6.44l-1.214-.14c-.094-.513.28-.887.747-.933l3.223-.187z"></path></svg>