@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
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
|
+
globalThis.__usagestat_bundled_options = {"labels":["Daily spend limit","Monthly spend limit","Additional"],"defaults":{},"autoMode":"api"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/munito.js
|
|
5
|
+
function _nullishCoalesce(lhs, rhsFn) {
|
|
6
|
+
if (lhs != null) {
|
|
7
|
+
return lhs;
|
|
8
|
+
} else {
|
|
9
|
+
return rhsFn();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
defineProvider({
|
|
13
|
+
id: "munito",
|
|
14
|
+
name: "Munito",
|
|
15
|
+
endpoints: ["https://api.munito.ai"],
|
|
16
|
+
auth: { type: "bearer", secret: "MUNITO_API_KEY" },
|
|
17
|
+
settings: [{ key: "MUNITO_API_KEY", title: "Munito admin API key", type: "secure" }],
|
|
18
|
+
capabilities: ["http-status"],
|
|
19
|
+
async fetchUsage(ctx) {
|
|
20
|
+
const base = "https://api.munito.ai/admin/v1";
|
|
21
|
+
const response = await ctx.http.getWithOptional(`${base}/limits`, `${base}/organization`, {
|
|
22
|
+
retryPolicy: "transientIdempotent",
|
|
23
|
+
});
|
|
24
|
+
const message = `Munito returned HTTP ${response.status}.`;
|
|
25
|
+
if (response.status === 401) throw ctx.fail.authenticationExpired(message);
|
|
26
|
+
if (response.status === 403) {
|
|
27
|
+
throw ctx.fail.permissionDenied(
|
|
28
|
+
"Munito rejected the key: the Admin API needs a key with Read account data permission.",
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
// The native transientIdempotent retry already honors Retry-After; an explicit retry hint
|
|
32
|
+
// here would schedule a second, outer retry cycle (docs/plugins.md plugin retry contract).
|
|
33
|
+
if (response.status === 429) throw ctx.fail.rateLimited(message);
|
|
34
|
+
if (response.status >= 500) throw ctx.fail.providerUnavailable(message);
|
|
35
|
+
if (response.status !== 200) throw ctx.fail.apiFailure(message);
|
|
36
|
+
const fail = () => {
|
|
37
|
+
throw ctx.fail.parseFailure("Munito returned an unrecognized spend limits response.");
|
|
38
|
+
};
|
|
39
|
+
let root;
|
|
40
|
+
try {
|
|
41
|
+
root = JSON.parse(response.bodyText);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
void error;
|
|
44
|
+
return fail();
|
|
45
|
+
}
|
|
46
|
+
if (!root || typeof root !== "object" || Array.isArray(root)) return fail();
|
|
47
|
+
const body = root;
|
|
48
|
+
const text = (value) => (typeof value === "string" && value.trim() ? value.trim() : undefined);
|
|
49
|
+
const money = (value, field) => {
|
|
50
|
+
const number =
|
|
51
|
+
typeof value === "number"
|
|
52
|
+
? value
|
|
53
|
+
: typeof value === "string" && /^\s*-?\d+(?:\.\d+)?\s*$/.test(value)
|
|
54
|
+
? Number(value)
|
|
55
|
+
: NaN;
|
|
56
|
+
if (!Number.isFinite(number) || number < 0) {
|
|
57
|
+
throw ctx.fail.parseFailure(`Munito returned an unusable ${field}.`);
|
|
58
|
+
}
|
|
59
|
+
return number;
|
|
60
|
+
};
|
|
61
|
+
const limit = (value, field) => (value == null ? undefined : money(value, field));
|
|
62
|
+
if (!Array.isArray(body.periods)) return fail();
|
|
63
|
+
|
|
64
|
+
const periods = [];
|
|
65
|
+
for (const raw of body.periods) {
|
|
66
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return fail();
|
|
67
|
+
const entry = raw;
|
|
68
|
+
const kind = text(entry.period);
|
|
69
|
+
if (kind !== "day" && kind !== "month") continue;
|
|
70
|
+
const stopped = text(entry.stopped_until);
|
|
71
|
+
let stoppedUntil;
|
|
72
|
+
if (stopped) {
|
|
73
|
+
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(stopped)) return fail();
|
|
74
|
+
try {
|
|
75
|
+
stoppedUntil = ctx.date.iso(stopped);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
void error;
|
|
78
|
+
return fail();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
periods.push({
|
|
82
|
+
period: kind,
|
|
83
|
+
spent: money(entry.spent_usd, `${kind} spend`),
|
|
84
|
+
limit: limit(entry.limit_usd, `${kind} limit`),
|
|
85
|
+
organizationLimit: limit(entry.organization_limit_usd, `${kind} organization limit`),
|
|
86
|
+
accountLimit: limit(entry.account_limit_usd, `${kind} account limit`),
|
|
87
|
+
stoppedUntil,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const find = (kind) => periods.find((entry) => entry.period === kind);
|
|
91
|
+
const day = find("day");
|
|
92
|
+
const month = find("month");
|
|
93
|
+
// The organization is a best-effort companion read; spend and limits stay authoritative.
|
|
94
|
+
let organization;
|
|
95
|
+
if (response.optional && response.optional.status === 200) {
|
|
96
|
+
try {
|
|
97
|
+
const parsed = JSON.parse(response.optional.bodyText);
|
|
98
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) organization = parsed;
|
|
99
|
+
} catch (error) {
|
|
100
|
+
void error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const usageTier = _nullishCoalesce(text(body.usage_tier), () =>
|
|
104
|
+
organization ? text(organization.usage_tier) : undefined,
|
|
105
|
+
);
|
|
106
|
+
const rows = [];
|
|
107
|
+
const moneyRow = (label, entry) => {
|
|
108
|
+
const spend = ctx.format.usd(entry.spent);
|
|
109
|
+
rows.push({
|
|
110
|
+
label,
|
|
111
|
+
value: entry.limit && entry.limit > 0 ? `${spend} of ${ctx.format.usd(entry.limit)}` : spend,
|
|
112
|
+
progress: entry.limit && entry.limit > 0 ? Math.min(1, entry.spent / entry.limit) : undefined,
|
|
113
|
+
usageValue: entry.spent,
|
|
114
|
+
});
|
|
115
|
+
const organizational =
|
|
116
|
+
entry.organizationLimit != null && entry.organizationLimit > 0 && entry.organizationLimit !== entry.limit
|
|
117
|
+
? entry.organizationLimit
|
|
118
|
+
: undefined;
|
|
119
|
+
const account =
|
|
120
|
+
entry.accountLimit != null && entry.accountLimit > 0 && entry.accountLimit !== entry.limit
|
|
121
|
+
? entry.accountLimit
|
|
122
|
+
: undefined;
|
|
123
|
+
if (organizational != null) {
|
|
124
|
+
rows.push({ label: `${label} organization limit`, value: ctx.format.usd(organizational) });
|
|
125
|
+
}
|
|
126
|
+
if (account != null) {
|
|
127
|
+
rows.push({ label: `${label} account limit`, value: ctx.format.usd(account) });
|
|
128
|
+
}
|
|
129
|
+
if (entry.stoppedUntil) rows.push({ label: `${label} stopped until`, value: entry.stoppedUntil.toISOString() });
|
|
130
|
+
};
|
|
131
|
+
if (day) moneyRow("Today", day);
|
|
132
|
+
if (month) moneyRow("This month", month);
|
|
133
|
+
if (usageTier) rows.push({ label: "Usage tier", value: usageTier });
|
|
134
|
+
const details = [];
|
|
135
|
+
if (rows.length) details.push({ title: "Spend limits", rows });
|
|
136
|
+
const organizationRows = [];
|
|
137
|
+
if (organization) {
|
|
138
|
+
const status = text(organization.status);
|
|
139
|
+
if (status) organizationRows.push({ label: "Status", value: status.charAt(0).toUpperCase() + status.slice(1) });
|
|
140
|
+
const region = text(organization.data_region);
|
|
141
|
+
if (region) organizationRows.push({ label: "Data region", value: region });
|
|
142
|
+
if (organizationRows.length) details.push({ title: "Organization", rows: organizationRows });
|
|
143
|
+
}
|
|
144
|
+
// The identity keeps the card visible even when every period is temporarily absent;
|
|
145
|
+
// spend windows and cost appear only while Munito reports them.
|
|
146
|
+
return {
|
|
147
|
+
primary:
|
|
148
|
+
day && day.limit && day.limit > 0 ? { usedPercent: ctx.pct(day.spent, day.limit), windowMinutes: 1440 } : null,
|
|
149
|
+
secondary: month && month.limit && month.limit > 0 ? { usedPercent: ctx.pct(month.spent, month.limit) } : null,
|
|
150
|
+
cost:
|
|
151
|
+
month != null || day != null
|
|
152
|
+
? {
|
|
153
|
+
used: _nullishCoalesce(month, () => day).spent,
|
|
154
|
+
limit: _nullishCoalesce(_nullishCoalesce(month, () => day).limit, () => 0),
|
|
155
|
+
currency: "USD",
|
|
156
|
+
period: month ? "This month" : "Today",
|
|
157
|
+
}
|
|
158
|
+
: null,
|
|
159
|
+
details,
|
|
160
|
+
identity: {
|
|
161
|
+
organization: organization ? text(organization.name) : undefined,
|
|
162
|
+
accountID: organization ? text(organization.id) : undefined,
|
|
163
|
+
loginMethod: "Admin API key",
|
|
164
|
+
},
|
|
165
|
+
dataConfidence: "exact",
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// END UPSTREAM
|
|
171
|
+
})(globalThis.defineProvider);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "munito",
|
|
4
|
+
"name": "Munito",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"api"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "api",
|
|
12
|
+
"usageDashboardUrl": "https://app.munito.ai",
|
|
13
|
+
"envVars": [
|
|
14
|
+
"MUNITO_API_KEY"
|
|
15
|
+
],
|
|
16
|
+
"setupFields": [],
|
|
17
|
+
"upstream": {
|
|
18
|
+
"repository": "https://github.com/steipete/CodexBar",
|
|
19
|
+
"revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
|
|
20
|
+
"path": "Sources/CodexBarCore/Resources/Plugins/munito.js",
|
|
21
|
+
"sha256": "6feee407bd3765acb723bca995e660ee9dc8d556e51bfdff158686e3ffaf0ffe",
|
|
22
|
+
"license": "MIT"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill="currentColor" d="M6.915 4.03c-1.968 0-3.683 1.28-4.871 3.113C.704 9.208 0 11.883 0 14.449c0 .706.07 1.369.21 1.973a6.624 6.624 0 0 0 .265.86 5.297 5.297 0 0 0 .371.761c.696 1.159 1.818 1.927 3.593 1.927 1.497 0 2.633-.671 3.965-2.444.76-1.012 1.144-1.626 2.663-4.32l.756-1.339.186-.325c.061.1.121.196.183.3l2.152 3.595c.724 1.21 1.665 2.556 2.47 3.314 1.046.987 1.992 1.22 3.06 1.22 1.075 0 1.876-.355 2.455-.843a3.743 3.743 0 0 0 .81-.973c.542-.939.861-2.127.861-3.745 0-2.72-.681-5.357-2.084-7.45-1.282-1.912-2.957-2.93-4.716-2.93-1.047 0-2.088.467-3.053 1.308-.652.57-1.257 1.29-1.82 2.05-.69-.875-1.335-1.547-1.958-2.056-1.182-.966-2.315-1.303-3.454-1.303zm10.16 2.053c1.147 0 2.188.758 2.992 1.999 1.132 1.748 1.647 4.195 1.647 6.4 0 1.548-.368 2.9-1.839 2.9-.58 0-1.027-.23-1.664-1.004-.496-.601-1.343-1.878-2.832-4.358l-.617-1.028a44.908 44.908 0 0 0-1.255-1.98c.07-.109.141-.224.211-.327 1.12-1.667 2.118-2.602 3.358-2.602zm-10.201.553c1.265 0 2.058.791 2.675 1.446.307.327.737.871 1.234 1.579l-1.02 1.566c-.757 1.163-1.882 3.017-2.837 4.338-1.191 1.649-1.81 1.817-2.486 1.817-.524 0-1.038-.237-1.383-.794-.263-.426-.464-1.13-.464-2.046 0-2.221.63-4.535 1.66-6.088.454-.687.964-1.226 1.533-1.533a2.264 2.264 0 0 1 1.088-.285z"/>
|
|
3
|
+
</svg>
|
package/plugins/muse/plugin.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
2
|
globalThis.__usagestat_bundled_options = {"labels":["Session","Weekly","Additional"],"defaults":{},"autoMode":"api"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/muse.js
|
|
3
5
|
function _nullishCoalesce(lhs, rhsFn) {
|
|
4
6
|
if (lhs != null) {
|
|
5
7
|
return lhs;
|
|
@@ -281,3 +283,6 @@ defineProvider({
|
|
|
281
283
|
};
|
|
282
284
|
},
|
|
283
285
|
});
|
|
286
|
+
|
|
287
|
+
// END UPSTREAM
|
|
288
|
+
})(globalThis.defineProvider);
|
package/plugins/muse/plugin.json
CHANGED
|
@@ -16,9 +16,17 @@
|
|
|
16
16
|
"MUSE_WEB_TEAM_ID",
|
|
17
17
|
"MUSE_COOKIE"
|
|
18
18
|
],
|
|
19
|
+
"setupFields": [
|
|
20
|
+
{
|
|
21
|
+
"key": "MUSE_WEB_TEAM_ID",
|
|
22
|
+
"title": "Browser team ID",
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "Provider-specific account or source selection."
|
|
25
|
+
}
|
|
26
|
+
],
|
|
19
27
|
"upstream": {
|
|
20
28
|
"repository": "https://github.com/steipete/CodexBar",
|
|
21
|
-
"revision": "
|
|
29
|
+
"revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
|
|
22
30
|
"path": "Sources/CodexBarCore/Resources/Plugins/muse.js",
|
|
23
31
|
"sha256": "85b6f9489f4e004d027cca1fe2a0a87884792d0be7aa50ef7b8df3b17902c424",
|
|
24
32
|
"license": "MIT"
|
package/plugins/museai/plugin.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
2
|
globalThis.__usagestat_bundled_options = {"labels":["Weekly","Additional tokens","Additional"],"defaults":{},"autoMode":"web","maxRequests":160};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/museai.js
|
|
3
5
|
defineProvider({
|
|
4
6
|
id: "museai",
|
|
5
7
|
name: "Muse (muse.ai)",
|
|
@@ -15,7 +17,8 @@ defineProvider({
|
|
|
15
17
|
if (policy === "off") throw ctx.fail.missingCredential("muse.ai cookies are disabled.");
|
|
16
18
|
const signedOut = (r) =>
|
|
17
19
|
r.status === 401 || r.status === 403 || (r.headers["location"] ?? "").startsWith("https://auth.muse.ai/");
|
|
18
|
-
|
|
20
|
+
// A redeployed muse.ai answers a stale action with 400, 404 or 409 (#5051).
|
|
21
|
+
const actionNeedsRediscovery = (r) => !signedOut(r) && [400, 404, 409].includes(r.status);
|
|
19
22
|
const discoveryFailure = () =>
|
|
20
23
|
ctx.fail.parseFailure(
|
|
21
24
|
"Could not find a working muse.ai subscription action. muse.ai may have changed. Refresh to retry.",
|
|
@@ -32,6 +35,7 @@ defineProvider({
|
|
|
32
35
|
"Sec-Fetch-Site": "same-origin",
|
|
33
36
|
"Sec-Fetch-Mode": "cors",
|
|
34
37
|
"Sec-Fetch-Dest": "empty",
|
|
38
|
+
"Content-Type": "text/plain;charset=UTF-8",
|
|
35
39
|
"User-Agent": userAgent,
|
|
36
40
|
},
|
|
37
41
|
});
|
|
@@ -82,14 +86,14 @@ defineProvider({
|
|
|
82
86
|
let actionID = ctx.storage.get("actionID");
|
|
83
87
|
const subscription = async (cookie) => {
|
|
84
88
|
const response = actionID ? await post(cookie, actionID) : undefined;
|
|
85
|
-
if (response && !
|
|
89
|
+
if (response && !actionNeedsRediscovery(response)) {
|
|
86
90
|
return signedOut(response) ? undefined : response;
|
|
87
91
|
}
|
|
88
92
|
ctx.storage.remove("actionID");
|
|
89
93
|
actionID = await discover(cookie);
|
|
90
94
|
if (!actionID) return undefined;
|
|
91
95
|
const fresh = await post(cookie, actionID);
|
|
92
|
-
if (
|
|
96
|
+
if (actionNeedsRediscovery(fresh)) throw discoveryFailure();
|
|
93
97
|
return signedOut(fresh) ? undefined : fresh;
|
|
94
98
|
};
|
|
95
99
|
|
|
@@ -152,3 +156,6 @@ defineProvider({
|
|
|
152
156
|
};
|
|
153
157
|
},
|
|
154
158
|
});
|
|
159
|
+
|
|
160
|
+
// END UPSTREAM
|
|
161
|
+
})(globalThis.defineProvider);
|
|
@@ -15,11 +15,12 @@
|
|
|
15
15
|
"MUSEAI_COOKIE"
|
|
16
16
|
],
|
|
17
17
|
"setupHelp": "Use a session Cookie header from muse.ai. This provider is separate from Muse Code and does not use its CLI login.",
|
|
18
|
+
"setupFields": [],
|
|
18
19
|
"upstream": {
|
|
19
20
|
"repository": "https://github.com/steipete/CodexBar",
|
|
20
|
-
"revision": "
|
|
21
|
+
"revision": "1f6da9bec44455288ddee5ef6f3617a803d8eb2a",
|
|
21
22
|
"path": "Sources/CodexBarCore/Resources/Plugins/museai.js",
|
|
22
|
-
"sha256": "
|
|
23
|
+
"sha256": "fa82f1936a5b59e16aab91d42e3c3591d3f6b50d65017557a341924095234f1d",
|
|
23
24
|
"license": "MIT"
|
|
24
25
|
}
|
|
25
26
|
}
|
package/plugins/nous/plugin.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
2
|
globalThis.__usagestat_bundled_options = {"labels":["Monthly credits","Weekly","Additional"],"defaults":{"PORTAL_URL":"https://portal.nousresearch.com"},"autoMode":"api"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/nous.js
|
|
3
5
|
function _nullishCoalesce(lhs, rhsFn) {
|
|
4
6
|
if (lhs != null) {
|
|
5
7
|
return lhs;
|
|
@@ -122,3 +124,6 @@ defineProvider({
|
|
|
122
124
|
};
|
|
123
125
|
},
|
|
124
126
|
});
|
|
127
|
+
|
|
128
|
+
// END UPSTREAM
|
|
129
|
+
})(globalThis.defineProvider);
|
package/plugins/nous/plugin.json
CHANGED
|
@@ -14,9 +14,17 @@
|
|
|
14
14
|
"PORTAL_URL",
|
|
15
15
|
"NOUS_PORTAL_ACCESS_TOKEN"
|
|
16
16
|
],
|
|
17
|
+
"setupFields": [
|
|
18
|
+
{
|
|
19
|
+
"key": "PORTAL_URL",
|
|
20
|
+
"title": "Portal URL",
|
|
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/nous.js",
|
|
21
29
|
"sha256": "160f5329bf4895a061d3bed74d0476283d3abad47e071fb868d667c0c5cb485e",
|
|
22
30
|
"license": "MIT"
|
package/plugins/ollama/plugin.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
var SETTINGS_URL = "https://ollama.com/settings";
|
|
3
3
|
var TAGS_URL = "https://ollama.com/api/tags";
|
|
4
4
|
var VALIDATION_URL = "https://ollama.com/api/web_search";
|
|
5
|
+
var BALANCE_URL = "https://ollama.com/api/balance";
|
|
5
6
|
var SESSION_COOKIE = "__Secure-session";
|
|
6
7
|
var SESSION_MS = 5 * 60 * 60 * 1000;
|
|
7
8
|
var WEEK_MS = 7 * 24 * 60 * 60 * 1000;
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
function env(ctx, name) {
|
|
25
|
+
if (ctx.provider && ctx.provider.instanceId && ctx.provider.instanceId !== 'ollama') return null;
|
|
24
26
|
try {
|
|
25
27
|
return clean(ctx.host.env.get(name));
|
|
26
28
|
} catch (_) {
|
|
@@ -89,6 +91,13 @@
|
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
function probeApi(ctx, apiKey) {
|
|
94
|
+
var balanceResponse = request(ctx, {method:'GET',url:BALANCE_URL,
|
|
95
|
+
headers:{Authorization:'Bearer '+apiKey,Accept:'application/json'},timeoutMs:15000});
|
|
96
|
+
if (balanceResponse.status !== 404) {
|
|
97
|
+
if (balanceResponse.status === 401 || balanceResponse.status === 403) throw "Ollama API key is invalid or revoked.";
|
|
98
|
+
if (balanceResponse.status !== 200) throw "Ollama balance API returned HTTP " + balanceResponse.status + ".";
|
|
99
|
+
return balanceResult(ctx, parseJson(ctx,balanceResponse.bodyText));
|
|
100
|
+
}
|
|
92
101
|
var validation = request(ctx, {
|
|
93
102
|
method: "POST",
|
|
94
103
|
url: VALIDATION_URL,
|
|
@@ -147,6 +156,55 @@
|
|
|
147
156
|
};
|
|
148
157
|
}
|
|
149
158
|
|
|
159
|
+
function balanceResult(ctx, payload) {
|
|
160
|
+
var data = payload && payload.data && typeof payload.data === 'object' ? payload.data : payload;
|
|
161
|
+
var fail = function() { throw 'Ollama returned an invalid credit balance response.'; };
|
|
162
|
+
if (!data || typeof data !== 'object' || Array.isArray(data)) return fail();
|
|
163
|
+
var amount = function(value) {
|
|
164
|
+
if (typeof value === 'string' && /^-?\d+(?:\.\d+)?$/.test(value.trim())) value = Number(value);
|
|
165
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : fail();
|
|
166
|
+
};
|
|
167
|
+
var date = function(value) {
|
|
168
|
+
if (value == null) return null;
|
|
169
|
+
if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value)) return fail();
|
|
170
|
+
var parts=value.slice(0,10).split('-').map(Number),ms=Date.parse(value);
|
|
171
|
+
if (!Number.isFinite(ms) || parts[1]<1 || parts[1]>12 || parts[2]<1 || parts[2]>new Date(Date.UTC(parts[0],parts[1],0)).getUTCDate()) return fail();
|
|
172
|
+
return new Date(ms).toISOString();
|
|
173
|
+
};
|
|
174
|
+
var included=data.included,lines=[];
|
|
175
|
+
if (included != null && (typeof included !== 'object' || Array.isArray(included))) return fail();
|
|
176
|
+
if (included && (included.allowance_usd != null || included.balance_usd != null)) {
|
|
177
|
+
var allowance=amount(included.allowance_usd),balance=amount(included.balance_usd);
|
|
178
|
+
if (allowance<0) return fail();
|
|
179
|
+
var used=Math.max(0,allowance-balance),period=included.period;
|
|
180
|
+
if (period!=null && (typeof period!=='object' || Array.isArray(period))) return fail();
|
|
181
|
+
var until=date(period && period.until),from=date(period && period.from);
|
|
182
|
+
if (from && until && Date.parse(until)<=Date.parse(from)) return fail();
|
|
183
|
+
if (allowance>0) lines.push(ctx.line.progress({label:'Monthly credits',used:used,limit:allowance,
|
|
184
|
+
format:{kind:'dollars'},resetsAt:until || undefined,
|
|
185
|
+
periodDurationMs:from && until ? Date.parse(until)-Date.parse(from) : until ? ctx.util.calendarMonthDuration(until) : undefined}));
|
|
186
|
+
else lines.push(ctx.line.text({label:'Monthly allowance',value:'$0.00'}));
|
|
187
|
+
lines.push(ctx.line.text({label:'Monthly remaining',value:'$'+balance.toFixed(2)}));
|
|
188
|
+
}
|
|
189
|
+
var limits=included || data.limits || data;
|
|
190
|
+
for (var spec of [['session','Session',SESSION_MS],['weekly','Weekly',WEEK_MS],['monthly','Monthly',null]]) {
|
|
191
|
+
var window=limits[spec[0]] || limits[spec[0]+'_usage'];
|
|
192
|
+
if (!window) continue;
|
|
193
|
+
var raw=window.used_percent ?? window.usedPercent ?? window.percent ?? window.percentage;
|
|
194
|
+
var percent;
|
|
195
|
+
if (raw!=null) percent=amount(raw);
|
|
196
|
+
else if (window.remaining_percent!=null || window.remainingPercent!=null) percent=100-amount(window.remaining_percent ?? window.remainingPercent);
|
|
197
|
+
else if (window.usage!=null) {percent=amount(window.usage);if(percent<=1) percent*=100;}
|
|
198
|
+
else continue;
|
|
199
|
+
if (percent<0) return fail();
|
|
200
|
+
lines.push(ctx.line.progress({label:spec[1],used:percent,limit:100,format:{kind:'percent'},
|
|
201
|
+
periodDurationMs:spec[2] || undefined,resetsAt:date(window.resets_at || window.resetsAt) || undefined}));
|
|
202
|
+
}
|
|
203
|
+
if (data.purchased!=null) lines.push(ctx.line.text({label:'Purchased credits',value:'$'+amount(data.purchased.balance_usd).toFixed(2)}));
|
|
204
|
+
if (!lines.length) return fail();
|
|
205
|
+
return {displayName:'Ollama',source:'api',plan:typeof data.plan==='string' ? ctx.fmt.planLabel(data.plan) : 'API key',lines:lines};
|
|
206
|
+
}
|
|
207
|
+
|
|
150
208
|
function blockEnd(html, start, currentLabel) {
|
|
151
209
|
var labels = ["Monthly usage", "Session usage", "Hourly usage", "Weekly usage"];
|
|
152
210
|
var end = html.length;
|
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
monthly: 60,
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
const TABLES_SQL = "SELECT name FROM sqlite_master WHERE type = 'table' AND name IN ('message','session_message','credential')";
|
|
15
|
+
const TABLES_SQL = "SELECT name FROM sqlite_master WHERE type = 'table' AND name IN ('message','session_message','credential','migration')";
|
|
16
|
+
const CREDENTIALS_IMPORTED_SQL = "SELECT 1 AS imported FROM migration WHERE id = '20260805200742_import_legacy_credentials' LIMIT 1";
|
|
16
17
|
const CREDENTIAL_SQL = `SELECT value FROM credential
|
|
17
|
-
WHERE integration_id = 'opencode-go' AND (active IS NULL OR active = 1)
|
|
18
|
-
|
|
18
|
+
WHERE (integration_id = 'opencode-go' AND (active IS NULL OR active = 1))
|
|
19
|
+
OR (integration_id = 'opencode' AND active = 1)
|
|
20
|
+
ORDER BY CASE integration_id WHEN 'opencode-go' THEN 0 ELSE 1 END, active DESC, time_updated DESC, id DESC LIMIT 1`;
|
|
19
21
|
function historySQL(tables) {
|
|
20
22
|
const sources = [];
|
|
21
23
|
if (tables.includes('session_message')) sources.push(`SELECT id, time_created, data FROM session_message
|
|
@@ -328,15 +330,19 @@
|
|
|
328
330
|
const configured = trim(ctx.provider && ctx.provider.apiKey) || env(ctx, "OPENCODE_GO_API_KEY");
|
|
329
331
|
if (configured) return configured;
|
|
330
332
|
const inline = ctx.host.env.get("OPENCODE_AUTH_CONTENT");
|
|
331
|
-
//
|
|
332
|
-
//
|
|
333
|
+
// OpenCode 1 also creates credential tables, but still signs in through
|
|
334
|
+
// auth.json. Only the completed v2 import makes database logout authoritative.
|
|
333
335
|
if (!inline) {
|
|
334
336
|
const database = databasePath(ctx);
|
|
335
337
|
if (ctx.host.fs.exists(database)) {
|
|
336
338
|
try {
|
|
337
339
|
const tables = ctx.util.tryParseJson(ctx.host.sqlite.query(database, TABLES_SQL));
|
|
338
340
|
if (!Array.isArray(tables)) throw new Error('Invalid schema');
|
|
339
|
-
|
|
341
|
+
const imported = tables.some(table => table.name === 'migration')
|
|
342
|
+
? ctx.util.tryParseJson(ctx.host.sqlite.query(database, CREDENTIALS_IMPORTED_SQL)) : [];
|
|
343
|
+
if (!Array.isArray(imported)) throw new Error('Invalid migration result');
|
|
344
|
+
if (imported.length) {
|
|
345
|
+
if (!tables.some(table => table.name === 'credential')) throw new Error('Imported credential storage is missing');
|
|
340
346
|
const rows = ctx.util.tryParseJson(ctx.host.sqlite.query(database, CREDENTIAL_SQL));
|
|
341
347
|
if (!Array.isArray(rows)) throw new Error('Invalid credential result');
|
|
342
348
|
if (!rows.length) return null;
|
|
@@ -362,7 +368,7 @@
|
|
|
362
368
|
if (inline) throw {code: "credential-malformed", message: "OPENCODE_AUTH_CONTENT must contain an auth JSON object."};
|
|
363
369
|
throw {code:'credential-malformed',message:'OpenCode auth file is not valid JSON.'};
|
|
364
370
|
}
|
|
365
|
-
const entry = parsed[PROVIDER_ID];
|
|
371
|
+
const entry = parsed[PROVIDER_ID] || parsed.opencode;
|
|
366
372
|
if (!entry || typeof entry !== "object") return null;
|
|
367
373
|
const key = typeof entry.key === "string" ? entry.key.trim() : "";
|
|
368
374
|
return key || null;
|
|
@@ -622,6 +628,9 @@
|
|
|
622
628
|
if (ctx.util.isAuthStatus(result.resp.status)) throw "OpenCode Go key was rejected. Sign into OpenCode Go again.";
|
|
623
629
|
if (result.resp.status < 200 || result.resp.status >= 300) throw "OpenCode Go usage API returned HTTP " + result.resp.status + ".";
|
|
624
630
|
const usage = result.json && result.json.usage;
|
|
631
|
+
const dateHeader = Object.entries(result.resp.headers || {}).find(([key]) => key.toLowerCase() === 'date');
|
|
632
|
+
const serverTime = dateHeader && Date.parse(dateHeader[1]);
|
|
633
|
+
const referenceTime = Number.isFinite(serverTime) ? serverTime : Date.parse(ctx.nowIso);
|
|
625
634
|
const specs = [["rolling", "Session", FIVE_HOURS_MS], ["weekly", "Weekly", WEEK_MS], ["monthly", "Monthly", null]];
|
|
626
635
|
const lines = [];
|
|
627
636
|
for (const spec of specs) {
|
|
@@ -630,8 +639,11 @@
|
|
|
630
639
|
const percent = window && readNumber(window.percent);
|
|
631
640
|
if (!Number.isFinite(percent)) throw "OpenCode Go usage API returned an invalid quota.";
|
|
632
641
|
const resetInSec = readNumber(window.resetInSec);
|
|
633
|
-
|
|
634
|
-
? ctx.util.toIso(
|
|
642
|
+
let resetsAt = ctx.util.toIso(window.resetsAt) || (resetInSec !== null && resetInSec >= 0
|
|
643
|
+
? ctx.util.toIso(referenceTime + resetInSec * 1000) : null);
|
|
644
|
+
if (window.resetsAt != null && !ctx.util.toIso(window.resetsAt)) throw 'OpenCode Go usage API returned an invalid reset.';
|
|
645
|
+
if (spec[0] === 'rolling' && percent === 0 && resetsAt && Math.abs(Date.parse(resetsAt)-referenceTime-FIVE_HOURS_MS)<=2000)
|
|
646
|
+
resetsAt = null;
|
|
635
647
|
lines.push(ctx.line.progress({ label: spec[1], used: Math.max(0, Math.min(100, percent)), limit: 100,
|
|
636
648
|
format: { kind: "percent" }, resetsAt, periodDurationMs: spec[2] }));
|
|
637
649
|
}
|
|
@@ -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="100 100 385 385" fill="currentColor">
|
|
2
|
+
<path fill-rule="evenodd" d="M292.716 112.374C392.751 112.374 473.845 193.468 473.845 293.503C473.845 393.538 392.751 474.632 292.716 474.632H135.685C122.347 474.632 111.587 463.874 111.587 450.536C111.587 410.139 111.587 329.633 111.587 293.503C111.587 193.468 192.681 112.374 292.716 112.374ZM292.716 148.6C212.689 148.6 147.813 213.476 147.813 293.504C147.813 373.532 212.689 438.407 292.716 438.407C372.744 438.407 437.619 373.532 437.619 293.504C437.619 213.476 372.744 148.6 292.716 148.6Z"/>
|
|
3
|
+
<path d="M281.618 378.232L226.395 232.908C224.608 228.205 229.201 223.594 233.873 225.402L379.265 281.651C385.249 283.966 383.6 292.898 377.189 292.898H292.803V376.155C292.803 382.61 283.91 384.262 281.618 378.232Z"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
|
+
globalThis.__usagestat_bundled_options = {"labels":["Session","Weekly","Additional"],"defaults":{},"autoMode":"web"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/opendesign.js
|
|
5
|
+
defineProvider({
|
|
6
|
+
id: "opendesign",
|
|
7
|
+
name: "OpenDesign",
|
|
8
|
+
settings: [{ key: "MESSAGES", title: "OpenDesign", type: "plain" }],
|
|
9
|
+
endpoints: ["https://amr-api.open-design.ai"],
|
|
10
|
+
capabilities: ["browser-cookies", "http-status"],
|
|
11
|
+
cookieDomains: ["amr-api.open-design.ai"],
|
|
12
|
+
cookiePolicy: {
|
|
13
|
+
selection: "request-url",
|
|
14
|
+
cache: "nonpersistent",
|
|
15
|
+
imports: "access-gated",
|
|
16
|
+
// The host's optional name filter excludes dots; validate the opaque session at the endpoint.
|
|
17
|
+
},
|
|
18
|
+
async fetchUsage(ctx) {
|
|
19
|
+
const domain = "amr-api.open-design.ai";
|
|
20
|
+
const messages = JSON.parse(ctx.settings.get("MESSAGES") || "{}");
|
|
21
|
+
const message = (key) => messages[key] || key;
|
|
22
|
+
const signIn = message("Sign in to OpenDesign, then refresh CodexBar.");
|
|
23
|
+
const expired = ctx.fail.authenticationExpired(signIn);
|
|
24
|
+
const malformed = () => {
|
|
25
|
+
throw ctx.fail.parseFailure(message("OpenDesign usage response format changed."));
|
|
26
|
+
};
|
|
27
|
+
const text = (value) => (typeof value === "string" && value.trim() ? value.trim() : undefined);
|
|
28
|
+
const credits = (value) => {
|
|
29
|
+
if (typeof value === "string" && /^\d+(\.\d+)?$/.test(value)) value = Number(value);
|
|
30
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= Number.MAX_SAFE_INTEGER
|
|
31
|
+
? value
|
|
32
|
+
: malformed();
|
|
33
|
+
};
|
|
34
|
+
if (ctx.browser.availability(domain) === "off") throw ctx.fail.missingCredential(signIn);
|
|
35
|
+
let rejected = false;
|
|
36
|
+
for await (const session of ctx.browser.sessions(domain)) {
|
|
37
|
+
const get = async (path, workspace) => {
|
|
38
|
+
const response = await ctx.http.get(`https://${domain}/api/v1/workspaces/${path}`, {
|
|
39
|
+
cookieSession: session.id,
|
|
40
|
+
headers: { Accept: "application/json", ...(workspace ? { "X-Vela-Workspace-Id": workspace } : {}) },
|
|
41
|
+
});
|
|
42
|
+
if (response.status === 401) throw expired;
|
|
43
|
+
if (response.status === 403) throw ctx.fail.permissionDenied(message("OpenDesign billing access was denied."));
|
|
44
|
+
const failed = message("OpenDesign request failed. Try again later.");
|
|
45
|
+
if (response.status === 429) throw ctx.fail.rateLimited(failed);
|
|
46
|
+
if (response.status >= 500 || response.status === 408) throw ctx.fail.providerUnavailable(failed);
|
|
47
|
+
if (response.status !== 200) throw ctx.fail.apiFailure(failed);
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(response.bodyText);
|
|
50
|
+
} catch {
|
|
51
|
+
return malformed();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
try {
|
|
55
|
+
const workspace = await get("current");
|
|
56
|
+
const id = text(workspace?.workspaceId);
|
|
57
|
+
if (!id || !/^[A-Za-z0-9_-]{1,128}$/.test(id)) return malformed();
|
|
58
|
+
const usage = await get(`${id}/billing/coding-plan-usage`, id);
|
|
59
|
+
if (usage?.workspaceId !== id || typeof usage.eligible !== "boolean" || !Array.isArray(usage.windows))
|
|
60
|
+
return malformed();
|
|
61
|
+
const unavailable = () => {
|
|
62
|
+
throw ctx.fail.providerUnavailable(
|
|
63
|
+
message("OpenDesign subscription usage is unavailable for this workspace."),
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
if (!usage.eligible) return unavailable();
|
|
67
|
+
const window = (seconds) => {
|
|
68
|
+
const matches = usage.windows.filter((item) => item?.durationSeconds === seconds);
|
|
69
|
+
if (matches.length === 0) return undefined;
|
|
70
|
+
if (matches.length !== 1) return malformed();
|
|
71
|
+
const item = matches[0];
|
|
72
|
+
const used = credits(item.usedCredits);
|
|
73
|
+
const limit = credits(item.limitCredits);
|
|
74
|
+
if (limit <= 0) return malformed();
|
|
75
|
+
const reset = text(item.resetsAt);
|
|
76
|
+
return {
|
|
77
|
+
usedPercent: ctx.pct(used, limit),
|
|
78
|
+
windowMinutes: seconds / 60,
|
|
79
|
+
quotaLimit: limit,
|
|
80
|
+
quotaUnit: "credits",
|
|
81
|
+
resetsAt:
|
|
82
|
+
reset && /^\d{4}-\d{2}-\d{2}T/.test(reset) && Number.isFinite(Date.parse(reset)) ? reset : undefined,
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
const primary = window(18000);
|
|
86
|
+
const secondary = window(604800);
|
|
87
|
+
if (!primary && !secondary) return unavailable();
|
|
88
|
+
return {
|
|
89
|
+
primary,
|
|
90
|
+
secondary,
|
|
91
|
+
identity: {
|
|
92
|
+
accountID: id,
|
|
93
|
+
organization: text(workspace.workspaceName),
|
|
94
|
+
loginMethod: text(usage.tier) ?? text(workspace.personalMembershipTier),
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
} catch (error) {
|
|
98
|
+
if (error !== expired) throw error;
|
|
99
|
+
ctx.browser.rejectCookie(domain, session);
|
|
100
|
+
rejected = true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
throw rejected ? expired : ctx.fail.missingCredential(signIn);
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// END UPSTREAM
|
|
108
|
+
})(globalThis.defineProvider);
|