@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,92 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0.00 0.00 128.00 128.00">
4
+ <g stroke-width="2.00" fill="none" stroke-linecap="butt">
5
+ <path stroke="currentColor" vector-effect="non-scaling-stroke" d="
6
+ M 27.46 27.54
7
+ C 23.31 31.70 16.50 34.46 10.57 34.99
8
+ Q 10.24 35.02 10.04 35.39
9
+ Q 9.90 35.65 9.90 36.04
10
+ Q 9.90 36.43 10.04 36.69
11
+ Q 10.24 37.06 10.57 37.09
12
+ C 16.50 37.62 23.31 40.38 27.46 44.54
13
+ C 31.62 48.69 34.38 55.50 34.91 61.43
14
+ Q 34.94 61.76 35.31 61.97
15
+ Q 35.57 62.11 35.96 62.11
16
+ Q 36.36 62.11 36.62 61.97
17
+ Q 36.98 61.76 37.02 61.43
18
+ C 37.54 55.50 40.31 48.69 44.46 44.54
19
+ C 48.62 40.38 55.43 37.62 61.36 37.09
20
+ Q 61.69 37.06 61.89 36.69
21
+ Q 62.03 36.43 62.03 36.04
22
+ Q 62.03 35.65 61.89 35.39
23
+ Q 61.69 35.02 61.36 34.99
24
+ C 55.43 34.46 48.62 31.70 44.46 27.54
25
+ C 40.31 23.38 37.54 16.58 37.02 10.65
26
+ Q 36.98 10.32 36.62 10.11
27
+ Q 36.36 9.97 35.96 9.97
28
+ Q 35.57 9.97 35.31 10.11
29
+ Q 34.94 10.32 34.91 10.65
30
+ C 34.38 16.58 31.62 23.38 27.46 27.54"
31
+ />
32
+ <path stroke="currentColor" vector-effect="non-scaling-stroke" d="
33
+ M 103.9557 64.7548
34
+ A 0.70 0.70 0.0 0 0 103.2569 64.0536
35
+ L 64.7970 63.9864
36
+ A 0.70 0.70 0.0 0 0 64.0958 64.6852
37
+ L 64.0843 75.2652
38
+ A 0.70 0.70 0.0 0 0 64.7831 75.9664
39
+ L 103.2430 76.0336
40
+ A 0.70 0.70 0.0 0 0 103.9442 75.3348
41
+ L 103.9557 64.7548"
42
+ />
43
+ </g>
44
+ <path fill="currentColor" d="
45
+ M 113.99 0.00
46
+ Q 125.60 2.32 128.00 13.94
47
+ L 128.00 113.98
48
+ Q 125.72 125.58 114.06 128.00
49
+ L 14.00 128.00
50
+ Q 2.44 125.69 0.00 114.05
51
+ L 0.00 14.01
52
+ Q 2.33 2.42 13.95 0.00
53
+ L 113.99 0.00
54
+ Z
55
+ M 27.46 27.54
56
+ C 23.31 31.70 16.50 34.46 10.57 34.99
57
+ Q 10.24 35.02 10.04 35.39
58
+ Q 9.90 35.65 9.90 36.04
59
+ Q 9.90 36.43 10.04 36.69
60
+ Q 10.24 37.06 10.57 37.09
61
+ C 16.50 37.62 23.31 40.38 27.46 44.54
62
+ C 31.62 48.69 34.38 55.50 34.91 61.43
63
+ Q 34.94 61.76 35.31 61.97
64
+ Q 35.57 62.11 35.96 62.11
65
+ Q 36.36 62.11 36.62 61.97
66
+ Q 36.98 61.76 37.02 61.43
67
+ C 37.54 55.50 40.31 48.69 44.46 44.54
68
+ C 48.62 40.38 55.43 37.62 61.36 37.09
69
+ Q 61.69 37.06 61.89 36.69
70
+ Q 62.03 36.43 62.03 36.04
71
+ Q 62.03 35.65 61.89 35.39
72
+ Q 61.69 35.02 61.36 34.99
73
+ C 55.43 34.46 48.62 31.70 44.46 27.54
74
+ C 40.31 23.38 37.54 16.58 37.02 10.65
75
+ Q 36.98 10.32 36.62 10.11
76
+ Q 36.36 9.97 35.96 9.97
77
+ Q 35.57 9.97 35.31 10.11
78
+ Q 34.94 10.32 34.91 10.65
79
+ C 34.38 16.58 31.62 23.38 27.46 27.54
80
+ Z
81
+ M 103.9557 64.7548
82
+ A 0.70 0.70 0.0 0 0 103.2569 64.0536
83
+ L 64.7970 63.9864
84
+ A 0.70 0.70 0.0 0 0 64.0958 64.6852
85
+ L 64.0843 75.2652
86
+ A 0.70 0.70 0.0 0 0 64.7831 75.9664
87
+ L 103.2430 76.0336
88
+ A 0.70 0.70 0.0 0 0 103.9442 75.3348
89
+ L 103.9557 64.7548
90
+ Z"
91
+ />
92
+ </svg>
@@ -0,0 +1,25 @@
1
+ (function () {
2
+ function probe(ctx) {
3
+ const response = ctx.host.command.run({program: 'coderabbit', args: ['usage'], timeoutMs: 15000});
4
+ const text = (response.stdout + '\n' + response.stderr).replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, '');
5
+ if (/not authenticated|please log in|auth login|authentication required|unauthorized|no session found/i.test(text))
6
+ throw {code: 'missing-auth', message: 'Run coderabbit auth login to sign in.'};
7
+ if (response.status !== 0) throw 'CodeRabbit usage command failed (exit ' + response.status + ').';
8
+ const fields = Object.create(null);
9
+ for (const line of text.split(/\r?\n/)) {
10
+ const colon = line.indexOf(':');
11
+ if (colon < 0) continue;
12
+ const label = line.slice(0, colon).trim().toLowerCase(), value = line.slice(colon + 1).trim();
13
+ if (value && !fields[label]) fields[label] = value;
14
+ }
15
+ const lines = [];
16
+ if (/^\d+$/.test(fields['your reviews'] || '') && Number.isSafeInteger(Number(fields['your reviews'])))
17
+ lines.push(ctx.line.text({label: 'Reviews', value: fields['your reviews']}));
18
+ for (const [key, label] of [['usage billing', 'Usage billing'], ['period resets', 'Period resets']])
19
+ if (fields[key]) lines.push(ctx.line.text({label, value: fields[key]}));
20
+ if (!lines.length) throw 'CodeRabbit did not report review counts or billing information.';
21
+ if (fields.organization) lines.push(ctx.line.text({label: 'Organization', value: fields.organization}));
22
+ return {displayName: 'CodeRabbit', source: 'cli', plan: fields.plan, lines};
23
+ }
24
+ globalThis.__usagestat_plugin = {id: 'coderabbit', probe};
25
+ })();
@@ -0,0 +1,12 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "coderabbit",
4
+ "name": "CodeRabbit",
5
+ "version": "0.1.0",
6
+ "entry": "plugin.js",
7
+ "enabledByDefault": false,
8
+ "supportedModes": ["cli"],
9
+ "autoMode": "cli",
10
+ "usageDashboardUrl": "https://app.coderabbit.ai",
11
+ "envVars": ["CODERABBIT_CLI_PATH"]
12
+ }
@@ -377,6 +377,7 @@
377
377
  if (!rawPlan) return null
378
378
  if (rawPlan.toLowerCase() === "prolite") return "Pro 5x"
379
379
  if (rawPlan.toLowerCase() === "pro") return "Pro 20x"
380
+ if (rawPlan.toLowerCase() === "self_serve_business_prolite") return "Business Premium"
380
381
  return ctx.fmt.planLabel(rawPlan) || null
381
382
  }
382
383
 
@@ -0,0 +1,3 @@
1
+ <svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M38 38H27C20.925 38 16 33.075 16 27C16 20.925 20.925 16 27 16C33.075 16 38 20.925 38 27V73C38 79.075 33.075 84 27 84C20.925 84 16 79.075 16 73C16 66.925 20.925 62 27 62H73C79.075 62 84 66.925 84 73C84 79.075 79.075 84 73 84C66.925 84 62 79.075 62 73V27C62 20.925 66.925 16 73 16C79.075 16 84 20.925 84 27C84 33.075 79.075 38 73 38H38V62" stroke="currentColor" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
3
+ </svg>
@@ -146,9 +146,11 @@
146
146
  }
147
147
 
148
148
  var lines = [];
149
- if (creditsRemaining !== null && monthlyUsed !== null) {
150
- var totalPlan = monthlyUsed + Math.max(0, creditsRemaining);
151
- var usedPercent = totalPlan > 0 ? (monthlyUsed / totalPlan) * 100 : 100;
149
+ var grants = { 'individual-go':10, 'individual-goat':70, 'individual-pro':30, 'individual-pro-v1':80, 'individual-max':150, 'individual-ultra':300 };
150
+ var totalPlan = readNumber(creditsResp && creditsResp.credits && creditsResp.credits.monthlyCreditsGranted);
151
+ if (!(totalPlan > 0)) totalPlan = subResp && subResp.success && subResp.data ? grants[subResp.data.planId] : null;
152
+ if (creditsRemaining !== null && totalPlan > 0) {
153
+ var usedPercent = Math.max(0, totalPlan - creditsRemaining) / totalPlan * 100;
152
154
  lines.push(ctx.line.progress({
153
155
  label: "Monthly credits",
154
156
  used: Math.max(0, Math.min(100, Math.round(usedPercent * 10) / 10)),
@@ -156,6 +158,8 @@
156
158
  format: { kind: "percent" },
157
159
  periodDurationMs: 30 * 24 * 60 * 60 * 1000,
158
160
  }));
161
+ } else if (creditsRemaining !== null) {
162
+ lines.push(ctx.line.text({label:'Monthly credits',value:'$'+Math.max(0,creditsRemaining).toFixed(2)+' remaining'}));
159
163
  }
160
164
 
161
165
  if (totalCost !== null && totalCost > 0) {
@@ -1 +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>GithubCopilot</title><path d="M19.245 5.364c1.322 1.36 1.877 3.216 2.11 5.817.622 0 1.2.135 1.592.654l.73.964c.21.278.323.61.323.955v2.62c0 .339-.173.669-.453.868C20.239 19.602 16.157 21.5 12 21.5c-4.6 0-9.205-2.583-11.547-4.258-.28-.2-.452-.53-.453-.868v-2.62c0-.345.113-.679.321-.956l.73-.963c.392-.517.974-.654 1.593-.654l.029-.297c.25-2.446.81-4.213 2.082-5.52 2.461-2.54 5.71-2.851 7.146-2.864h.198c1.436.013 4.685.323 7.146 2.864zm-7.244 4.328c-.284 0-.613.016-.962.05-.123.447-.305.85-.57 1.108-1.05 1.023-2.316 1.18-2.994 1.18-.638 0-1.306-.13-1.851-.464-.516.165-1.012.403-1.044.996a65.882 65.882 0 00-.063 2.884l-.002.48c-.002.563-.005 1.126-.013 1.69.002.326.204.63.51.765 2.482 1.102 4.83 1.657 6.99 1.657 2.156 0 4.504-.555 6.985-1.657a.854.854 0 00.51-.766c.03-1.682.006-3.372-.076-5.053-.031-.596-.528-.83-1.046-.996-.546.333-1.212.464-1.85.464-.677 0-1.942-.157-2.993-1.18-.266-.258-.447-.661-.57-1.108-.32-.032-.64-.049-.96-.05zm-2.525 4.013c.539 0 .976.426.976.95v1.753c0 .525-.437.95-.976.95a.964.964 0 01-.976-.95v-1.752c0-.525.437-.951.976-.951zm5 0c.539 0 .976.426.976.95v1.753c0 .525-.437.95-.976.95a.964.964 0 01-.976-.95v-1.752c0-.525.437-.951.976-.951zM7.635 5.087c-1.05.102-1.935.438-2.385.906-.975 1.037-.765 3.668-.21 4.224.405.394 1.17.657 1.995.657h.09c.649-.013 1.785-.176 2.73-1.11.435-.41.705-1.433.675-2.47-.03-.834-.27-1.52-.63-1.813-.39-.336-1.275-.482-2.265-.394zm6.465.394c-.36.292-.6.98-.63 1.813-.03 1.037.24 2.06.675 2.47.968.957 2.136 1.104 2.776 1.11h.044c.825 0 1.59-.263 1.995-.657.555-.556.765-3.187-.21-4.224-.45-.468-1.335-.804-2.385-.906-.99-.088-1.875.058-2.265.394zM12 7.615c-.24 0-.525.015-.84.044.03.16.045.336.06.526l-.001.159a2.94 2.94 0 01-.014.25c.225-.022.425-.027.612-.028h.366c.187 0 .387.006.612.028-.015-.146-.015-.277-.015-.409.015-.19.03-.365.06-.526a9.29 9.29 0 00-.84-.044z"></path></svg>
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>Copilot</title><path d="M9 23l.073-.001a2.53 2.53 0 01-2.347-1.838l-.697-2.433a2.529 2.529 0 00-2.426-1.839h-.497l-.104-.002c-4.485 0-2.935-5.278-1.75-9.225l.162-.525C2.412 3.99 3.883 1 6.25 1h8.86c1.12 0 2.106.745 2.422 1.829l.715 2.453a2.53 2.53 0 002.247 1.823l.147.005.534.001c3.557.115 3.088 3.745 2.156 7.206l-.113.413c-.154.548-.315 1.089-.47 1.607l-.163.525C21.588 20.01 20.116 23 17.75 23h-8.75zm8.22-15.89l-3.856.001a2.526 2.526 0 00-2.35 1.615L9.21 15.04a2.529 2.529 0 01-2.43 1.847l3.853.002c1.056 0 1.992-.661 2.361-1.644l1.796-6.287a2.529 2.529 0 012.43-1.848z"></path></svg>
@@ -0,0 +1,3 @@
1
+ <svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M44.2 8.5H82.4C85.6 8.5 88.1 11.1 87.8 14.2C87.7 15.5 87.2 16.7 86.4 17.8L73.3 35.5C69.7 40.3 64.1 43.1 58.1 43.1H28.1L40.2 60.1H68.4C72.8 60.1 76.9 62.1 79.6 65.6L88.2 76.9C89.8 79.1 89.7 82.1 87.8 84.2C86.6 85.5 84.9 86.3 83.1 86.3H45.1C36.5 86.3 28.5 82.1 23.6 75L8.9 53.6C5.2 48.2 5.3 41 9.2 35.7L20.6 20.1C26.1 12.8 34.8 8.5 44.2 8.5ZM28.1 43.1H15.4C13.5 43.1 12.4 45.2 13.5 46.8L27.3 66.9C31.3 72.8 38 76.3 45.1 76.3H75L68.6 68.1C67.2 66.3 65.1 65.2 62.8 65.2H38.6C34.4 65.2 30.5 63.2 28.1 59.8L19.7 48.1C18.2 45.9 19.8 43.1 22.5 43.1H28.1Z" fill="currentColor"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M44.2 8.5H82.4C85.6 8.5 88.1 11.1 87.8 14.2C87.7 15.5 87.2 16.7 86.4 17.8L73.3 35.5C69.7 40.3 64.1 43.1 58.1 43.1H28.1L40.2 60.1H68.4C72.8 60.1 76.9 62.1 79.6 65.6L88.2 76.9C89.8 79.1 89.7 82.1 87.8 84.2C86.6 85.5 84.9 86.3 83.1 86.3H45.1C36.5 86.3 28.5 82.1 23.6 75L8.9 53.6C5.2 48.2 5.3 41 9.2 35.7L20.6 20.1C26.1 12.8 34.8 8.5 44.2 8.5ZM28.1 43.1H15.4C13.5 43.1 12.4 45.2 13.5 46.8L27.3 66.9C31.3 72.8 38 76.3 45.1 76.3H75L68.6 68.1C67.2 66.3 65.1 65.2 62.8 65.2H38.6C34.4 65.2 30.5 63.2 28.1 59.8L19.7 48.1C18.2 45.9 19.8 43.1 22.5 43.1H28.1Z" fill="currentColor"/>
3
+ </svg>
@@ -1,16 +1,3 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 388 388" role="img" aria-label="CrofAI logo">
2
- <path fill="currentColor" d="
3
- M 103 107
4
- H 161
5
- V 135
6
- C 173 114, 195 103, 226 103
7
- C 264 103, 285 131, 285 185
8
- V 294
9
- H 226
10
- V 189
11
- C 226 159, 215 146, 194 146
12
- C 172 146, 161 163, 161 193
13
- V 294
14
- H 103
15
- Z"/>
1
+ <svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M44.2 8.5H82.4C85.6 8.5 88.1 11.1 87.8 14.2C87.7 15.5 87.2 16.7 86.4 17.8L73.3 35.5C69.7 40.3 64.1 43.1 58.1 43.1H28.1L40.2 60.1H68.4C72.8 60.1 76.9 62.1 79.6 65.6L88.2 76.9C89.8 79.1 89.7 82.1 87.8 84.2C86.6 85.5 84.9 86.3 83.1 86.3H45.1C36.5 86.3 28.5 82.1 23.6 75L8.9 53.6C5.2 48.2 5.3 41 9.2 35.7L20.6 20.1C26.1 12.8 34.8 8.5 44.2 8.5ZM28.1 43.1H15.4C13.5 43.1 12.4 45.2 13.5 46.8L27.3 66.9C31.3 72.8 38 76.3 45.1 76.3H75L68.6 68.1C67.2 66.3 65.1 65.2 62.8 65.2H38.6C34.4 65.2 30.5 63.2 28.1 59.8L19.7 48.1C18.2 45.9 19.8 43.1 22.5 43.1H28.1Z" fill="currentColor"/>
16
3
  </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>Cursor</title><path d="M22.106 5.68L12.5.135a.998.998 0 00-.998 0L1.893 5.68a.84.84 0 00-.419.726v11.186c0 .3.16.577.42.727l9.607 5.547a.999.999 0 00.998 0l9.608-5.547a.84.84 0 00.42-.727V6.407a.84.84 0 00-.42-.726zm-.603 1.176L12.228 22.92c-.063.108-.228.064-.228-.061V12.34a.59.59 0 00-.295-.51l-9.11-5.26c-.107-.062-.063-.228.062-.228h18.55c.264 0 .428.286.296.514z"></path></svg>
@@ -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>DeepInfra</title><path d="M3.294 7.821A2.297 2.297 0 011 5.527a2.297 2.297 0 012.294-2.295A2.297 2.297 0 015.59 5.527 2.297 2.297 0 013.294 7.82zm0-3.688a1.396 1.396 0 000 2.79 1.396 1.396 0 000-2.79zM3.294 14.293A2.297 2.297 0 011 11.998a2.297 2.297 0 012.294-2.294 2.297 2.297 0 012.295 2.294 2.297 2.297 0 01-2.295 2.295zm0-3.688a1.395 1.395 0 000 2.788 1.395 1.395 0 100-2.788zM3.294 20.761A2.297 2.297 0 011 18.467a2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.295 2.294zm0-3.688a1.396 1.396 0 000 2.79 1.396 1.396 0 000-2.79zM20.738 7.821a2.297 2.297 0 01-2.295-2.294 2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.294 2.294zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM20.738 14.293a2.297 2.297 0 01-2.295-2.295 2.297 2.297 0 012.294-2.294 2.297 2.297 0 012.295 2.294 2.297 2.297 0 01-2.294 2.295zm0-3.688c-.769 0-1.395.625-1.395 1.393a1.396 1.396 0 002.79 0c0-.77-.626-1.393-1.395-1.393zM20.738 20.761a2.297 2.297 0 01-2.295-2.294 2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.294 2.294zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM12.016 11.057a2.297 2.297 0 01-2.294-2.294 2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.295 2.294zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.625-1.395-1.395-1.395zM12.017 4.589a2.297 2.297 0 01-2.295-2.295A2.297 2.297 0 0112.017 0a2.297 2.297 0 012.294 2.294 2.297 2.297 0 01-2.294 2.295zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM12.017 17.529a2.297 2.297 0 01-2.295-2.295 2.297 2.297 0 012.295-2.294 2.297 2.297 0 012.294 2.294 2.297 2.297 0 01-2.294 2.295zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM12.016 24a2.297 2.297 0 01-2.294-2.295 2.297 2.297 0 012.294-2.294 2.297 2.297 0 012.295 2.294A2.297 2.297 0 0112.016 24zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.625-1.395-1.395-1.395z" fill="#2A3275"></path><path d="M8.363 8.222a.742.742 0 01-.277-.053l-1.494-.596a.75.75 0 11.557-1.392l1.493.595a.75.75 0 01-.278 1.446h-.001zM8.363 14.566a.743.743 0 01-.277-.053l-1.494-.595a.75.75 0 11.557-1.393l1.493.596a.75.75 0 01-.278 1.445h-.001zM17.124 11.397a.741.741 0 01-.277-.054l-1.493-.595a.75.75 0 11.555-1.392l1.493.595a.75.75 0 01-.278 1.446zM17.124 5.05a.744.744 0 01-.277-.054L15.354 4.4a.75.75 0 01.555-1.392l1.493.596a.75.75 0 01-.278 1.445zM17.124 17.739a.743.743 0 01-.277-.053l-1.494-.596a.75.75 0 11.556-1.392l1.493.596a.75.75 0 01-.278 1.445zM6.91 17.966a.75.75 0 01-.279-1.445l1.494-.595a.749.749 0 11.556 1.392l-1.493.595a.743.743 0 01-.277.053H6.91zM6.91 11.66a.75.75 0 01-.279-1.446l1.494-.595a.75.75 0 01.556 1.392l-1.493.595a.743.743 0 01-.277.053H6.91zM6.91 5.033a.75.75 0 01-.279-1.446l1.494-.595a.75.75 0 01.556 1.392l-1.493.596a.744.744 0 01-.277.053H6.91zM8.363 21.364a.743.743 0 01-.277-.053l-1.494-.596a.75.75 0 01.555-1.392l1.494.595a.75.75 0 01-.278 1.446zM15.63 8.223a.75.75 0 01-.278-1.447l1.494-.595a.75.75 0 01.556 1.393l-1.494.595a.744.744 0 01-.276.054h-.002zM15.63 14.567a.75.75 0 01-.278-1.446l1.494-.596a.75.75 0 01.556 1.394l-1.494.595a.743.743 0 01-.276.053h-.002zM15.63 21.363a.749.749 0 01-.278-1.445l1.494-.595a.75.75 0 11.555 1.392l-1.494.595a.741.741 0 01-.277.053z" fill="#5699DB"></path></svg>
@@ -1,4 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 32">
2
- <title>DeepInfra</title>
3
- <path fill="currentColor" d="M2.833 10.66A2.837 2.837 0 0 1 0 7.825a2.837 2.837 0 0 1 2.833-2.834 2.837 2.837 0 0 1 2.834 2.834 2.837 2.837 0 0 1-2.834 2.833m0-4.555a1.723 1.723 0 0 0 0 3.445 1.724 1.724 0 0 0 0-3.445m0 12.552A2.837 2.837 0 0 1 0 15.822a2.837 2.837 0 0 1 2.833-2.834 2.837 2.837 0 0 1 2.834 2.834 2.837 2.837 0 0 1-2.834 2.833m0-4.554a1.722 1.722 0 0 0 0 3.443 1.722 1.722 0 1 0 0-3.443m0 12.539A2.837 2.837 0 0 1 0 23.806a2.837 2.837 0 0 1 2.833-2.833 2.837 2.837 0 0 1 2.834 2.833 2.837 2.837 0 0 1-2.834 2.834m0-4.555a1.723 1.723 0 0 0 0 3.445c.95 0 1.723-.772 1.723-1.722s-.772-1.723-1.723-1.723M24.376 10.66a2.837 2.837 0 0 1-2.833-2.834 2.837 2.837 0 0 1 2.833-2.834 2.837 2.837 0 0 1 2.834 2.834 2.837 2.837 0 0 1-2.834 2.833m0-4.555c-.948 0-1.722.772-1.722 1.722a1.724 1.724 0 0 0 3.445 0c0-.95-.772-1.722-1.723-1.722m0 12.551a2.837 2.837 0 0 1-2.833-2.833 2.837 2.837 0 0 1 2.833-2.834 2.837 2.837 0 0 1 2.834 2.834 2.837 2.837 0 0 1-2.834 2.833m0-4.554c-.948 0-1.722.772-1.722 1.72 0 .95.772 1.723 1.722 1.723s1.723-.772 1.723-1.722-.772-1.721-1.723-1.721m0 12.539a2.837 2.837 0 0 1-2.833-2.834 2.837 2.837 0 0 1 2.833-2.833 2.837 2.837 0 0 1 2.834 2.833 2.837 2.837 0 0 1-2.834 2.834m0-4.555a1.724 1.724 0 1 0 1.723 1.723c0-.95-.772-1.723-1.723-1.723m-10.771-7.43a2.837 2.837 0 0 1-2.834-2.833 2.837 2.837 0 0 1 2.834-2.834 2.837 2.837 0 0 1 2.833 2.834 2.837 2.837 0 0 1-2.833 2.833m0-4.554c-.949 0-1.723.772-1.723 1.722s.773 1.723 1.723 1.723 1.723-.772 1.723-1.723c0-.95-.773-1.722-1.723-1.722m0-3.434a2.837 2.837 0 0 1-2.834-2.834A2.837 2.837 0 0 1 13.606 1a2.837 2.837 0 0 1 2.833 2.833 2.837 2.837 0 0 1-2.833 2.834m0-4.554c-.949 0-1.723.772-1.723 1.722a1.724 1.724 0 0 0 3.446 0c0-.95-.773-1.722-1.723-1.722m-.001 20.534a2.837 2.837 0 0 1-2.834-2.833 2.837 2.837 0 0 1 2.834-2.834 2.837 2.837 0 0 1 2.833 2.834 2.837 2.837 0 0 1-2.833 2.833m0-4.554a1.724 1.724 0 0 0 0 3.445 1.724 1.724 0 0 0 0-3.445m0 12.547a2.837 2.837 0 0 1-2.834-2.834 2.837 2.837 0 0 1 2.834-2.833 2.837 2.837 0 0 1 2.833 2.833 2.837 2.837 0 0 1-2.833 2.834m0-4.555a1.724 1.724 0 1 0 1.723 1.723c0-.95-.773-1.723-1.723-1.723M9.094 11.154a.9.9 0 0 1-.342-.066l-1.845-.735a.926.926 0 1 1 .687-1.72l1.845.735a.926.926 0 0 1-.344 1.786zm0 7.835a.9.9 0 0 1-.342-.066l-1.845-.735a.925.925 0 1 1 .687-1.72l1.845.736a.925.925 0 0 1-.344 1.785zm10.82-3.914a.9.9 0 0 1-.342-.066l-1.844-.735a.926.926 0 0 1 .685-1.72l1.845.736a.926.926 0 0 1-.344 1.785m0-7.835a.9.9 0 0 1-.342-.066l-1.844-.735a.926.926 0 0 1 .685-1.72l1.845.735a.926.926 0 0 1-.344 1.786m0 15.668a.9.9 0 0 1-.342-.066l-1.844-.735a.926.926 0 0 1 .685-1.72l1.845.735a.926.926 0 0 1-.344 1.785m-12.616.281a.926.926 0 0 1-.344-1.785l1.845-.735a.925.925 0 1 1 .687 1.72l-1.845.734a.9.9 0 0 1-.342.066zm0-7.793a.926.926 0 0 1-.344-1.785l1.845-.735a.925.925 0 1 1 .687 1.72l-1.845.734a.9.9 0 0 1-.342.066zm0-8.18a.926.926 0 0 1-.344-1.785L8.8 4.695a.925.925 0 1 1 .687 1.72L7.64 7.15a.9.9 0 0 1-.342.065zm1.796 20.169a.9.9 0 0 1-.342-.066l-1.845-.735a.925.925 0 0 1 .686-1.72l1.844.736a.926.926 0 0 1-.343 1.785m8.976-16.229a.926.926 0 0 1-.344-1.787l1.844-.735a.927.927 0 0 1 .687 1.72l-1.844.736a.9.9 0 0 1-.342.066zm0 7.835a.926.926 0 0 1-.344-1.786l1.844-.736a.927.927 0 0 1 .687 1.721l-1.844.736a.9.9 0 0 1-.342.066zm0 8.393a.925.925 0 0 1-.343-1.785l1.843-.735a.925.925 0 1 1 .686 1.72l-1.845.735a.9.9 0 0 1-.342.065"/>
4
- </svg>
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>DeepInfra</title><path d="M3.294 7.821A2.297 2.297 0 011 5.527a2.297 2.297 0 012.294-2.295A2.297 2.297 0 015.59 5.527 2.297 2.297 0 013.294 7.82zm0-3.688a1.396 1.396 0 000 2.79 1.396 1.396 0 000-2.79zM3.294 14.293A2.297 2.297 0 011 11.998a2.297 2.297 0 012.294-2.294 2.297 2.297 0 012.295 2.294 2.297 2.297 0 01-2.295 2.295zm0-3.688a1.395 1.395 0 000 2.788 1.395 1.395 0 100-2.788zM3.294 20.761A2.297 2.297 0 011 18.467a2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.295 2.294zm0-3.688a1.396 1.396 0 000 2.79 1.396 1.396 0 000-2.79zM20.738 7.821a2.297 2.297 0 01-2.295-2.294 2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.294 2.294zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM20.738 14.293a2.297 2.297 0 01-2.295-2.295 2.297 2.297 0 012.294-2.294 2.297 2.297 0 012.295 2.294 2.297 2.297 0 01-2.294 2.295zm0-3.688c-.769 0-1.395.625-1.395 1.393a1.396 1.396 0 002.79 0c0-.77-.626-1.393-1.395-1.393zM20.738 20.761a2.297 2.297 0 01-2.295-2.294 2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.294 2.294zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM12.016 11.057a2.297 2.297 0 01-2.294-2.294 2.297 2.297 0 012.294-2.295 2.297 2.297 0 012.295 2.295 2.297 2.297 0 01-2.295 2.294zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.625-1.395-1.395-1.395zM12.017 4.589a2.297 2.297 0 01-2.295-2.295A2.297 2.297 0 0112.017 0a2.297 2.297 0 012.294 2.294 2.297 2.297 0 01-2.294 2.295zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM12.017 17.529a2.297 2.297 0 01-2.295-2.295 2.297 2.297 0 012.295-2.294 2.297 2.297 0 012.294 2.294 2.297 2.297 0 01-2.294 2.295zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.626-1.395-1.395-1.395zM12.016 24a2.297 2.297 0 01-2.294-2.295 2.297 2.297 0 012.294-2.294 2.297 2.297 0 012.295 2.294A2.297 2.297 0 0112.016 24zm0-3.688a1.396 1.396 0 101.395 1.395c0-.77-.625-1.395-1.395-1.395z"></path><path d="M8.363 8.222a.742.742 0 01-.277-.053l-1.494-.596a.75.75 0 11.557-1.392l1.493.595a.75.75 0 01-.278 1.446h-.001zM8.363 14.566a.743.743 0 01-.277-.053l-1.494-.595a.75.75 0 11.557-1.393l1.493.596a.75.75 0 01-.278 1.445h-.001zM17.124 11.397a.741.741 0 01-.277-.054l-1.493-.595a.75.75 0 11.555-1.392l1.493.595a.75.75 0 01-.278 1.446zM17.124 5.05a.744.744 0 01-.277-.054L15.354 4.4a.75.75 0 01.555-1.392l1.493.596a.75.75 0 01-.278 1.445zM17.124 17.739a.743.743 0 01-.277-.053l-1.494-.596a.75.75 0 11.556-1.392l1.493.596a.75.75 0 01-.278 1.445zM6.91 17.966a.75.75 0 01-.279-1.445l1.494-.595a.749.749 0 11.556 1.392l-1.493.595a.743.743 0 01-.277.053H6.91zM6.91 11.66a.75.75 0 01-.279-1.446l1.494-.595a.75.75 0 01.556 1.392l-1.493.595a.743.743 0 01-.277.053H6.91zM6.91 5.033a.75.75 0 01-.279-1.446l1.494-.595a.75.75 0 01.556 1.392l-1.493.596a.744.744 0 01-.277.053H6.91zM8.363 21.364a.743.743 0 01-.277-.053l-1.494-.596a.75.75 0 01.555-1.392l1.494.595a.75.75 0 01-.278 1.446zM15.63 8.223a.75.75 0 01-.278-1.447l1.494-.595a.75.75 0 01.556 1.393l-1.494.595a.744.744 0 01-.276.054h-.002zM15.63 14.567a.75.75 0 01-.278-1.446l1.494-.596a.75.75 0 01.556 1.394l-1.494.595a.743.743 0 01-.276.053h-.002zM15.63 21.363a.749.749 0 01-.278-1.445l1.494-.595a.75.75 0 11.555 1.392l-1.494.595a.741.741 0 01-.277.053z"></path></svg>
@@ -1,71 +1,162 @@
1
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;
2
+ const PLATFORM = 'https://platform.deepseek.com/api/v0/';
3
+ const own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
4
+ const clean = value => typeof value === 'string' && value.trim() ? value.trim().replace(/^Bearer\s+/i, '') : null;
5
+ function amount(value) {
6
+ if (typeof value !== 'number' && typeof value !== 'string' || typeof value === 'string' && !value.trim()) return null;
7
+ const n = Number(value);
8
+ return Number.isFinite(n) && n >= 0 ? n : null;
11
9
  }
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.";
10
+ function fail(code, message) { throw {code, message}; }
11
+ function request(ctx, url, token, timeoutMs) {
12
+ const result = ctx.util.requestJson({method:'GET', url, timeoutMs,
13
+ headers:{Authorization:'Bearer '+token, Accept:'application/json', 'x-client-platform':'web'}});
14
+ const body = result.json;
15
+ if ([401,403].includes(result.resp.status) || [40002,40003].includes(body?.code) || [40002,40003].includes(body?.data?.biz_code))
16
+ fail('credential-rejected', 'DeepSeek credential expired. Sign in again.');
17
+ if (result.resp.status === 429) fail('failed', 'DeepSeek is rate limited.');
18
+ if (result.resp.status < 200 || result.resp.status >= 300 || !body || body.code && body.code !== 0 || body.data?.biz_code && body.data.biz_code !== 0)
19
+ fail('failed', 'DeepSeek request failed (HTTP '+result.resp.status+').');
20
+ return body;
21
+ }
22
+ function choose(values) {
23
+ return values.find(v => v.currency === 'USD' && v.total > 0) || values.find(v => v.total > 0) || values.find(v => v.currency === 'USD') || values[0];
24
+ }
25
+ function balance(ctx, key, token) {
26
+ if (key) {
27
+ const data = request(ctx, 'https://api.deepseek.com/user/balance', key, 15000);
28
+ if (!Array.isArray(data.balance_infos)) fail('failed', 'DeepSeek balance response changed.');
29
+ const values = data.balance_infos.map(value => ({currency:String(value.currency || '').toUpperCase(), total:amount(value.total_balance),
30
+ paid:amount(value.topped_up_balance), granted:amount(value.granted_balance)}));
31
+ if (values.some(v => !v.currency || v.total === null || v.paid === null || v.granted === null)) fail('failed', 'DeepSeek returned an invalid balance.');
32
+ return {value:choose(values), available:data.is_available !== false};
17
33
  }
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.";
34
+ const data = request(ctx, PLATFORM+'users/get_user_summary', token, 15000).data?.biz_data;
35
+ if (!data || !Array.isArray(data.normal_wallets) || !Array.isArray(data.bonus_wallets)) fail('failed', 'DeepSeek wallet response changed.');
36
+ const values = new Map();
37
+ for (const [field, wallets] of [['paid',data.normal_wallets],['granted',data.bonus_wallets]]) {
38
+ for (const wallet of wallets) {
39
+ const currency = String(wallet.currency || '').toUpperCase(), value = amount(wallet.balance);
40
+ if (!currency || value === null) fail('failed', 'DeepSeek returned an invalid wallet.');
41
+ if (!values.has(currency)) values.set(currency,{currency,total:0,paid:0,granted:0});
42
+ values.get(currency)[field] += value;
43
+ values.get(currency).total += value;
44
+ }
28
45
  }
29
- if (result.resp.status < 200 || result.resp.status >= 300) {
30
- throw "DeepSeek API error (HTTP " + result.resp.status + ").";
46
+ return {value:choose([...values.values()]),available:true};
47
+ }
48
+ function details(ctx, token, lines) {
49
+ const now = new Date(ctx.nowIso), end = Date.parse(ctx.nowIso.slice(0,10)) + 86400000, start = end - 30*86400000;
50
+ const deadline = Date.now() + 5000;
51
+ const fetch = suffix => {
52
+ const left = deadline - Date.now();
53
+ if (left <= 0) fail('failed','DeepSeek detail deadline exceeded.');
54
+ return request(ctx, PLATFORM+'usage/'+suffix, token, Math.min(1500,left)).data?.biz_data;
55
+ };
56
+ let amounts, costs, monthly = false;
57
+ try {
58
+ const query = '?start='+Math.floor(start/1000)+'&end='+Math.floor(end/1000)+'&tz=0';
59
+ amounts = fetch('by_api_key/amount'+query);
60
+ costs = fetch('by_api_key/cost'+query);
61
+ if (!Array.isArray(amounts?.series) || !Array.isArray(costs?.data)) throw new Error('Unrecognized series');
62
+ } catch (error) {
63
+ if (error?.code === 'credential-rejected' || /rate limited/.test(error?.message || '')) throw error;
64
+ monthly = true;
65
+ const query = '?month='+(now.getUTCMonth()+1)+'&year='+now.getUTCFullYear();
66
+ amounts = fetch('amount'+query);
67
+ costs = fetch('cost'+query);
68
+ if (!Array.isArray(amounts?.days) || !Array.isArray(costs)) throw new Error('Unrecognized monthly usage');
31
69
  }
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; }
70
+ const blocks = monthly ? costs : costs.data;
71
+ const block = blocks.find(b => b.currency === 'USD') || blocks[0];
72
+ if (!block || typeof block.currency !== 'string') throw new Error('Unknown currency');
73
+ const currency = block.currency.toUpperCase(), days = new Map(), models = new Map(), keys = new Set();
74
+ const lower = monthly ? ctx.nowIso.slice(0,7)+'-01' : new Date(start).toISOString().slice(0,10), upper = ctx.nowIso.slice(0,10);
75
+ function day(date) {
76
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(date) || date < lower || date > upper || new Date(date).toISOString().slice(0,10) !== date) return null;
77
+ if (!days.has(date)) days.set(date,{date,inputTokens:0,outputTokens:0,cacheReadTokens:0,totalTokens:0,costUsd:0,
78
+ requests:0,tokensKnown:false,costKnown:false,amountSeen:false,costSeen:false,badTokens:false,badCost:false});
79
+ return days.get(date);
38
80
  }
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 };
81
+ function addAmount(date, usage) {
82
+ const row = day(date);
83
+ if (!row || !usage || typeof usage !== 'object') return;
84
+ for (const [type, field] of [['PROMPT_CACHE_MISS_TOKEN','inputTokens'],['PROMPT_CACHE_HIT_TOKEN','cacheReadTokens'],['RESPONSE_TOKEN','outputTokens'],['REQUEST','requests']]) {
85
+ if (!own(usage,type)) continue;
86
+ const value = amount(usage[type]);
87
+ if (value === null || !Number.isSafeInteger(value)) { row.badTokens=true; continue; }
88
+ row[field] += value;
89
+ if (field !== 'requests') { row.totalTokens += value; row.amountSeen=true; }
90
+ }
45
91
  }
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";
92
+ function addCost(date, model, raw) {
93
+ const row = day(date), value = amount(raw);
94
+ if (!row) return;
95
+ if (value === null) { row.badCost=true; if(model) models.set(model,null); return; }
96
+ row.costUsd += value; row.costSeen=true;
97
+ if (model && models.get(model) !== null) models.set(model,(models.get(model)||0)+value);
98
+ }
99
+ const dateFor = time => typeof time === 'number' && time*1000 >= start && time*1000 < end ? new Date(time*1000).toISOString().slice(0,10) : '';
100
+ if (!monthly) {
101
+ if (amounts.series.length > 10000 || !Array.isArray(block.series) || block.series.length > 10000) throw new Error('Too many series');
102
+ for (const series of amounts.series) {
103
+ if (series.api_key) keys.add(JSON.stringify(series.api_key));
104
+ if (!Array.isArray(series.buckets) || series.buckets.length > 32) throw new Error('Invalid buckets');
105
+ for (const bucket of series.buckets) addAmount(dateFor(bucket.time),bucket.usage);
106
+ }
107
+ for (const series of block.series) {
108
+ if (series.api_key) keys.add(JSON.stringify(series.api_key));
109
+ if (!Array.isArray(series.buckets) || series.buckets.length > 32) throw new Error('Invalid buckets');
110
+ for (const bucket of series.buckets) addCost(dateFor(bucket.time),series.model,bucket.cost);
111
+ }
58
112
  } else {
59
- detail = symbol + total.toFixed(2) + " (Paid: " + symbol + toppedUp.toFixed(2) + " / Granted: " + symbol + granted.toFixed(2) + ")";
113
+ for (const item of amounts.days.slice(0,32)) for (const model of (item.data || []).slice(0,1000))
114
+ addAmount(item.date, Object.fromEntries((model.usage || []).map(value => [value.type,value.amount])));
115
+ for (const item of (block.days || []).slice(0,32)) for (const model of (item.data || []).slice(0,1000))
116
+ for (const value of model.usage || []) addCost(item.date,model.model,value.amount);
117
+ }
118
+ const daily = [...days.values()].sort((a,b)=>a.date.localeCompare(b.date));
119
+ for (const row of daily) {
120
+ row.tokensKnown = row.amountSeen && !row.badTokens && Number.isSafeInteger(row.totalTokens);
121
+ row.costKnown = row.costSeen && !row.badCost && Number.isFinite(row.costUsd);
122
+ if (!Number.isFinite(row.costUsd)) throw new Error('Cost overflow');
123
+ delete row.amountSeen; delete row.costSeen; delete row.badTokens; delete row.badCost;
60
124
  }
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" }));
125
+ if (!daily.length) return;
126
+ const total = daily.reduce((sum,row)=>sum+row.costUsd,0), complete = daily.every(row=>row.costKnown);
127
+ if(!Number.isFinite(total)) throw new Error('Cost overflow');
128
+ const usageLines = [
129
+ ctx.line.text({label:monthly?'This month':'Last 30 days',value:currency+' '+total.toFixed(2)+(complete?'':'+'),subtitle:'Platform-account spend across API keys'}),
130
+ ctx.line.text({label:'Tokens',value:String(daily.reduce((sum,row)=>sum+row.totalTokens,0))+(daily.every(row=>row.tokensKnown)?'':'+')}),
131
+ ctx.line.text({label:'Requests',value:String(daily.reduce((sum,row)=>sum+row.requests,0))})
132
+ ];
133
+ if(keys.size) usageLines.push(ctx.line.text({label:'API keys',value:String(keys.size)}));
134
+ for(const [model,cost] of [...models].filter(([,v])=>v!==null && Number.isFinite(v)).sort((a,b)=>b[1]-a[1]).slice(0,30))
135
+ usageLines.push(ctx.line.text({label:model,value:currency+' '+cost.toFixed(2)}));
136
+ usageLines.push(ctx.line.barChart({label:'Daily tokens',points:daily.map(row=>({label:row.date,value:row.totalTokens}))}));
137
+ usageLines.push(ctx.line.barChart({label:'Daily spend',points:daily.filter(row=>row.costKnown).map(row=>({label:row.date,value:row.costUsd,valueLabel:currency+' '+row.costUsd.toFixed(2)}))}));
138
+ // The shared ledger is USD-only; never relabel CNY spend as dollars.
139
+ const stored = daily.map(row=>currency==='USD'?row:{...row,costUsd:0,costKnown:false});
140
+ ctx.host.usageDaily.ingest({displayName:'DeepSeek',source:'deepseek_platform',daily:stored});
141
+ lines.push(...usageLines);
142
+ }
143
+ function probe(ctx) {
144
+ const provider = ctx.provider || {}, settings = provider.settings || {}, scoped = provider.instanceId && provider.instanceId !== 'deepseek';
145
+ const env = key => scoped ? null : clean(ctx.host.env.get(key));
146
+ const key = ctx.sourceMode === 'web' ? null : own(provider,'apiKey') ? clean(provider.apiKey) : env('DEEPSEEK_API_KEY') || env('DEEPSEEK_KEY');
147
+ const token = own(settings,'platformToken') ? clean(settings.platformToken) : own(provider,'cookieHeader') ? clean(provider.cookieHeader) : env('DEEPSEEK_PLATFORM_TOKEN') || env('DEEPSEEK_USER_TOKEN');
148
+ if (!key && !token || ctx.sourceMode === 'api' && !key) fail('missing-auth','Set a DeepSeek API key or a Platform token in web mode.');
149
+ const data = balance(ctx,key,token), lines = [], value = data.value;
150
+ if (value) lines.push(ctx.line.text({label:'Balance',value:value.currency+' '+value.total.toFixed(2),
151
+ subtitle:'Paid: '+value.paid.toFixed(2)+' / Granted: '+value.granted.toFixed(2)}));
152
+ else lines.push(ctx.line.badge({label:'Balance',text:'No balance data',color:'#a3a3a3'}));
153
+ if (!data.available) lines.push(ctx.line.badge({label:'Status',text:'Balance unavailable for API calls',color:'#ef4444'}));
154
+ // Pair website totals only with an explicitly bound API key, never ambient account state.
155
+ if (token && (!key || own(settings,'platformToken') && settings.platformApiKeyHash === ctx.host.crypto.sha256(key)) && settings.extraUsage !== false) {
156
+ try { details(ctx,token,lines); }
157
+ catch (_) { lines.push(ctx.line.text({label:'Details',value:'Detailed usage unavailable'})); }
65
158
  }
66
-
67
- return { lines: lines };
159
+ return {source:key?'api':'web',lines};
68
160
  }
69
-
70
- globalThis.__openusage_plugin = { id: "deepseek", probe: probe };
161
+ globalThis.__openusage_plugin = {id:'deepseek',probe};
71
162
  })();
@@ -9,8 +9,10 @@
9
9
  { "label": "Platform", "url": "https://platform.deepseek.com/usage" }
10
10
  ],
11
11
  "usageDashboardUrl": "https://platform.deepseek.com/usage",
12
- "supportedModes": ["api"],
12
+ "supportedModes": ["api", "web"],
13
13
  "autoMode": "api",
14
+ "webUrl": "https://platform.deepseek.com",
15
+ "envVars": ["DEEPSEEK_API_KEY", "DEEPSEEK_KEY", "DEEPSEEK_PLATFORM_TOKEN", "DEEPSEEK_USER_TOKEN"],
14
16
  "lines": [
15
17
  { "type": "text", "label": "Balance", "scope": "overview" }
16
18
  ]
@@ -273,8 +273,11 @@
273
273
  var hideDailyQuota = planInfo.hideDailyQuota === true
274
274
  var dailyRemaining = readFiniteNumber(planStatus.dailyQuotaRemainingPercent)
275
275
  var weeklyRemaining = readFiniteNumber(planStatus.weeklyQuotaRemainingPercent)
276
+ if (Object.prototype.hasOwnProperty.call(planStatus, "weeklyQuotaRemainingPercent") && weeklyRemaining === null) throw QUOTA_HINT
276
277
  var dailyReset = !hideDailyQuota ? unixSecondsToIso(ctx, planStatus.dailyQuotaResetAtUnix) : null
277
278
  var weeklyReset = unixSecondsToIso(ctx, planStatus.weeklyQuotaResetAtUnix)
279
+ // Proto3 omits a zero remaining percentage; a reset identifies the exhausted window.
280
+ if (weeklyRemaining === null && weeklyReset) weeklyRemaining = 0
278
281
  var extraUsageBalance = formatDollarsFromMicros(planStatus.overageBalanceMicros)
279
282
 
280
283
  var dailyLine = !hideDailyQuota
@@ -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.