@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.
- package/native-manifest.json +808 -148
- package/package.json +112 -2
- package/plugins/abliteration/LICENSE +21 -0
- package/plugins/abliteration/icon.svg +5 -0
- package/plugins/abliteration/plugin.js +89 -0
- package/plugins/abliteration/plugin.json +24 -0
- package/plugins/aerostack/LICENSE +21 -0
- package/plugins/aerostack/icon.svg +1 -0
- package/plugins/aerostack/plugin.js +94 -0
- package/plugins/aerostack/plugin.json +24 -0
- package/plugins/aixy/icon.svg +1 -0
- package/plugins/aixy/plugin.js +5 -0
- package/plugins/aixy/plugin.json +9 -1
- package/plugins/antigravity/plugin.js +19 -10
- package/plugins/antigravity-cli/plugin.js +8 -3
- package/plugins/antigravity-ide/plugin.js +8 -5
- package/plugins/atlascloud/plugin.js +5 -0
- package/plugins/atlascloud/plugin.json +2 -1
- package/plugins/bifrost/icon.svg +3 -0
- package/plugins/bifrost/plugin.js +5 -0
- package/plugins/bifrost/plugin.json +9 -1
- package/plugins/chatbox/LICENSE +21 -0
- package/plugins/chatbox/icon.svg +4 -0
- package/plugins/chatbox/plugin.js +208 -0
- package/plugins/chatbox/plugin.json +24 -0
- package/plugins/claude/plugin.js +39 -2
- package/plugins/claudeplatform/LICENSE +21 -0
- package/plugins/claudeplatform/icon.svg +3 -0
- package/plugins/claudeplatform/plugin.js +244 -0
- package/plugins/claudeplatform/plugin.json +25 -0
- package/plugins/codex/plugin.js +14 -8
- package/plugins/codex/plugin.json +11 -2
- package/plugins/cosmic/LICENSE +21 -0
- package/plugins/cosmic/icon.svg +1 -0
- package/plugins/cosmic/plugin.js +134 -0
- package/plugins/cosmic/plugin.json +32 -0
- package/plugins/cursor/plugin.js +27 -8
- package/plugins/cursor-nightly/plugin.json +1 -1
- package/plugins/devpass/icon.svg +3 -0
- package/plugins/devpass/plugin.js +5 -0
- package/plugins/devpass/plugin.json +2 -1
- package/plugins/exa/LICENSE +21 -0
- package/plugins/exa/icon-color.svg +1 -0
- package/plugins/exa/icon.svg +1 -0
- package/plugins/exa/plugin.js +75 -0
- package/plugins/exa/plugin.json +32 -0
- package/plugins/fal/LICENSE +21 -0
- package/plugins/fal/icon-color.svg +1 -0
- package/plugins/fal/icon.svg +1 -0
- package/plugins/fal/plugin.js +74 -0
- package/plugins/fal/plugin.json +24 -0
- package/plugins/flora/LICENSE +21 -0
- package/plugins/flora/icon.svg +4 -0
- package/plugins/flora/plugin.js +93 -0
- package/plugins/flora/plugin.json +32 -0
- package/plugins/futureagi/LICENSE +21 -0
- package/plugins/futureagi/icon.svg +24 -0
- package/plugins/futureagi/plugin.js +139 -0
- package/plugins/futureagi/plugin.json +32 -0
- package/plugins/gemini-apps/LICENSE +1 -2
- package/plugins/gemini-apps/plugin.js +136 -465
- package/plugins/gemini-apps/plugin.json +13 -7
- package/plugins/gitkraken/icon.svg +2 -0
- package/plugins/gitkraken/plugin.js +5 -0
- package/plugins/gitkraken/plugin.json +9 -1
- package/plugins/googledeveloper/LICENSE +21 -0
- package/plugins/googledeveloper/icon.svg +3 -0
- package/plugins/googledeveloper/plugin.js +204 -0
- package/plugins/googledeveloper/plugin.json +25 -0
- package/plugins/helmcode/icon.svg +5 -0
- package/plugins/helmcode/plugin.js +120 -55
- package/plugins/helmcode/plugin.json +10 -2
- package/plugins/huggingface/plugin.js +6 -1
- package/plugins/huggingface/plugin.json +4 -3
- package/plugins/hyper/plugin.js +53 -47
- package/plugins/hyper/plugin.json +3 -2
- package/plugins/jetbrains-ai-assistant/LICENSE +22 -0
- package/plugins/jetbrains-ai-assistant/plugin.js +502 -16
- package/plugins/jetbrains-ai-assistant/plugin.json +27 -4
- package/plugins/kimi/plugin.js +54 -14
- package/plugins/kimi/plugin.json +46 -6
- package/plugins/langdock/LICENSE +21 -0
- package/plugins/langdock/icon.svg +4 -0
- package/plugins/langdock/plugin.js +106 -0
- package/plugins/langdock/plugin.json +25 -0
- package/plugins/linkup/LICENSE +21 -0
- package/plugins/linkup/icon.svg +10 -0
- package/plugins/linkup/plugin.js +46 -0
- package/plugins/linkup/plugin.json +24 -0
- package/plugins/lithosai/plugin.js +5 -0
- package/plugins/lithosai/plugin.json +2 -1
- package/plugins/llmman/icon.svg +4 -0
- package/plugins/llmman/plugin.js +5 -0
- package/plugins/llmman/plugin.json +9 -1
- package/plugins/munito/LICENSE +21 -0
- package/plugins/munito/icon.svg +7 -0
- package/plugins/munito/plugin.js +171 -0
- package/plugins/munito/plugin.json +24 -0
- package/plugins/muse/icon.svg +3 -0
- package/plugins/muse/plugin.js +5 -0
- package/plugins/muse/plugin.json +9 -1
- package/plugins/museai/plugin.js +10 -3
- package/plugins/museai/plugin.json +3 -2
- package/plugins/nous/plugin.js +5 -0
- package/plugins/nous/plugin.json +9 -1
- package/plugins/ollama/plugin.js +58 -0
- package/plugins/opencode-go/plugin.js +21 -9
- package/plugins/opendesign/LICENSE +21 -0
- package/plugins/opendesign/icon.svg +4 -0
- package/plugins/opendesign/plugin.js +108 -0
- package/plugins/opendesign/plugin.json +25 -0
- package/plugins/parallel/LICENSE +21 -0
- package/plugins/parallel/icon.svg +11 -0
- package/plugins/parallel/plugin.js +97 -0
- package/plugins/parallel/plugin.json +25 -0
- package/plugins/perplexity/LICENSE +22 -0
- package/plugins/perplexity/plugin.js +122 -0
- package/plugins/perplexity/plugin.json +36 -7
- package/plugins/qwencloud/LICENSE +21 -0
- package/plugins/qwencloud/plugin.js +197 -0
- package/plugins/qwencloud/plugin.json +17 -0
- package/plugins/raycast/icon.svg +4 -0
- package/plugins/raycast/plugin.js +5 -0
- package/plugins/raycast/plugin.json +9 -1
- package/plugins/replicate/plugin.js +5 -0
- package/plugins/replicate/plugin.json +2 -1
- package/plugins/sailresearch/LICENSE +21 -0
- package/plugins/sailresearch/icon.svg +4 -0
- package/plugins/sailresearch/plugin.js +104 -0
- package/plugins/sailresearch/plugin.json +24 -0
- package/plugins/siliconflow/LICENSE +21 -0
- package/plugins/siliconflow/icon.svg +3 -0
- package/plugins/siliconflow/plugin.js +87 -0
- package/plugins/siliconflow/plugin.json +32 -0
- package/plugins/sofya/LICENSE +21 -0
- package/plugins/sofya/icon.svg +3 -0
- package/plugins/sofya/plugin.js +86 -0
- package/plugins/sofya/plugin.json +24 -0
- package/plugins/soniox/LICENSE +21 -0
- package/plugins/soniox/icon.svg +3 -0
- package/plugins/soniox/plugin.js +103 -0
- package/plugins/soniox/plugin.json +24 -0
- package/plugins/synthetic/plugin.js +12 -0
- package/plugins/synthetic/plugin.json +51 -9
- package/plugins/tavily/LICENSE +21 -0
- package/plugins/tavily/icon.svg +3 -0
- package/plugins/tavily/plugin.js +61 -0
- package/plugins/tavily/plugin.json +24 -0
- package/plugins/tinyapi/LICENSE +21 -0
- package/plugins/tinyapi/icon.svg +4 -0
- package/plugins/tinyapi/plugin.js +73 -0
- package/plugins/tinyapi/plugin.json +25 -0
- package/plugins/traecn/LICENSE +21 -0
- package/plugins/traecn/icon.svg +3 -0
- package/plugins/traecn/plugin.js +103 -0
- package/plugins/traecn/plugin.json +25 -0
- package/plugins/tripo/LICENSE +21 -0
- package/plugins/tripo/icon.svg +4 -0
- package/plugins/tripo/plugin.js +60 -0
- package/plugins/tripo/plugin.json +24 -0
- package/plugins/typesafe/icon.svg +4 -0
- package/plugins/typesafe/plugin.js +85 -129
- package/plugins/typesafe/plugin.json +3 -2
- package/plugins/v0/plugin.js +5 -0
- package/plugins/v0/plugin.json +9 -1
- package/plugins/vercel/plugin.js +147 -0
- package/plugins/vercel/plugin.json +34 -3
- package/plugins/workbuddy/icon.svg +1 -1
- package/plugins/workbuddy/plugin.js +110 -19
- package/plugins/workbuddy/plugin.json +32 -2
- package/plugins/xai/plugin.js +9 -0
- package/plugins/xapi/LICENSE +21 -0
- package/plugins/xapi/icon.svg +1 -0
- package/plugins/xapi/plugin.js +90 -0
- package/plugins/xapi/plugin.json +25 -0
- package/plugins/xkiro/icon.svg +1 -0
- package/plugins/xkiro/plugin.js +5 -0
- package/plugins/xkiro/plugin.json +2 -1
- package/usagestat +0 -0
- package/usagestatd +0 -0
- package/plugins/cursor-nightly/plugin.js +0 -1416
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
2
|
globalThis.__usagestat_bundled_options = {"labels":["Credits","Plan","Additional"],"defaults":{},"autoMode":"web"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/raycast.js
|
|
3
5
|
function _nullishCoalesce(lhs, rhsFn) {
|
|
4
6
|
if (lhs != null) {
|
|
5
7
|
return lhs;
|
|
@@ -172,3 +174,6 @@ defineProvider({
|
|
|
172
174
|
};
|
|
173
175
|
},
|
|
174
176
|
});
|
|
177
|
+
|
|
178
|
+
// END UPSTREAM
|
|
179
|
+
})(globalThis.defineProvider);
|
|
@@ -14,9 +14,17 @@
|
|
|
14
14
|
"envVars": [
|
|
15
15
|
"RAYCAST_COOKIE"
|
|
16
16
|
],
|
|
17
|
+
"setupFields": [
|
|
18
|
+
{
|
|
19
|
+
"key": "webTimeoutSeconds",
|
|
20
|
+
"title": "Web timeout",
|
|
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": "
|
|
27
|
+
"revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
|
|
20
28
|
"path": "Sources/CodexBarCore/Resources/Plugins/raycast.js",
|
|
21
29
|
"sha256": "df8f6d185cb67fd9ec9b622d2321a6d4e5395576b9ab54b1725aac272c95ecb7",
|
|
22
30
|
"license": "MIT"
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
2
|
globalThis.__usagestat_bundled_options = {"labels":["Spend","Spend","Additional"],"defaults":{},"autoMode":"web"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/replicate.js
|
|
3
5
|
function _optionalChain(ops) {
|
|
4
6
|
let lastAccessLHS = undefined;
|
|
5
7
|
let value = ops[0];
|
|
@@ -163,3 +165,6 @@ defineProvider({
|
|
|
163
165
|
};
|
|
164
166
|
},
|
|
165
167
|
});
|
|
168
|
+
|
|
169
|
+
// END UPSTREAM
|
|
170
|
+
})(globalThis.defineProvider);
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
"envVars": [
|
|
15
15
|
"REPLICATE_COOKIE"
|
|
16
16
|
],
|
|
17
|
+
"setupFields": [],
|
|
17
18
|
"upstream": {
|
|
18
19
|
"repository": "https://github.com/steipete/CodexBar",
|
|
19
|
-
"revision": "
|
|
20
|
+
"revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
|
|
20
21
|
"path": "Sources/CodexBarCore/Resources/Plugins/replicate.js",
|
|
21
22
|
"sha256": "d240c36fa142ee91ce90ae52a2c6814613d2d5533a00c8a4c7ecec2f9386006c",
|
|
22
23
|
"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,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 167 149">
|
|
2
|
+
<path fill="#000" d="M165.371.267c-6.511 13.076-45.948 89.68-104.083 147.779-.316.315-.093.856.354.856h104.182a.5.5 0 0 0 .5-.5V.528c0-.532-.716-.737-.953 0Z"/>
|
|
3
|
+
<path fill="#000" d="M87.497 49.707C81.025 58.66 40.157 114.303.178 148.022c-.357.301-.141.88.327.88h87.428c.276 0 .45-.224.45-.5V50.041c0-.487-.601-.728-.886-.334Z"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
|
+
globalThis.__usagestat_bundled_options = {"labels":["Balance","Additional","Additional"],"defaults":{},"autoMode":"api"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/sailresearch.js
|
|
5
|
+
function _nullishCoalesce(lhs, rhsFn) {
|
|
6
|
+
if (lhs != null) {
|
|
7
|
+
return lhs;
|
|
8
|
+
} else {
|
|
9
|
+
return rhsFn();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function _optionalChain(ops) {
|
|
13
|
+
let lastAccessLHS = undefined;
|
|
14
|
+
let value = ops[0];
|
|
15
|
+
let i = 1;
|
|
16
|
+
while (i < ops.length) {
|
|
17
|
+
const op = ops[i];
|
|
18
|
+
const fn = ops[i + 1];
|
|
19
|
+
i += 2;
|
|
20
|
+
if ((op === "optionalAccess" || op === "optionalCall") && value == null) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
if (op === "access" || op === "optionalAccess") {
|
|
24
|
+
lastAccessLHS = value;
|
|
25
|
+
value = fn(value);
|
|
26
|
+
} else if (op === "call" || op === "optionalCall") {
|
|
27
|
+
value = fn((...args) => value.call(lastAccessLHS, ...args));
|
|
28
|
+
lastAccessLHS = undefined;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
defineProvider({
|
|
34
|
+
id: "sailresearch",
|
|
35
|
+
name: "Sail Research",
|
|
36
|
+
endpoints: ["https://api.sailresearch.com"],
|
|
37
|
+
auth: { type: "bearer", secret: "SAIL_API_KEY" },
|
|
38
|
+
settings: [{ key: "SAIL_API_KEY", title: "Sail Research API key", type: "secure" }],
|
|
39
|
+
capabilities: ["http-status"],
|
|
40
|
+
async fetchUsage(ctx) {
|
|
41
|
+
const response = await ctx.http.get("https://api.sailresearch.com/v2/usage/summary?range=30d");
|
|
42
|
+
const message = `Sail Research returned HTTP ${response.status}.`;
|
|
43
|
+
if (response.status === 401) throw ctx.fail.authenticationExpired(message);
|
|
44
|
+
if (response.status === 402)
|
|
45
|
+
throw ctx.fail.apiFailure("Sail Research disabled this API key because credits are exhausted.");
|
|
46
|
+
if (response.status === 403) throw ctx.fail.permissionDenied("Sail Research API key has no organization access.");
|
|
47
|
+
if (response.status === 429) {
|
|
48
|
+
const delay = Number(_nullishCoalesce(response.headers["retry-after"], () => 1));
|
|
49
|
+
throw ctx.fail.rateLimited(message, {
|
|
50
|
+
retryAfterSeconds: Number.isFinite(delay) && delay >= 0 ? Math.min(delay, 10) : 1,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (response.status >= 500) throw ctx.fail.providerUnavailable(message);
|
|
54
|
+
if (response.status !== 200) throw ctx.fail.apiFailure(message);
|
|
55
|
+
function fail() {
|
|
56
|
+
throw ctx.fail.parseFailure("Sail Research returned an unrecognized billing summary.");
|
|
57
|
+
}
|
|
58
|
+
let data;
|
|
59
|
+
try {
|
|
60
|
+
data = JSON.parse(response.bodyText);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
void error;
|
|
63
|
+
return fail();
|
|
64
|
+
}
|
|
65
|
+
if (
|
|
66
|
+
_optionalChain([data, "optionalAccess", (_) => _.object]) !== "usage.summary" ||
|
|
67
|
+
typeof data.available !== "boolean"
|
|
68
|
+
)
|
|
69
|
+
return fail();
|
|
70
|
+
if (!data.available) throw ctx.fail.providerUnavailable("Sail Research billing data is unavailable.");
|
|
71
|
+
if (typeof data.has_metronome_customer !== "boolean") return fail();
|
|
72
|
+
if (!data.has_metronome_customer) throw ctx.fail.apiFailure("Sail Research organization has no billing account.");
|
|
73
|
+
if (typeof data.balance_unavailable !== "boolean") return fail();
|
|
74
|
+
function dollars(key) {
|
|
75
|
+
const value = data[key];
|
|
76
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fail();
|
|
77
|
+
return value / 100;
|
|
78
|
+
}
|
|
79
|
+
const spend = dollars("period_spend");
|
|
80
|
+
if (spend < 0) return fail();
|
|
81
|
+
const rangeLabels = {
|
|
82
|
+
"1h": "Last hour spend",
|
|
83
|
+
"6h": "Last 6 hours spend",
|
|
84
|
+
"24h": "Last 24 hours spend",
|
|
85
|
+
"7d": "Last 7 days spend",
|
|
86
|
+
"30d": "Last 30 days spend",
|
|
87
|
+
period: "Billing-period spend",
|
|
88
|
+
};
|
|
89
|
+
const rangeLabel = typeof data.effective_range === "string" ? rangeLabels[data.effective_range] : null;
|
|
90
|
+
if (typeof rangeLabel !== "string") return fail();
|
|
91
|
+
const rows = [
|
|
92
|
+
{ label: "Credit balance", value: data.balance_unavailable ? "Unavailable" : ctx.format.usd(dollars("balance")) },
|
|
93
|
+
{ label: rangeLabel, value: ctx.format.usd(spend) },
|
|
94
|
+
];
|
|
95
|
+
return {
|
|
96
|
+
details: [{ title: "Organization billing", rows }],
|
|
97
|
+
identity: { loginMethod: "API key" },
|
|
98
|
+
dataConfidence: "exact",
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// END UPSTREAM
|
|
104
|
+
})(globalThis.defineProvider);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "sailresearch",
|
|
4
|
+
"name": "Sail Research",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"api"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "api",
|
|
12
|
+
"usageDashboardUrl": "https://sailresearch.com",
|
|
13
|
+
"envVars": [
|
|
14
|
+
"SAIL_API_KEY"
|
|
15
|
+
],
|
|
16
|
+
"setupFields": [],
|
|
17
|
+
"upstream": {
|
|
18
|
+
"repository": "https://github.com/steipete/CodexBar",
|
|
19
|
+
"revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
|
|
20
|
+
"path": "Sources/CodexBarCore/Resources/Plugins/sailresearch.js",
|
|
21
|
+
"sha256": "3823be0a067659d6ae8dc4691e1b346cc7c7656e7f57134c12d898babcebb809",
|
|
22
|
+
"license": "MIT"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Peter Steinberger
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-3 -17 59 59">
|
|
2
|
+
<path d="M50.7172 0H27.6622C26.3877 0 25.3586 1.03397 25.3586 2.30358V9.21911C25.3586 10.4935 24.3294 11.5227 23.055 11.5227H2.30357C1.02914 11.5227 0 12.5567 0 13.8263V23.0502C0 24.3246 1.03395 25.3538 2.30357 25.3538H25.3586C26.633 25.3538 27.6622 24.3198 27.6622 23.0502V16.1347C27.6622 14.8602 28.6913 13.8311 29.9657 13.8311H50.7172C51.9916 13.8311 53.0207 12.7971 53.0207 11.5275V2.30358C53.0207 1.02916 51.9868 0 50.7172 0Z" fill="currentColor"/>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
|
+
globalThis.__usagestat_bundled_options = {"labels":["Balance","Additional","Additional"],"defaults":{"SILICONFLOW_BASE_URL":"https://api.siliconflow.com"},"autoMode":"api"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/siliconflow.js
|
|
5
|
+
defineProvider({
|
|
6
|
+
id: "siliconflow",
|
|
7
|
+
name: "SiliconFlow",
|
|
8
|
+
endpoints: ["https://api.siliconflow.cn", "https://api.siliconflow.com"],
|
|
9
|
+
auth: { type: "bearer", secret: "SILICONFLOW_API_KEY" },
|
|
10
|
+
settings: [
|
|
11
|
+
{ key: "SILICONFLOW_API_KEY", title: "API key", type: "secure" },
|
|
12
|
+
{ key: "SILICONFLOW_BASE_URL", title: "API URL", type: "plain" },
|
|
13
|
+
{ key: "MESSAGES", title: "SiliconFlow", type: "plain" },
|
|
14
|
+
],
|
|
15
|
+
capabilities: ["http-status"],
|
|
16
|
+
async fetchUsage(ctx) {
|
|
17
|
+
const messages = JSON.parse(ctx.settings.get("MESSAGES") || "{}");
|
|
18
|
+
const message = (key) => messages[key] || key;
|
|
19
|
+
const origin = ctx.settings.get("SILICONFLOW_BASE_URL");
|
|
20
|
+
const currency =
|
|
21
|
+
origin === "https://api.siliconflow.cn" ? "CNY" : origin === "https://api.siliconflow.com" ? "USD" : "";
|
|
22
|
+
if (!currency) {
|
|
23
|
+
throw ctx.fail.apiFailure(
|
|
24
|
+
message("SiliconFlow API origin must be https://api.siliconflow.cn or https://api.siliconflow.com."),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
const response = await ctx.http.get(`${origin}/v1/user/info`, {
|
|
28
|
+
headers: { Accept: "application/json" },
|
|
29
|
+
});
|
|
30
|
+
// The China balance API was retired on 2026-08-14; its balance is read from the console web source instead.
|
|
31
|
+
const retired = message(
|
|
32
|
+
currency === "CNY"
|
|
33
|
+
? "The SiliconFlow China balance API was retired. Switch SiliconFlow to Web and sign in to cloud.siliconflow.cn."
|
|
34
|
+
: "SiliconFlow refused the balance query. Check the balance in the SiliconFlow console.",
|
|
35
|
+
);
|
|
36
|
+
const checkKey = message("Check your API key in Settings.");
|
|
37
|
+
const tryLater = message("SiliconFlow request failed. Try refreshing later.");
|
|
38
|
+
if (response.status === 410) throw ctx.fail.providerUnavailable(retired);
|
|
39
|
+
if (response.status === 401 || response.status === 403) throw ctx.fail.authenticationExpired(checkKey);
|
|
40
|
+
if (response.status === 429)
|
|
41
|
+
throw ctx.fail.rateLimited(message("SiliconFlow is rate limiting requests. Try again later."));
|
|
42
|
+
if (response.status >= 500) throw ctx.fail.providerUnavailable(tryLater);
|
|
43
|
+
if (response.status !== 200) throw ctx.fail.apiFailure(tryLater);
|
|
44
|
+
const fail = () => {
|
|
45
|
+
throw ctx.fail.parseFailure(
|
|
46
|
+
message("SiliconFlow returned an unrecognized response. Update CodexBar and try again."),
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
const record = (value) => (value && typeof value === "object" && !Array.isArray(value) ? value : undefined);
|
|
50
|
+
let decoded;
|
|
51
|
+
try {
|
|
52
|
+
decoded = JSON.parse(response.bodyText);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
void error;
|
|
55
|
+
return fail();
|
|
56
|
+
}
|
|
57
|
+
const root = record(decoded);
|
|
58
|
+
if (!root || typeof root.code !== "number" || !Number.isInteger(root.code)) return fail();
|
|
59
|
+
if (root.code === 20092) throw ctx.fail.providerUnavailable(retired);
|
|
60
|
+
if (root.code === 30014) throw ctx.fail.authenticationExpired(checkKey);
|
|
61
|
+
if (root.code !== 20000 || root.status !== true) return fail();
|
|
62
|
+
const data = record(root.data);
|
|
63
|
+
if (!data) return fail();
|
|
64
|
+
const money = (value) => {
|
|
65
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
66
|
+
if (typeof value !== "string" || !/^-?(?:\d+|\d+\.\d+)$/.test(value)) return fail();
|
|
67
|
+
const amount = Number(value);
|
|
68
|
+
return Number.isFinite(amount) ? amount : fail();
|
|
69
|
+
};
|
|
70
|
+
const rows = [{ label: "Balance", value: ctx.format.currency(money(data.totalBalance), currency) }];
|
|
71
|
+
if (data.chargeBalance !== undefined && data.chargeBalance !== null) {
|
|
72
|
+
rows.push({ label: "Purchased", value: ctx.format.currency(money(data.chargeBalance), currency) });
|
|
73
|
+
}
|
|
74
|
+
if (data.balance !== undefined && data.balance !== null) {
|
|
75
|
+
rows.push({ label: "Bonus", value: ctx.format.currency(money(data.balance), currency) });
|
|
76
|
+
}
|
|
77
|
+
const status = data.status;
|
|
78
|
+
if (status !== undefined && status !== null) {
|
|
79
|
+
if (typeof status !== "string" || !/^[A-Za-z0-9_-]{1,32}$/.test(status)) return fail();
|
|
80
|
+
if (status !== "normal") rows.push({ label: "Status", value: status });
|
|
81
|
+
}
|
|
82
|
+
return { details: [{ title: "Balance", rows }], dataConfidence: "exact" };
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// END UPSTREAM
|
|
87
|
+
})(globalThis.defineProvider);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "siliconflow",
|
|
4
|
+
"name": "SiliconFlow",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"api"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "api",
|
|
12
|
+
"usageDashboardUrl": "https://cloud.siliconflow.com",
|
|
13
|
+
"envVars": [
|
|
14
|
+
"SILICONFLOW_API_KEY",
|
|
15
|
+
"SILICONFLOW_BASE_URL"
|
|
16
|
+
],
|
|
17
|
+
"setupFields": [
|
|
18
|
+
{
|
|
19
|
+
"key": "SILICONFLOW_BASE_URL",
|
|
20
|
+
"title": "API URL",
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Provider-specific account or source selection."
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"upstream": {
|
|
26
|
+
"repository": "https://github.com/steipete/CodexBar",
|
|
27
|
+
"revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
|
|
28
|
+
"path": "Sources/CodexBarCore/Resources/Plugins/siliconflow.js",
|
|
29
|
+
"sha256": "8525a5a8f02749119930b9d814e987ccdab308827de016355c8ae34136325a86",
|
|
30
|
+
"license": "MIT"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -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,86 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
|
+
globalThis.__usagestat_bundled_options = {"labels":["Credits","Additional","Additional"],"defaults":{},"autoMode":"api"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/sofya.js
|
|
5
|
+
function _nullishCoalesce(lhs, rhsFn) {
|
|
6
|
+
if (lhs != null) {
|
|
7
|
+
return lhs;
|
|
8
|
+
} else {
|
|
9
|
+
return rhsFn();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
defineProvider({
|
|
13
|
+
id: "sofya",
|
|
14
|
+
name: "Sofya",
|
|
15
|
+
endpoints: ["https://sofya.co"],
|
|
16
|
+
auth: { type: "bearer", secret: "SOFYA_API_KEY" },
|
|
17
|
+
settings: [{ key: "SOFYA_API_KEY", title: "Sofya API key", type: "secure" }],
|
|
18
|
+
capabilities: ["http-status"],
|
|
19
|
+
async fetchUsage(ctx) {
|
|
20
|
+
const response = await ctx.http.get("https://sofya.co/v1/auth/me");
|
|
21
|
+
const message = `Sofya returned HTTP ${response.status}.`;
|
|
22
|
+
if (response.status === 401) throw ctx.fail.authenticationExpired(message);
|
|
23
|
+
if (response.status === 403) throw ctx.fail.permissionDenied(message);
|
|
24
|
+
if (response.status === 429) {
|
|
25
|
+
const delay = Number(_nullishCoalesce(response.headers["retry-after"], () => 1));
|
|
26
|
+
throw ctx.fail.rateLimited(message, {
|
|
27
|
+
retryAfterSeconds: Number.isFinite(delay) && delay >= 0 ? Math.min(delay, 10) : 1,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (response.status >= 500) throw ctx.fail.providerUnavailable(message);
|
|
31
|
+
if (response.status !== 200) throw ctx.fail.apiFailure(message);
|
|
32
|
+
function fail() {
|
|
33
|
+
throw ctx.fail.parseFailure("Sofya returned an unrecognized account credit response.");
|
|
34
|
+
}
|
|
35
|
+
let data;
|
|
36
|
+
try {
|
|
37
|
+
data = JSON.parse(response.bodyText);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
void error;
|
|
40
|
+
return fail();
|
|
41
|
+
}
|
|
42
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) return fail();
|
|
43
|
+
const rows = [];
|
|
44
|
+
for (const [key, label] of [
|
|
45
|
+
["credits", "Available credits"],
|
|
46
|
+
["plan_credits", "Plan credits"],
|
|
47
|
+
["purchased_credits", "Purchased credits"],
|
|
48
|
+
]) {
|
|
49
|
+
const value = data[key];
|
|
50
|
+
if (value === null || value === undefined) continue;
|
|
51
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return fail();
|
|
52
|
+
rows.push({ label, value: ctx.format.number(value, { maximumFractionDigits: 6 }) });
|
|
53
|
+
}
|
|
54
|
+
if (!rows.length) return fail();
|
|
55
|
+
const eligible = data.is_free_tier;
|
|
56
|
+
if (eligible !== undefined && eligible !== null && typeof eligible !== "boolean") return fail();
|
|
57
|
+
const reset = data.credits_reset_at;
|
|
58
|
+
if (reset !== undefined && reset !== null) {
|
|
59
|
+
if (
|
|
60
|
+
typeof reset !== "string" ||
|
|
61
|
+
!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(reset)
|
|
62
|
+
)
|
|
63
|
+
return fail();
|
|
64
|
+
const date = new Date(reset);
|
|
65
|
+
const [year, month, day] = reset.slice(0, 10).split("-").map(Number);
|
|
66
|
+
if (!Number.isFinite(date.getTime()) || day > new Date(Date.UTC(year, month, 0)).getUTCDate()) return fail();
|
|
67
|
+
if (eligible === true) {
|
|
68
|
+
rows.push({
|
|
69
|
+
label: "Monthly reset",
|
|
70
|
+
value: date
|
|
71
|
+
.toISOString()
|
|
72
|
+
.replace("T", " ")
|
|
73
|
+
.replace(/(?:\.000)?Z$/, " UTC"),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
details: [{ title: "Account credits", rows }],
|
|
79
|
+
identity: { loginMethod: eligible === true ? "Free tier" : eligible === false ? "Pay as you go" : "API" },
|
|
80
|
+
dataConfidence: "exact",
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// END UPSTREAM
|
|
86
|
+
})(globalThis.defineProvider);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "sofya",
|
|
4
|
+
"name": "Sofya",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"api"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "api",
|
|
12
|
+
"usageDashboardUrl": "https://sofya.co",
|
|
13
|
+
"envVars": [
|
|
14
|
+
"SOFYA_API_KEY"
|
|
15
|
+
],
|
|
16
|
+
"setupFields": [],
|
|
17
|
+
"upstream": {
|
|
18
|
+
"repository": "https://github.com/steipete/CodexBar",
|
|
19
|
+
"revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
|
|
20
|
+
"path": "Sources/CodexBarCore/Resources/Plugins/sofya.js",
|
|
21
|
+
"sha256": "4190c42d42a1b70b6ed284821ef7803420564b4b020e939e60d79e4b0991c281",
|
|
22
|
+
"license": "MIT"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Peter Steinberger
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-4 -3 23 23" fill="currentColor">
|
|
2
|
+
<path d="m0 14.866 2.1606-3.5214c1.8927 1.2576 3.9669 1.8995 5.6694 1.8995 1.0025 0 1.4606-0.3036 1.4606-0.8847v-0.0607c0-0.6419-0.9161-0.9194-2.6532-1.4138-3.2582-0.8587-5.8509-1.9602-5.8509-5.2995v-0.06938c0-3.5214 2.8088-5.4903 6.6114-5.4903 2.4112 0 4.9089 0.70255 6.8016 1.9342l-1.9791 3.6775c-1.7112-0.95408-3.5693-1.5352-4.8744-1.5352-0.88152 0-1.3396 0.33827-1.3396 0.79796v0.06071c0 0.64184 0.94202 0.95409 2.6792 1.4745 3.2582 0.91939 5.8509 2.0556 5.8509 5.2735v0.0607c0 3.6515-2.7137 5.551-6.741 5.551-2.7656-0.0087-5.5052-0.798-7.7955-2.4546z"/>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
|
+
globalThis.__usagestat_bundled_options = {"labels":["Monthly budget","Additional","Additional"],"defaults":{},"autoMode":"api"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/soniox.js
|
|
5
|
+
defineProvider({
|
|
6
|
+
id: "soniox",
|
|
7
|
+
name: "Soniox",
|
|
8
|
+
endpoints: ["https://api.soniox.com"],
|
|
9
|
+
auth: { type: "bearer", secret: "SONIOX_ORG_API_KEY" },
|
|
10
|
+
settings: [{ key: "SONIOX_ORG_API_KEY", title: "Organization API key", type: "secure" }],
|
|
11
|
+
async fetchUsage(ctx) {
|
|
12
|
+
const invalid = (field) => {
|
|
13
|
+
throw ctx.fail.parseFailure(
|
|
14
|
+
`Soniox returned invalid billing data: ${field}. Refresh to try again. If this persists, update CodexBar or report the issue.`,
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
const money = (value, field, signed = false) => {
|
|
18
|
+
if (typeof value !== "string" || !/^-?\d+(?:\.\d+)?$/.test(value.trim())) return invalid(field);
|
|
19
|
+
const amount = Number(value);
|
|
20
|
+
if (!Number.isFinite(amount) || (!signed && amount < 0)) return invalid(field);
|
|
21
|
+
return amount;
|
|
22
|
+
};
|
|
23
|
+
const get = async (path) => {
|
|
24
|
+
const response = await ctx.http.get(`https://api.soniox.com/v1/organization/${path}`);
|
|
25
|
+
if (response.status === 401) {
|
|
26
|
+
throw ctx.fail.authenticationExpired(
|
|
27
|
+
"Soniox rejected the organization API key. Check that it has not been revoked.",
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
if (response.status === 403) {
|
|
31
|
+
throw ctx.fail.permissionDenied(
|
|
32
|
+
"Soniox requires an organization API key with Balance and spend and Usage and limits access. Project API keys are not supported.",
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
if (response.status === 429) {
|
|
36
|
+
throw ctx.fail.rateLimited("Soniox rate limit reached (HTTP 429). Wait a moment, then refresh.");
|
|
37
|
+
}
|
|
38
|
+
if (response.status >= 500) {
|
|
39
|
+
throw ctx.fail.providerUnavailable(
|
|
40
|
+
`Soniox is temporarily unavailable (HTTP ${response.status}). Try again later or check https://status.soniox.com.`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (response.status !== 200) {
|
|
44
|
+
throw ctx.fail.apiFailure(
|
|
45
|
+
`Soniox billing request failed (HTTP ${response.status}). Refresh to try again. If this persists, update CodexBar or report the issue.`,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
let data;
|
|
49
|
+
try {
|
|
50
|
+
data = JSON.parse(response.bodyText);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
void error;
|
|
53
|
+
return invalid("invalid JSON");
|
|
54
|
+
}
|
|
55
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) return invalid("expected an object");
|
|
56
|
+
return data;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const billing = await get("balance");
|
|
60
|
+
const available = money(billing.available_balance_usd, "available_balance_usd", true);
|
|
61
|
+
if (typeof billing.invoice_billing_enabled !== "boolean") return invalid("invoice_billing_enabled");
|
|
62
|
+
const monthly = await get("usage/monthly");
|
|
63
|
+
const used = money(monthly.usage_usd, "usage_usd");
|
|
64
|
+
const budget = money(monthly.monthly_budget_usd, "monthly_budget_usd");
|
|
65
|
+
if (typeof monthly.month !== "string" || !/^\d{4}-(0[1-9]|1[0-2])$/.test(monthly.month)) {
|
|
66
|
+
return invalid("month");
|
|
67
|
+
}
|
|
68
|
+
const resetsAt = new Date(`${monthly.month}-01T00:00:00Z`);
|
|
69
|
+
resetsAt.setUTCMonth(resetsAt.getUTCMonth() + 1);
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
primary:
|
|
73
|
+
budget > 0
|
|
74
|
+
? {
|
|
75
|
+
usedPercent: ctx.pct(used, budget),
|
|
76
|
+
resetsAt,
|
|
77
|
+
resetDescription: `${ctx.format.usd(used)} / ${ctx.format.usd(budget)}`,
|
|
78
|
+
}
|
|
79
|
+
: undefined,
|
|
80
|
+
cost: {
|
|
81
|
+
used,
|
|
82
|
+
limit: budget,
|
|
83
|
+
currency: "USD",
|
|
84
|
+
period: "This month",
|
|
85
|
+
resetsAt,
|
|
86
|
+
balance: billing.invoice_billing_enabled ? undefined : available,
|
|
87
|
+
},
|
|
88
|
+
details: [
|
|
89
|
+
{
|
|
90
|
+
title: "Billing",
|
|
91
|
+
rows: [
|
|
92
|
+
{ label: billing.invoice_billing_enabled ? "Invoice billing" : "Prepaid", value: "USD" },
|
|
93
|
+
...(budget === 0 ? [{ label: "Monthly budget", value: ctx.format.usd(budget) }] : []),
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
dataConfidence: "exact",
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// END UPSTREAM
|
|
103
|
+
})(globalThis.defineProvider);
|