@hashimkarim/usagestat-linux-x64-gnu 2.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +57744 -0
- package/native-manifest.json +1414 -0
- package/package.json +254 -0
- package/plugins/abacus-ai/icon.svg +18 -0
- package/plugins/abacus-ai/plugin.js +121 -0
- package/plugins/abacus-ai/plugin.json +17 -0
- package/plugins/alibaba/icon-color.svg +1 -0
- package/plugins/alibaba/icon.svg +1 -0
- package/plugins/alibaba/plugin.js +322 -0
- package/plugins/alibaba/plugin.json +20 -0
- package/plugins/alibaba-token-plan/icon-color.svg +1 -0
- package/plugins/alibaba-token-plan/icon.svg +1 -0
- package/plugins/alibaba-token-plan/plugin.js +544 -0
- package/plugins/alibaba-token-plan/plugin.json +19 -0
- package/plugins/amp/icon-color.svg +1 -0
- package/plugins/amp/icon-conflict.svg +6 -0
- package/plugins/amp/icon.svg +1 -0
- package/plugins/amp/plugin.js +175 -0
- package/plugins/amp/plugin.json +16 -0
- package/plugins/antigravity/icon-color.svg +1 -0
- package/plugins/antigravity/icon-conflict.svg +3 -0
- package/plugins/antigravity/icon.svg +1 -0
- package/plugins/antigravity/plugin.js +739 -0
- package/plugins/antigravity/plugin.json +31 -0
- package/plugins/antigravity-cli/icon.svg +3 -0
- package/plugins/antigravity-cli/plugin.js +570 -0
- package/plugins/antigravity-cli/plugin.json +16 -0
- package/plugins/antigravity-ide/icon.svg +3 -0
- package/plugins/antigravity-ide/plugin.js +257 -0
- package/plugins/antigravity-ide/plugin.json +29 -0
- package/plugins/augment/icon.svg +14 -0
- package/plugins/augment/plugin.js +59 -0
- package/plugins/augment/plugin.json +18 -0
- package/plugins/aws-bedrock/icon-color.svg +1 -0
- package/plugins/aws-bedrock/icon.svg +1 -0
- package/plugins/aws-bedrock/plugin.js +206 -0
- package/plugins/aws-bedrock/plugin.json +18 -0
- package/plugins/azure-openai/icon-color.svg +1 -0
- package/plugins/azure-openai/icon.svg +1 -0
- package/plugins/azure-openai/plugin.js +145 -0
- package/plugins/azure-openai/plugin.json +17 -0
- package/plugins/chutes/icon.svg +7 -0
- package/plugins/chutes/plugin.js +236 -0
- package/plugins/chutes/plugin.json +19 -0
- package/plugins/claude/icon-color.svg +1 -0
- package/plugins/claude/icon.svg +1 -0
- package/plugins/claude/plugin.js +1723 -0
- package/plugins/claude/plugin.json +30 -0
- package/plugins/codebuff/icon.svg +92 -0
- package/plugins/codebuff/plugin.js +113 -0
- package/plugins/codebuff/plugin.json +17 -0
- package/plugins/codex/icon-color.svg +5 -0
- package/plugins/codex/icon.svg +1 -0
- package/plugins/codex/plugin.js +1009 -0
- package/plugins/codex/plugin.json +82 -0
- package/plugins/command-code/icon.svg +3 -0
- package/plugins/command-code/plugin.js +184 -0
- package/plugins/command-code/plugin.json +20 -0
- package/plugins/copilot/icon-color.svg +1 -0
- package/plugins/copilot/icon.svg +1 -0
- package/plugins/copilot/plugin.js +684 -0
- package/plugins/copilot/plugin.json +21 -0
- package/plugins/crof/icon.svg +3 -0
- package/plugins/crof/plugin.js +53 -0
- package/plugins/crof/plugin.json +17 -0
- package/plugins/crofai/icon.svg +16 -0
- package/plugins/crofai/plugin.js +81 -0
- package/plugins/crofai/plugin.json +18 -0
- package/plugins/cursor/icon-conflict.svg +3 -0
- package/plugins/cursor/icon.svg +1 -0
- package/plugins/cursor/plugin.js +1379 -0
- package/plugins/cursor/plugin.json +23 -0
- package/plugins/cursor-nightly/icon.png +0 -0
- package/plugins/cursor-nightly/plugin.js +1379 -0
- package/plugins/cursor-nightly/plugin.json +23 -0
- package/plugins/deepgram/icon.svg +1 -0
- package/plugins/deepgram/plugin.js +20 -0
- package/plugins/deepgram/plugin.json +17 -0
- package/plugins/deepseek/icon-color.svg +1 -0
- package/plugins/deepseek/icon.svg +1 -0
- package/plugins/deepseek/plugin.js +71 -0
- package/plugins/deepseek/plugin.json +17 -0
- package/plugins/devin/icon.svg +5 -0
- package/plugins/devin/plugin.js +341 -0
- package/plugins/devin/plugin.json +16 -0
- package/plugins/doubao/icon-color.svg +1 -0
- package/plugins/doubao/icon.svg +1 -0
- package/plugins/doubao/plugin.js +92 -0
- package/plugins/doubao/plugin.json +17 -0
- package/plugins/droid/icon.svg +1 -0
- package/plugins/droid/plugin.json +20 -0
- package/plugins/elevenlabs/icon.svg +4 -0
- package/plugins/elevenlabs/plugin.js +48 -0
- package/plugins/elevenlabs/plugin.json +18 -0
- package/plugins/factory/icon-conflict.svg +1 -0
- package/plugins/factory/icon.svg +1 -0
- package/plugins/factory/plugin.js +487 -0
- package/plugins/factory/plugin.json +15 -0
- package/plugins/fireworks-ai/icon.svg +6 -0
- package/plugins/fireworks-ai/plugin.js +370 -0
- package/plugins/fireworks-ai/plugin.json +19 -0
- package/plugins/gemini/icon-color.svg +1 -0
- package/plugins/gemini/icon.svg +1 -0
- package/plugins/gemini/plugin.js +460 -0
- package/plugins/gemini/plugin.json +16 -0
- package/plugins/grok/icon.svg +1 -0
- package/plugins/grok/plugin.js +297 -0
- package/plugins/grok/plugin.json +19 -0
- package/plugins/groqcloud/icon.svg +1 -0
- package/plugins/groqcloud/plugin.js +117 -0
- package/plugins/groqcloud/plugin.json +19 -0
- package/plugins/jetbrains-ai-assistant/icon-color.svg +14 -0
- package/plugins/jetbrains-ai-assistant/icon-conflict.svg +3 -0
- package/plugins/jetbrains-ai-assistant/icon.svg +14 -0
- package/plugins/jetbrains-ai-assistant/plugin.js +313 -0
- package/plugins/jetbrains-ai-assistant/plugin.json +16 -0
- package/plugins/kilo/icon.svg +1 -0
- package/plugins/kilo/plugin.js +111 -0
- package/plugins/kilo/plugin.json +19 -0
- package/plugins/kimi/icon-color.svg +1 -0
- package/plugins/kimi/icon-conflict.svg +3 -0
- package/plugins/kimi/icon.svg +1 -0
- package/plugins/kimi/plugin.js +358 -0
- package/plugins/kimi/plugin.json +15 -0
- package/plugins/kimi-k2/icon-color.svg +1 -0
- package/plugins/kimi-k2/icon.svg +1 -0
- package/plugins/kimi-k2/plugin.js +58 -0
- package/plugins/kimi-k2/plugin.json +18 -0
- package/plugins/kiro/icon-color.svg +5 -0
- package/plugins/kiro/icon-conflict.svg +1 -0
- package/plugins/kiro/icon.svg +4 -0
- package/plugins/kiro/plugin.js +390 -0
- package/plugins/kiro/plugin.json +16 -0
- package/plugins/litellm/icon.svg +16 -0
- package/plugins/litellm/plugin.js +199 -0
- package/plugins/litellm/plugin.json +16 -0
- package/plugins/llm-proxy/icon.svg +1 -0
- package/plugins/llm-proxy/plugin.js +40 -0
- package/plugins/llm-proxy/plugin.json +17 -0
- package/plugins/manus/icon.svg +6 -0
- package/plugins/manus/plugin.js +50 -0
- package/plugins/manus/plugin.json +17 -0
- package/plugins/mimo/icon.svg +1 -0
- package/plugins/mimo/plugin.js +177 -0
- package/plugins/mimo/plugin.json +19 -0
- package/plugins/minimax/icon-color.svg +1 -0
- package/plugins/minimax/icon-conflict.svg +4 -0
- package/plugins/minimax/icon.svg +1 -0
- package/plugins/minimax/plugin.js +453 -0
- package/plugins/minimax/plugin.json +14 -0
- package/plugins/mistral/icon-color.svg +1 -0
- package/plugins/mistral/icon.svg +1 -0
- package/plugins/mistral/plugin.js +152 -0
- package/plugins/mistral/plugin.json +18 -0
- package/plugins/moonshot/icon.svg +1 -0
- package/plugins/moonshot/plugin.js +43 -0
- package/plugins/moonshot/plugin.json +16 -0
- package/plugins/nanogpt/icon-color.svg +17 -0
- package/plugins/nanogpt/icon.svg +10 -0
- package/plugins/nanogpt/plugin.js +80 -0
- package/plugins/nanogpt/plugin.json +17 -0
- package/plugins/neuralwatt/icon.svg +3 -0
- package/plugins/neuralwatt/plugin.js +152 -0
- package/plugins/neuralwatt/plugin.json +17 -0
- package/plugins/ollama/icon.svg +1 -0
- package/plugins/ollama/plugin.js +92 -0
- package/plugins/ollama/plugin.json +20 -0
- package/plugins/openai-api/icon.svg +1 -0
- package/plugins/openai-api/plugin.js +533 -0
- package/plugins/openai-api/plugin.json +26 -0
- package/plugins/opencode/icon.svg +1 -0
- package/plugins/opencode/plugin.js +342 -0
- package/plugins/opencode/plugin.json +19 -0
- package/plugins/opencode-go/icon-conflict.svg +1 -0
- package/plugins/opencode-go/icon.svg +1 -0
- package/plugins/opencode-go/plugin.js +617 -0
- package/plugins/opencode-go/plugin.json +50 -0
- package/plugins/openrouter/icon.svg +1 -0
- package/plugins/openrouter/plugin.js +156 -0
- package/plugins/openrouter/plugin.json +8 -0
- package/plugins/perplexity/icon-color.svg +1 -0
- package/plugins/perplexity/icon-conflict.svg +1 -0
- package/plugins/perplexity/icon.svg +1 -0
- package/plugins/perplexity/plugin.js +425 -0
- package/plugins/perplexity/plugin.json +19 -0
- package/plugins/poe/icon.svg +1 -0
- package/plugins/poe/plugin.js +190 -0
- package/plugins/poe/plugin.json +19 -0
- package/plugins/stepfun/icon-color.svg +1 -0
- package/plugins/stepfun/icon.svg +1 -0
- package/plugins/stepfun/plugin.js +155 -0
- package/plugins/stepfun/plugin.json +18 -0
- package/plugins/synthetic/icon-conflict.svg +12 -0
- package/plugins/synthetic/icon.svg +14 -0
- package/plugins/synthetic/plugin.js +331 -0
- package/plugins/synthetic/plugin.json +23 -0
- package/plugins/t3chat/icon-color.svg +28 -0
- package/plugins/t3chat/icon.svg +4 -0
- package/plugins/t3chat/plugin.js +243 -0
- package/plugins/t3chat/plugin.json +20 -0
- package/plugins/venice/icon-color.svg +1 -0
- package/plugins/venice/icon.svg +1 -0
- package/plugins/venice/plugin.js +69 -0
- package/plugins/venice/plugin.json +16 -0
- package/plugins/vertex-ai/icon-color.svg +1 -0
- package/plugins/vertex-ai/icon.svg +1 -0
- package/plugins/vertex-ai/plugin.js +172 -0
- package/plugins/vertex-ai/plugin.json +18 -0
- package/plugins/warp/icon-color.svg +10 -0
- package/plugins/warp/icon.svg +6 -0
- package/plugins/warp/plugin.js +108 -0
- package/plugins/warp/plugin.json +18 -0
- package/plugins/windsurf/icon-conflict.svg +3 -0
- package/plugins/windsurf/icon.svg +1 -0
- package/plugins/windsurf/plugin.js +208 -0
- package/plugins/windsurf/plugin.json +16 -0
- package/plugins/zai/icon-conflict.svg +5 -0
- package/plugins/zai/icon.svg +1 -0
- package/plugins/zai/plugin.js +188 -0
- package/plugins/zai/plugin.json +16 -0
- package/plugins/zed/icon.svg +4 -0
- package/plugins/zed/plugin.js +270 -0
- package/plugins/zed/plugin.json +19 -0
- package/usagestat +0 -0
- package/usagestatd +0 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var BASE_URL = "https://opencode.ai";
|
|
3
|
+
var SERVER_URL = "https://opencode.ai/_server";
|
|
4
|
+
var WORKSPACES_SERVER_ID = "def39973159c7f0483d8793a822b8dbb10d067e12c65455fcb4608459ba0234f";
|
|
5
|
+
var SUBSCRIPTION_SERVER_ID = "7abeebee372f304e050aaaf92be863f4a86490e382f8c79db68fd94040d691b4";
|
|
6
|
+
var FIVE_HOURS_MS = 5 * 60 * 60 * 1000;
|
|
7
|
+
var WEEK_MS = 7 * 24 * 60 * 60 * 1000;
|
|
8
|
+
var PERCENT_KEYS = [
|
|
9
|
+
"usagePercent", "usedPercent", "percentUsed", "percent", "usage_percent", "used_percent",
|
|
10
|
+
"utilization", "utilizationPercent", "utilization_percent", "usage",
|
|
11
|
+
];
|
|
12
|
+
var RESET_IN_KEYS = [
|
|
13
|
+
"resetInSec", "resetInSeconds", "resetSeconds", "reset_sec", "reset_in_sec",
|
|
14
|
+
"resetsInSec", "resetsInSeconds", "resetIn", "resetSec",
|
|
15
|
+
];
|
|
16
|
+
var RESET_AT_KEYS = [
|
|
17
|
+
"resetAt", "resetsAt", "reset_at", "resets_at", "nextReset", "next_reset", "renewAt", "renew_at",
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
function trim(value) {
|
|
21
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function env(ctx, name) {
|
|
25
|
+
try {
|
|
26
|
+
return trim(ctx.host.env.get(name));
|
|
27
|
+
} catch (_) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function setting(ctx, names) {
|
|
33
|
+
var settings = ctx.provider && ctx.provider.settings ? ctx.provider.settings : {};
|
|
34
|
+
for (var i = 0; i < names.length; i++) {
|
|
35
|
+
var value = trim(settings[names[i]]);
|
|
36
|
+
if (value) return value;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function cookieHeader(ctx) {
|
|
42
|
+
var cookie = trim(ctx.provider && ctx.provider.cookieHeader) ||
|
|
43
|
+
setting(ctx, ["cookieHeader", "cookie"]) ||
|
|
44
|
+
env(ctx, "OPENCODE_COOKIE");
|
|
45
|
+
if (!cookie) throw "OpenCode session not configured. Set OPENCODE_COOKIE.";
|
|
46
|
+
return cookie;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function workspaceOverride(ctx) {
|
|
50
|
+
return normalizeWorkspaceId(
|
|
51
|
+
setting(ctx, ["workspaceId", "workspace"]) ||
|
|
52
|
+
(ctx.provider && trim(ctx.provider.workspaceId)) ||
|
|
53
|
+
env(ctx, "OPENCODE_WORKSPACE_ID") ||
|
|
54
|
+
env(ctx, "CODEXBAR_OPENCODE_WORKSPACE_ID")
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function normalizeWorkspaceId(raw) {
|
|
59
|
+
var text = trim(raw);
|
|
60
|
+
if (!text) return null;
|
|
61
|
+
var match = /wrk_[A-Za-z0-9]+/.exec(text);
|
|
62
|
+
return match ? match[0] : null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function serverInstance() {
|
|
66
|
+
return "server-fn:" + Math.random().toString(16).slice(2) + Date.now().toString(16);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function serverRequest(ctx, opts) {
|
|
70
|
+
var method = opts.method || "GET";
|
|
71
|
+
var url = SERVER_URL;
|
|
72
|
+
if (method === "GET") {
|
|
73
|
+
url += "?id=" + encodeURIComponent(opts.serverId);
|
|
74
|
+
if (opts.args && opts.args.length) url += "&args=" + encodeURIComponent(JSON.stringify(opts.args));
|
|
75
|
+
}
|
|
76
|
+
var req = {
|
|
77
|
+
method: method,
|
|
78
|
+
url: url,
|
|
79
|
+
headers: {
|
|
80
|
+
Cookie: opts.cookie,
|
|
81
|
+
"X-Server-Id": opts.serverId,
|
|
82
|
+
"X-Server-Instance": serverInstance(),
|
|
83
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
|
|
84
|
+
Origin: BASE_URL,
|
|
85
|
+
Referer: opts.referer,
|
|
86
|
+
Accept: "text/javascript, application/json;q=0.9, */*;q=0.8",
|
|
87
|
+
},
|
|
88
|
+
timeoutMs: 15000,
|
|
89
|
+
};
|
|
90
|
+
if (method !== "GET") {
|
|
91
|
+
req.headers["Content-Type"] = "application/json";
|
|
92
|
+
req.bodyText = JSON.stringify(opts.args || []);
|
|
93
|
+
}
|
|
94
|
+
var resp = ctx.util.request(req);
|
|
95
|
+
var text = String(resp.bodyText || "");
|
|
96
|
+
if (looksSignedOut(text) || ctx.util.isAuthStatus(resp.status)) {
|
|
97
|
+
throw "OpenCode session cookie is invalid or expired.";
|
|
98
|
+
}
|
|
99
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
100
|
+
throw "OpenCode API error: HTTP " + resp.status + ".";
|
|
101
|
+
}
|
|
102
|
+
return text;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function looksSignedOut(text) {
|
|
106
|
+
var lower = String(text || "").toLowerCase();
|
|
107
|
+
return lower.indexOf("login") >= 0 || lower.indexOf("sign in") >= 0 || lower.indexOf("auth/authorize") >= 0;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function collectWorkspaceIds(value, out) {
|
|
111
|
+
if (typeof value === "string" && /^wrk_[A-Za-z0-9]+/.test(value) && out.indexOf(value) < 0) {
|
|
112
|
+
out.push(value);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (Array.isArray(value)) {
|
|
116
|
+
for (var i = 0; i < value.length; i++) collectWorkspaceIds(value[i], out);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (value && typeof value === "object") {
|
|
120
|
+
Object.keys(value).forEach(function (key) { collectWorkspaceIds(value[key], out); });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function parseWorkspaceIds(ctx, text) {
|
|
125
|
+
var ids = [];
|
|
126
|
+
var json = ctx.util.tryParseJson(text);
|
|
127
|
+
if (json) collectWorkspaceIds(json, ids);
|
|
128
|
+
var regex = /"id"\s*:\s*"(wrk_[^"]+)"|id\s*:\s*"(wrk_[^"]+)"/g;
|
|
129
|
+
var match;
|
|
130
|
+
while ((match = regex.exec(String(text || ""))) !== null) {
|
|
131
|
+
var id = match[1] || match[2];
|
|
132
|
+
if (id && ids.indexOf(id) < 0) ids.push(id);
|
|
133
|
+
}
|
|
134
|
+
return ids;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function fetchWorkspaceId(ctx, cookie) {
|
|
138
|
+
var text = serverRequest(ctx, {
|
|
139
|
+
method: "GET",
|
|
140
|
+
serverId: WORKSPACES_SERVER_ID,
|
|
141
|
+
cookie: cookie,
|
|
142
|
+
referer: BASE_URL,
|
|
143
|
+
});
|
|
144
|
+
var ids = parseWorkspaceIds(ctx, text);
|
|
145
|
+
if (ids.length) return ids[0];
|
|
146
|
+
text = serverRequest(ctx, {
|
|
147
|
+
method: "POST",
|
|
148
|
+
serverId: WORKSPACES_SERVER_ID,
|
|
149
|
+
args: [],
|
|
150
|
+
cookie: cookie,
|
|
151
|
+
referer: BASE_URL,
|
|
152
|
+
});
|
|
153
|
+
ids = parseWorkspaceIds(ctx, text);
|
|
154
|
+
if (ids.length) return ids[0];
|
|
155
|
+
throw "OpenCode parse error: missing workspace id.";
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function fetchSubscription(ctx, workspaceId, cookie) {
|
|
159
|
+
var referer = BASE_URL + "/workspace/" + workspaceId + "/billing";
|
|
160
|
+
var text = serverRequest(ctx, {
|
|
161
|
+
method: "GET",
|
|
162
|
+
serverId: SUBSCRIPTION_SERVER_ID,
|
|
163
|
+
args: [workspaceId],
|
|
164
|
+
cookie: cookie,
|
|
165
|
+
referer: referer,
|
|
166
|
+
});
|
|
167
|
+
if (parseSubscription(ctx, text, Date.now())) return text;
|
|
168
|
+
return serverRequest(ctx, {
|
|
169
|
+
method: "POST",
|
|
170
|
+
serverId: SUBSCRIPTION_SERVER_ID,
|
|
171
|
+
args: [workspaceId],
|
|
172
|
+
cookie: cookie,
|
|
173
|
+
referer: referer,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function numberValue(value) {
|
|
178
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
179
|
+
if (typeof value === "string" && value.trim()) {
|
|
180
|
+
var parsed = Number(value);
|
|
181
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function firstNumber(obj, keys) {
|
|
187
|
+
if (!obj || typeof obj !== "object") return null;
|
|
188
|
+
for (var i = 0; i < keys.length; i++) {
|
|
189
|
+
var n = numberValue(obj[keys[i]]);
|
|
190
|
+
if (n !== null) return n;
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function dateFromValue(ctx, value) {
|
|
196
|
+
var n = numberValue(value);
|
|
197
|
+
if (n !== null && n > 0) return ctx.util.toIso(n);
|
|
198
|
+
return ctx.util.toIso(value);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function findDatetime(ctx, json, keys) {
|
|
202
|
+
if (Array.isArray(json)) {
|
|
203
|
+
for (var i = 0; i < json.length; i++) {
|
|
204
|
+
var inArray = findDatetime(ctx, json[i], keys);
|
|
205
|
+
if (inArray) return inArray;
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
if (!json || typeof json !== "object") return null;
|
|
210
|
+
for (var k = 0; k < keys.length; k++) {
|
|
211
|
+
if (json[keys[k]] !== undefined) {
|
|
212
|
+
var parsed = dateFromValue(ctx, json[keys[k]]);
|
|
213
|
+
if (parsed) return parsed;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
var objectKeys = Object.keys(json);
|
|
217
|
+
for (var j = 0; j < objectKeys.length; j++) {
|
|
218
|
+
var nested = findDatetime(ctx, json[objectKeys[j]], keys);
|
|
219
|
+
if (nested) return nested;
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function percentFromUsedLimit(obj) {
|
|
225
|
+
var used = numberValue(obj && (obj.used !== undefined ? obj.used : obj.usage));
|
|
226
|
+
var limit = numberValue(obj && (obj.limit !== undefined ? obj.limit : obj.total));
|
|
227
|
+
if (used === null || limit === null || limit <= 0) return null;
|
|
228
|
+
return (used / limit) * 100;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function parseWindow(ctx, obj, nowMs) {
|
|
232
|
+
if (!obj || typeof obj !== "object") return null;
|
|
233
|
+
var percent = firstNumber(obj, PERCENT_KEYS);
|
|
234
|
+
if (percent === null) percent = percentFromUsedLimit(obj);
|
|
235
|
+
if (percent === null) return null;
|
|
236
|
+
if (percent <= 1) percent *= 100;
|
|
237
|
+
percent = Math.max(0, Math.min(100, percent));
|
|
238
|
+
|
|
239
|
+
var resetSeconds = firstNumber(obj, RESET_IN_KEYS);
|
|
240
|
+
var resetIso = null;
|
|
241
|
+
if (resetSeconds !== null) {
|
|
242
|
+
resetIso = new Date(nowMs + Math.max(0, resetSeconds) * 1000).toISOString();
|
|
243
|
+
} else {
|
|
244
|
+
resetIso = findDatetime(ctx, obj, RESET_AT_KEYS);
|
|
245
|
+
}
|
|
246
|
+
return { percent: percent, resetsAt: resetIso };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function findUsageWindow(ctx, json, keys, nowMs) {
|
|
250
|
+
if (Array.isArray(json)) {
|
|
251
|
+
for (var i = 0; i < json.length; i++) {
|
|
252
|
+
var inArray = findUsageWindow(ctx, json[i], keys, nowMs);
|
|
253
|
+
if (inArray) return inArray;
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
if (!json || typeof json !== "object") return null;
|
|
258
|
+
for (var k = 0; k < keys.length; k++) {
|
|
259
|
+
var direct = parseWindow(ctx, json[keys[k]], nowMs);
|
|
260
|
+
if (direct) return direct;
|
|
261
|
+
}
|
|
262
|
+
var objectKeys = Object.keys(json);
|
|
263
|
+
for (var j = 0; j < objectKeys.length; j++) {
|
|
264
|
+
var nested = findUsageWindow(ctx, json[objectKeys[j]], keys, nowMs);
|
|
265
|
+
if (nested) return nested;
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function parseSubscriptionJson(ctx, text, nowMs) {
|
|
271
|
+
var json = ctx.util.tryParseJson(text);
|
|
272
|
+
if (!json) return null;
|
|
273
|
+
var rolling = findUsageWindow(ctx, json, ["rollingUsage", "rolling", "rolling_usage"], nowMs);
|
|
274
|
+
var weekly = findUsageWindow(ctx, json, ["weeklyUsage", "weekly", "weekly_usage"], nowMs);
|
|
275
|
+
if (!rolling || !weekly) return null;
|
|
276
|
+
return {
|
|
277
|
+
rolling: rolling,
|
|
278
|
+
weekly: weekly,
|
|
279
|
+
renewsAt: findDatetime(ctx, json, ["renewAt", "renew_at"]),
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function regexNumber(text, regex) {
|
|
284
|
+
var match = regex.exec(String(text || ""));
|
|
285
|
+
return match ? numberValue(match[1]) : null;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function parseSubscriptionRegex(ctx, text, nowMs) {
|
|
289
|
+
var rollingPercent = regexNumber(text, /rollingUsage[^}]*?usagePercent\s*:\s*([0-9]+(?:\.[0-9]+)?)/);
|
|
290
|
+
var rollingReset = regexNumber(text, /rollingUsage[^}]*?resetInSec\s*:\s*([0-9]+)/);
|
|
291
|
+
var weeklyPercent = regexNumber(text, /weeklyUsage[^}]*?usagePercent\s*:\s*([0-9]+(?:\.[0-9]+)?)/);
|
|
292
|
+
var weeklyReset = regexNumber(text, /weeklyUsage[^}]*?resetInSec\s*:\s*([0-9]+)/);
|
|
293
|
+
if (rollingPercent === null || rollingReset === null || weeklyPercent === null || weeklyReset === null) return null;
|
|
294
|
+
var renewMatch = /(?:"renewAt"|"renew_at"|renewAt|renew_at)\s*[:=]\s*"?([^",}\s]+)"?/.exec(String(text || ""));
|
|
295
|
+
return {
|
|
296
|
+
rolling: { percent: rollingPercent, resetsAt: new Date(nowMs + rollingReset * 1000).toISOString() },
|
|
297
|
+
weekly: { percent: weeklyPercent, resetsAt: new Date(nowMs + weeklyReset * 1000).toISOString() },
|
|
298
|
+
renewsAt: renewMatch ? dateFromValue(ctx, renewMatch[1]) : null,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function parseSubscription(ctx, text, nowMs) {
|
|
303
|
+
return parseSubscriptionJson(ctx, text, nowMs) || parseSubscriptionRegex(ctx, text, nowMs);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function probe(ctx) {
|
|
307
|
+
var cookie = cookieHeader(ctx);
|
|
308
|
+
var workspaceId = workspaceOverride(ctx) || fetchWorkspaceId(ctx, cookie);
|
|
309
|
+
var nowMs = Date.now();
|
|
310
|
+
var parsed = parseSubscription(ctx, fetchSubscription(ctx, workspaceId, cookie), nowMs);
|
|
311
|
+
if (!parsed) {
|
|
312
|
+
throw "OpenCode parse error: missing usage fields.";
|
|
313
|
+
}
|
|
314
|
+
var lines = [
|
|
315
|
+
ctx.line.progress({
|
|
316
|
+
label: "5-hour",
|
|
317
|
+
used: parsed.rolling.percent,
|
|
318
|
+
limit: 100,
|
|
319
|
+
format: { kind: "percent" },
|
|
320
|
+
resetsAt: parsed.rolling.resetsAt,
|
|
321
|
+
periodDurationMs: FIVE_HOURS_MS,
|
|
322
|
+
}),
|
|
323
|
+
ctx.line.progress({
|
|
324
|
+
label: "Weekly",
|
|
325
|
+
used: parsed.weekly.percent,
|
|
326
|
+
limit: 100,
|
|
327
|
+
format: { kind: "percent" },
|
|
328
|
+
resetsAt: parsed.weekly.resetsAt,
|
|
329
|
+
periodDurationMs: WEEK_MS,
|
|
330
|
+
}),
|
|
331
|
+
];
|
|
332
|
+
if (parsed.renewsAt) lines.push(ctx.line.text({ label: "Renews", value: parsed.renewsAt }));
|
|
333
|
+
return {
|
|
334
|
+
displayName: "OpenCode",
|
|
335
|
+
source: "web",
|
|
336
|
+
plan: "OpenCode",
|
|
337
|
+
lines: lines,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
globalThis.__openusage_plugin = { id: "opencode", probe: probe };
|
|
342
|
+
})();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "opencode",
|
|
4
|
+
"name": "OpenCode",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"brandColor": "#9CA3AF",
|
|
8
|
+
"links": [
|
|
9
|
+
{ "label": "Dashboard", "url": "https://opencode.ai" }
|
|
10
|
+
],
|
|
11
|
+
"supportedModes": ["web"],
|
|
12
|
+
"autoMode": "web",
|
|
13
|
+
"webUrl": "https://opencode.ai",
|
|
14
|
+
"lines": [
|
|
15
|
+
{ "type": "progress", "label": "5-hour", "scope": "overview", "primaryOrder": 1 },
|
|
16
|
+
{ "type": "progress", "label": "Weekly", "scope": "detail" },
|
|
17
|
+
{ "type": "text", "label": "Renews", "scope": "detail" }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg data-hk="0000000100000000000100000210" width="24" height="30" viewBox="0 0 24 30" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M18 6H6V24H18V6ZM24 30H0V0H24V30Z" fill="currentColor"></path></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>opencode</title><path d="M16 6H8v12h8V6zm4 16H4V2h16v20z"></path></svg>
|