@hashimkarim/usagestat-linux-x64-gnu 2.0.0-alpha.3 → 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 (142) hide show
  1. package/native-manifest.json +731 -65
  2. package/package.json +112 -1
  3. package/plugins/UPSTREAM-LICENSES.md +6 -2
  4. package/plugins/_provider-icons/LICENSE +21 -0
  5. package/plugins/_provider-icons/NOTICE +12 -0
  6. package/plugins/_provider-icons/licenses/CodexBar-MIT.txt +21 -0
  7. package/plugins/_provider-icons/licenses/LobeHub-MIT.txt +21 -0
  8. package/plugins/_provider-icons/licenses/UsageStat-Bar-MIT.txt +21 -0
  9. package/plugins/_provider-icons/manifest.json +1219 -0
  10. package/plugins/_provider-icons/provenance.json +269 -0
  11. package/plugins/_provider-icons/source.json +4 -0
  12. package/plugins/abacus-ai/icon-color.svg +18 -0
  13. package/plugins/aixy/LICENSE +21 -0
  14. package/plugins/aixy/plugin.js +261 -0
  15. package/plugins/aixy/plugin.json +24 -0
  16. package/plugins/antigravity/plugin.js +136 -46
  17. package/plugins/antigravity-cli/icon-color.svg +1 -0
  18. package/plugins/antigravity-cli/icon.svg +1 -3
  19. package/plugins/antigravity-cli/plugin.js +11 -15
  20. package/plugins/antigravity-ide/icon-color.svg +1 -0
  21. package/plugins/antigravity-ide/icon.svg +1 -3
  22. package/plugins/atlascloud/LICENSE +21 -0
  23. package/plugins/atlascloud/icon-color.svg +1 -0
  24. package/plugins/atlascloud/icon.svg +1 -0
  25. package/plugins/atlascloud/plugin.js +49 -0
  26. package/plugins/atlascloud/plugin.json +23 -0
  27. package/plugins/augment/icon-color.svg +14 -0
  28. package/plugins/bifrost/LICENSE +21 -0
  29. package/plugins/bifrost/plugin.js +361 -0
  30. package/plugins/bifrost/plugin.json +23 -0
  31. package/plugins/claude/plugin.js +302 -152
  32. package/plugins/claude/plugin.json +1 -1
  33. package/plugins/clinepass/plugin.js +19 -3
  34. package/plugins/codebuff/icon-color.svg +92 -0
  35. package/plugins/coderabbit/plugin.js +25 -0
  36. package/plugins/coderabbit/plugin.json +12 -0
  37. package/plugins/codex/plugin.js +1 -0
  38. package/plugins/command-code/icon-color.svg +3 -0
  39. package/plugins/command-code/plugin.js +7 -3
  40. package/plugins/copilot/icon.svg +1 -1
  41. package/plugins/crof/icon-color.svg +3 -0
  42. package/plugins/crofai/icon-color.svg +3 -0
  43. package/plugins/crofai/icon.svg +2 -15
  44. package/plugins/cursor/icon-color.svg +1 -0
  45. package/plugins/deepinfra/icon-color.svg +1 -0
  46. package/plugins/deepinfra/icon.svg +1 -4
  47. package/plugins/deepseek/plugin.js +150 -59
  48. package/plugins/deepseek/plugin.json +3 -1
  49. package/plugins/devin/plugin.js +3 -0
  50. package/plugins/devpass/LICENSE +21 -0
  51. package/plugins/devpass/plugin.js +115 -0
  52. package/plugins/devpass/plugin.json +23 -0
  53. package/plugins/elevenlabs/icon-color.svg +4 -0
  54. package/plugins/factory/icon-color.svg +1 -0
  55. package/plugins/fireworks-ai/icon-color.svg +1 -0
  56. package/plugins/fireworks-ai/icon.svg +1 -6
  57. package/plugins/gemini-apps/LICENSE +22 -0
  58. package/plugins/gemini-apps/icon-color.svg +1 -0
  59. package/plugins/gemini-apps/icon.svg +1 -0
  60. package/plugins/gemini-apps/plugin.js +470 -0
  61. package/plugins/gemini-apps/plugin.json +19 -0
  62. package/plugins/gitkraken/LICENSE +21 -0
  63. package/plugins/gitkraken/plugin.js +153 -0
  64. package/plugins/gitkraken/plugin.json +24 -0
  65. package/plugins/grok/icon-color.svg +1 -0
  66. package/plugins/groqcloud/icon-color.svg +1 -0
  67. package/plugins/helmcode/LICENSE +21 -0
  68. package/plugins/helmcode/plugin.js +188 -0
  69. package/plugins/helmcode/plugin.json +24 -0
  70. package/plugins/huggingface/LICENSE +21 -0
  71. package/plugins/huggingface/icon-color.svg +1 -0
  72. package/plugins/huggingface/icon.svg +1 -0
  73. package/plugins/huggingface/plugin.js +293 -0
  74. package/plugins/huggingface/plugin.json +25 -0
  75. package/plugins/hyper/LICENSE +21 -0
  76. package/plugins/hyper/plugin.js +131 -0
  77. package/plugins/hyper/plugin.json +26 -0
  78. package/plugins/kilo/icon-color.svg +1 -0
  79. package/plugins/litellm/plugin.js +54 -3
  80. package/plugins/llmman/LICENSE +21 -0
  81. package/plugins/llmman/plugin.js +133 -0
  82. package/plugins/llmman/plugin.json +23 -0
  83. package/plugins/longcat/icon-color.svg +1 -0
  84. package/plugins/longcat/icon.svg +1 -4
  85. package/plugins/manus/icon-color.svg +6 -0
  86. package/plugins/mimo/icon-color.svg +4 -0
  87. package/plugins/mimo/icon.svg +4 -1
  88. package/plugins/mistral/plugin.js +110 -5
  89. package/plugins/moonshot/icon-color.svg +1 -0
  90. package/plugins/muse/LICENSE +21 -0
  91. package/plugins/muse/plugin.js +319 -0
  92. package/plugins/muse/plugin.json +26 -0
  93. package/plugins/nous/LICENSE +21 -0
  94. package/plugins/nous/icon-color.svg +1 -0
  95. package/plugins/nous/icon.svg +1 -0
  96. package/plugins/nous/plugin.js +124 -0
  97. package/plugins/nous/plugin.json +24 -0
  98. package/plugins/ollama/icon-color.svg +1 -0
  99. package/plugins/openai-api/icon-color.svg +1 -0
  100. package/plugins/opencode/icon-color.svg +1 -0
  101. package/plugins/opencode-go/icon-color.svg +1 -0
  102. package/plugins/opencode-go/plugin.js +30 -12
  103. package/plugins/openrouter/icon-color.svg +1 -0
  104. package/plugins/pi/plugin.js +113 -0
  105. package/plugins/pi/plugin.json +11 -0
  106. package/plugins/qwencloud/icon-color.svg +1 -0
  107. package/plugins/qwencloud/icon.svg +1 -4
  108. package/plugins/raycast/LICENSE +21 -0
  109. package/plugins/raycast/plugin.js +174 -0
  110. package/plugins/raycast/plugin.json +24 -0
  111. package/plugins/replicate/LICENSE +21 -0
  112. package/plugins/replicate/icon-color.svg +1 -0
  113. package/plugins/replicate/icon.svg +1 -0
  114. package/plugins/replicate/plugin.js +165 -0
  115. package/plugins/replicate/plugin.json +24 -0
  116. package/plugins/synthetic/icon-color.svg +14 -0
  117. package/plugins/typesafe/LICENSE +21 -0
  118. package/plugins/typesafe/plugin.js +225 -0
  119. package/plugins/typesafe/plugin.json +24 -0
  120. package/plugins/v0/LICENSE +21 -0
  121. package/plugins/v0/icon-color.svg +1 -0
  122. package/plugins/v0/icon.svg +1 -0
  123. package/plugins/v0/plugin.js +214 -0
  124. package/plugins/v0/plugin.json +24 -0
  125. package/plugins/venice/plugin.js +50 -1
  126. package/plugins/venice/plugin.json +2 -1
  127. package/plugins/vercel/LICENSE +21 -0
  128. package/plugins/vercel/icon-color.svg +1 -0
  129. package/plugins/vercel/icon.svg +1 -0
  130. package/plugins/vercel/plugin.js +55 -0
  131. package/plugins/vercel/plugin.json +23 -0
  132. package/plugins/windsurf/icon-color.svg +1 -0
  133. package/plugins/xai/icon-color.svg +1 -0
  134. package/plugins/xai/icon.svg +1 -7
  135. package/plugins/xkiro/LICENSE +21 -0
  136. package/plugins/xkiro/plugin.js +99 -0
  137. package/plugins/xkiro/plugin.json +23 -0
  138. package/plugins/zai/icon-color.svg +1 -0
  139. package/plugins/zenmux/icon-color.svg +1 -0
  140. package/plugins/zenmux/icon.svg +1 -3
  141. package/usagestat +0 -0
  142. package/usagestatd +0 -0
@@ -0,0 +1,24 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "replicate",
4
+ "name": "Replicate",
5
+ "version": "0.1.0",
6
+ "entry": "plugin.js",
7
+ "enabledByDefault": false,
8
+ "supportedModes": [
9
+ "web"
10
+ ],
11
+ "autoMode": "web",
12
+ "usageDashboardUrl": "https://replicate.com/account/billing",
13
+ "webUrl": "https://replicate.com",
14
+ "envVars": [
15
+ "REPLICATE_COOKIE"
16
+ ],
17
+ "upstream": {
18
+ "repository": "https://github.com/steipete/CodexBar",
19
+ "revision": "78ba5a1e65e6859da59a21b799df95ab91bc0b89",
20
+ "path": "Sources/CodexBarCore/Resources/Plugins/replicate.js",
21
+ "sha256": "d240c36fa142ee91ce90ae52a2c6814613d2d5533a00c8a4c7ecec2f9386006c",
22
+ "license": "MIT"
23
+ }
24
+ }
@@ -0,0 +1,14 @@
1
+ <svg width="100" height="100" viewBox="0 0 54 54" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M27.8517 26.3314C27.8439 26.1451 27.8371 25.9303 27.8337 25.692C27.8203 24.7571 27.8545 23.4581 28.0457 22.0052C28.4322 19.0688 29.4394 15.6521 31.8222 13.2693C34.205 10.8867 37.6212 9.87992 40.5575 9.49344C42.0107 9.30219 43.3101 9.26734 44.245 9.28076C44.4829 9.28417 44.6968 9.29231 44.883 9.30009C44.8908 9.48595 44.8975 9.69933 44.901 9.93676C44.9144 10.8716 44.8795 12.171 44.6883 13.6242C44.3018 16.5605 43.2958 19.9773 40.9131 22.3602C38.5303 24.743 35.1129 25.7495 32.1765 26.136C30.7234 26.3272 29.4246 26.3614 28.4897 26.348C28.2518 26.3446 28.0378 26.3392 27.8517 26.3314Z" stroke="currentColor" stroke-width="2.5"/>
3
+ <path d="M27.8916 27.1592C28.0179 27.0219 28.165 26.8653 28.3311 26.6943C28.9826 26.0238 29.9253 25.1295 31.0879 24.2373C33.4375 22.4342 36.5658 20.7305 39.9355 20.7305C43.3051 20.7306 46.4327 22.4343 48.7822 24.2373C49.945 25.1296 50.8885 26.0238 51.54 26.6943C51.7059 26.865 51.8514 27.022 51.9775 27.1592C51.8516 27.2961 51.7055 27.4518 51.54 27.6221C50.8885 28.2926 49.945 29.1868 48.7822 30.0791C46.4327 31.8821 43.3052 33.5868 39.9355 33.5869C36.5657 33.5869 33.4375 31.8822 31.0879 30.0791C29.9252 29.1868 28.9826 28.2926 28.3311 27.6221C28.1652 27.4514 28.0177 27.2963 27.8916 27.1592Z" stroke="currentColor" stroke-width="2.5"/>
4
+ <path d="M27.4459 27.6915C27.6323 27.6837 27.8471 27.677 28.0854 27.6736C29.0202 27.6602 30.3192 27.6943 31.7721 27.8856C34.7085 28.272 38.1253 29.2793 40.5081 31.6621C42.8906 34.0448 43.8974 37.4611 44.2839 40.3973C44.4752 41.8505 44.51 43.1499 44.4966 44.0848C44.4932 44.3228 44.485 44.5367 44.4773 44.7229C44.2914 44.7306 44.078 44.7374 43.8406 44.7408C42.9057 44.7542 41.6063 44.7194 40.1531 44.5281C37.2168 44.1417 33.8 43.1356 31.4172 40.753C29.0343 38.3701 28.0278 34.9528 27.6413 32.0163C27.4501 30.5633 27.4159 29.2644 27.4294 28.3296C27.4328 28.0916 27.4381 27.8777 27.4459 27.6915Z" stroke="currentColor" stroke-width="2.5"/>
5
+ <path d="M26.916 28.1289C27.0533 28.2552 27.2099 28.4023 27.3809 28.5684C28.0514 29.2199 28.9457 30.1626 29.8379 31.3252C31.641 33.6748 33.3447 36.8031 33.3447 40.1728C33.3446 43.5424 31.6409 46.67 29.8379 49.0195C28.9456 50.1823 28.0514 51.1258 27.3809 51.7773C27.2102 51.9432 27.0532 52.0887 26.916 52.2148C26.7791 52.0889 26.6234 51.9428 26.4531 51.7773C25.7826 51.1258 24.8884 50.1823 23.9961 49.0195C22.1931 46.67 20.4884 43.5426 20.4883 40.1728C20.4883 36.803 22.193 33.6748 23.9961 31.3252C24.8884 30.1625 25.7826 29.2199 26.4531 28.5684C26.6238 28.4025 26.7789 28.255 26.916 28.1289Z" stroke="currentColor" stroke-width="2.5"/>
6
+ <path d="M26.2147 27.691C26.2225 27.8774 26.2293 28.0922 26.2327 28.3305C26.2461 29.2653 26.2119 30.5643 26.0207 32.0172C25.6342 34.9536 24.627 38.3704 22.2442 40.7532C19.8614 43.1357 16.4452 44.1425 13.5089 44.529C12.0557 44.7203 10.7563 44.7551 9.82145 44.7417C9.58349 44.7383 9.36957 44.7301 9.1834 44.7224C9.17564 44.5365 9.16886 44.3231 9.16545 44.0857C9.15203 43.1508 9.18689 41.8514 9.37813 40.3982C9.76458 37.4619 10.7706 34.0451 13.1533 31.6623C15.5361 29.2795 18.9535 28.2729 21.8899 27.8865C23.343 27.6952 24.6419 27.6611 25.5767 27.6745C25.8146 27.6779 26.0286 27.6833 26.2147 27.691Z" stroke="currentColor" stroke-width="2.5"/>
7
+ <path d="M25.7021 27.1602C25.5759 27.2974 25.4288 27.4541 25.2627 27.625C24.6111 28.2955 23.6684 29.1899 22.5059 30.082C20.1562 31.8851 17.028 33.5889 13.6582 33.5889C10.2886 33.5887 7.16105 31.885 4.81153 30.082C3.64873 29.1897 2.70529 28.2955 2.05372 27.625C1.88786 27.4543 1.74236 27.2973 1.61622 27.1602C1.74215 27.0232 1.88824 26.8676 2.05372 26.6973C2.70527 26.0267 3.64874 25.1326 4.81153 24.2402C7.16108 22.4372 10.2885 20.7326 13.6582 20.7324C17.0281 20.7324 20.1562 22.4371 22.5059 24.2402C23.6686 25.1325 24.6112 26.0268 25.2627 26.6973C25.4285 26.8679 25.576 27.023 25.7021 27.1602Z" stroke="currentColor" stroke-width="2.5"/>
8
+ <path d="M25.7338 25.9813C25.5474 25.9891 25.3326 25.9959 25.0943 25.9993C24.1595 26.0127 22.8605 25.9785 21.4076 25.7873C18.4712 25.4008 15.0544 24.3936 12.6716 22.0108C10.2891 19.628 9.28226 16.2118 8.89579 13.2755C8.70453 11.8223 8.66969 10.5229 8.6831 9.58806C8.68652 9.35009 8.69466 9.13618 8.70244 8.95C8.8883 8.94224 9.10168 8.93546 9.33911 8.93205C10.274 8.91863 11.5734 8.95349 13.0266 9.14473C15.9629 9.53118 19.3797 10.5372 21.7625 12.9199C24.1454 15.3027 25.1519 18.7201 25.5383 21.6565C25.7296 23.1096 25.7638 24.4085 25.7503 25.3433C25.7469 25.5812 25.7415 25.7952 25.7338 25.9813Z" stroke="currentColor" stroke-width="2.5"/>
9
+ <path d="M26.9121 25.7031C26.7748 25.5769 26.6182 25.4298 26.4473 25.2637C25.7768 24.6121 24.8824 23.6694 23.9902 22.5068C22.1872 20.1572 20.4834 17.029 20.4834 13.6592C20.4835 10.2896 22.1873 7.16203 23.9902 4.8125C24.8826 3.6497 25.7767 2.70627 26.4473 2.05469C26.618 1.88883 26.775 1.74333 26.9121 1.61719C27.049 1.74312 27.2047 1.88921 27.375 2.05469C28.0455 2.70624 28.9397 3.64971 29.832 4.8125C31.6351 7.16206 33.3397 10.2895 33.3398 13.6592C33.3398 17.029 31.6351 20.1572 29.832 22.5068C28.9398 23.6695 28.0455 24.6121 27.375 25.2637C27.2043 25.4295 27.0492 25.577 26.9121 25.7031Z" stroke="currentColor" stroke-width="2.5"/>
10
+ <g transform="translate(21.7222 21.7222) scale(0.5555556)">
11
+ <path d="M8.56067 1.3799L10.4618 1.34671C10.5492 1.34522 10.6286 1.38935 10.6747 1.45923L10.7093 1.53774L11.045 2.92076C11.1559 3.37707 11.4798 3.75232 11.9152 3.92819C12.3419 4.10041 12.8251 4.0605 13.2183 3.82145L14.3036 3.16178C14.3771 3.11703 14.4662 3.1144 14.5407 3.14983L14.6099 3.19745L15.9965 4.57385C16.0577 4.63461 16.0825 4.72126 16.0659 4.80217L16.035 4.88085L15.4788 5.80573C15.2386 6.20505 15.1867 6.68631 15.3299 7.12299L15.4034 7.30728C15.5966 7.71593 15.9524 8.02086 16.3793 8.15073L16.5666 8.19532L17.4238 8.34639C17.5414 8.36729 17.628 8.46852 17.6302 8.58794L17.6642 10.533C17.6662 10.6479 17.5891 10.7499 17.478 10.7794L16.3785 11.0721C15.9508 11.1859 15.5956 11.4767 15.399 11.8666L15.3249 12.0398C15.1648 12.4858 15.2187 12.9804 15.4714 13.3812L16.0028 14.2246C16.0497 14.2991 16.0532 14.3908 16.0168 14.4666L15.9672 14.5358L14.5394 15.9448C14.4825 16.0008 14.4038 16.025 14.3277 16.0139L14.2531 15.9908L13.2136 15.4747C12.8594 15.2989 12.4528 15.2697 12.0801 15.388L11.9219 15.4474C11.5639 15.6067 11.2838 15.8977 11.1361 16.2562L11.0812 16.4134L10.7617 17.5217C10.7312 17.6271 10.6352 17.7006 10.5255 17.7026L8.58735 17.7364C8.46855 17.7385 8.36456 17.6565 8.33878 17.5405L8.08316 16.3817L8.03422 16.2078C7.91462 15.8694 7.67485 15.5859 7.36105 15.4118L7.19756 15.3345L7.04329 15.2815C6.73077 15.1941 6.39776 15.2128 6.0968 15.3342L5.94955 15.4032L4.77293 16.0371C4.6979 16.0774 4.60969 16.0756 4.53755 16.0373L4.47222 15.9877L3.13752 14.5596C3.0776 14.4954 3.05736 14.4064 3.07873 14.3252L3.11353 14.2484L3.7373 13.3331C3.98342 12.9717 4.04895 12.5208 3.923 12.109L3.85746 11.9353L3.78169 11.7911C3.61486 11.5129 3.35814 11.2998 3.05423 11.1865L2.89807 11.1374L1.49728 10.7907C1.38749 10.7635 1.30969 10.6659 1.30755 10.5528L1.27503 8.6898C1.27334 8.58474 1.33722 8.49154 1.43207 8.45363L1.47385 8.44118L2.69615 8.18641C3.14512 8.09283 3.52318 7.80066 3.72943 7.39873L3.80738 7.2196C3.94662 6.83155 3.92084 6.40585 3.73992 6.04091L3.6523 5.8891L3.04806 4.9581C2.98255 4.85725 2.99751 4.72403 3.08453 4.64101L4.58516 3.20932C4.67146 3.12699 4.80459 3.11666 4.90217 3.18523L5.71797 3.75897C6.12951 4.04818 6.65895 4.11193 7.1274 3.92874C7.53749 3.76829 7.85309 3.43752 7.99657 3.02769L8.04812 2.84707L8.32092 1.57747C8.34533 1.46387 8.44449 1.38193 8.56067 1.3799Z" fill="currentColor" stroke="currentColor" stroke-width="1.5"/>
12
+ <circle cx="9.46694" cy="9.5416" r="2.53895" transform="rotate(-1 9.46694 9.5416)" fill="currentColor" stroke="currentColor" stroke-width="1.5"/>
13
+ </g>
14
+ </svg>
@@ -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,225 @@
1
+ // Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
2
+ globalThis.__usagestat_bundled_options = {"labels":["Spend","Spend","Additional"],"defaults":{},"autoMode":"web"};
3
+ function _optionalChain(ops) {
4
+ let lastAccessLHS = undefined;
5
+ let value = ops[0];
6
+ let i = 1;
7
+ while (i < ops.length) {
8
+ const op = ops[i];
9
+ const fn = ops[i + 1];
10
+ i += 2;
11
+ if ((op === "optionalAccess" || op === "optionalCall") && value == null) {
12
+ return undefined;
13
+ }
14
+ if (op === "access" || op === "optionalAccess") {
15
+ lastAccessLHS = value;
16
+ value = fn(value);
17
+ } else if (op === "call" || op === "optionalCall") {
18
+ value = fn((...args) => value.call(lastAccessLHS, ...args));
19
+ lastAccessLHS = undefined;
20
+ }
21
+ }
22
+ return value;
23
+ }
24
+
25
+ const billingURL = "https://console.typesafe.ai/settings/billing";
26
+ const billingOrigin = "https://console.typesafe.ai";
27
+ const actionCacheKey = "typesafe.billing.next-action";
28
+ const actionCacheTTL = 12 * 60 * 60;
29
+ const maximumChunkCount = 60;
30
+
31
+ defineProvider({
32
+ id: "typesafe",
33
+ name: "TypeSafe",
34
+ endpoints: [billingOrigin],
35
+ settings: [],
36
+ capabilities: ["browser-cookies", "http-status"],
37
+ cookieDomains: ["console.typesafe.ai", "typesafe.ai"],
38
+ async fetchUsage(ctx) {
39
+ const record = (value) =>
40
+ value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
41
+ const expired = () => {
42
+ throw ctx.fail.authenticationExpired("TypeSafe session expired. Sign in again or paste a fresh Cookie header.");
43
+ };
44
+ const retryAfter = (response) => {
45
+ const raw = response.headers["retry-after"];
46
+ const value = raw && /^\d+(?:\.\d+)?$/.test(raw.trim()) ? Number(raw) : 1;
47
+ return Number.isFinite(value) ? Math.min(10, value) : 1;
48
+ };
49
+ const validate = (response) => {
50
+ if (response.status === 401 || response.status === 403 || (response.status >= 300 && response.status < 400))
51
+ expired();
52
+ if (response.status === 429)
53
+ throw ctx.fail.rateLimited("TypeSafe rate limit reached.", { retryAfterSeconds: retryAfter(response) });
54
+ if (response.status === 408 || response.status >= 500)
55
+ throw ctx.fail.providerUnavailable("TypeSafe billing is unavailable.", {
56
+ retryAfterSeconds: retryAfter(response),
57
+ });
58
+ if (response.status < 200 || response.status >= 300)
59
+ throw ctx.fail.apiFailure(`TypeSafe returned HTTP ${response.status}.`);
60
+ };
61
+ // Login pages can also arrive directly with HTTP 200, without an HTTP redirect.
62
+ const isLoginLanding = (body) => /\\?"\(auth\)\\?",\{\\?"children\\?":\[\\?"login\\?"/.test(body);
63
+ const validateBody = (response) => {
64
+ validate(response);
65
+ if (isLoginLanding(response.bodyText)) expired();
66
+ };
67
+ const actionIDPattern = /"([0-9a-f]{40,})"[^)]{0,150}"getBillingOverviewResult"/i;
68
+ const discoverActionID = async (cookie) => {
69
+ const page = await ctx.http.get(billingURL, {
70
+ headers: { Cookie: cookie, Accept: "text/html" },
71
+ timeoutSeconds: 6,
72
+ });
73
+ validateBody(page);
74
+ const scriptPattern = /<script\b[^>]*\bsrc=["']([^"']+)["'][^>]*>/gi;
75
+ const chunkURLs = [];
76
+ let match;
77
+ while ((match = scriptPattern.exec(page.bodyText)) && chunkURLs.length < maximumChunkCount) {
78
+ const source = match[1];
79
+ const normalized = source.startsWith("/") ? `${billingOrigin}${source}` : source;
80
+ if (!normalized.startsWith(`${billingOrigin}/`) || !/\.js(?:$|\?)/i.test(normalized)) continue;
81
+ if (!chunkURLs.includes(normalized)) chunkURLs.push(normalized);
82
+ }
83
+ let discoveryFailure;
84
+ for (const url of chunkURLs) {
85
+ try {
86
+ const chunk = await ctx.http.get(url, { timeoutSeconds: 2 });
87
+ if (chunk.status === 429 || chunk.status === 408 || chunk.status >= 500) validate(chunk);
88
+ if (chunk.status < 200 || chunk.status >= 300) continue;
89
+ const action = _optionalChain([
90
+ actionIDPattern,
91
+ "access",
92
+ (_) => _.exec,
93
+ "call",
94
+ (_2) => _2(chunk.bodyText),
95
+ "optionalAccess",
96
+ (_3) => _3[1],
97
+ ]);
98
+ if (action) return action;
99
+ } catch (error) {
100
+ discoveryFailure ??= error;
101
+ }
102
+ }
103
+ if (discoveryFailure !== undefined) throw discoveryFailure;
104
+ throw ctx.fail.parseFailure("TypeSafe billing page format changed: action id not found.");
105
+ };
106
+ const cookie = await ctx.browser.cookieHeader("typesafe.ai");
107
+ let actionID = ctx.cache.get(actionCacheKey);
108
+ if (!actionID || !/^[0-9a-f]{40,}$/i.test(actionID)) {
109
+ actionID = await discoverActionID(cookie);
110
+ ctx.cache.set(actionCacheKey, actionID, actionCacheTTL);
111
+ }
112
+ const post = async (id) =>
113
+ ctx.http.post(billingURL, {
114
+ headers: {
115
+ Cookie: cookie,
116
+ Origin: billingOrigin,
117
+ "Next-Action": id,
118
+ Accept: "text/x-component",
119
+ "Content-Type": "application/json",
120
+ },
121
+ body: [],
122
+ timeoutSeconds: 6,
123
+ });
124
+ let response = await post(actionID);
125
+ if (response.status === 404 && response.headers["x-nextjs-action-not-found"] === "1") {
126
+ ctx.cache.set(actionCacheKey, "", 1);
127
+ actionID = await discoverActionID(cookie);
128
+ ctx.cache.set(actionCacheKey, actionID, actionCacheTTL);
129
+ response = await post(actionID);
130
+ }
131
+ validateBody(response);
132
+
133
+ let result;
134
+ for (const line of response.bodyText.split(/\r?\n/)) {
135
+ const separator = line.indexOf(":");
136
+ if (separator < 1) continue;
137
+ let candidate;
138
+ try {
139
+ candidate = JSON.parse(line.slice(separator + 1));
140
+ } catch (error) {
141
+ void error;
142
+ continue;
143
+ }
144
+ const object = record(candidate);
145
+ if (object && Object.prototype.hasOwnProperty.call(object, "ok")) {
146
+ result = object;
147
+ break;
148
+ }
149
+ }
150
+ if (!result) throw ctx.fail.parseFailure("TypeSafe billing response format changed: missing result.");
151
+ if (result.ok !== true) throw ctx.fail.apiFailure("TypeSafe billing request failed.");
152
+ const billing = record(
153
+ _optionalChain([record, "call", (_4) => _4(result.data), "optionalAccess", (_5) => _5.billing]),
154
+ );
155
+ if (!billing) throw ctx.fail.parseFailure("TypeSafe billing response format changed: missing billing.");
156
+ const number = (value) => (typeof value === "number" && Number.isFinite(value) ? value : undefined);
157
+ const spent = number(billing.spent);
158
+ const balance = number(billing.balance);
159
+ if (spent === undefined || balance === undefined)
160
+ throw ctx.fail.parseFailure("TypeSafe billing response format changed: missing billing numbers.");
161
+ const cycleLabel =
162
+ typeof billing.cycleLabel === "string" && billing.cycleLabel.trim() ? billing.cycleLabel.trim() : undefined;
163
+ const plan = typeof billing.plan === "string" && billing.plan.trim() ? billing.plan.trim() : undefined;
164
+ const planLabel =
165
+ plan === "free_plan"
166
+ ? "Free"
167
+ : _optionalChain([
168
+ plan,
169
+ "optionalAccess",
170
+ (_6) => _6.split,
171
+ "call",
172
+ (_7) => _7(/[_-]+/),
173
+ "access",
174
+ (_8) => _8.filter,
175
+ "call",
176
+ (_9) => _9(Boolean),
177
+ "access",
178
+ (_10) => _10.map,
179
+ "call",
180
+ (_11) => _11((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()),
181
+ "access",
182
+ (_12) => _12.join,
183
+ "call",
184
+ (_13) => _13(" "),
185
+ ]);
186
+ const rows = [{ label: cycleLabel ? `Spent (${cycleLabel})` : "Spent", value: ctx.format.usd(spent) }];
187
+ if (planLabel) rows.push({ label: "Plan", value: planLabel });
188
+ const availableRows = 24 - rows.length;
189
+ const creditRows = [];
190
+ let creditCount = 0;
191
+ if (Array.isArray(billing.credits)) {
192
+ for (const item of billing.credits) {
193
+ const credit = record(item);
194
+ const amount = number(_optionalChain([credit, "optionalAccess", (_14) => _14.amount]));
195
+ const remaining = number(_optionalChain([credit, "optionalAccess", (_15) => _15.remaining]));
196
+ const expiresAt =
197
+ typeof _optionalChain([credit, "optionalAccess", (_16) => _16.expiresAt]) === "string"
198
+ ? credit.expiresAt
199
+ : undefined;
200
+ if (amount === undefined || remaining === undefined || remaining <= 0 || !expiresAt) continue;
201
+ const expires = Date.parse(expiresAt);
202
+ if (!Number.isFinite(expires)) continue;
203
+ creditCount++;
204
+ if (creditRows.length >= availableRows) continue;
205
+ creditRows.push({
206
+ label: "Credit",
207
+ value: `${ctx.format.number(remaining)} of ${ctx.format.number(amount)}, expires ${ctx.format.monthDay(expires)}`,
208
+ });
209
+ }
210
+ }
211
+ if (creditCount > availableRows) {
212
+ const shown = availableRows - 1;
213
+ rows.push(...creditRows.slice(0, shown));
214
+ rows.push({ label: "Additional credits", value: String(creditCount - shown) });
215
+ } else {
216
+ rows.push(...creditRows);
217
+ }
218
+ return {
219
+ cost: { used: spent, balance, currency: "USD", period: cycleLabel },
220
+ details: [{ title: "Billing", rows }],
221
+ identity: { loginMethod: `Balance: ${ctx.format.usd(balance)}` },
222
+ dataConfidence: "exact",
223
+ };
224
+ },
225
+ });
@@ -0,0 +1,24 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "typesafe",
4
+ "name": "TypeSafe",
5
+ "version": "0.1.0",
6
+ "entry": "plugin.js",
7
+ "enabledByDefault": false,
8
+ "supportedModes": [
9
+ "web"
10
+ ],
11
+ "autoMode": "web",
12
+ "usageDashboardUrl": "https://console.typesafe.ai/usage",
13
+ "webUrl": "https://console.typesafe.ai",
14
+ "envVars": [
15
+ "TYPESAFE_COOKIE"
16
+ ],
17
+ "upstream": {
18
+ "repository": "https://github.com/steipete/CodexBar",
19
+ "revision": "78ba5a1e65e6859da59a21b799df95ab91bc0b89",
20
+ "path": "Sources/CodexBarCore/Resources/Plugins/typesafe.js",
21
+ "sha256": "eb3941346a966b3f5f9e0010f17edaeed7dfb6c8b0331319a86f26da10d51980",
22
+ "license": "MIT"
23
+ }
24
+ }
@@ -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 @@
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>V0</title><path clip-rule="evenodd" d="M14.252 8.25h5.624c.088 0 .176.006.26.018l-5.87 5.87a1.889 1.889 0 01-.019-.265V8.25h-2.25v5.623a4.124 4.124 0 004.125 4.125h5.624v-2.25h-5.624c-.09 0-.179-.006-.265-.018l5.874-5.875a1.9 1.9 0 01.02.27v5.623H24v-5.624A4.124 4.124 0 0019.876 6h-5.624v2.25zM0 7.5v.006l7.686 9.788c.924 1.176 2.813.523 2.813-.973V7.5H8.25v6.87L2.856 7.5H0z"></path></svg>
@@ -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>V0</title><path clip-rule="evenodd" d="M14.252 8.25h5.624c.088 0 .176.006.26.018l-5.87 5.87a1.889 1.889 0 01-.019-.265V8.25h-2.25v5.623a4.124 4.124 0 004.125 4.125h5.624v-2.25h-5.624c-.09 0-.179-.006-.265-.018l5.874-5.875a1.9 1.9 0 01.02.27v5.623H24v-5.624A4.124 4.124 0 0019.876 6h-5.624v2.25zM0 7.5v.006l7.686 9.788c.924 1.176 2.813.523 2.813-.973V7.5H8.25v6.87L2.856 7.5H0z"></path></svg>
@@ -0,0 +1,214 @@
1
+ // Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
2
+ globalThis.__usagestat_bundled_options = {"labels":["Billing","Rate limit","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
+ const V0_API_BASE = "https://api.v0.dev/v1";
32
+
33
+ defineProvider({
34
+ id: "v0",
35
+ name: "v0",
36
+ endpoints: ["https://api.v0.dev"],
37
+ auth: { type: "bearer", secret: "V0_API_KEY" },
38
+ settings: [
39
+ {
40
+ key: "V0_API_KEY",
41
+ title: "API key",
42
+ subtitle: "A v0 Platform API key.",
43
+ type: "secure",
44
+ },
45
+ {
46
+ key: "V0_SCOPE",
47
+ title: "Scope",
48
+ subtitle: "Optional project ID or slug.",
49
+ type: "plain",
50
+ },
51
+ ],
52
+ capabilities: ["http-status"],
53
+
54
+ async fetchUsage(ctx) {
55
+ const scope = _optionalChain([
56
+ ctx,
57
+ "access",
58
+ (_) => _.settings,
59
+ "access",
60
+ (_2) => _2.get,
61
+ "call",
62
+ (_3) => _3("V0_SCOPE"),
63
+ "optionalAccess",
64
+ (_4) => _4.trim,
65
+ "call",
66
+ (_5) => _5(),
67
+ ]);
68
+ const query = scope ? `?scope=${encodeURIComponent(scope)}` : "";
69
+
70
+ function apiError(response) {
71
+ if (response.status === 401) throw ctx.fail.authenticationExpired("v0 API key was rejected.");
72
+ if (response.status === 403) throw ctx.fail.permissionDenied("v0 denied access to this scope.");
73
+ if (response.status === 429) {
74
+ const delay = Number(_nullishCoalesce(response.headers["retry-after"], () => 1));
75
+ throw ctx.fail.rateLimited("v0 API rate limit reached.", {
76
+ retryAfterSeconds: Number.isFinite(delay) && delay >= 0 ? Math.min(delay, 10) : 1,
77
+ });
78
+ }
79
+ if (response.status >= 500) throw ctx.fail.providerUnavailable(`v0 API returned HTTP ${response.status}.`);
80
+ throw ctx.fail.apiFailure(`v0 API returned HTTP ${response.status}.`);
81
+ }
82
+
83
+ function fail(field) {
84
+ throw ctx.fail.parseFailure(`Could not parse v0 usage: ${field}`);
85
+ }
86
+
87
+ async function getJSON(path) {
88
+ const response = await ctx.http.get(`${V0_API_BASE}${path}${query}`);
89
+ if (response.status !== 200) apiError(response);
90
+ try {
91
+ return JSON.parse(response.bodyText);
92
+ } catch (error) {
93
+ void error;
94
+ return fail(`${path} returned invalid JSON`);
95
+ }
96
+ }
97
+
98
+ function object(value, field) {
99
+ if (!value || typeof value !== "object" || Array.isArray(value)) return fail(field);
100
+ return value;
101
+ }
102
+
103
+ function number(value, field) {
104
+ if (typeof value !== "number" || !Number.isFinite(value)) return fail(field);
105
+ return value;
106
+ }
107
+
108
+ function text(value, field) {
109
+ if (value === undefined || value === null) return undefined;
110
+ if (typeof value !== "string") return fail(field);
111
+ return value.trim() || undefined;
112
+ }
113
+
114
+ function reset(value, field) {
115
+ if (value === undefined || value === null) return undefined;
116
+ const timestamp = number(value, field);
117
+ if (timestamp <= 0) return undefined;
118
+ return timestamp >= 1000000000000 ? ctx.date.unixMillis(timestamp) : ctx.date.unixSeconds(timestamp);
119
+ }
120
+
121
+ function optionalNumber(value, field) {
122
+ if (value === undefined || value === null) return undefined;
123
+ return number(value, field);
124
+ }
125
+
126
+ function quota(value, field) {
127
+ const payload = object(value, field);
128
+ const limit = number(payload.limit, `${field}.limit`);
129
+ const remaining = optionalNumber(payload.remaining, `${field}.remaining`);
130
+ if (limit < 0) return fail(`${field}.limit must not be negative`);
131
+ return {
132
+ usedPercent: remaining === undefined ? undefined : ctx.pct(Math.max(0, limit - remaining), limit),
133
+ resetsAt: reset(payload.reset, `${field}.reset`),
134
+ remaining,
135
+ limit,
136
+ };
137
+ }
138
+
139
+ function tokenBilling(value, field) {
140
+ const payload = object(value, field);
141
+ const balance = object(payload.balance, `${field}.balance`);
142
+ const total = number(balance.total, `${field}.balance.total`);
143
+ const remaining = number(balance.remaining, `${field}.balance.remaining`);
144
+ const billingCycle = object(payload.billingCycle, `${field}.billingCycle`);
145
+ const onDemand =
146
+ payload.onDemand === undefined || payload.onDemand === null
147
+ ? undefined
148
+ : object(payload.onDemand, `${field}.onDemand`);
149
+ if (total < 0) return fail(`${field}.balance.total must not be negative`);
150
+ return {
151
+ usedPercent: ctx.pct(Math.max(0, total - remaining), total),
152
+ resetsAt: reset(billingCycle.end, `${field}.billingCycle.end`),
153
+ remaining,
154
+ limit: total,
155
+ onDemandBalance: onDemand === undefined ? undefined : number(onDemand.balance, `${field}.onDemand.balance`),
156
+ };
157
+ }
158
+
159
+ const billing = object(await getJSON("/user/billing"), "billing response");
160
+ const billingType = text(billing.billingType, "billingType");
161
+ if (billingType !== "token" && billingType !== "legacy") return fail("billingType");
162
+ const tokenBillingData = billingType === "token" ? tokenBilling(billing.data, "billing.data") : undefined;
163
+ const billingData = _nullishCoalesce(tokenBillingData, () => quota(billing.data, "billing.data"));
164
+
165
+ const rateLimit = quota(await getJSON("/rate-limits"), "rate limit response");
166
+ const rateRemaining = rateLimit.remaining;
167
+
168
+ const billingRemaining = billingData.remaining;
169
+ const rows = [
170
+ {
171
+ label: "Billing remaining",
172
+ value:
173
+ billingRemaining === undefined
174
+ ? "Unavailable"
175
+ : ctx.format.number(billingRemaining, { maximumFractionDigits: 2 }),
176
+ secondaryValue: `${billingRemaining === undefined ? "limit" : "of"} ${ctx.format.number(billingData.limit, { maximumFractionDigits: 2 })}`,
177
+ },
178
+ ];
179
+ if (_optionalChain([tokenBillingData, "optionalAccess", (_6) => _6.onDemandBalance]) !== undefined) {
180
+ rows.push({
181
+ label: "On-demand balance",
182
+ value: ctx.format.number(tokenBillingData.onDemandBalance, { maximumFractionDigits: 2 }),
183
+ });
184
+ }
185
+ rows.push({
186
+ label: "Rate-limit remaining",
187
+ value:
188
+ rateRemaining === undefined ? "Unavailable" : ctx.format.number(rateRemaining, { maximumFractionDigits: 2 }),
189
+ secondaryValue:
190
+ rateRemaining === undefined
191
+ ? `limit ${ctx.format.number(rateLimit.limit, { maximumFractionDigits: 2 })}`
192
+ : `of ${ctx.format.number(rateLimit.limit, { maximumFractionDigits: 2 })}`,
193
+ });
194
+ if (billingType) rows.push({ label: "Billing type", value: billingType });
195
+ if (scope) rows.push({ label: "Scope", value: scope.slice(0, 120) });
196
+
197
+ return {
198
+ primary:
199
+ billingData.usedPercent === undefined
200
+ ? null
201
+ : { usedPercent: billingData.usedPercent, resetsAt: billingData.resetsAt },
202
+ secondary:
203
+ rateRemaining === undefined
204
+ ? null
205
+ : {
206
+ usedPercent: ctx.pct(Math.max(0, rateLimit.limit - rateRemaining), rateLimit.limit),
207
+ resetsAt: rateLimit.resetsAt,
208
+ },
209
+ details: [{ title: "v0 API", rows }],
210
+ identity: { loginMethod: "API key" },
211
+ dataConfidence: "exact",
212
+ };
213
+ },
214
+ });
@@ -0,0 +1,24 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "v0",
4
+ "name": "v0",
5
+ "version": "0.1.0",
6
+ "entry": "plugin.js",
7
+ "enabledByDefault": false,
8
+ "supportedModes": [
9
+ "api"
10
+ ],
11
+ "autoMode": "api",
12
+ "usageDashboardUrl": "https://v0.app/settings/billing",
13
+ "envVars": [
14
+ "V0_API_KEY",
15
+ "V0_SCOPE"
16
+ ],
17
+ "upstream": {
18
+ "repository": "https://github.com/steipete/CodexBar",
19
+ "revision": "78ba5a1e65e6859da59a21b799df95ab91bc0b89",
20
+ "path": "Sources/CodexBarCore/Resources/Plugins/v0.js",
21
+ "sha256": "5f54a9329dca35d59d76e427c34d4d9db8d3400d0b38c5fcee8899928a900019",
22
+ "license": "MIT"
23
+ }
24
+ }
@@ -2,12 +2,15 @@
2
2
  var API_URL = "https://api.venice.ai/api/v1/billing/balance";
3
3
 
4
4
  function loadApiKey(ctx) {
5
+ if (Object.prototype.hasOwnProperty.call(ctx.provider || {}, 'apiKey')) return ctx.provider.apiKey;
6
+ if (ctx.provider && ctx.provider.instanceId && ctx.provider.instanceId !== 'venice') return null;
5
7
  var v = ctx.host.env.get("VENICE_API_KEY");
6
8
  if (typeof v === "string" && v.trim()) return v.trim();
7
9
  return null;
8
10
  }
9
11
 
10
12
  function probe(ctx) {
13
+ if (ctx.sourceMode === 'web') return webUsage(ctx);
11
14
  var apiKey = loadApiKey(ctx);
12
15
  if (!apiKey) {
13
16
  throw "Venice API key not found. Set VENICE_API_KEY.";
@@ -62,7 +65,53 @@
62
65
  lines.push(ctx.line.badge({ label: "Balance", text: "No Venice API balance", color: "#a3a3a3" }));
63
66
  }
64
67
 
65
- return { lines: lines };
68
+ return { source: 'api', lines: lines };
69
+ }
70
+
71
+ function webUsage(ctx) {
72
+ var provider = ctx.provider || {};
73
+ if (provider.settings && provider.settings.cookies === 'off') throw new Error('Venice web cookies are disabled.');
74
+ var raw = Object.prototype.hasOwnProperty.call(provider, 'cookieHeader') ? provider.cookieHeader :
75
+ provider.instanceId && provider.instanceId !== 'venice' ? '' : ctx.host.env.get('VENICE_COOKIE');
76
+ var cookies = {};
77
+ String(raw || '').replace(/^Cookie:\s*/i, '').split(';').forEach(function(pair) {
78
+ var at = pair.indexOf('='); if (at > 0) cookies[pair.slice(0,at).trim()] = pair.slice(at+1).trim();
79
+ });
80
+ var legacy = '__venice-auth.session-token';
81
+ var token = cookies[legacy];
82
+ var chunks = Object.keys(cookies).filter(function(key){return /^__venice-auth\.session-token\.\d+$/.test(key);});
83
+ if (!token && chunks.length && chunks.every(function(_,i){return cookies[legacy+'.'+i];}))
84
+ token = chunks.map(function(_,i){return cookies[legacy+'.'+i];}).join('');
85
+ var headers = {Accept:'application/json'};
86
+ if (token) headers.Cookie = legacy+'='+token;
87
+ else {
88
+ token = cookies.__session || cookies[Object.keys(cookies).sort().find(function(key){return /^__session_.+/.test(key);})];
89
+ if (!token) throw new Error('Import a fresh Venice session cookie.');
90
+ headers.Authorization = 'Bearer '+token;
91
+ }
92
+ var resp = ctx.host.http.request({method:'GET',url:'https://outerface.venice.ai/api/user/session',headers:headers,timeoutMs:15000});
93
+ if (resp.status === 401 || resp.status === 403) throw new Error('Venice session expired. Reopen venice.ai and import fresh cookies.');
94
+ if (resp.status < 200 || resp.status >= 300) throw new Error('Venice session request failed (HTTP '+resp.status+').');
95
+ var payload = ctx.util.tryParseJson(resp.bodyText);
96
+ var claims = payload && ctx.jwt.decodePayload(payload.token);
97
+ function amount(value) { if (typeof value !== 'number' && typeof value !== 'string' || value === '') return null; var n=Number(value); return Number.isFinite(n)&&n>=0?n:null; }
98
+ var expiry = claims && amount(claims.exp);
99
+ if (!claims || expiry === null || expiry < 1e9 || expiry > 4e9 || expiry*1000 < Date.parse(ctx.nowIso)-60000)
100
+ throw new Error('Venice session expired. Import fresh cookies.');
101
+ if (['anonymous','anon','guest','unauthenticated','logged_out'].includes(String(claims.userType).toLowerCase())) throw new Error('Sign in to Venice.');
102
+ var usage = claims.bundledCreditsUsage || {};
103
+ var used = amount(usage.usedThisCycle), refill = amount(usage.monthlyRefillCredits);
104
+ if (used === null || !(refill > 0)) throw new Error('Venice subscription credits unavailable.');
105
+ var lines = [];
106
+ var available = amount(usage.availableCredits);
107
+ if (available === null) available = amount(claims.bundledCredits);
108
+ [['Subscription credits available',available],['Total credits available',amount(claims.veniceCredits)],['Bank cap',amount(usage.tierCap)]]
109
+ .forEach(function(pair){if(pair[1] !== null) lines.push(ctx.line.text({label:pair[0],value:String(pair[1])}));});
110
+ lines.push(ctx.line.text({label:'Used this cycle',value:String(used),subtitle:'Monthly refill: '+refill}));
111
+ var next = amount(usage.nextRefillAt);
112
+ if (next >= 1e12 && next <= 4e12) lines.push(ctx.line.text({label:'Next refill',value:new Date(next).toISOString()}));
113
+ // A refill is not a spending cap. Banked credits must never appear exhausted.
114
+ return {source:'web',lines:lines};
66
115
  }
67
116
 
68
117
  globalThis.__openusage_plugin = { id: "venice", probe: probe };