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

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 (225) hide show
  1. package/LICENSE +57744 -0
  2. package/native-manifest.json +1414 -0
  3. package/package.json +254 -0
  4. package/plugins/abacus-ai/icon.svg +18 -0
  5. package/plugins/abacus-ai/plugin.js +121 -0
  6. package/plugins/abacus-ai/plugin.json +17 -0
  7. package/plugins/alibaba/icon-color.svg +1 -0
  8. package/plugins/alibaba/icon.svg +1 -0
  9. package/plugins/alibaba/plugin.js +322 -0
  10. package/plugins/alibaba/plugin.json +20 -0
  11. package/plugins/alibaba-token-plan/icon-color.svg +1 -0
  12. package/plugins/alibaba-token-plan/icon.svg +1 -0
  13. package/plugins/alibaba-token-plan/plugin.js +544 -0
  14. package/plugins/alibaba-token-plan/plugin.json +19 -0
  15. package/plugins/amp/icon-color.svg +1 -0
  16. package/plugins/amp/icon-conflict.svg +6 -0
  17. package/plugins/amp/icon.svg +1 -0
  18. package/plugins/amp/plugin.js +175 -0
  19. package/plugins/amp/plugin.json +16 -0
  20. package/plugins/antigravity/icon-color.svg +1 -0
  21. package/plugins/antigravity/icon-conflict.svg +3 -0
  22. package/plugins/antigravity/icon.svg +1 -0
  23. package/plugins/antigravity/plugin.js +739 -0
  24. package/plugins/antigravity/plugin.json +31 -0
  25. package/plugins/antigravity-cli/icon.svg +3 -0
  26. package/plugins/antigravity-cli/plugin.js +570 -0
  27. package/plugins/antigravity-cli/plugin.json +16 -0
  28. package/plugins/antigravity-ide/icon.svg +3 -0
  29. package/plugins/antigravity-ide/plugin.js +257 -0
  30. package/plugins/antigravity-ide/plugin.json +29 -0
  31. package/plugins/augment/icon.svg +14 -0
  32. package/plugins/augment/plugin.js +59 -0
  33. package/plugins/augment/plugin.json +18 -0
  34. package/plugins/aws-bedrock/icon-color.svg +1 -0
  35. package/plugins/aws-bedrock/icon.svg +1 -0
  36. package/plugins/aws-bedrock/plugin.js +206 -0
  37. package/plugins/aws-bedrock/plugin.json +18 -0
  38. package/plugins/azure-openai/icon-color.svg +1 -0
  39. package/plugins/azure-openai/icon.svg +1 -0
  40. package/plugins/azure-openai/plugin.js +145 -0
  41. package/plugins/azure-openai/plugin.json +17 -0
  42. package/plugins/chutes/icon.svg +7 -0
  43. package/plugins/chutes/plugin.js +236 -0
  44. package/plugins/chutes/plugin.json +19 -0
  45. package/plugins/claude/icon-color.svg +1 -0
  46. package/plugins/claude/icon.svg +1 -0
  47. package/plugins/claude/plugin.js +1723 -0
  48. package/plugins/claude/plugin.json +30 -0
  49. package/plugins/codebuff/icon.svg +92 -0
  50. package/plugins/codebuff/plugin.js +113 -0
  51. package/plugins/codebuff/plugin.json +17 -0
  52. package/plugins/codex/icon-color.svg +5 -0
  53. package/plugins/codex/icon.svg +1 -0
  54. package/plugins/codex/plugin.js +1009 -0
  55. package/plugins/codex/plugin.json +82 -0
  56. package/plugins/command-code/icon.svg +3 -0
  57. package/plugins/command-code/plugin.js +184 -0
  58. package/plugins/command-code/plugin.json +20 -0
  59. package/plugins/copilot/icon-color.svg +1 -0
  60. package/plugins/copilot/icon.svg +1 -0
  61. package/plugins/copilot/plugin.js +684 -0
  62. package/plugins/copilot/plugin.json +21 -0
  63. package/plugins/crof/icon.svg +3 -0
  64. package/plugins/crof/plugin.js +53 -0
  65. package/plugins/crof/plugin.json +17 -0
  66. package/plugins/crofai/icon.svg +16 -0
  67. package/plugins/crofai/plugin.js +81 -0
  68. package/plugins/crofai/plugin.json +18 -0
  69. package/plugins/cursor/icon-conflict.svg +3 -0
  70. package/plugins/cursor/icon.svg +1 -0
  71. package/plugins/cursor/plugin.js +1379 -0
  72. package/plugins/cursor/plugin.json +23 -0
  73. package/plugins/cursor-nightly/icon.png +0 -0
  74. package/plugins/cursor-nightly/plugin.js +1379 -0
  75. package/plugins/cursor-nightly/plugin.json +23 -0
  76. package/plugins/deepgram/icon.svg +1 -0
  77. package/plugins/deepgram/plugin.js +20 -0
  78. package/plugins/deepgram/plugin.json +17 -0
  79. package/plugins/deepseek/icon-color.svg +1 -0
  80. package/plugins/deepseek/icon.svg +1 -0
  81. package/plugins/deepseek/plugin.js +71 -0
  82. package/plugins/deepseek/plugin.json +17 -0
  83. package/plugins/devin/icon.svg +5 -0
  84. package/plugins/devin/plugin.js +341 -0
  85. package/plugins/devin/plugin.json +16 -0
  86. package/plugins/doubao/icon-color.svg +1 -0
  87. package/plugins/doubao/icon.svg +1 -0
  88. package/plugins/doubao/plugin.js +92 -0
  89. package/plugins/doubao/plugin.json +17 -0
  90. package/plugins/droid/icon.svg +1 -0
  91. package/plugins/droid/plugin.json +20 -0
  92. package/plugins/elevenlabs/icon.svg +4 -0
  93. package/plugins/elevenlabs/plugin.js +48 -0
  94. package/plugins/elevenlabs/plugin.json +18 -0
  95. package/plugins/factory/icon-conflict.svg +1 -0
  96. package/plugins/factory/icon.svg +1 -0
  97. package/plugins/factory/plugin.js +487 -0
  98. package/plugins/factory/plugin.json +15 -0
  99. package/plugins/fireworks-ai/icon.svg +6 -0
  100. package/plugins/fireworks-ai/plugin.js +370 -0
  101. package/plugins/fireworks-ai/plugin.json +19 -0
  102. package/plugins/gemini/icon-color.svg +1 -0
  103. package/plugins/gemini/icon.svg +1 -0
  104. package/plugins/gemini/plugin.js +460 -0
  105. package/plugins/gemini/plugin.json +16 -0
  106. package/plugins/grok/icon.svg +1 -0
  107. package/plugins/grok/plugin.js +297 -0
  108. package/plugins/grok/plugin.json +19 -0
  109. package/plugins/groqcloud/icon.svg +1 -0
  110. package/plugins/groqcloud/plugin.js +117 -0
  111. package/plugins/groqcloud/plugin.json +19 -0
  112. package/plugins/jetbrains-ai-assistant/icon-color.svg +14 -0
  113. package/plugins/jetbrains-ai-assistant/icon-conflict.svg +3 -0
  114. package/plugins/jetbrains-ai-assistant/icon.svg +14 -0
  115. package/plugins/jetbrains-ai-assistant/plugin.js +313 -0
  116. package/plugins/jetbrains-ai-assistant/plugin.json +16 -0
  117. package/plugins/kilo/icon.svg +1 -0
  118. package/plugins/kilo/plugin.js +111 -0
  119. package/plugins/kilo/plugin.json +19 -0
  120. package/plugins/kimi/icon-color.svg +1 -0
  121. package/plugins/kimi/icon-conflict.svg +3 -0
  122. package/plugins/kimi/icon.svg +1 -0
  123. package/plugins/kimi/plugin.js +358 -0
  124. package/plugins/kimi/plugin.json +15 -0
  125. package/plugins/kimi-k2/icon-color.svg +1 -0
  126. package/plugins/kimi-k2/icon.svg +1 -0
  127. package/plugins/kimi-k2/plugin.js +58 -0
  128. package/plugins/kimi-k2/plugin.json +18 -0
  129. package/plugins/kiro/icon-color.svg +5 -0
  130. package/plugins/kiro/icon-conflict.svg +1 -0
  131. package/plugins/kiro/icon.svg +4 -0
  132. package/plugins/kiro/plugin.js +390 -0
  133. package/plugins/kiro/plugin.json +16 -0
  134. package/plugins/litellm/icon.svg +16 -0
  135. package/plugins/litellm/plugin.js +199 -0
  136. package/plugins/litellm/plugin.json +16 -0
  137. package/plugins/llm-proxy/icon.svg +1 -0
  138. package/plugins/llm-proxy/plugin.js +40 -0
  139. package/plugins/llm-proxy/plugin.json +17 -0
  140. package/plugins/manus/icon.svg +6 -0
  141. package/plugins/manus/plugin.js +50 -0
  142. package/plugins/manus/plugin.json +17 -0
  143. package/plugins/mimo/icon.svg +1 -0
  144. package/plugins/mimo/plugin.js +177 -0
  145. package/plugins/mimo/plugin.json +19 -0
  146. package/plugins/minimax/icon-color.svg +1 -0
  147. package/plugins/minimax/icon-conflict.svg +4 -0
  148. package/plugins/minimax/icon.svg +1 -0
  149. package/plugins/minimax/plugin.js +453 -0
  150. package/plugins/minimax/plugin.json +14 -0
  151. package/plugins/mistral/icon-color.svg +1 -0
  152. package/plugins/mistral/icon.svg +1 -0
  153. package/plugins/mistral/plugin.js +152 -0
  154. package/plugins/mistral/plugin.json +18 -0
  155. package/plugins/moonshot/icon.svg +1 -0
  156. package/plugins/moonshot/plugin.js +43 -0
  157. package/plugins/moonshot/plugin.json +16 -0
  158. package/plugins/nanogpt/icon-color.svg +17 -0
  159. package/plugins/nanogpt/icon.svg +10 -0
  160. package/plugins/nanogpt/plugin.js +80 -0
  161. package/plugins/nanogpt/plugin.json +17 -0
  162. package/plugins/neuralwatt/icon.svg +3 -0
  163. package/plugins/neuralwatt/plugin.js +152 -0
  164. package/plugins/neuralwatt/plugin.json +17 -0
  165. package/plugins/ollama/icon.svg +1 -0
  166. package/plugins/ollama/plugin.js +92 -0
  167. package/plugins/ollama/plugin.json +20 -0
  168. package/plugins/openai-api/icon.svg +1 -0
  169. package/plugins/openai-api/plugin.js +533 -0
  170. package/plugins/openai-api/plugin.json +26 -0
  171. package/plugins/opencode/icon.svg +1 -0
  172. package/plugins/opencode/plugin.js +342 -0
  173. package/plugins/opencode/plugin.json +19 -0
  174. package/plugins/opencode-go/icon-conflict.svg +1 -0
  175. package/plugins/opencode-go/icon.svg +1 -0
  176. package/plugins/opencode-go/plugin.js +617 -0
  177. package/plugins/opencode-go/plugin.json +50 -0
  178. package/plugins/openrouter/icon.svg +1 -0
  179. package/plugins/openrouter/plugin.js +156 -0
  180. package/plugins/openrouter/plugin.json +8 -0
  181. package/plugins/perplexity/icon-color.svg +1 -0
  182. package/plugins/perplexity/icon-conflict.svg +1 -0
  183. package/plugins/perplexity/icon.svg +1 -0
  184. package/plugins/perplexity/plugin.js +425 -0
  185. package/plugins/perplexity/plugin.json +19 -0
  186. package/plugins/poe/icon.svg +1 -0
  187. package/plugins/poe/plugin.js +190 -0
  188. package/plugins/poe/plugin.json +19 -0
  189. package/plugins/stepfun/icon-color.svg +1 -0
  190. package/plugins/stepfun/icon.svg +1 -0
  191. package/plugins/stepfun/plugin.js +155 -0
  192. package/plugins/stepfun/plugin.json +18 -0
  193. package/plugins/synthetic/icon-conflict.svg +12 -0
  194. package/plugins/synthetic/icon.svg +14 -0
  195. package/plugins/synthetic/plugin.js +331 -0
  196. package/plugins/synthetic/plugin.json +23 -0
  197. package/plugins/t3chat/icon-color.svg +28 -0
  198. package/plugins/t3chat/icon.svg +4 -0
  199. package/plugins/t3chat/plugin.js +243 -0
  200. package/plugins/t3chat/plugin.json +20 -0
  201. package/plugins/venice/icon-color.svg +1 -0
  202. package/plugins/venice/icon.svg +1 -0
  203. package/plugins/venice/plugin.js +69 -0
  204. package/plugins/venice/plugin.json +16 -0
  205. package/plugins/vertex-ai/icon-color.svg +1 -0
  206. package/plugins/vertex-ai/icon.svg +1 -0
  207. package/plugins/vertex-ai/plugin.js +172 -0
  208. package/plugins/vertex-ai/plugin.json +18 -0
  209. package/plugins/warp/icon-color.svg +10 -0
  210. package/plugins/warp/icon.svg +6 -0
  211. package/plugins/warp/plugin.js +108 -0
  212. package/plugins/warp/plugin.json +18 -0
  213. package/plugins/windsurf/icon-conflict.svg +3 -0
  214. package/plugins/windsurf/icon.svg +1 -0
  215. package/plugins/windsurf/plugin.js +208 -0
  216. package/plugins/windsurf/plugin.json +16 -0
  217. package/plugins/zai/icon-conflict.svg +5 -0
  218. package/plugins/zai/icon.svg +1 -0
  219. package/plugins/zai/plugin.js +188 -0
  220. package/plugins/zai/plugin.json +16 -0
  221. package/plugins/zed/icon.svg +4 -0
  222. package/plugins/zed/plugin.js +270 -0
  223. package/plugins/zed/plugin.json +19 -0
  224. package/usagestat +0 -0
  225. package/usagestatd +0 -0
@@ -0,0 +1,23 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "cursor-nightly",
4
+ "name": "Cursor Nightly",
5
+ "version": "0.0.1",
6
+ "entry": "plugin.js",
7
+ "icon": "icon.png",
8
+ "brandColor": "#E85D3A",
9
+ "supportedModes": ["oauth", "local"],
10
+ "autoMode": "local",
11
+ "links": [
12
+ { "label": "Status", "url": "https://status.cursor.com/" },
13
+ { "label": "Dashboard", "url": "https://www.cursor.com/dashboard" }
14
+ ],
15
+ "lines": [
16
+ { "type": "progress", "label": "Credits", "scope": "overview", "primaryOrder": 2 },
17
+ { "type": "progress", "label": "Total usage", "scope": "overview", "primaryOrder": 1 },
18
+ { "type": "progress", "label": "Requests", "scope": "overview", "primaryOrder": 3 },
19
+ { "type": "progress", "label": "Auto usage", "scope": "detail" },
20
+ { "type": "progress", "label": "API usage", "scope": "detail" },
21
+ { "type": "progress", "label": "On-demand", "scope": "detail" }
22
+ ]
23
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><title>Deepgram SVG Icon</title><path fill="currentColor" d="M11.203 24H1.517a.364.364 0 0 1-.258-.62l6.239-6.275a.37.37 0 0 1 .259-.108h3.52c2.723 0 5.025-2.127 5.107-4.845a5.004 5.004 0 0 0-4.999-5.148H7.613v4.646c0 .2-.164.364-.365.364H.968a.365.365 0 0 1-.363-.364V.364C.605.164.768 0 .969 0h10.416c6.684 0 12.111 5.485 12.01 12.187C23.293 18.77 17.794 24 11.202 24z"/></svg>
@@ -0,0 +1,20 @@
1
+ (function () {
2
+ function probe(ctx) {
3
+ var key = ctx.host.env.get("DEEPGRAM_API_KEY");
4
+ if (!key) throw "Deepgram API key not found. Set DEEPGRAM_API_KEY.";
5
+
6
+ var result = ctx.util.requestJson({
7
+ method: "GET",
8
+ url: "https://api.deepgram.com/v1/projects",
9
+ headers: { Authorization: "Token " + key, Accept: "application/json" },
10
+ timeoutMs: 15000,
11
+ });
12
+ if (ctx.util.isAuthStatus(result.resp.status)) throw "Deepgram API key invalid or expired.";
13
+ if (result.resp.status < 200 || result.resp.status >= 300) throw "Deepgram API error (HTTP " + result.resp.status + ").";
14
+ var projects = result.json && result.json.projects;
15
+ if (!Array.isArray(projects)) throw "Could not parse Deepgram projects response.";
16
+ return { lines: [ctx.line.text({ label: "Projects", value: String(projects.length) })] };
17
+ }
18
+
19
+ globalThis.__openusage_plugin = { id: "deepgram", probe: probe };
20
+ })();
@@ -0,0 +1,17 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "deepgram",
4
+ "name": "Deepgram",
5
+ "version": "0.0.1",
6
+ "entry": "plugin.js",
7
+ "brandColor": "#13EF93",
8
+ "links": [
9
+ { "label": "Console", "url": "https://console.deepgram.com" },
10
+ { "label": "Status", "url": "https://status.deepgram.com" }
11
+ ],
12
+ "supportedModes": ["api"],
13
+ "autoMode": "api",
14
+ "lines": [
15
+ { "type": "text", "label": "Projects", "scope": "overview", "primaryOrder": 1 }
16
+ ]
17
+ }
@@ -0,0 +1 @@
1
+ <svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>DeepSeek</title><path d="M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z" fill="#4D6BFE"></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>DeepSeek</title><path d="M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z"></path></svg>
@@ -0,0 +1,71 @@
1
+ (function () {
2
+ var API_URL = "https://api.deepseek.com/user/balance";
3
+
4
+ function loadApiKey(ctx) {
5
+ var names = ["DEEPSEEK_API_KEY", "DEEPSEEK_KEY"];
6
+ for (var i = 0; i < names.length; i++) {
7
+ var v = ctx.host.env.get(names[i]);
8
+ if (typeof v === "string" && v.trim()) return v.trim();
9
+ }
10
+ return null;
11
+ }
12
+
13
+ function probe(ctx) {
14
+ var apiKey = loadApiKey(ctx);
15
+ if (!apiKey) {
16
+ throw "DeepSeek API key not found. Set DEEPSEEK_API_KEY or DEEPSEEK_KEY.";
17
+ }
18
+
19
+ var result = ctx.util.requestJson({
20
+ method: "GET",
21
+ url: API_URL,
22
+ headers: { Authorization: "Bearer " + apiKey, Accept: "application/json" },
23
+ timeoutMs: 15000,
24
+ });
25
+
26
+ if (ctx.util.isAuthStatus(result.resp.status)) {
27
+ throw "API key invalid or expired.";
28
+ }
29
+ if (result.resp.status < 200 || result.resp.status >= 300) {
30
+ throw "DeepSeek API error (HTTP " + result.resp.status + ").";
31
+ }
32
+ if (!result.json) throw "Could not parse DeepSeek balance response.";
33
+
34
+ var infos = result.json.balance_infos || [];
35
+ var info = null;
36
+ for (var i = 0; i < infos.length; i++) {
37
+ if ((infos[i].currency || "").toUpperCase() === "USD") { info = infos[i]; break; }
38
+ }
39
+ if (!info && infos.length > 0) info = infos[0];
40
+
41
+ var lines = [];
42
+ if (!info) {
43
+ lines.push(ctx.line.badge({ label: "Balance", text: "No balance data", color: "#a3a3a3" }));
44
+ return { lines: lines };
45
+ }
46
+
47
+ var total = parseFloat(info.total_balance) || 0;
48
+ var granted = parseFloat(info.granted_balance) || 0;
49
+ var toppedUp = parseFloat(info.topped_up_balance) || 0;
50
+ var symbol = (info.currency || "").toUpperCase() === "CNY" ? "¥" : "$";
51
+ var available = result.json.is_available !== false;
52
+
53
+ var detail;
54
+ if (!available) {
55
+ detail = "Balance unavailable for API calls";
56
+ } else if (total <= 0) {
57
+ detail = symbol + "0.00 — add credits at platform.deepseek.com";
58
+ } else {
59
+ detail = symbol + total.toFixed(2) + " (Paid: " + symbol + toppedUp.toFixed(2) + " / Granted: " + symbol + granted.toFixed(2) + ")";
60
+ }
61
+
62
+ lines.push(ctx.line.text({ label: "Balance", value: detail }));
63
+ if (!available) {
64
+ lines.push(ctx.line.badge({ label: "Status", text: "Unavailable", color: "#ef4444" }));
65
+ }
66
+
67
+ return { lines: lines };
68
+ }
69
+
70
+ globalThis.__openusage_plugin = { id: "deepseek", probe: probe };
71
+ })();
@@ -0,0 +1,17 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "deepseek",
4
+ "name": "DeepSeek",
5
+ "version": "0.0.1",
6
+ "entry": "plugin.js",
7
+ "brandColor": "#4D6BFE",
8
+ "links": [
9
+ { "label": "Platform", "url": "https://platform.deepseek.com/usage" }
10
+ ],
11
+ "usageDashboardUrl": "https://platform.deepseek.com/usage",
12
+ "supportedModes": ["api"],
13
+ "autoMode": "api",
14
+ "lines": [
15
+ { "type": "text", "label": "Balance", "scope": "overview" }
16
+ ]
17
+ }
@@ -0,0 +1,5 @@
1
+ <svg width="100" height="100" viewBox="0 0 44 50" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill="currentColor" d="M1.117,20.553l5.351,3.089c0.192,0.111,0.406,0.165,0.621,0.165c0.214,0,0.429-0.057,0.621-0.165l5.351-3.089 c0,0,0.015-0.012,0.022-0.017c0.081-0.049,0.158-0.108,0.227-0.175c0.01-0.01,0.02-0.022,0.03-0.032 c0.059-0.064,0.113-0.133,0.158-0.207c0.007-0.012,0.017-0.022,0.022-0.035c0.047-0.081,0.081-0.167,0.108-0.259 c0.005-0.02,0.01-0.039,0.015-0.059c0.022-0.094,0.039-0.19,0.039-0.291v-3.089c0-1.192,0.643-2.303,1.675-2.9s2.316-0.596,3.35,0 l2.675,1.545c0.086,0.049,0.177,0.084,0.271,0.111c0.02,0.005,0.04,0.012,0.059,0.017c0.091,0.022,0.185,0.035,0.278,0.037 c0.005,0,0.01,0,0.012,0c0.01,0,0.02-0.005,0.029-0.005c0.086,0,0.173-0.012,0.256-0.035c0.015-0.003,0.03-0.005,0.044-0.01 c0.091-0.025,0.18-0.062,0.264-0.108c0.007-0.005,0.017-0.005,0.025-0.01l5.351-3.089c0.384-0.222,0.621-0.631,0.621-1.074V4.69 c0-0.443-0.236-0.852-0.621-1.074l-5.356-3.087c-0.384-0.222-0.855-0.222-1.239,0l-5.351,3.089c0,0-0.015,0.012-0.022,0.017 c-0.081,0.049-0.158,0.108-0.227,0.175c-0.01,0.01-0.02,0.022-0.03,0.032c-0.059,0.064-0.113,0.133-0.158,0.207 c-0.007,0.012-0.017,0.022-0.022,0.034c-0.047,0.081-0.081,0.168-0.108,0.259c-0.005,0.02-0.01,0.039-0.015,0.059 c-0.022,0.094-0.039,0.19-0.039,0.291v3.089c0,1.192-0.643,2.303-1.675,2.902c-1.032,0.596-2.316,0.596-3.35,0L7.705,9.139 C7.618,9.09,7.527,9.055,7.434,9.028c-0.02-0.005-0.039-0.012-0.059-0.017C7.283,8.989,7.19,8.977,7.096,8.974 c-0.015,0-0.027,0-0.042,0c-0.089,0-0.175,0.012-0.259,0.034c-0.015,0.002-0.027,0.005-0.042,0.01 C6.663,9.043,6.574,9.08,6.49,9.127c-0.007,0.005-0.017,0.005-0.025,0.01l-5.348,3.092c-0.384,0.222-0.621,0.631-0.621,1.074v6.178 c0,0.444,0.236,0.852,0.621,1.074V20.553z"></path>
3
+ <path fill="currentColor" d="M30.262,22.097c1.032-0.596,2.316-0.596,3.35,0l2.675,1.545c0.086,0.049,0.177,0.084,0.271,0.111 c0.02,0.005,0.039,0.012,0.059,0.017c0.091,0.022,0.185,0.034,0.278,0.037c0.005,0,0.01,0,0.012,0c0.01,0,0.02-0.003,0.029-0.005 c0.086,0,0.173-0.012,0.256-0.034c0.015-0.003,0.03-0.005,0.044-0.01c0.091-0.025,0.177-0.062,0.264-0.108 c0.007-0.005,0.017-0.005,0.027-0.01l5.351-3.089c0.384-0.222,0.621-0.631,0.621-1.074v-6.179c0-0.443-0.237-0.852-0.621-1.074 L37.53,9.134c-0.384-0.222-0.855-0.222-1.239,0l-5.351,3.089c0,0-0.015,0.012-0.022,0.017c-0.081,0.049-0.158,0.108-0.227,0.175 c-0.01,0.01-0.02,0.022-0.029,0.032c-0.059,0.064-0.113,0.133-0.158,0.207c-0.007,0.012-0.017,0.022-0.022,0.035 c-0.047,0.081-0.081,0.168-0.108,0.259c-0.005,0.02-0.01,0.039-0.015,0.059c-0.022,0.094-0.039,0.19-0.039,0.291v3.089 c0,1.192-0.643,2.303-1.675,2.902c-1.032,0.596-2.316,0.596-3.35,0l-2.675-1.545c-0.086-0.049-0.177-0.084-0.271-0.111 c-0.02-0.005-0.039-0.012-0.059-0.017c-0.091-0.022-0.185-0.035-0.278-0.037c-0.015,0-0.027,0-0.042,0 c-0.089,0-0.175,0.012-0.259,0.035c-0.015,0.003-0.027,0.005-0.042,0.01c-0.091,0.025-0.18,0.062-0.264,0.108 c-0.007,0.005-0.017,0.005-0.025,0.01l-5.351,3.089c-0.384,0.222-0.621,0.631-0.621,1.074v6.179c0,0.443,0.236,0.852,0.621,1.074 l5.351,3.089c0,0,0.017,0.005,0.025,0.01c0.084,0.047,0.173,0.084,0.264,0.108c0.015,0.005,0.03,0.005,0.044,0.01 c0.084,0.02,0.17,0.032,0.256,0.035c0.01,0,0.02,0.005,0.03,0.005c0.005,0,0.01,0,0.012,0c0.094,0,0.185-0.015,0.278-0.037 c0.02-0.005,0.039-0.01,0.059-0.017c0.094-0.027,0.185-0.062,0.271-0.111l2.675-1.545c1.032-0.596,2.316-0.596,3.35,0 c1.032,0.596,1.675,1.707,1.675,2.9v3.089c0,0.101,0.015,0.197,0.039,0.291c0.005,0.02,0.01,0.039,0.015,0.059 c0.027,0.091,0.061,0.177,0.108,0.259c0.007,0.012,0.015,0.022,0.022,0.034c0.044,0.074,0.099,0.143,0.158,0.207 c0.01,0.01,0.02,0.022,0.029,0.032c0.067,0.066,0.143,0.123,0.227,0.175c0.007,0.005,0.012,0.012,0.022,0.017l5.351,3.089 c0.192,0.111,0.407,0.165,0.621,0.165c0.214,0,0.429-0.057,0.621-0.165l5.351-3.089c0.384-0.222,0.621-0.631,0.621-1.074v-6.179 c0-0.443-0.236-0.852-0.621-1.074l-5.351-3.089c0,0-0.017-0.005-0.025-0.01c-0.084-0.047-0.173-0.084-0.264-0.108 c-0.015-0.005-0.027-0.005-0.042-0.01c-0.086-0.02-0.172-0.032-0.261-0.035c-0.012,0-0.027,0-0.039,0 c-0.094,0-0.187,0.015-0.278,0.037c-0.02,0.005-0.037,0.01-0.057,0.017c-0.094,0.027-0.185,0.062-0.271,0.111l-2.675,1.545 c-1.032,0.596-2.316,0.596-3.348,0c-1.032-0.596-1.675-1.707-1.675-2.902c0-1.195,0.643-2.303,1.675-2.9H30.262z"></path>
4
+ <path fill="currentColor" d="M27.967,38.054l-5.351-3.089c0,0-0.017-0.005-0.025-0.01c-0.084-0.047-0.172-0.084-0.264-0.108 c-0.015-0.005-0.03-0.005-0.044-0.01c-0.086-0.02-0.172-0.032-0.259-0.035c-0.015,0-0.027,0-0.042,0 c-0.094,0-0.187,0.015-0.278,0.037c-0.02,0.005-0.037,0.01-0.057,0.017c-0.094,0.027-0.185,0.062-0.271,0.111l-2.675,1.545 c-1.032,0.596-2.316,0.596-3.348,0c-1.032-0.596-1.675-1.707-1.675-2.902V30.52c0-0.101-0.015-0.197-0.039-0.291 c-0.005-0.02-0.01-0.039-0.015-0.059c-0.027-0.091-0.062-0.177-0.108-0.259c-0.007-0.012-0.015-0.022-0.022-0.035 c-0.044-0.074-0.099-0.143-0.158-0.207c-0.01-0.01-0.02-0.022-0.03-0.032c-0.066-0.066-0.143-0.123-0.227-0.175 c-0.007-0.005-0.012-0.012-0.022-0.017l-5.351-3.089c-0.384-0.222-0.855-0.222-1.239,0l-5.351,3.089 c-0.384,0.222-0.621,0.631-0.621,1.074v6.179c0,0.443,0.236,0.852,0.621,1.074l5.351,3.089c0,0,0.017,0.007,0.025,0.01 c0.084,0.047,0.17,0.084,0.261,0.108c0.015,0.005,0.03,0.007,0.044,0.01c0.084,0.02,0.17,0.032,0.256,0.035 c0.01,0,0.02,0.005,0.032,0.005c0.005,0,0.01,0,0.015,0c0.094,0,0.185-0.015,0.276-0.037c0.02-0.005,0.039-0.01,0.059-0.017 c0.094-0.027,0.185-0.062,0.271-0.111l2.675-1.545c1.032-0.596,2.316-0.596,3.35,0c1.032,0.596,1.675,1.707,1.675,2.9v3.089 c0,0.101,0.015,0.197,0.039,0.291c0.005,0.02,0.01,0.039,0.015,0.059c0.027,0.091,0.062,0.177,0.108,0.259 c0.007,0.012,0.015,0.022,0.022,0.035c0.044,0.074,0.099,0.143,0.158,0.207c0.01,0.01,0.02,0.022,0.03,0.032 c0.067,0.067,0.143,0.123,0.227,0.175c0.007,0.005,0.012,0.012,0.022,0.017l5.351,3.089c0.192,0.111,0.406,0.165,0.621,0.165 s0.429-0.057,0.621-0.165l5.351-3.089c0.384-0.222,0.621-0.631,0.621-1.074V39.13c0-0.443-0.236-0.852-0.621-1.074L27.967,38.054z"></path>
5
+ </svg>
@@ -0,0 +1,341 @@
1
+ (function () {
2
+ var CLOUD_SERVICE = "exa.seat_management_pb.SeatManagementService"
3
+ var DEFAULT_API_SERVER_URL = "https://server.codeium.com"
4
+ var CLOUD_COMPAT_VERSION = "1.108.2"
5
+ var APP_STATE_VARIANTS = [
6
+ {id: "devin", source: "Devin app", appSupportRel: "Devin/User/globalStorage/state.vscdb"},
7
+ {id: "devin-next", source: "Devin - Next app", appSupportRel: "Devin - Next/User/globalStorage/state.vscdb"},
8
+ {id: "windsurf", source: "Devin app (legacy Windsurf)", appSupportRel: "Windsurf/User/globalStorage/state.vscdb"},
9
+ {id: "windsurf-next", source: "Windsurf - Next app", appSupportRel: "Windsurf - Next/User/globalStorage/state.vscdb"},
10
+ ]
11
+ var LOGIN_HINT = "Run devin auth login or sign in to Devin and try again."
12
+ var QUOTA_HINT = "Devin quota data unavailable. Try again later."
13
+ var DAY_MS = 24 * 60 * 60 * 1000
14
+ var WEEK_MS = 7 * DAY_MS
15
+
16
+ function readFiniteNumber(value) {
17
+ if (typeof value === "number") return Number.isFinite(value) ? value : null
18
+ if (typeof value !== "string") return null
19
+ var trimmed = value.trim()
20
+ if (!trimmed) return null
21
+ var parsed = Number(trimmed)
22
+ return Number.isFinite(parsed) ? parsed : null
23
+ }
24
+
25
+ function clampPercent(value) {
26
+ if (!Number.isFinite(value)) return 0
27
+ if (value < 0) return 0
28
+ if (value > 100) return 100
29
+ return value
30
+ }
31
+
32
+ function readTomlString(text, key) {
33
+ var lines = String(text || "").split(/\r?\n/)
34
+ var prefix = new RegExp("^\\s*" + key + "\\s*=\\s*(.*)$")
35
+ for (var i = 0; i < lines.length; i++) {
36
+ var match = prefix.exec(lines[i])
37
+ if (!match) continue
38
+ var value = match[1].trim()
39
+ if (!value) return null
40
+ if (value[0] === '"' || value[0] === "'") {
41
+ var quote = value[0]
42
+ var out = ""
43
+ for (var j = 1; j < value.length; j++) {
44
+ var ch = value[j]
45
+ if (ch === quote && value[j - 1] !== "\\") return out.trim() || null
46
+ out += ch
47
+ }
48
+ return null
49
+ }
50
+ var commentIndex = value.indexOf("#")
51
+ if (commentIndex >= 0) value = value.slice(0, commentIndex).trim()
52
+ return value || null
53
+ }
54
+ return null
55
+ }
56
+
57
+ function cleanApiServerUrl(value) {
58
+ if (typeof value !== "string") return null
59
+ var trimmed = value.trim().replace(/\/+$/, "")
60
+ if (!/^https:\/\//.test(trimmed)) return null
61
+ return trimmed
62
+ }
63
+
64
+ function effectiveApiServerUrl(auth) {
65
+ return (auth && auth.apiServerUrl) || DEFAULT_API_SERVER_URL
66
+ }
67
+
68
+ function hasOwn(obj, key) {
69
+ return Boolean(obj && Object.prototype.hasOwnProperty.call(obj, key))
70
+ }
71
+
72
+ function readHost(value) {
73
+ if (typeof value !== "string") return null
74
+ var match = /^https?:\/\/([^/]+)/.exec(value.trim())
75
+ return match ? match[1] : null
76
+ }
77
+
78
+ function valueOrMissing(value) {
79
+ return value === null || value === undefined || value === "" ? "missing" : String(value)
80
+ }
81
+
82
+ function logQuotaDiagnostics(ctx, auth, userStatus) {
83
+ var planStatus = (userStatus && userStatus.planStatus) || {}
84
+ var planInfo = planStatus.planInfo || {}
85
+ var devinInfo = planInfo.devinInfo || {}
86
+ var apiServerHost = readHost(auth.apiServerUrl || DEFAULT_API_SERVER_URL)
87
+ var webappHost = readHost(devinInfo.webappHost) || devinInfo.webappHost || null
88
+ var devinApiHost = readHost(devinInfo.apiUrl)
89
+
90
+ ctx.host.log.info(
91
+ "Devin quota diagnostics" +
92
+ " source=" + auth.source +
93
+ " apiServerHost=" + valueOrMissing(apiServerHost) +
94
+ " planName=" + valueOrMissing(planInfo.planName) +
95
+ " teamsTier=" + valueOrMissing(userStatus && userStatus.teamsTier) +
96
+ " planTeamsTier=" + valueOrMissing(planInfo.teamsTier) +
97
+ " billingStrategy=" + valueOrMissing(planInfo.billingStrategy) +
98
+ " isDevin=" + String(planInfo.isDevin === true) +
99
+ " hideDailyQuota=" + String(planInfo.hideDailyQuota === true) +
100
+ " hasDailyQuotaPercent=" + String(hasOwn(planStatus, "dailyQuotaRemainingPercent")) +
101
+ " hasWeeklyQuotaPercent=" + String(hasOwn(planStatus, "weeklyQuotaRemainingPercent")) +
102
+ " hasOverageBalance=" + String(hasOwn(planStatus, "overageBalanceMicros")) +
103
+ " hasDailyReset=" + String(hasOwn(planStatus, "dailyQuotaResetAtUnix")) +
104
+ " hasWeeklyReset=" + String(hasOwn(planStatus, "weeklyQuotaResetAtUnix")) +
105
+ " hasTopUpStatus=" + String(hasOwn(planStatus, "topUpStatus")) +
106
+ " availablePromptCredits=" + valueOrMissing(planStatus.availablePromptCredits) +
107
+ " canUseCli=" + String(devinInfo.canUseCli === true) +
108
+ " canUseCascade=" + String(devinInfo.canUseCascade === true) +
109
+ " devinReviewEnabled=" + String(devinInfo.devinReviewEnabled === true) +
110
+ " webappHost=" + valueOrMissing(webappHost) +
111
+ " devinApiHost=" + valueOrMissing(devinApiHost)
112
+ )
113
+ }
114
+
115
+ function settings(ctx) { return (ctx.provider && ctx.provider.settings) || {} }
116
+
117
+ function resolveCredentialsPath(ctx) {
118
+ var explicit = settings(ctx).credentialsPath
119
+ if (explicit) return ctx.host.fs.exists(explicit) ? explicit : null
120
+ // Carried CLI layout; credentialsPath supports other CLI versions without
121
+ // guessing a different account's directory. Never search Unix paths on Windows.
122
+ var paths = ctx.app.platform === "windows"
123
+ ? [ctx.host.fs.localAppDataPath("devin/credentials.toml")]
124
+ : ["~/.local/share/devin/credentials.toml", "~/.local/share/cognition/credentials.toml"]
125
+ return ctx.host.fs.firstExisting(paths.filter(function(path) { return !!path })) || null
126
+ }
127
+
128
+ function resolveStateDbForVariant(ctx, variant) {
129
+ var custom = settings(ctx).userDataDir
130
+ var path = custom ? custom.replace(/[\\/]+$/, "") + "/User/globalStorage/state.vscdb"
131
+ : ctx.host.fs.appSupportPath(variant.appSupportRel)
132
+ return path && ctx.host.fs.exists(path) ? path : null
133
+ }
134
+
135
+ function loadCredentialsFile(ctx) {
136
+ var credentialsPath = resolveCredentialsPath(ctx)
137
+ if (!credentialsPath) return null
138
+ try {
139
+ var text = ctx.host.fs.readText(credentialsPath)
140
+ var apiKey = readTomlString(text, "windsurf_api_key")
141
+ if (!apiKey) {
142
+ throw {code: "credential-malformed", message: "Selected Devin credentials do not contain windsurf_api_key; select the correct credentialsPath or sign in again."}
143
+ }
144
+ return {
145
+ apiKey: apiKey,
146
+ apiServerUrl: cleanApiServerUrl(readTomlString(text, "api_server_url")),
147
+ source: "credentials.toml",
148
+ }
149
+ } catch (e) {
150
+ if (e && e.code) throw e
151
+ throw {code: "credential-unavailable", message: "Cannot read the selected Devin credential file."}
152
+ }
153
+ }
154
+
155
+ function readAppAuth(ctx, variant) {
156
+ var stateDb = resolveStateDbForVariant(ctx, variant)
157
+ if (!stateDb) return null
158
+ try {
159
+ var rows = ctx.host.sqlite.query(
160
+ stateDb,
161
+ "SELECT value FROM ItemTable WHERE key = 'windsurfAuthStatus' LIMIT 1"
162
+ )
163
+ var parsed = ctx.util.tryParseJson(rows)
164
+ if (!parsed || !parsed.length || !parsed[0].value) return null
165
+ var auth = ctx.util.tryParseJson(parsed[0].value)
166
+ if (!auth || !auth.apiKey) return null
167
+ return {
168
+ apiKey: auth.apiKey,
169
+ apiServerUrl: null,
170
+ source: variant.source,
171
+ }
172
+ } catch (e) {
173
+ ctx.host.log.warn("failed to read " + variant.source + " auth: " + String(e))
174
+ return null
175
+ }
176
+ }
177
+
178
+ function callCloud(ctx, auth) {
179
+ var apiServerUrl = effectiveApiServerUrl(auth)
180
+ try {
181
+ var resp = ctx.host.http.request({
182
+ method: "POST",
183
+ url: apiServerUrl + "/" + CLOUD_SERVICE + "/GetUserStatus",
184
+ headers: {
185
+ "Content-Type": "application/json",
186
+ "Connect-Protocol-Version": "1",
187
+ },
188
+ bodyText: JSON.stringify({
189
+ metadata: {
190
+ apiKey: auth.apiKey,
191
+ ideName: "devin",
192
+ ideVersion: CLOUD_COMPAT_VERSION,
193
+ extensionName: "devin",
194
+ extensionVersion: CLOUD_COMPAT_VERSION,
195
+ locale: "en",
196
+ },
197
+ }),
198
+ timeoutMs: 15000,
199
+ })
200
+ if (resp.status < 200 || resp.status >= 300) {
201
+ ctx.host.log.warn("cloud request returned status " + resp.status + " for " + auth.source)
202
+ if (ctx.util && typeof ctx.util.isAuthStatus === "function" && ctx.util.isAuthStatus(resp.status)) {
203
+ return { __openusageAuthError: true }
204
+ }
205
+ return null
206
+ }
207
+ return ctx.util.tryParseJson(resp.bodyText)
208
+ } catch (e) {
209
+ ctx.host.log.warn("cloud request failed for " + auth.source + ": " + String(e))
210
+ return null
211
+ }
212
+ }
213
+
214
+ function tryAuth(ctx, auth) {
215
+ var data = callCloud(ctx, auth)
216
+ if (data && data.__openusageAuthError) {
217
+ return { authFailure: true }
218
+ }
219
+ if (!data || !data.userStatus) return {}
220
+
221
+ try {
222
+ logQuotaDiagnostics(ctx, auth, data.userStatus)
223
+ return { output: buildOutput(ctx, data.userStatus) }
224
+ } catch (e) {
225
+ if (e === QUOTA_HINT) {
226
+ ctx.host.log.warn("quota contract unavailable for " + auth.source)
227
+ return {}
228
+ }
229
+ throw e
230
+ }
231
+ }
232
+
233
+ function unixSecondsToIso(ctx, value) {
234
+ var seconds = readFiniteNumber(value)
235
+ if (seconds === null) return null
236
+ return ctx.util.toIso(seconds * 1000)
237
+ }
238
+
239
+ function formatDollarsFromMicros(value) {
240
+ var micros = readFiniteNumber(value)
241
+ if (micros === null) return null
242
+ if (!Number.isFinite(micros)) return null
243
+ if (micros < 0) micros = 0
244
+ return "$" + (micros / 1000000).toFixed(2)
245
+ }
246
+
247
+ function buildQuotaLine(ctx, label, remaining, resetsAt, periodDurationMs) {
248
+ if (remaining === null) return null
249
+ return buildUsedQuotaLine(ctx, label, 100 - remaining, resetsAt, periodDurationMs)
250
+ }
251
+
252
+ function buildUsedQuotaLine(ctx, label, used, resetsAt, periodDurationMs) {
253
+ if (used === null) return null
254
+ var line = {
255
+ label: label,
256
+ used: clampPercent(used),
257
+ limit: 100,
258
+ format: { kind: "percent" },
259
+ periodDurationMs: periodDurationMs,
260
+ }
261
+ if (resetsAt) line.resetsAt = resetsAt
262
+ return ctx.line.progress(line)
263
+ }
264
+
265
+ function buildOutput(ctx, userStatus) {
266
+ var planStatus = (userStatus && userStatus.planStatus) || {}
267
+
268
+ var planInfo = planStatus.planInfo || {}
269
+ var planName = typeof planInfo.planName === "string" && planInfo.planName.trim()
270
+ ? planInfo.planName.trim()
271
+ : "Unknown"
272
+
273
+ var hideDailyQuota = planInfo.hideDailyQuota === true
274
+ var dailyRemaining = readFiniteNumber(planStatus.dailyQuotaRemainingPercent)
275
+ var weeklyRemaining = readFiniteNumber(planStatus.weeklyQuotaRemainingPercent)
276
+ var dailyReset = !hideDailyQuota ? unixSecondsToIso(ctx, planStatus.dailyQuotaResetAtUnix) : null
277
+ var weeklyReset = unixSecondsToIso(ctx, planStatus.weeklyQuotaResetAtUnix)
278
+ var extraUsageBalance = formatDollarsFromMicros(planStatus.overageBalanceMicros)
279
+
280
+ var dailyLine = !hideDailyQuota
281
+ ? buildQuotaLine(ctx, "Daily quota", dailyRemaining, dailyReset, DAY_MS)
282
+ : null
283
+ var weeklyLine = weeklyRemaining !== null
284
+ ? buildQuotaLine(ctx, "Weekly quota", weeklyRemaining, weeklyReset, WEEK_MS)
285
+ : hideDailyQuota
286
+ ? buildUsedQuotaLine(ctx, "Weekly quota", dailyRemaining, weeklyReset, WEEK_MS)
287
+ : null
288
+
289
+ var lines = []
290
+ if (dailyLine) lines.push(dailyLine)
291
+ if (weeklyLine) lines.push(weeklyLine)
292
+ if (extraUsageBalance) {
293
+ lines.push(ctx.line.text({ label: "Extra usage balance", value: extraUsageBalance }))
294
+ }
295
+
296
+ if (!lines.length) throw QUOTA_HINT
297
+
298
+ return {
299
+ plan: planName,
300
+ lines: lines,
301
+ }
302
+ }
303
+
304
+ function authFingerprint(auth) {
305
+ return auth.apiKey + "\n" + effectiveApiServerUrl(auth)
306
+ }
307
+
308
+ function probe(ctx) {
309
+ var opts = settings(ctx)
310
+ var source = opts.authSource || (opts.credentialsPath ? "cli" : opts.ideVariant || opts.userDataDir ? "ide" : "auto")
311
+ if (["auto", "cli", "ide"].indexOf(source) < 0) throw {code: "failed", message: "Set Devin settings.authSource to auto, cli or ide."}
312
+ if ((opts.credentialsPath && source !== "cli") || ((opts.ideVariant || opts.userDataDir) && source !== "ide")) {
313
+ throw {code: "failed", message: "Select either a Devin CLI credential file or an IDE profile."}
314
+ }
315
+ var variants = APP_STATE_VARIANTS
316
+ if (opts.ideVariant) {
317
+ variants = variants.filter(function(variant) { return variant.id === opts.ideVariant })
318
+ if (!variants.length) throw {code: "failed", message: "Unknown Devin ideVariant; use devin, devin-next, windsurf or windsurf-next."}
319
+ }
320
+ if (opts.userDataDir && !opts.ideVariant) throw {code: "failed", message: "Set ideVariant when selecting a Devin userDataDir."}
321
+ var candidates = []
322
+ if (source !== "ide") {
323
+ var credentials = loadCredentialsFile(ctx)
324
+ if (credentials) candidates.push(credentials)
325
+ }
326
+ if (source !== "cli") {
327
+ for (var i = 0; i < variants.length; i++) {
328
+ var auth = readAppAuth(ctx, variants[i])
329
+ if (auth && !candidates.some(function(candidate) { return authFingerprint(candidate) === authFingerprint(auth) })) candidates.push(auth)
330
+ }
331
+ }
332
+ if (candidates.length > 1) throw {code: "failed", message: "Multiple Devin accounts or installations found; select settings.authSource and credentialsPath or ideVariant."}
333
+ if (!candidates.length) throw LOGIN_HINT
334
+ // Once selected, a rejected token cannot silently select another account.
335
+ var attempt = tryAuth(ctx, candidates[0])
336
+ if (attempt.output) return attempt.output
337
+ throw attempt.authFailure ? LOGIN_HINT : QUOTA_HINT
338
+ }
339
+
340
+ globalThis.__openusage_plugin = { id: "devin", probe: probe }
341
+ })()
@@ -0,0 +1,16 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "devin",
4
+ "name": "Devin",
5
+ "version": "0.0.1",
6
+ "entry": "plugin.js",
7
+ "icon": "icon.svg",
8
+ "brandColor": "#000000",
9
+ "supportedModes": ["local"],
10
+ "autoMode": "local",
11
+ "lines": [
12
+ { "type": "progress", "label": "Weekly quota", "scope": "overview", "primaryOrder": 1 },
13
+ { "type": "progress", "label": "Daily quota", "scope": "overview" },
14
+ { "type": "text", "label": "Extra usage balance", "scope": "detail" }
15
+ ]
16
+ }
@@ -0,0 +1 @@
1
+ <svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Doubao</title><path d="M5.31 15.756c.172-3.75 1.883-5.999 2.549-6.739-3.26 2.058-5.425 5.658-6.358 8.308v1.12C1.501 21.513 4.226 24 7.59 24a6.59 6.59 0 002.2-.375c.353-.12.7-.248 1.039-.378.913-.899 1.65-1.91 2.243-2.992-4.877 2.431-7.974.072-7.763-4.5l.002.001z" fill="#1E37FC"></path><path d="M22.57 10.283c-1.212-.901-4.109-2.404-7.397-2.8.295 3.792.093 8.766-2.1 12.773a12.782 12.782 0 01-2.244 2.992c3.764-1.448 6.746-3.457 8.596-5.219 2.82-2.683 3.353-5.178 3.361-6.66a2.737 2.737 0 00-.216-1.084v-.002z" fill="#37E1BE"></path><path d="M14.303 1.867C12.955.7 11.248 0 9.39 0 7.532 0 5.883.677 4.545 1.807 2.791 3.29 1.627 5.557 1.5 8.125v9.201c.932-2.65 3.097-6.25 6.357-8.307.5-.318 1.025-.595 1.569-.829 1.883-.801 3.878-.932 5.746-.706-.222-2.83-.718-5.002-.87-5.617h.001z" fill="#A569FF"></path><path d="M17.305 4.961a199.47 199.47 0 01-1.08-1.094c-.202-.213-.398-.419-.586-.622l-1.333-1.378c.151.615.648 2.786.869 5.617 3.288.395 6.185 1.898 7.396 2.8-1.306-1.275-3.475-3.487-5.266-5.323z" fill="#1E37FC"></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>Doubao</title><path d="M5.31 15.756c.172-3.75 1.883-5.999 2.549-6.739-3.26 2.058-5.425 5.658-6.358 8.308v1.12C1.501 21.513 4.226 24 7.59 24a6.59 6.59 0 002.2-.375c.353-.12.7-.248 1.039-.378.913-.899 1.65-1.91 2.243-2.992-4.877 2.431-7.974.072-7.763-4.5l.002.001z" fill-opacity=".5"></path><path d="M22.57 10.283c-1.212-.901-4.109-2.404-7.397-2.8.295 3.792.093 8.766-2.1 12.773a12.782 12.782 0 01-2.244 2.992c3.764-1.448 6.746-3.457 8.596-5.219 2.82-2.683 3.353-5.178 3.361-6.66a2.737 2.737 0 00-.216-1.084v-.002zM14.303 1.867C12.955.7 11.248 0 9.39 0 7.532 0 5.883.677 4.545 1.807 2.791 3.29 1.627 5.557 1.5 8.125v9.201c.932-2.65 3.097-6.25 6.357-8.307.5-.318 1.025-.595 1.569-.829 1.883-.801 3.878-.932 5.746-.706-.222-2.83-.718-5.002-.87-5.617h.001z"></path><path d="M17.305 4.961a199.47 199.47 0 01-1.08-1.094c-.202-.213-.398-.419-.586-.622l-1.333-1.378c.151.615.648 2.786.869 5.617 3.288.395 6.185 1.898 7.396 2.8-1.306-1.275-3.475-3.487-5.266-5.323z" fill-opacity=".5"></path></svg>
@@ -0,0 +1,92 @@
1
+ (function () {
2
+ var API_URL = "https://ark.cn-beijing.volces.com/api/coding/v3/chat/completions"
3
+ var PROBE_MODELS = ["doubao-seed-2.0-code", "doubao-1.5-pro-32k", "doubao-lite-32k"]
4
+
5
+ function getApiKey(ctx) {
6
+ var key = ctx.host.env.get("ARK_API_KEY")
7
+ || ctx.host.env.get("DOUBAO_API_KEY")
8
+ || ctx.host.env.get("VOLCENGINE_API_KEY")
9
+ if (!key) throw "Set ARK_API_KEY, DOUBAO_API_KEY, or VOLCENGINE_API_KEY to use Doubao."
10
+ return key
11
+ }
12
+
13
+ function probeModel(ctx, apiKey, model) {
14
+ var resp = ctx.host.http.request({
15
+ method: "POST",
16
+ url: API_URL,
17
+ headers: {
18
+ "Authorization": "Bearer " + apiKey,
19
+ "Content-Type": "application/json",
20
+ "Accept": "application/json",
21
+ },
22
+ bodyText: JSON.stringify({
23
+ model: model,
24
+ max_tokens: 1,
25
+ messages: [{ role: "user", content: "hi" }],
26
+ }),
27
+ timeoutMs: 20000,
28
+ })
29
+
30
+ if (resp.status === 401 || resp.status === 403) {
31
+ throw "Invalid API key. Check ARK_API_KEY."
32
+ }
33
+
34
+ // Accept 200 (success) or 429 (rate-limited) — both return useful headers
35
+ if (resp.status !== 200 && resp.status !== 429) {
36
+ return null
37
+ }
38
+
39
+ return resp
40
+ }
41
+
42
+ function parseResetMs(value) {
43
+ if (!value) return null
44
+ var trimmed = value.trim()
45
+ var ts = Number(trimmed)
46
+ if (Number.isFinite(ts) && ts > 0) return ts * 1000
47
+ var ms = Date.parse(trimmed)
48
+ return Number.isFinite(ms) ? ms : null
49
+ }
50
+
51
+ function probe(ctx) {
52
+ var apiKey = getApiKey(ctx)
53
+
54
+ var resp = null
55
+ for (var i = 0; i < PROBE_MODELS.length; i++) {
56
+ resp = probeModel(ctx, apiKey, PROBE_MODELS[i])
57
+ if (resp) break
58
+ }
59
+
60
+ if (!resp) throw "All Doubao probe models failed. Check your API key and account."
61
+
62
+ var headers = resp.headers || {}
63
+ var remaining = parseInt(headers["x-ratelimit-remaining-requests"] || headers["X-Ratelimit-Remaining-Requests"], 10)
64
+ var limit = parseInt(headers["x-ratelimit-limit-requests"] || headers["X-Ratelimit-Limit-Requests"], 10)
65
+ var resetRaw = headers["x-ratelimit-reset-requests"] || headers["X-Ratelimit-Reset-Requests"]
66
+
67
+ var lines = []
68
+
69
+ if (Number.isFinite(remaining) && Number.isFinite(limit) && limit > 0) {
70
+ var used = Math.max(0, limit - remaining)
71
+ var resetMs = parseResetMs(resetRaw)
72
+ lines.push(ctx.line.progress({
73
+ label: "Requests",
74
+ used: used,
75
+ limit: limit,
76
+ format: { kind: "count", suffix: "req" },
77
+ resetsAt: ctx.util.toIso(resetMs ? resetMs / 1000 : null),
78
+ }))
79
+ } else {
80
+ var json = ctx.util.tryParseJson(resp.bodyText) || {}
81
+ var totalTokens = json.usage && json.usage.total_tokens
82
+ var detail = totalTokens
83
+ ? "Active — " + totalTokens + " tokens observed"
84
+ : "Active — check dashboard for details"
85
+ lines.push(ctx.line.badge({ label: "Status", text: detail, color: "#22c55e" }))
86
+ }
87
+
88
+ return { lines: lines }
89
+ }
90
+
91
+ globalThis.__openusage_plugin = { id: "doubao", probe: probe }
92
+ })()