@hashimkarim/usagestat-linux-x64-gnu 2.0.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/native-manifest.json +808 -148
  2. package/package.json +112 -2
  3. package/plugins/abliteration/LICENSE +21 -0
  4. package/plugins/abliteration/icon.svg +5 -0
  5. package/plugins/abliteration/plugin.js +89 -0
  6. package/plugins/abliteration/plugin.json +24 -0
  7. package/plugins/aerostack/LICENSE +21 -0
  8. package/plugins/aerostack/icon.svg +1 -0
  9. package/plugins/aerostack/plugin.js +94 -0
  10. package/plugins/aerostack/plugin.json +24 -0
  11. package/plugins/aixy/icon.svg +1 -0
  12. package/plugins/aixy/plugin.js +5 -0
  13. package/plugins/aixy/plugin.json +9 -1
  14. package/plugins/antigravity/plugin.js +19 -10
  15. package/plugins/antigravity-cli/plugin.js +8 -3
  16. package/plugins/antigravity-ide/plugin.js +8 -5
  17. package/plugins/atlascloud/plugin.js +5 -0
  18. package/plugins/atlascloud/plugin.json +2 -1
  19. package/plugins/bifrost/icon.svg +3 -0
  20. package/plugins/bifrost/plugin.js +5 -0
  21. package/plugins/bifrost/plugin.json +9 -1
  22. package/plugins/chatbox/LICENSE +21 -0
  23. package/plugins/chatbox/icon.svg +4 -0
  24. package/plugins/chatbox/plugin.js +208 -0
  25. package/plugins/chatbox/plugin.json +24 -0
  26. package/plugins/claude/plugin.js +39 -2
  27. package/plugins/claudeplatform/LICENSE +21 -0
  28. package/plugins/claudeplatform/icon.svg +3 -0
  29. package/plugins/claudeplatform/plugin.js +244 -0
  30. package/plugins/claudeplatform/plugin.json +25 -0
  31. package/plugins/codex/plugin.js +14 -8
  32. package/plugins/codex/plugin.json +11 -2
  33. package/plugins/cosmic/LICENSE +21 -0
  34. package/plugins/cosmic/icon.svg +1 -0
  35. package/plugins/cosmic/plugin.js +134 -0
  36. package/plugins/cosmic/plugin.json +32 -0
  37. package/plugins/cursor/plugin.js +27 -8
  38. package/plugins/cursor-nightly/plugin.json +1 -1
  39. package/plugins/devpass/icon.svg +3 -0
  40. package/plugins/devpass/plugin.js +5 -0
  41. package/plugins/devpass/plugin.json +2 -1
  42. package/plugins/exa/LICENSE +21 -0
  43. package/plugins/exa/icon-color.svg +1 -0
  44. package/plugins/exa/icon.svg +1 -0
  45. package/plugins/exa/plugin.js +75 -0
  46. package/plugins/exa/plugin.json +32 -0
  47. package/plugins/fal/LICENSE +21 -0
  48. package/plugins/fal/icon-color.svg +1 -0
  49. package/plugins/fal/icon.svg +1 -0
  50. package/plugins/fal/plugin.js +74 -0
  51. package/plugins/fal/plugin.json +24 -0
  52. package/plugins/flora/LICENSE +21 -0
  53. package/plugins/flora/icon.svg +4 -0
  54. package/plugins/flora/plugin.js +93 -0
  55. package/plugins/flora/plugin.json +32 -0
  56. package/plugins/futureagi/LICENSE +21 -0
  57. package/plugins/futureagi/icon.svg +24 -0
  58. package/plugins/futureagi/plugin.js +139 -0
  59. package/plugins/futureagi/plugin.json +32 -0
  60. package/plugins/gemini-apps/LICENSE +1 -2
  61. package/plugins/gemini-apps/plugin.js +136 -465
  62. package/plugins/gemini-apps/plugin.json +13 -7
  63. package/plugins/gitkraken/icon.svg +2 -0
  64. package/plugins/gitkraken/plugin.js +5 -0
  65. package/plugins/gitkraken/plugin.json +9 -1
  66. package/plugins/googledeveloper/LICENSE +21 -0
  67. package/plugins/googledeveloper/icon.svg +3 -0
  68. package/plugins/googledeveloper/plugin.js +204 -0
  69. package/plugins/googledeveloper/plugin.json +25 -0
  70. package/plugins/helmcode/icon.svg +5 -0
  71. package/plugins/helmcode/plugin.js +120 -55
  72. package/plugins/helmcode/plugin.json +10 -2
  73. package/plugins/huggingface/plugin.js +6 -1
  74. package/plugins/huggingface/plugin.json +4 -3
  75. package/plugins/hyper/plugin.js +53 -47
  76. package/plugins/hyper/plugin.json +3 -2
  77. package/plugins/jetbrains-ai-assistant/LICENSE +22 -0
  78. package/plugins/jetbrains-ai-assistant/plugin.js +502 -16
  79. package/plugins/jetbrains-ai-assistant/plugin.json +27 -4
  80. package/plugins/kimi/plugin.js +54 -14
  81. package/plugins/kimi/plugin.json +46 -6
  82. package/plugins/langdock/LICENSE +21 -0
  83. package/plugins/langdock/icon.svg +4 -0
  84. package/plugins/langdock/plugin.js +106 -0
  85. package/plugins/langdock/plugin.json +25 -0
  86. package/plugins/linkup/LICENSE +21 -0
  87. package/plugins/linkup/icon.svg +10 -0
  88. package/plugins/linkup/plugin.js +46 -0
  89. package/plugins/linkup/plugin.json +24 -0
  90. package/plugins/lithosai/plugin.js +5 -0
  91. package/plugins/lithosai/plugin.json +2 -1
  92. package/plugins/llmman/icon.svg +4 -0
  93. package/plugins/llmman/plugin.js +5 -0
  94. package/plugins/llmman/plugin.json +9 -1
  95. package/plugins/munito/LICENSE +21 -0
  96. package/plugins/munito/icon.svg +7 -0
  97. package/plugins/munito/plugin.js +171 -0
  98. package/plugins/munito/plugin.json +24 -0
  99. package/plugins/muse/icon.svg +3 -0
  100. package/plugins/muse/plugin.js +5 -0
  101. package/plugins/muse/plugin.json +9 -1
  102. package/plugins/museai/plugin.js +10 -3
  103. package/plugins/museai/plugin.json +3 -2
  104. package/plugins/nous/plugin.js +5 -0
  105. package/plugins/nous/plugin.json +9 -1
  106. package/plugins/ollama/plugin.js +58 -0
  107. package/plugins/opencode-go/plugin.js +21 -9
  108. package/plugins/opendesign/LICENSE +21 -0
  109. package/plugins/opendesign/icon.svg +4 -0
  110. package/plugins/opendesign/plugin.js +108 -0
  111. package/plugins/opendesign/plugin.json +25 -0
  112. package/plugins/parallel/LICENSE +21 -0
  113. package/plugins/parallel/icon.svg +11 -0
  114. package/plugins/parallel/plugin.js +97 -0
  115. package/plugins/parallel/plugin.json +25 -0
  116. package/plugins/perplexity/LICENSE +22 -0
  117. package/plugins/perplexity/plugin.js +122 -0
  118. package/plugins/perplexity/plugin.json +36 -7
  119. package/plugins/qwencloud/LICENSE +21 -0
  120. package/plugins/qwencloud/plugin.js +197 -0
  121. package/plugins/qwencloud/plugin.json +17 -0
  122. package/plugins/raycast/icon.svg +4 -0
  123. package/plugins/raycast/plugin.js +5 -0
  124. package/plugins/raycast/plugin.json +9 -1
  125. package/plugins/replicate/plugin.js +5 -0
  126. package/plugins/replicate/plugin.json +2 -1
  127. package/plugins/sailresearch/LICENSE +21 -0
  128. package/plugins/sailresearch/icon.svg +4 -0
  129. package/plugins/sailresearch/plugin.js +104 -0
  130. package/plugins/sailresearch/plugin.json +24 -0
  131. package/plugins/siliconflow/LICENSE +21 -0
  132. package/plugins/siliconflow/icon.svg +3 -0
  133. package/plugins/siliconflow/plugin.js +87 -0
  134. package/plugins/siliconflow/plugin.json +32 -0
  135. package/plugins/sofya/LICENSE +21 -0
  136. package/plugins/sofya/icon.svg +3 -0
  137. package/plugins/sofya/plugin.js +86 -0
  138. package/plugins/sofya/plugin.json +24 -0
  139. package/plugins/soniox/LICENSE +21 -0
  140. package/plugins/soniox/icon.svg +3 -0
  141. package/plugins/soniox/plugin.js +103 -0
  142. package/plugins/soniox/plugin.json +24 -0
  143. package/plugins/synthetic/plugin.js +12 -0
  144. package/plugins/synthetic/plugin.json +51 -9
  145. package/plugins/tavily/LICENSE +21 -0
  146. package/plugins/tavily/icon.svg +3 -0
  147. package/plugins/tavily/plugin.js +61 -0
  148. package/plugins/tavily/plugin.json +24 -0
  149. package/plugins/tinyapi/LICENSE +21 -0
  150. package/plugins/tinyapi/icon.svg +4 -0
  151. package/plugins/tinyapi/plugin.js +73 -0
  152. package/plugins/tinyapi/plugin.json +25 -0
  153. package/plugins/traecn/LICENSE +21 -0
  154. package/plugins/traecn/icon.svg +3 -0
  155. package/plugins/traecn/plugin.js +103 -0
  156. package/plugins/traecn/plugin.json +25 -0
  157. package/plugins/tripo/LICENSE +21 -0
  158. package/plugins/tripo/icon.svg +4 -0
  159. package/plugins/tripo/plugin.js +60 -0
  160. package/plugins/tripo/plugin.json +24 -0
  161. package/plugins/typesafe/icon.svg +4 -0
  162. package/plugins/typesafe/plugin.js +85 -129
  163. package/plugins/typesafe/plugin.json +3 -2
  164. package/plugins/v0/plugin.js +5 -0
  165. package/plugins/v0/plugin.json +9 -1
  166. package/plugins/vercel/plugin.js +147 -0
  167. package/plugins/vercel/plugin.json +34 -3
  168. package/plugins/workbuddy/icon.svg +1 -1
  169. package/plugins/workbuddy/plugin.js +110 -19
  170. package/plugins/workbuddy/plugin.json +32 -2
  171. package/plugins/xai/plugin.js +9 -0
  172. package/plugins/xapi/LICENSE +21 -0
  173. package/plugins/xapi/icon.svg +1 -0
  174. package/plugins/xapi/plugin.js +90 -0
  175. package/plugins/xapi/plugin.json +25 -0
  176. package/plugins/xkiro/icon.svg +1 -0
  177. package/plugins/xkiro/plugin.js +5 -0
  178. package/plugins/xkiro/plugin.json +2 -1
  179. package/usagestat +0 -0
  180. package/usagestatd +0 -0
  181. package/plugins/cursor-nightly/plugin.js +0 -1416
@@ -14,9 +14,17 @@
14
14
  "GITKRAKEN_API_TOKEN",
15
15
  "GITKRAKEN_ORG_ID"
16
16
  ],
17
+ "setupFields": [
18
+ {
19
+ "key": "GITKRAKEN_ORG_ID",
20
+ "title": "API organization ID",
21
+ "type": "string",
22
+ "description": "Provider-specific account or source selection."
23
+ }
24
+ ],
17
25
  "upstream": {
18
26
  "repository": "https://github.com/steipete/CodexBar",
19
- "revision": "6ba06fe9ec1522dd5c59e16810115bce28aa148f",
27
+ "revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
20
28
  "path": "Sources/CodexBarCore/Resources/Plugins/gitkraken.js",
21
29
  "sha256": "c583890b74fc4c054cd818e560b30a17dd716c7611b554bd5b559f533a824ca2",
22
30
  "license": "MIT"
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Peter Steinberger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ <svg fill="currentColor" viewBox="0.25 -0.25 24 24" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M2.5 14.5a4.5 4.5 0 1 0 9 0a4.5 4.5 0 1 0-9 0ZM6.5 10.5a6 6 0 1 0 12 0a6 6 0 1 0-12 0ZM13 14.5a4.5 4.5 0 1 0 9 0a4.5 4.5 0 1 0-9 0ZM7 12v7h10.5v-7Z"/>
3
+ </svg>
@@ -0,0 +1,204 @@
1
+ // Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
2
+ globalThis.__usagestat_bundled_options = {"labels":["Credits","Additional","Additional"],"defaults":{},"autoMode":"web","balanceOnly":true};
3
+ (function(defineProvider) {
4
+ // BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/googledeveloper.js
5
+ function _nullishCoalesce(lhs, rhsFn) {
6
+ if (lhs != null) {
7
+ return lhs;
8
+ } else {
9
+ return rhsFn();
10
+ }
11
+ }
12
+ defineProvider({
13
+ id: "googledeveloper",
14
+ name: "Google Developer Program",
15
+ settings: [{ key: "MESSAGES", title: "Google Developer Program", type: "plain" }],
16
+ endpoints: ["https://me.developers.google.com"],
17
+ capabilities: ["browser-cookies", "http-status"],
18
+ cookieDomains: ["me.developers.google.com", "google.com"],
19
+ cookiePolicy: { selection: "request-url", cache: "nonpersistent", imports: "access-gated" },
20
+ async fetchUsage(ctx) {
21
+ const domain = "me.developers.google.com";
22
+ const origin = `https://${domain}`;
23
+ const messages = JSON.parse(ctx.settings.get("MESSAGES") || "{}");
24
+ const message = (key, ...values) => {
25
+ let text = messages[key] || key;
26
+ for (const value of values) text = text.replace("%@", () => value);
27
+ return text;
28
+ };
29
+ const signIn = message(
30
+ "No Google Developer Program session cookies found. Sign in at me.developers.google.com/benefits or paste a Cookie header.",
31
+ );
32
+ if (ctx.browser.availability(domain) === "off")
33
+ throw ctx.fail.missingCredential(message("%@ cookies are disabled.", "Google Developer Program"));
34
+ const invalid = () => {
35
+ throw ctx.fail.parseFailure(
36
+ message("Google Developer Program returned an unrecognized response. Update CodexBar and try again."),
37
+ );
38
+ };
39
+ const json = (text) => {
40
+ try {
41
+ return JSON.parse(text);
42
+ } catch (error) {
43
+ void error;
44
+ return invalid();
45
+ }
46
+ };
47
+ const array = (value) => (Array.isArray(value) ? value : invalid());
48
+ // Google Money arrays omit zero units and nanos.
49
+ const integer = (value) =>
50
+ value === null || value === undefined
51
+ ? 0
52
+ : typeof value === "number" && Number.isSafeInteger(value)
53
+ ? value
54
+ : invalid();
55
+ const money = (value) => {
56
+ const [currency, units, nanos] = array(value);
57
+ if (typeof currency !== "string" || !/^[A-Z]{3}$/.test(currency)) return invalid();
58
+ return { currency, amount: integer(units) + integer(nanos) / 1e9 };
59
+ };
60
+ // A malformed timestamp means an unknown date, never a failed refresh.
61
+ const date = (value) => {
62
+ const seconds = Array.isArray(value) ? value[0] : undefined;
63
+ return typeof seconds === "number" && Number.isSafeInteger(seconds) && seconds > 0
64
+ ? ctx.date.unixSeconds(seconds)
65
+ : undefined;
66
+ };
67
+ const day = (value) =>
68
+ `${value.getFullYear()}-${String(value.getMonth() + 1).padStart(2, "0")}-${String(value.getDate()).padStart(2, "0")}`;
69
+ // WIZ_global_data values are JSON string literals.
70
+ const pageValue = (html, key) => {
71
+ const literal = ctx.html.matchFirst(html, `"${key}":("(?:[^"\\\\]|\\\\.)*")`);
72
+ return literal ? json(literal) : undefined;
73
+ };
74
+ // Signed-out requests redirect to accounts.google.com, which the host refuses, or answer 401 or 403.
75
+ const denied = (response) => {
76
+ if ((response.status >= 300 && response.status < 400) || response.status === 401 || response.status === 403)
77
+ return true;
78
+ if (response.status === 429) {
79
+ throw ctx.fail.rateLimited(message("Google Developer Program is rate limiting requests. Try again later."));
80
+ }
81
+ if (response.status >= 500) {
82
+ throw ctx.fail.providerUnavailable(message("Google Developer Program request failed. Try refreshing later."));
83
+ }
84
+ if (response.status !== 200) {
85
+ throw ctx.fail.apiFailure(message("Google Developer Program request failed. Try refreshing later."));
86
+ }
87
+ return false;
88
+ };
89
+ let unapplied;
90
+ let signedIn = false;
91
+ let rejected = false;
92
+ for await (const session of ctx.browser.sessions(domain)) {
93
+ const emails = [];
94
+ // Each authuser index is one signed-in Google account, and only one of them may hold the credit.
95
+ for (let account = 0; account < 8; account += 1) {
96
+ const page = await ctx.http.get(`${origin}/benefits?authuser=${account}`, {
97
+ cookieSession: session.id,
98
+ headers: { Accept: "text/html" },
99
+ retryPolicy: "transientIdempotent",
100
+ });
101
+ if (denied(page)) break;
102
+ // Signed-out pages also omit the page tokens.
103
+ const token = pageValue(page.bodyText, "SNlM0e");
104
+ const email = pageValue(page.bodyText, "oPEP7c");
105
+ if (!token || !email || emails.includes(email)) break;
106
+
107
+ const response = await ctx.http.post(
108
+ `${origin}/_/GoogleDeveloperProfile/data/batchexecute` +
109
+ `?rpcids=Ro0AYc&source-path=%2Fbenefits&hl=en&authuser=${account}&rt=c`,
110
+ {
111
+ cookieSession: session.id,
112
+ form: { "f.req": JSON.stringify([[["Ro0AYc", "[]", null, "generic"]]]), at: token },
113
+ headers: { Origin: origin, Referer: `${origin}/benefits` },
114
+ },
115
+ );
116
+ if (denied(response)) break;
117
+ emails.push(email);
118
+ signedIn = true;
119
+ // The chunked envelope alternates length lines with JSON chunks. Only the Ro0AYc result matters.
120
+ const result = response.bodyText
121
+ .split("\n")
122
+ .filter((line) => line.startsWith("["))
123
+ .flatMap((line) => array(json(line)))
124
+ .find((entry) => Array.isArray(entry) && entry[0] === "wrb.fr" && entry[1] === "Ro0AYc");
125
+ if (!result) return invalid();
126
+ // A per-account RPC error has no string payload, so try the next account.
127
+ if (typeof result[2] !== "string") continue;
128
+ const list = array(json(result[2]))[0];
129
+ // Benefit type 19 is the monthly Gen AI & Cloud credit of Google AI Pro and Ultra.
130
+ const credit = array(_nullishCoalesce(list, () => []))
131
+ .map((benefit) => array(benefit))
132
+ .find((benefit) => benefit[0] === 19);
133
+ if (!credit) continue;
134
+ const offer = array(_nullishCoalesce(credit[9], () => []));
135
+ // A credit that is not applied to a billing account yet has no money fields.
136
+ if (offer[6] === null || offer[6] === undefined) {
137
+ unapplied ??= email;
138
+ continue;
139
+ }
140
+ const billing = array(offer[6]);
141
+ const granted = money(billing[0]);
142
+ const remaining = money(billing[1]);
143
+ if (granted.amount <= 0) return invalid();
144
+ if (remaining.currency !== granted.currency) return invalid();
145
+ const currency = granted.currency;
146
+ const left = Math.max(0, remaining.amount);
147
+ const expiresAt = date(offer[1]);
148
+ const grantedAt = date(offer[16]);
149
+ const amounts = message(
150
+ "%@ of %@ left",
151
+ ctx.format.currency(left, currency),
152
+ ctx.format.currency(granted.amount, currency),
153
+ );
154
+ // The billing account is display-only, so an unexpected format never fails the refresh.
155
+ const rows =
156
+ typeof billing[2] === "string"
157
+ ? [{ label: "Billing account", value: billing[2].replace(/^billingAccounts\//, "") }]
158
+ : [];
159
+ if (grantedAt) rows.push({ label: "Granted", value: day(grantedAt) });
160
+ return {
161
+ primary: {
162
+ usedPercent: ctx.pct(granted.amount - left, granted.amount),
163
+ resetDescription: expiresAt ? `${amounts} · ${message("Expires %@", day(expiresAt))}` : amounts,
164
+ },
165
+ cost: { used: left, currency, period: "Monthly credits", balance: left },
166
+ details: [{ title: "Billing", rows }],
167
+ identity: { email, loginMethod: message("Browser session") },
168
+ dataConfidence: "exact",
169
+ };
170
+ }
171
+ if (signedIn) break;
172
+ // A session whose first account fails the page or the RPC is signed out.
173
+ ctx.browser.rejectCookie(domain, session);
174
+ rejected = true;
175
+ }
176
+ if (unapplied) {
177
+ return {
178
+ details: [
179
+ {
180
+ title: "Cloud credits",
181
+ rows: [
182
+ {
183
+ label: "Status",
184
+ value: message("Not applied"),
185
+ secondaryValue: "me.developers.google.com/benefits",
186
+ },
187
+ ],
188
+ },
189
+ ],
190
+ identity: { email: unapplied, loginMethod: message("Browser session") },
191
+ dataConfidence: "exact",
192
+ };
193
+ }
194
+ if (signedIn)
195
+ throw ctx.fail.permissionDenied(message("No Cloud credit found. Check your Google Developer Program benefits."));
196
+ if (rejected) throw ctx.fail.authenticationExpired(`${message("Google session expired or invalid.")} ${signIn}`);
197
+ throw ctx.fail.missingCredential(
198
+ `${signIn} ${message("Supported browsers: %@. Use Manual for other browsers.", ctx.browser.supportedBrowsers)}`,
199
+ );
200
+ },
201
+ });
202
+
203
+ // END UPSTREAM
204
+ })(globalThis.defineProvider);
@@ -0,0 +1,25 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "googledeveloper",
4
+ "name": "Google Developer Program",
5
+ "version": "0.1.0",
6
+ "entry": "plugin.js",
7
+ "enabledByDefault": false,
8
+ "supportedModes": [
9
+ "web"
10
+ ],
11
+ "autoMode": "web",
12
+ "usageDashboardUrl": "https://me.developers.google.com/benefits",
13
+ "webUrl": "https://me.developers.google.com",
14
+ "envVars": [
15
+ "GOOGLEDEVELOPER_COOKIE"
16
+ ],
17
+ "setupFields": [],
18
+ "upstream": {
19
+ "repository": "https://github.com/steipete/CodexBar",
20
+ "revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
21
+ "path": "Sources/CodexBarCore/Resources/Plugins/googledeveloper.js",
22
+ "sha256": "16f97c5fa06d7f4b4255f1e0413af01fa9a0ee7af03243701a40b0f6294564c0",
23
+ "license": "MIT"
24
+ }
25
+ }
@@ -0,0 +1,5 @@
1
+ <svg width="132" height="132" viewBox="0 0 132 132" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g transform="translate(8.5)">
3
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M57.5 0C54.9373 0 52.3747 0.6439 50.1323 1.9317L7.20752 26.8829C2.72284 29.4585 0 34.2878 0 39.439V92.561C0 97.712 2.72284 102.541 7.20752 105.117L50.1323 130.068C52.3747 131.356 54.9373 132 57.5 132C60.0627 132 62.6253 131.356 64.8677 130.068L107.792 105.117C112.277 102.541 115 97.712 115 92.561V39.439C115 34.2878 112.277 29.4585 107.792 26.8829L64.8677 1.9317C62.6253 0.6439 60.0627 0 57.5 0ZM57.5 23.8244L20.0055 43.7423L57.4199 64.8294V109.302H57.5L97.6901 86.0459V47.285L57.5 23.8244Z" fill="currentColor"/>
4
+ </g>
5
+ </svg>
@@ -1,5 +1,7 @@
1
1
  // Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
2
2
  globalThis.__usagestat_bundled_options = {"labels":["Model quota","Model quota","Additional"],"defaults":{},"autoMode":"web"};
3
+ (function(defineProvider) {
4
+ // BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/helmcode.js
3
5
  function _nullishCoalesce(lhs, rhsFn) {
4
6
  if (lhs != null) {
5
7
  return lhs;
@@ -34,13 +36,13 @@ defineProvider({
34
36
  endpoints: ["https://cloud-api.helmcode.com", "https://cloud-api.nan.builders"],
35
37
  settings: [{ key: "TENANT", title: "Manual cookie tenant", type: "plain" }],
36
38
  capabilities: ["browser-cookies", "http-status"],
37
- cookieDomains: ["helmcode.com", "nan.builders"],
39
+ cookieDomains: ["helmcode.com", "cloud-api.helmcode.com", "nan.builders"],
38
40
  async fetchUsage(ctx) {
39
41
  const tenants = [
40
- { domain: "helmcode.com", name: "Helmcode Cloud" },
41
- { domain: "nan.builders", name: "NaN Builders" },
42
+ { domain: "helmcode.com", cookieDomain: "cloud-api.helmcode.com", name: "Helmcode Cloud" },
43
+ { domain: "nan.builders", cookieDomain: "nan.builders", name: "NaN Builders" },
42
44
  ];
43
- const policy = ctx.browser.availability(tenants[0].domain);
45
+ const policy = ctx.browser.availability(tenants[0].cookieDomain);
44
46
  if (policy === "off") throw ctx.fail.missingCredential("Helmcode dashboard cookies are disabled.");
45
47
  // A pasted header has no origin metadata. Never try it against both tenants.
46
48
  const candidates = policy === "manual" ? [tenants[ctx.settings.get("TENANT") === "nanBuilders" ? 1 : 0]] : tenants;
@@ -57,51 +59,110 @@ defineProvider({
57
59
  return fail("invalid JSON");
58
60
  }
59
61
  };
60
- const integer = (value, field) => {
61
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) return fail(field);
62
+ const amount = (value, field, fractional = false) => {
63
+ const valid = fractional ? Number.isFinite(value) : Number.isSafeInteger(value);
64
+ if (typeof value !== "number" || !valid || value < 0) return fail(field);
62
65
  return value;
63
66
  };
64
- const date = (value) => {
65
- if (typeof value !== "string") return undefined;
66
- try {
67
- return ctx.date.iso(value);
68
- } catch (error) {
69
- void error;
70
- return undefined;
67
+ async function* sessions() {
68
+ for (const tenant of candidates) {
69
+ const domains =
70
+ policy !== "manual" && tenant.domain !== tenant.cookieDomain
71
+ ? [tenant.domain, tenant.cookieDomain, tenant.domain]
72
+ : [tenant.cookieDomain];
73
+ // Try the old cache first, then API-host and parent-domain browser sessions.
74
+ for (const [index, domain] of domains.entries()) {
75
+ try {
76
+ for await (const session of ctx.browser.sessions(domain, {
77
+ cachedOnly: domains.length > 1 && index === 0,
78
+ })) {
79
+ yield { tenant, domain, session };
80
+ }
81
+ } catch (error) {
82
+ void error;
83
+ }
84
+ }
71
85
  }
72
- };
73
- const validate = (response) => {
74
- const seconds = Number(_nullishCoalesce(response.headers["retry-after"], () => 1));
75
- const retryAfterSeconds = Number.isFinite(seconds) && seconds >= 0 ? Math.min(10, seconds) : 1;
76
- if (response.status === 429) throw ctx.fail.rateLimited("Helmcode rate limit reached.", { retryAfterSeconds });
77
- if (response.status === 408 || response.status >= 500)
78
- throw ctx.fail.providerUnavailable("Helmcode dashboard is unavailable.", { retryAfterSeconds });
79
- if (response.status < 200 || response.status >= 300)
80
- throw ctx.fail.apiFailure(`Helmcode dashboard returned HTTP ${response.status}.`);
81
- };
86
+ }
82
87
  let rejected = false;
83
- for (const tenant of candidates) {
84
- let cookie;
85
- try {
86
- cookie = await ctx.browser.cookieHeader(tenant.domain);
87
- } catch (error) {
88
- void error;
89
- continue;
90
- }
88
+ for await (const { tenant, domain, session } of sessions()) {
89
+ if (!session.header) continue;
91
90
  const headers = {
92
- Cookie: cookie,
91
+ Cookie: session.header,
93
92
  Origin: `https://cloud.${tenant.domain}`,
94
93
  Referer: `https://cloud.${tenant.domain}/dashboard`,
95
94
  };
96
95
  const get = (path, timeoutSeconds = 8) =>
97
96
  ctx.http.get(`https://cloud-api.${tenant.domain}${path}`, { headers, timeoutSeconds });
98
- const response = await get("/api/usage/quota");
99
- if ((response.status >= 300 && response.status < 400) || response.status === 401 || response.status === 403) {
100
- ctx.browser.rejectCookie(tenant.domain);
101
- rejected = true;
102
- continue;
97
+ const required = async (path, allowMissing = false) => {
98
+ const response = await get(path);
99
+ if ((response.status >= 300 && response.status < 400) || response.status === 401 || response.status === 403) {
100
+ ctx.browser.rejectCookie(domain, session);
101
+ rejected = true;
102
+ return undefined;
103
+ }
104
+ const seconds = Number(_nullishCoalesce(response.headers["retry-after"], () => 1));
105
+ const retryAfterSeconds = Number.isFinite(seconds) && seconds >= 0 ? Math.min(10, seconds) : 1;
106
+ if (response.status === 429) throw ctx.fail.rateLimited("Helmcode rate limit reached.", { retryAfterSeconds });
107
+ if (response.status === 408 || response.status >= 500)
108
+ throw ctx.fail.providerUnavailable("Helmcode dashboard is unavailable.", { retryAfterSeconds });
109
+ if ((response.status < 200 || response.status >= 300) && !(allowMissing && response.status === 404))
110
+ throw ctx.fail.apiFailure(`Helmcode dashboard returned HTTP ${response.status}.`);
111
+ return response;
112
+ };
113
+ const creditResponse = await required("/api/usage/credits", true);
114
+ if (!creditResponse) continue;
115
+ const credits = creditResponse.status === 404 ? undefined : parse(creditResponse.bodyText);
116
+ if (credits && typeof credits.enabled !== "boolean") return fail("enabled");
117
+ // Only an absent or explicitly disabled credit plan permits legacy token quotas.
118
+ if (_optionalChain([credits, "optionalAccess", (_) => _.enabled])) {
119
+ const allowance = amount(credits.allowanceCredits, "allowanceCredits", true);
120
+ const spent = amount(credits.usedCredits, "usedCredits", true);
121
+ if (allowance <= 0) return fail("allowanceCredits");
122
+ const start = typeof credits.periodStart === "string" ? ctx.date.iso(credits.periodStart) : undefined;
123
+ const end = typeof credits.periodEnd === "string" ? ctx.date.iso(credits.periodEnd) : undefined;
124
+ const format = (value, field) =>
125
+ value == null ? "—" : ctx.format.number(amount(value, field, true), { maximumFractionDigits: 3 });
126
+ const models = (Array.isArray(credits.models) ? credits.models : []).map((value) => {
127
+ const row = _nullishCoalesce(object(value), () => fail("credit model"));
128
+ if (typeof row.model !== "string" || !ctx.isDetailLabel(row.model)) return fail("credit model name");
129
+ return {
130
+ label: row.model,
131
+ value: format(row.creditsThisMonth, "creditsThisMonth"),
132
+ weight: format(row.approxCreditsPerMTokens, "approxCreditsPerMTokens"),
133
+ };
134
+ });
135
+ const rows = models.slice(0, 20).map(({ label, value }) => ({ label, value }));
136
+ if (models.length > 20) rows.push({ label: "Other models", value: "—" });
137
+ const planRows = [];
138
+ if (credits.packCredits != null)
139
+ planRows.push({ label: "Top-up credits", value: format(credits.packCredits, "packCredits") });
140
+ if (credits.frozen === true) planRows.push({ label: "Paused during grace period", value: "—" });
141
+ return {
142
+ primary: {
143
+ title: "Credits",
144
+ usedPercent: ctx.pct(spent, allowance),
145
+ resetsAt: end,
146
+ windowMinutes:
147
+ start && end && end > start ? Math.round((end.getTime() - start.getTime()) / 60000) : undefined,
148
+ quotaLimit: allowance,
149
+ quotaUnit: "credits",
150
+ resetDescription: `${format(spent, "usedCredits")} / ${format(allowance, "allowanceCredits")}`,
151
+ },
152
+ details: [
153
+ { title: "Credits used", rows },
154
+ {
155
+ title: "Credits per million tokens",
156
+ rows: models.slice(0, 20).map(({ label, weight }) => ({ label, value: weight })),
157
+ },
158
+ ...(planRows.length ? [{ title: "Credits", rows: planRows }] : []),
159
+ ],
160
+ identity: { organization: tenant.name, loginMethod: "Dashboard session" },
161
+ dataConfidence: "exact",
162
+ };
103
163
  }
104
- validate(response);
164
+ const response = await required("/api/usage/quota");
165
+ if (!response) continue;
105
166
  const quota = parse(response.bodyText);
106
167
  if (typeof quota.periodStart !== "string" || !Array.isArray(quota.models)) return fail("periodStart or models");
107
168
  const optional = async (path) => {
@@ -118,9 +179,9 @@ defineProvider({
118
179
  _optionalChain([
119
180
  object,
120
181
  "call",
121
- (_) => _(_optionalChain([billing, "optionalAccess", (_2) => _2.subscription])),
182
+ (_2) => _2(_optionalChain([billing, "optionalAccess", (_3) => _3.subscription])),
122
183
  "optionalAccess",
123
- (_3) => _3.premium,
184
+ (_4) => _4.premium,
124
185
  ]) === true;
125
186
  const start = /^(\d{4})-(\d{2})-(\d{2})(?:T|$)/.exec(quota.periodStart);
126
187
  const fallback =
@@ -131,19 +192,20 @@ defineProvider({
131
192
  .map((value) => {
132
193
  const row = _nullishCoalesce(object(value), () => fail("model"));
133
194
  if (typeof row.model !== "string" || !ctx.isDetailLabel(row.model)) return fail("model name");
134
- const cap = integer(row.cap, "cap");
135
- const used = integer(row.tokensUsed, "tokensUsed");
136
- const credit = row.creditTokens == null ? 0 : integer(row.creditTokens, "creditTokens");
137
- const hours = row.windowHours == null ? undefined : integer(row.windowHours, "windowHours");
195
+ const cap = amount(row.cap, "cap");
196
+ const used = amount(row.tokensUsed, "tokensUsed");
197
+ const credit = row.creditTokens == null ? 0 : amount(row.creditTokens, "creditTokens");
198
+ const hours = row.windowHours == null ? undefined : amount(row.windowHours, "windowHours");
138
199
  if (hours !== undefined && (hours < 1 || hours > 525600 / 60)) return fail("windowHours");
139
- return {
140
- name: row.model,
141
- cap,
142
- used,
143
- credit,
144
- hours,
145
- resetsAt: _nullishCoalesce(date(row.periodEnd), () => fallback),
146
- };
200
+ let resetsAt = fallback;
201
+ if (typeof row.periodEnd === "string") {
202
+ try {
203
+ resetsAt = _nullishCoalesce(ctx.date.iso(row.periodEnd), () => fallback);
204
+ } catch (error) {
205
+ void error;
206
+ }
207
+ }
208
+ return { name: row.model, cap, used, credit, hours, resetsAt };
147
209
  })
148
210
  .filter((row) => row.cap > 0 && (row.hours === undefined || premium));
149
211
  models.sort((a, b) => b.used / b.cap - a.used / a.cap || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
@@ -162,9 +224,9 @@ defineProvider({
162
224
  let cost;
163
225
  if (tenant.domain === "helmcode.com") {
164
226
  const credits = await optional("/api/billing/credits");
165
- const balance = _optionalChain([credits, "optionalAccess", (_4) => _4.balanceMicros]);
227
+ const balance = _optionalChain([credits, "optionalAccess", (_5) => _5.balanceMicros]);
166
228
  const currency =
167
- _optionalChain([credits, "optionalAccess", (_5) => _5.currency]) == null
229
+ _optionalChain([credits, "optionalAccess", (_6) => _6.currency]) == null
168
230
  ? "EUR"
169
231
  : typeof credits.currency === "string"
170
232
  ? credits.currency.toUpperCase()
@@ -173,7 +235,7 @@ defineProvider({
173
235
  cost = { used: Math.max(0, balance / 1e6), limit: 0, currency, period: "Prepaid balance" };
174
236
  }
175
237
  return {
176
- primary: _optionalChain([windows, "access", (_6) => _6[0], "optionalAccess", (_7) => _7.window]),
238
+ primary: _optionalChain([windows, "access", (_7) => _7[0], "optionalAccess", (_8) => _8.window]),
177
239
  extraWindows: windows.slice(1),
178
240
  cost,
179
241
  identity: { organization: tenant.name, loginMethod: "Dashboard session" },
@@ -186,3 +248,6 @@ defineProvider({
186
248
  );
187
249
  },
188
250
  });
251
+
252
+ // END UPSTREAM
253
+ })(globalThis.defineProvider);
@@ -14,11 +14,19 @@
14
14
  "envVars": [
15
15
  "HELMCODE_COOKIE"
16
16
  ],
17
+ "setupFields": [
18
+ {
19
+ "key": "TENANT",
20
+ "title": "Manual cookie tenant",
21
+ "type": "string",
22
+ "description": "Provider-specific account or source selection."
23
+ }
24
+ ],
17
25
  "upstream": {
18
26
  "repository": "https://github.com/steipete/CodexBar",
19
- "revision": "6ba06fe9ec1522dd5c59e16810115bce28aa148f",
27
+ "revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
20
28
  "path": "Sources/CodexBarCore/Resources/Plugins/helmcode.js",
21
- "sha256": "3192630337f9b8bbd577acb930357e54d1f02ec9435a49dcc01411448f072ff1",
29
+ "sha256": "058d7d04a6d2fca8221a96aa6c451f4c6f4ad2a4653c9dd03d6b714a63f8c1dd",
22
30
  "license": "MIT"
23
31
  }
24
32
  }
@@ -1,5 +1,7 @@
1
1
  // Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
2
- globalThis.__usagestat_bundled_options = {"labels":["Inference","ZeroGPU","Additional"],"defaults":{},"autoMode":"api"};
2
+ globalThis.__usagestat_bundled_options = {"labels":["Inference","ZeroGPU","Additional"],"defaults":{},"autoMode":"web"};
3
+ (function(defineProvider) {
4
+ // BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/huggingface.js
3
5
  function _nullishCoalesce(lhs, rhsFn) {
4
6
  if (lhs != null) {
5
7
  return lhs;
@@ -291,3 +293,6 @@ defineProvider({
291
293
  };
292
294
  },
293
295
  });
296
+
297
+ // END UPSTREAM
298
+ })(globalThis.defineProvider);
@@ -6,18 +6,19 @@
6
6
  "entry": "plugin.js",
7
7
  "enabledByDefault": false,
8
8
  "supportedModes": [
9
- "api"
9
+ "web"
10
10
  ],
11
- "autoMode": "api",
11
+ "autoMode": "web",
12
12
  "usageDashboardUrl": "https://huggingface.co/settings/billing",
13
13
  "webUrl": "https://huggingface.co",
14
14
  "envVars": [
15
15
  "HF_TOKEN",
16
16
  "HUGGINGFACE_COOKIE"
17
17
  ],
18
+ "setupFields": [],
18
19
  "upstream": {
19
20
  "repository": "https://github.com/steipete/CodexBar",
20
- "revision": "6ba06fe9ec1522dd5c59e16810115bce28aa148f",
21
+ "revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
21
22
  "path": "Sources/CodexBarCore/Resources/Plugins/huggingface.js",
22
23
  "sha256": "78cb1bb09535c71f7cb9d1a6336efb4ead44b36a1d4716602c1f7a1e35821291",
23
24
  "license": "MIT"