@hashimkarim/usagestat-linux-x64-gnu 2.0.0-alpha.1 → 2.0.0-alpha.3
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 +0 -0
- package/native-manifest.json +365 -77
- package/package.json +49 -1
- package/plugins/UPSTREAM-LICENSES.md +109 -0
- package/plugins/abacus-ai/icon.svg +0 -0
- package/plugins/abacus-ai/plugin.js +0 -0
- package/plugins/abacus-ai/plugin.json +0 -0
- package/plugins/aiand/icon.svg +6 -0
- package/plugins/aiand/plugin.js +108 -0
- package/plugins/aiand/plugin.json +22 -0
- package/plugins/alibaba/icon-color.svg +0 -0
- package/plugins/alibaba/icon.svg +0 -0
- package/plugins/alibaba/plugin.js +0 -0
- package/plugins/alibaba/plugin.json +0 -0
- package/plugins/alibaba-token-plan/icon-color.svg +0 -0
- package/plugins/alibaba-token-plan/icon.svg +0 -0
- package/plugins/alibaba-token-plan/plugin.js +0 -0
- package/plugins/alibaba-token-plan/plugin.json +0 -0
- package/plugins/amp/icon-color.svg +0 -0
- package/plugins/amp/icon-conflict.svg +0 -0
- package/plugins/amp/icon.svg +0 -0
- package/plugins/amp/plugin.js +0 -0
- package/plugins/amp/plugin.json +0 -0
- package/plugins/antigravity/icon-color.svg +0 -0
- package/plugins/antigravity/icon-conflict.svg +0 -0
- package/plugins/antigravity/icon.svg +0 -0
- package/plugins/antigravity/plugin.js +0 -0
- package/plugins/antigravity/plugin.json +0 -0
- package/plugins/antigravity-cli/icon.svg +0 -0
- package/plugins/antigravity-cli/plugin.js +0 -0
- package/plugins/antigravity-cli/plugin.json +0 -0
- package/plugins/antigravity-ide/icon.svg +0 -0
- package/plugins/antigravity-ide/plugin.js +0 -0
- package/plugins/antigravity-ide/plugin.json +0 -0
- package/plugins/augment/icon.svg +0 -0
- package/plugins/augment/plugin.js +0 -0
- package/plugins/augment/plugin.json +0 -0
- package/plugins/aws-bedrock/icon-color.svg +0 -0
- package/plugins/aws-bedrock/icon.svg +0 -0
- package/plugins/aws-bedrock/plugin.js +0 -0
- package/plugins/aws-bedrock/plugin.json +0 -0
- package/plugins/azure-openai/icon-color.svg +0 -0
- package/plugins/azure-openai/icon.svg +0 -0
- package/plugins/azure-openai/plugin.js +0 -0
- package/plugins/azure-openai/plugin.json +0 -0
- package/plugins/chutes/icon.svg +0 -0
- package/plugins/chutes/plugin.js +0 -0
- package/plugins/chutes/plugin.json +0 -0
- package/plugins/claude/icon-color.svg +0 -0
- package/plugins/claude/icon.svg +0 -0
- package/plugins/claude/plugin.js +70 -23
- package/plugins/claude/plugin.json +0 -0
- package/plugins/clawrouter/icon.svg +7 -0
- package/plugins/clawrouter/plugin.js +45 -0
- package/plugins/clawrouter/plugin.json +22 -0
- package/plugins/clinepass/icon.svg +4 -0
- package/plugins/clinepass/plugin.js +71 -0
- package/plugins/clinepass/plugin.json +23 -0
- package/plugins/codebuddy/plugin.js +331 -0
- package/plugins/codebuddy/plugin.json +30 -0
- package/plugins/codebuff/icon.svg +0 -0
- package/plugins/codebuff/plugin.js +0 -0
- package/plugins/codebuff/plugin.json +0 -0
- package/plugins/codex/icon-color.svg +0 -0
- package/plugins/codex/icon.svg +0 -0
- package/plugins/codex/plugin.js +7 -2
- package/plugins/codex/plugin.json +0 -0
- package/plugins/command-code/icon.svg +0 -0
- package/plugins/command-code/plugin.js +7 -0
- package/plugins/command-code/plugin.json +0 -0
- package/plugins/copilot/icon-color.svg +0 -0
- package/plugins/copilot/icon.svg +0 -0
- package/plugins/copilot/plugin.js +61 -9
- package/plugins/copilot/plugin.json +4 -1
- package/plugins/crof/icon.svg +0 -0
- package/plugins/crof/plugin.js +0 -0
- package/plugins/crof/plugin.json +0 -0
- package/plugins/crofai/icon.svg +0 -0
- package/plugins/crofai/plugin.js +0 -0
- package/plugins/crofai/plugin.json +0 -0
- package/plugins/cursor/icon-conflict.svg +0 -0
- package/plugins/cursor/icon.svg +0 -0
- package/plugins/cursor/plugin.js +46 -9
- package/plugins/cursor/plugin.json +3 -2
- package/plugins/cursor-nightly/icon.png +0 -0
- package/plugins/cursor-nightly/plugin.js +45 -8
- package/plugins/cursor-nightly/plugin.json +3 -2
- package/plugins/deepgram/icon.svg +0 -0
- package/plugins/deepgram/plugin.js +0 -0
- package/plugins/deepgram/plugin.json +0 -0
- package/plugins/deepinfra/icon.svg +4 -0
- package/plugins/deepinfra/plugin.js +97 -0
- package/plugins/deepinfra/plugin.json +28 -0
- package/plugins/deepseek/icon-color.svg +0 -0
- package/plugins/deepseek/icon.svg +0 -0
- package/plugins/deepseek/plugin.js +0 -0
- package/plugins/deepseek/plugin.json +0 -0
- package/plugins/devin/icon.svg +0 -0
- package/plugins/devin/plugin.js +111 -0
- package/plugins/devin/plugin.json +2 -1
- package/plugins/doubao/icon-color.svg +0 -0
- package/plugins/doubao/icon.svg +0 -0
- package/plugins/doubao/plugin.js +0 -0
- package/plugins/doubao/plugin.json +0 -0
- package/plugins/droid/icon.svg +0 -0
- package/plugins/droid/plugin.json +2 -1
- package/plugins/elevenlabs/icon.svg +0 -0
- package/plugins/elevenlabs/plugin.js +17 -2
- package/plugins/elevenlabs/plugin.json +0 -0
- package/plugins/factory/icon-conflict.svg +0 -0
- package/plugins/factory/icon.svg +0 -0
- package/plugins/factory/plugin.js +38 -14
- package/plugins/factory/plugin.json +2 -1
- package/plugins/fireworks-ai/icon.svg +0 -0
- package/plugins/fireworks-ai/plugin.js +0 -0
- package/plugins/fireworks-ai/plugin.json +0 -0
- package/plugins/gemini/icon-color.svg +0 -0
- package/plugins/gemini/icon.svg +0 -0
- package/plugins/gemini/plugin.js +0 -0
- package/plugins/gemini/plugin.json +0 -0
- package/plugins/grok/icon.svg +0 -0
- package/plugins/grok/plugin.js +30 -5
- package/plugins/grok/plugin.json +3 -1
- package/plugins/groqcloud/icon.svg +0 -0
- package/plugins/groqcloud/plugin.js +0 -0
- package/plugins/groqcloud/plugin.json +0 -0
- package/plugins/ibmbob/icon.svg +23 -0
- package/plugins/ibmbob/plugin.js +61 -0
- package/plugins/ibmbob/plugin.json +22 -0
- package/plugins/jetbrains-ai-assistant/icon-color.svg +0 -0
- package/plugins/jetbrains-ai-assistant/icon-conflict.svg +0 -0
- package/plugins/jetbrains-ai-assistant/icon.svg +0 -0
- package/plugins/jetbrains-ai-assistant/plugin.js +0 -0
- package/plugins/jetbrains-ai-assistant/plugin.json +0 -0
- package/plugins/kilo/icon.svg +0 -0
- package/plugins/kilo/plugin.js +0 -0
- package/plugins/kilo/plugin.json +0 -0
- package/plugins/kimi/icon-color.svg +0 -0
- package/plugins/kimi/icon-conflict.svg +0 -0
- package/plugins/kimi/icon.svg +0 -0
- package/plugins/kimi/plugin.js +122 -141
- package/plugins/kimi/plugin.json +5 -2
- package/plugins/kimi-k2/icon-color.svg +0 -0
- package/plugins/kimi-k2/icon.svg +0 -0
- package/plugins/kimi-k2/plugin.js +0 -0
- package/plugins/kimi-k2/plugin.json +0 -0
- package/plugins/kiro/icon-color.svg +0 -0
- package/plugins/kiro/icon-conflict.svg +0 -0
- package/plugins/kiro/icon.svg +0 -0
- package/plugins/kiro/plugin.js +49 -10
- package/plugins/kiro/plugin.json +3 -1
- package/plugins/litellm/icon.svg +0 -0
- package/plugins/litellm/plugin.js +0 -0
- package/plugins/litellm/plugin.json +0 -0
- package/plugins/llm-proxy/icon.svg +0 -0
- package/plugins/llm-proxy/plugin.js +0 -0
- package/plugins/llm-proxy/plugin.json +0 -0
- package/plugins/longcat/icon.svg +4 -0
- package/plugins/longcat/plugin.js +182 -0
- package/plugins/longcat/plugin.json +23 -0
- package/plugins/manus/icon.svg +0 -0
- package/plugins/manus/plugin.js +0 -0
- package/plugins/manus/plugin.json +0 -0
- package/plugins/mimo/icon.svg +0 -0
- package/plugins/mimo/plugin.js +0 -0
- package/plugins/mimo/plugin.json +0 -0
- package/plugins/minimax/icon-color.svg +0 -0
- package/plugins/minimax/icon-conflict.svg +0 -0
- package/plugins/minimax/icon.svg +0 -0
- package/plugins/minimax/plugin.js +25 -31
- package/plugins/minimax/plugin.json +0 -0
- package/plugins/mistral/icon-color.svg +0 -0
- package/plugins/mistral/icon.svg +0 -0
- package/plugins/mistral/plugin.js +0 -0
- package/plugins/mistral/plugin.json +0 -0
- package/plugins/moonshot/icon.svg +0 -0
- package/plugins/moonshot/plugin.js +8 -6
- package/plugins/moonshot/plugin.json +0 -0
- package/plugins/nanogpt/icon-color.svg +0 -0
- package/plugins/nanogpt/icon.svg +0 -0
- package/plugins/nanogpt/plugin.js +0 -0
- package/plugins/nanogpt/plugin.json +0 -0
- package/plugins/neuralwatt/icon.svg +0 -0
- package/plugins/neuralwatt/plugin.js +0 -0
- package/plugins/neuralwatt/plugin.json +0 -0
- package/plugins/notion/icon.svg +1 -0
- package/plugins/notion/plugin.js +282 -0
- package/plugins/notion/plugin.json +29 -0
- package/plugins/ollama/icon.svg +0 -0
- package/plugins/ollama/plugin.js +257 -56
- package/plugins/ollama/plugin.json +6 -3
- package/plugins/openai-api/icon.svg +0 -0
- package/plugins/openai-api/plugin.js +0 -0
- package/plugins/openai-api/plugin.json +0 -0
- package/plugins/opencode/icon.svg +0 -0
- package/plugins/opencode/plugin.js +0 -0
- package/plugins/opencode/plugin.json +0 -0
- package/plugins/opencode-go/icon-conflict.svg +0 -0
- package/plugins/opencode-go/icon.svg +0 -0
- package/plugins/opencode-go/plugin.js +78 -10
- package/plugins/opencode-go/plugin.json +5 -2
- package/plugins/openrouter/icon.svg +0 -0
- package/plugins/openrouter/plugin.js +371 -114
- package/plugins/openrouter/plugin.json +6 -0
- package/plugins/perplexity/icon-color.svg +0 -0
- package/plugins/perplexity/icon-conflict.svg +0 -0
- package/plugins/perplexity/icon.svg +0 -0
- package/plugins/perplexity/plugin.js +0 -0
- package/plugins/perplexity/plugin.json +0 -0
- package/plugins/poe/icon.svg +0 -0
- package/plugins/poe/plugin.js +24 -18
- package/plugins/poe/plugin.json +2 -0
- package/plugins/qoder/icon.svg +3 -0
- package/plugins/qoder/plugin.js +227 -0
- package/plugins/qoder/plugin.json +23 -0
- package/plugins/qwencloud/icon.svg +4 -0
- package/plugins/qwencloud/plugin.js +677 -0
- package/plugins/qwencloud/plugin.json +29 -0
- package/plugins/sakana/icon.svg +5 -0
- package/plugins/sakana/plugin.js +156 -0
- package/plugins/sakana/plugin.json +23 -0
- package/plugins/stepfun/icon-color.svg +0 -0
- package/plugins/stepfun/icon.svg +0 -0
- package/plugins/stepfun/plugin.js +0 -0
- package/plugins/stepfun/plugin.json +0 -0
- package/plugins/sub2api/icon.svg +4 -0
- package/plugins/sub2api/plugin.js +191 -0
- package/plugins/sub2api/plugin.json +16 -0
- package/plugins/synthetic/icon-conflict.svg +0 -0
- package/plugins/synthetic/icon.svg +0 -0
- package/plugins/synthetic/plugin.js +0 -0
- package/plugins/synthetic/plugin.json +0 -0
- package/plugins/t3chat/icon-color.svg +0 -0
- package/plugins/t3chat/icon.svg +0 -0
- package/plugins/t3chat/plugin.js +0 -0
- package/plugins/t3chat/plugin.json +0 -0
- package/plugins/venice/icon-color.svg +0 -0
- package/plugins/venice/icon.svg +0 -0
- package/plugins/venice/plugin.js +0 -0
- package/plugins/venice/plugin.json +0 -0
- package/plugins/vertex-ai/icon-color.svg +0 -0
- package/plugins/vertex-ai/icon.svg +0 -0
- package/plugins/vertex-ai/plugin.js +0 -0
- package/plugins/vertex-ai/plugin.json +0 -0
- package/plugins/warp/icon-color.svg +0 -0
- package/plugins/warp/icon.svg +0 -0
- package/plugins/warp/plugin.js +0 -0
- package/plugins/warp/plugin.json +0 -0
- package/plugins/wayfinder/icon.svg +5 -0
- package/plugins/wayfinder/plugin.js +47 -0
- package/plugins/wayfinder/plugin.json +16 -0
- package/plugins/windsurf/icon-conflict.svg +0 -0
- package/plugins/windsurf/icon.svg +0 -0
- package/plugins/windsurf/plugin.js +0 -0
- package/plugins/windsurf/plugin.json +0 -0
- package/plugins/xai/icon.svg +7 -0
- package/plugins/xai/plugin.js +162 -0
- package/plugins/xai/plugin.json +28 -0
- package/plugins/zai/icon-conflict.svg +0 -0
- package/plugins/zai/icon.svg +0 -0
- package/plugins/zai/plugin.js +111 -161
- package/plugins/zai/plugin.json +4 -1
- package/plugins/zed/icon.svg +0 -0
- package/plugins/zed/plugin.js +0 -0
- package/plugins/zed/plugin.json +0 -0
- package/plugins/zenmux/icon.svg +3 -0
- package/plugins/zenmux/plugin.js +102 -0
- package/plugins/zenmux/plugin.json +23 -0
- package/plugins/zoommate/icon.svg +1 -0
- package/plugins/zoommate/plugin.js +244 -0
- package/plugins/zoommate/plugin.json +29 -0
- package/usagestat +0 -0
- package/usagestatd +0 -0
|
@@ -1,156 +1,413 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
(function () {
|
|
2
|
+
var DEFAULT_BASE = "https://openrouter.ai/api/v1";
|
|
3
|
+
var ACTIVITY_URL = DEFAULT_BASE + "/activity";
|
|
4
|
+
var ACTIVITY_DAYS = 30;
|
|
5
|
+
var MAX_ACTIVITY_ROWS = 20000;
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
function clean(value) {
|
|
8
|
+
if (typeof value !== "string") return null;
|
|
9
|
+
var v = value.trim();
|
|
10
|
+
if (!v) return null;
|
|
11
|
+
if (
|
|
12
|
+
v.length >= 2 &&
|
|
13
|
+
((v.charAt(0) === '"' && v.charAt(v.length - 1) === '"') ||
|
|
14
|
+
(v.charAt(0) === "'" && v.charAt(v.length - 1) === "'"))
|
|
15
|
+
) {
|
|
16
|
+
v = v.slice(1, -1).trim();
|
|
17
|
+
}
|
|
18
|
+
return v || null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function env(ctx, name) {
|
|
22
|
+
try {
|
|
23
|
+
return clean(ctx.host.env.get(name));
|
|
24
|
+
} catch (_) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function setting(ctx, names) {
|
|
30
|
+
var settings = ctx.provider && ctx.provider.settings ? ctx.provider.settings : {};
|
|
31
|
+
for (var i = 0; i < names.length; i++) {
|
|
32
|
+
var value = clean(settings[names[i]]);
|
|
33
|
+
if (value) return value;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function readApiKey(ctx) {
|
|
39
|
+
return clean(ctx.provider && ctx.provider.apiKey) || env(ctx, "OPENROUTER_API_KEY");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function readManagementKey(ctx) {
|
|
43
|
+
return setting(ctx, ["managementApiKey", "managementKey", "activityApiKey"]) ||
|
|
44
|
+
env(ctx, "OPENROUTER_MANAGEMENT_API_KEY");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function readApiBase(ctx) {
|
|
48
|
+
var value = env(ctx, "OPENROUTER_API_BASE") || setting(ctx, ["apiBase", "baseUrl", "apiUrl"]);
|
|
49
|
+
var base = (value || DEFAULT_BASE).replace(/\/+$/, "");
|
|
50
|
+
if (/\/auth$/i.test(base)) base = base.slice(0, -5);
|
|
51
|
+
return ctx.host.http.validateBaseUrl(base || DEFAULT_BASE, true);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function requestJson(ctx, request) {
|
|
55
|
+
var resp;
|
|
56
|
+
try {
|
|
57
|
+
resp = ctx.host.http.request(request);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
ctx.host.log.error("HTTP request failed: " + String(error));
|
|
60
|
+
throw "OpenRouter request failed. Check your connection.";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
var json = null;
|
|
64
|
+
try {
|
|
65
|
+
json = resp.bodyText ? JSON.parse(resp.bodyText) : null;
|
|
66
|
+
} catch (_) {
|
|
67
|
+
throw "OpenRouter response was not valid JSON.";
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { resp: resp, json: json };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function fetchOpenRouterJson(ctx, url, key, timeoutMs) {
|
|
74
|
+
var result = requestJson(ctx, {
|
|
7
75
|
method: "GET",
|
|
8
|
-
url:
|
|
76
|
+
url: url,
|
|
9
77
|
headers: {
|
|
10
|
-
|
|
11
|
-
|
|
78
|
+
Authorization: "Bearer " + key,
|
|
79
|
+
Accept: "application/json",
|
|
12
80
|
},
|
|
13
|
-
timeoutMs: 15000
|
|
81
|
+
timeoutMs: timeoutMs || 15000,
|
|
14
82
|
});
|
|
15
|
-
|
|
16
|
-
if (credits.resp.status === 401 || credits.resp.status === 403) {
|
|
83
|
+
if (result.resp.status === 401 || result.resp.status === 403) {
|
|
17
84
|
throw "OpenRouter API key is invalid.";
|
|
18
85
|
}
|
|
19
|
-
if (
|
|
20
|
-
throw "OpenRouter
|
|
86
|
+
if (result.resp.status < 200 || result.resp.status >= 300) {
|
|
87
|
+
throw "OpenRouter request failed (HTTP " + result.resp.status + ").";
|
|
88
|
+
}
|
|
89
|
+
return result.json;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function readNumber(value) {
|
|
93
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
94
|
+
if (typeof value === "string" && value.trim()) {
|
|
95
|
+
var parsed = Number(value.trim().replace(/,/g, ""));
|
|
96
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
21
97
|
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function clamp(value, min, max) {
|
|
102
|
+
return Math.max(min, Math.min(max, value));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function round1(value) {
|
|
106
|
+
return Math.round(value * 10) / 10;
|
|
107
|
+
}
|
|
22
108
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
109
|
+
function round2(value) {
|
|
110
|
+
return Math.round(value * 100) / 100;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function money(value) {
|
|
114
|
+
return "$" + round2(value || 0).toFixed(2);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function progressLine(label, used, limit, format) {
|
|
118
|
+
return {
|
|
119
|
+
type: "progress",
|
|
120
|
+
label: label,
|
|
121
|
+
used: used,
|
|
122
|
+
limit: limit,
|
|
123
|
+
format: format || { kind: "percent" },
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function appendCreditsMetrics(metrics, data) {
|
|
128
|
+
var totalCredits = readNumber(data.total_credits);
|
|
129
|
+
var totalUsage = readNumber(data.total_usage);
|
|
26
130
|
|
|
27
131
|
if (totalCredits === null || totalUsage === null) {
|
|
28
132
|
throw "OpenRouter credits response did not include usage totals.";
|
|
29
133
|
}
|
|
30
134
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
135
|
+
var remaining = Math.max(0, totalCredits - totalUsage);
|
|
136
|
+
var usedPercent = totalCredits > 0 ? clamp((totalUsage / totalCredits) * 100, 0, 100) : 0;
|
|
137
|
+
metrics.push(progressLine("Credits", round2(totalUsage), round2(totalCredits), { kind: "dollars" }));
|
|
138
|
+
metrics.push({ type: "text", label: "Balance", value: money(remaining) });
|
|
139
|
+
metrics.push({
|
|
140
|
+
type: "text",
|
|
141
|
+
label: "Used",
|
|
142
|
+
value: money(totalUsage) + " (" + round1(usedPercent) + "%)",
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function quotaFallbackUsage(data) {
|
|
147
|
+
var reset = typeof data.limit_reset === "string" ? data.limit_reset.toLowerCase() : "";
|
|
148
|
+
if (reset === "daily") return readNumber(data.usage_daily);
|
|
149
|
+
if (reset === "weekly") return readNumber(data.usage_weekly);
|
|
150
|
+
if (reset === "monthly") return readNumber(data.usage_monthly);
|
|
151
|
+
return readNumber(data.usage);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function appendKeyMetrics(metrics, data) {
|
|
155
|
+
var limit = readNumber(data.limit);
|
|
156
|
+
if (limit !== null && limit > 0) {
|
|
157
|
+
var remaining = readNumber(data.limit_remaining);
|
|
158
|
+
if (remaining === null) remaining = readNumber(data.limitRemaining);
|
|
159
|
+
var used = null;
|
|
160
|
+
if (remaining !== null) {
|
|
161
|
+
used = limit - clamp(remaining, 0, limit);
|
|
162
|
+
} else {
|
|
163
|
+
used = quotaFallbackUsage(data);
|
|
50
164
|
}
|
|
51
|
-
|
|
165
|
+
if (used !== null && used >= 0 && Number.isFinite(used)) {
|
|
166
|
+
metrics.push(progressLine("Key Cap", round2(used), round2(limit), { kind: "dollars" }));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
52
169
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
170
|
+
appendSpendText(metrics, "Daily Spend", data.usage_daily, "today");
|
|
171
|
+
appendSpendText(metrics, "Weekly Spend", data.usage_weekly, "this week");
|
|
172
|
+
appendSpendText(metrics, "Monthly Spend", data.usage_monthly, "this month");
|
|
173
|
+
|
|
174
|
+
var rateLimit = data.rate_limit || data.rateLimit;
|
|
175
|
+
if (rateLimit && rateLimit.requests !== undefined) {
|
|
176
|
+
var interval = typeof rateLimit.interval === "string" ? " / " + rateLimit.interval : "";
|
|
177
|
+
metrics.push({
|
|
178
|
+
type: "text",
|
|
179
|
+
label: "Rate Limit",
|
|
180
|
+
value: String(rateLimit.requests) + " requests" + interval,
|
|
62
181
|
});
|
|
63
|
-
|
|
64
|
-
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function appendSpendText(metrics, label, value, subtitle) {
|
|
186
|
+
var n = readNumber(value);
|
|
187
|
+
if (n === null || n < 0) return;
|
|
188
|
+
metrics.push({ type: "text", label: label, value: money(n), subtitle: subtitle });
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function parseDay(value) {
|
|
192
|
+
if (typeof value === "string") {
|
|
193
|
+
var trimmed = value.trim();
|
|
194
|
+
var match = trimmed.match(/^(\d{4}-\d{2}-\d{2})/);
|
|
195
|
+
if (match) {
|
|
196
|
+
var calendarMs = Date.parse(match[1] + "T00:00:00Z");
|
|
197
|
+
return Number.isFinite(calendarMs) && new Date(calendarMs).toISOString().slice(0, 10) === match[1] ? match[1] : null;
|
|
65
198
|
}
|
|
66
|
-
|
|
67
|
-
|
|
199
|
+
var ms = Date.parse(trimmed);
|
|
200
|
+
if (Number.isFinite(ms)) return new Date(ms).toISOString().slice(0, 10);
|
|
68
201
|
}
|
|
202
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
203
|
+
var date = new Date(value > 1000000000000 ? value : value * 1000);
|
|
204
|
+
return Number.isFinite(date.getTime()) ? date.toISOString().slice(0, 10) : null;
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
69
208
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
source: "api",
|
|
73
|
-
metrics
|
|
74
|
-
};
|
|
209
|
+
function dayToMs(day) {
|
|
210
|
+
return Date.parse(day + "T00:00:00Z");
|
|
75
211
|
}
|
|
76
|
-
};
|
|
77
212
|
|
|
78
|
-
function
|
|
79
|
-
|
|
80
|
-
if (typeof value === "string" && value.trim()) {
|
|
81
|
-
return value.trim();
|
|
213
|
+
function shortDay(day) {
|
|
214
|
+
return Number(day.slice(5, 7)) + "/" + Number(day.slice(8, 10));
|
|
82
215
|
}
|
|
83
|
-
throw "No OPENROUTER_API_KEY found.";
|
|
84
|
-
}
|
|
85
216
|
|
|
86
|
-
function
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
217
|
+
function latestCompletedUtcDay(ctx) {
|
|
218
|
+
var nowMs = Date.parse(ctx.nowIso);
|
|
219
|
+
if (!Number.isFinite(nowMs)) nowMs = Date.now();
|
|
220
|
+
var now = new Date(nowMs);
|
|
221
|
+
var today = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
|
|
222
|
+
return new Date(today - 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
|
|
90
223
|
}
|
|
91
|
-
return "https://openrouter.ai/api/v1/auth";
|
|
92
|
-
}
|
|
93
224
|
|
|
94
|
-
function
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
throw "OpenRouter
|
|
225
|
+
function activityRowCost(row, index) {
|
|
226
|
+
var metered = readNumber(row.usage);
|
|
227
|
+
if (metered === null || metered < 0) throw "OpenRouter Activity usage is invalid at row " + index + ".";
|
|
228
|
+
var estimated = readNumber(row.byok_usage_inference);
|
|
229
|
+
if (estimated === null && row.byok_usage_inference != null) throw "OpenRouter Activity BYOK usage is invalid at row " + index + ".";
|
|
230
|
+
if (estimated === null) estimated = 0;
|
|
231
|
+
if (estimated < 0) throw "OpenRouter Activity BYOK usage is invalid at row " + index + ".";
|
|
232
|
+
var total = metered + estimated;
|
|
233
|
+
if (!Number.isFinite(total)) throw "OpenRouter Activity cost total is invalid.";
|
|
234
|
+
return { metered: metered, estimated: estimated, total: total };
|
|
101
235
|
}
|
|
102
236
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
237
|
+
function tokenCount(value) {
|
|
238
|
+
if (value == null) return 0;
|
|
239
|
+
var n = readNumber(value);
|
|
240
|
+
if (!Number.isSafeInteger(n) || n < 0) throw "OpenRouter Activity token count is invalid.";
|
|
241
|
+
return n;
|
|
108
242
|
}
|
|
109
243
|
|
|
110
|
-
|
|
111
|
-
|
|
244
|
+
function rowId(value) {
|
|
245
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
246
|
+
return clean(value) || "";
|
|
247
|
+
}
|
|
112
248
|
|
|
113
|
-
function
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
249
|
+
function summarizeActivityPayloads(payloads, latestCompleted) {
|
|
250
|
+
var latestMs = dayToMs(latestCompleted);
|
|
251
|
+
var cutoffMs = latestMs - (ACTIVITY_DAYS - 1) * 24 * 60 * 60 * 1000;
|
|
252
|
+
var seen = {};
|
|
253
|
+
var byDay = {};
|
|
254
|
+
var total = 0;
|
|
255
|
+
var estimated = 0;
|
|
256
|
+
var rowsSeen = 0;
|
|
257
|
+
var aggregateTokens = 0;
|
|
258
|
+
var aggregateRequests = 0;
|
|
259
|
+
|
|
260
|
+
for (var p = 0; p < payloads.length; p++) {
|
|
261
|
+
var rows = payloads[p] && Array.isArray(payloads[p].data) ? payloads[p].data : null;
|
|
262
|
+
if (!rows) throw "OpenRouter Activity response missing data array.";
|
|
263
|
+
rowsSeen += rows.length;
|
|
264
|
+
if (rowsSeen > MAX_ACTIVITY_ROWS) throw "OpenRouter Activity returned too many rows.";
|
|
265
|
+
for (var i = 0; i < rows.length; i++) {
|
|
266
|
+
var row = rows[i];
|
|
267
|
+
if (!row || typeof row !== "object") throw "OpenRouter Activity row is invalid.";
|
|
268
|
+
var day = parseDay(row.date);
|
|
269
|
+
if (!day) throw "OpenRouter Activity row is missing a usable date.";
|
|
270
|
+
var dayMs = dayToMs(day);
|
|
271
|
+
if (dayMs < cutoffMs || dayMs > latestMs) continue;
|
|
272
|
+
var model = clean(row.model_permaslug) || clean(row.model) || "";
|
|
273
|
+
if (model.length > 512) throw "OpenRouter Activity model name is too long.";
|
|
274
|
+
var cost = activityRowCost(row, i);
|
|
275
|
+
var input = tokenCount(row.prompt_tokens);
|
|
276
|
+
var output = tokenCount(row.completion_tokens);
|
|
277
|
+
var combined = tokenCount(input + output);
|
|
278
|
+
var reasoning = tokenCount(row.reasoning_tokens);
|
|
279
|
+
if (reasoning > output) throw "OpenRouter Activity reasoning tokens exceed completion tokens.";
|
|
280
|
+
var identity = JSON.stringify([
|
|
281
|
+
day,
|
|
282
|
+
model,
|
|
283
|
+
rowId(row.endpoint_id),
|
|
284
|
+
clean(row.provider_name) || "",
|
|
285
|
+
clean(row.workspace_id) || "",
|
|
286
|
+
]);
|
|
287
|
+
var signature = JSON.stringify([input, output, reasoning, tokenCount(row.requests), cost.metered, cost.estimated]);
|
|
288
|
+
if (seen[identity]) {
|
|
289
|
+
if (seen[identity] !== signature) throw "OpenRouter Activity contains conflicting duplicate rows.";
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
seen[identity] = signature;
|
|
293
|
+
aggregateTokens = tokenCount(aggregateTokens + combined);
|
|
294
|
+
aggregateRequests = tokenCount(aggregateRequests + tokenCount(row.requests));
|
|
295
|
+
total += cost.total;
|
|
296
|
+
estimated += cost.estimated;
|
|
297
|
+
if (!Number.isFinite(total) || !Number.isFinite(estimated)) throw "OpenRouter Activity cost total is invalid.";
|
|
298
|
+
var daily = byDay[day] || { date: day, costUsd: 0, inputTokens: 0, outputTokens: 0, reasoningOutputTokens: 0, totalTokens: 0 };
|
|
299
|
+
daily.costUsd += cost.total;
|
|
300
|
+
daily.inputTokens = tokenCount(daily.inputTokens + input);
|
|
301
|
+
// Reasoning is a subset of completion tokens; the history store sums these fields.
|
|
302
|
+
daily.outputTokens = tokenCount(daily.outputTokens + (output - reasoning));
|
|
303
|
+
daily.reasoningOutputTokens = tokenCount(daily.reasoningOutputTokens + reasoning);
|
|
304
|
+
daily.totalTokens = tokenCount(daily.totalTokens + combined);
|
|
305
|
+
byDay[day] = daily;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return { total: total, estimated: estimated, byDay: byDay };
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function fetchActivityPayload(ctx, managementKey, date) {
|
|
313
|
+
var url = ACTIVITY_URL;
|
|
314
|
+
if (date) url += "?date=" + encodeURIComponent(date);
|
|
315
|
+
var result = requestJson(ctx, {
|
|
316
|
+
method: "GET",
|
|
317
|
+
url: url,
|
|
318
|
+
headers: {
|
|
319
|
+
Authorization: "Bearer " + managementKey,
|
|
320
|
+
Accept: "application/json",
|
|
321
|
+
},
|
|
322
|
+
timeoutMs: 3000,
|
|
123
323
|
});
|
|
324
|
+
if (result.resp.status === 401 || result.resp.status === 403) {
|
|
325
|
+
throw "OpenRouter management API key is invalid.";
|
|
326
|
+
}
|
|
327
|
+
if (result.resp.status < 200 || result.resp.status >= 300) {
|
|
328
|
+
throw "OpenRouter Activity request failed (HTTP " + result.resp.status + ").";
|
|
329
|
+
}
|
|
330
|
+
return result.json;
|
|
124
331
|
}
|
|
125
332
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
333
|
+
function appendActivityMetrics(ctx, metrics, managementKey) {
|
|
334
|
+
var latestCompleted = latestCompletedUtcDay(ctx);
|
|
335
|
+
var summary = summarizeActivityPayloads([
|
|
336
|
+
fetchActivityPayload(ctx, managementKey, null),
|
|
337
|
+
fetchActivityPayload(ctx, managementKey, latestCompleted),
|
|
338
|
+
], latestCompleted);
|
|
339
|
+
|
|
129
340
|
metrics.push({
|
|
130
341
|
type: "text",
|
|
131
|
-
label: "
|
|
132
|
-
value:
|
|
342
|
+
label: "Cost",
|
|
343
|
+
value: money(summary.total),
|
|
344
|
+
subtitle: "Last 30 completed days (UTC)" + (summary.estimated > 0 ? "; includes " + money(summary.estimated) + " estimated BYOK inference" : ""),
|
|
133
345
|
});
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
346
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
347
|
+
var days = Object.keys(summary.byDay).sort();
|
|
348
|
+
var chartPoints = [];
|
|
349
|
+
var dailyRows = [];
|
|
350
|
+
for (var i = 0; i < days.length; i++) {
|
|
351
|
+
var amount = summary.byDay[days[i]].costUsd;
|
|
352
|
+
chartPoints.push({
|
|
353
|
+
label: shortDay(days[i]),
|
|
354
|
+
value: amount,
|
|
355
|
+
valueLabel: money(amount),
|
|
356
|
+
});
|
|
357
|
+
dailyRows.push(summary.byDay[days[i]]);
|
|
358
|
+
}
|
|
359
|
+
if (chartPoints.length) {
|
|
360
|
+
metrics.push({
|
|
361
|
+
type: "barChart",
|
|
362
|
+
label: "Usage Trend",
|
|
363
|
+
points: chartPoints,
|
|
364
|
+
note: "OpenRouter Activity spend from completed UTC days." + (summary.estimated > 0 ? " Includes estimated BYOK inference." : ""),
|
|
365
|
+
color: "#7c3aed",
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
try {
|
|
370
|
+
if (ctx.host.usageDaily && typeof ctx.host.usageDaily.ingest === "function" && dailyRows.length) {
|
|
371
|
+
ctx.host.usageDaily.ingest({
|
|
372
|
+
displayName: "OpenRouter",
|
|
373
|
+
source: summary.estimated > 0 ? "openrouter_activity_estimated" : "openrouter_activity",
|
|
374
|
+
daily: dailyRows,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
} catch (_) {}
|
|
142
378
|
}
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
379
|
|
|
146
|
-
function
|
|
147
|
-
|
|
148
|
-
|
|
380
|
+
function probe(ctx) {
|
|
381
|
+
var apiKey = readApiKey(ctx);
|
|
382
|
+
if (!apiKey) throw "No OPENROUTER_API_KEY found.";
|
|
383
|
+
var apiBase = readApiBase(ctx);
|
|
384
|
+
var metrics = [];
|
|
149
385
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
386
|
+
var credits = fetchOpenRouterJson(ctx, apiBase + "/credits", apiKey, 15000);
|
|
387
|
+
appendCreditsMetrics(metrics, credits && credits.data ? credits.data : {});
|
|
388
|
+
|
|
389
|
+
try {
|
|
390
|
+
var key = fetchOpenRouterJson(ctx, apiBase + "/key", apiKey, 1000);
|
|
391
|
+
if (key && key.data) appendKeyMetrics(metrics, key.data);
|
|
392
|
+
} catch (error) {
|
|
393
|
+
ctx.host.log.warn("OpenRouter key details request degraded: " + String(error));
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
var managementKey = readManagementKey(ctx);
|
|
397
|
+
if (managementKey) {
|
|
398
|
+
try {
|
|
399
|
+
appendActivityMetrics(ctx, metrics, managementKey);
|
|
400
|
+
} catch (error) {
|
|
401
|
+
ctx.host.log.warn("OpenRouter Activity degraded: " + String(error));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
displayName: "OpenRouter",
|
|
407
|
+
source: "api",
|
|
408
|
+
metrics: metrics,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
153
411
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
412
|
+
globalThis.__usagestat_plugin = { probe: probe };
|
|
413
|
+
})();
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
"id": "openrouter",
|
|
3
3
|
"name": "OpenRouter",
|
|
4
4
|
"entry": "plugin.js",
|
|
5
|
+
"envVars": ["OPENROUTER_API_KEY", "OPENROUTER_API_BASE", "OPENROUTER_MANAGEMENT_API_KEY"],
|
|
6
|
+
"usageDashboardUrl": "https://openrouter.ai/activity",
|
|
7
|
+
"links": [
|
|
8
|
+
{ "label": "Activity", "url": "https://openrouter.ai/activity" },
|
|
9
|
+
{ "label": "Credits", "url": "https://openrouter.ai/settings/credits" }
|
|
10
|
+
],
|
|
5
11
|
"enabledByDefault": false,
|
|
6
12
|
"supportedModes": ["api"],
|
|
7
13
|
"autoMode": "api"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/plugins/poe/icon.svg
CHANGED
|
File without changes
|
package/plugins/poe/plugin.js
CHANGED
|
@@ -49,16 +49,12 @@
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
function parseDate(value) {
|
|
52
|
-
if (typeof value
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
var ms = Date.parse(value);
|
|
59
|
-
if (Number.isFinite(ms)) return new Date(ms);
|
|
60
|
-
}
|
|
61
|
-
return null;
|
|
52
|
+
if (typeof value !== "number" && (typeof value !== "string" || !value.trim())) return null;
|
|
53
|
+
var numeric = Number(value);
|
|
54
|
+
var date = Number.isFinite(numeric)
|
|
55
|
+
? new Date(Math.abs(numeric) > 100000000000000 ? numeric / 1000 : Math.abs(numeric) > 1000000000000 ? numeric : numeric * 1000)
|
|
56
|
+
: new Date(value);
|
|
57
|
+
return Number.isFinite(date.getTime()) && date.getUTCFullYear() >= 1 && date.getUTCFullYear() <= 9999 ? date : null;
|
|
62
58
|
}
|
|
63
59
|
|
|
64
60
|
function dayKey(date) {
|
|
@@ -77,6 +73,7 @@
|
|
|
77
73
|
}
|
|
78
74
|
|
|
79
75
|
function parseHistoryEntry(row) {
|
|
76
|
+
if (!row || typeof row !== "object") return null;
|
|
80
77
|
var createdAt = parseDate(row.creation_time ?? row.timestamp ?? row.created_at);
|
|
81
78
|
if (!createdAt) return null;
|
|
82
79
|
var points = numberValue(row.cost_points ?? row.points ?? row.point_cost) || 0;
|
|
@@ -90,10 +87,10 @@
|
|
|
90
87
|
};
|
|
91
88
|
}
|
|
92
89
|
|
|
93
|
-
function fetchHistory(ctx, key) {
|
|
90
|
+
function fetchHistory(ctx, key, nowMs) {
|
|
94
91
|
var entries = [];
|
|
95
92
|
var cursor = null;
|
|
96
|
-
var cutoff =
|
|
93
|
+
var cutoff = nowMs - 30 * 24 * 3600 * 1000;
|
|
97
94
|
for (var page = 0; page < 5; page++) {
|
|
98
95
|
var url = HISTORY_URL + "?limit=100";
|
|
99
96
|
if (cursor) url += "&starting_after=" + encodeURIComponent(cursor);
|
|
@@ -111,7 +108,7 @@
|
|
|
111
108
|
var lastEntry = entries[entries.length - 1];
|
|
112
109
|
if (!cursor || (lastEntry && lastEntry.createdAt.getTime() < cutoff)) break;
|
|
113
110
|
}
|
|
114
|
-
return entries.filter(function (entry) { return entry.createdAt.getTime() >= cutoff; });
|
|
111
|
+
return entries.filter(function (entry) { return entry.createdAt.getTime() >= cutoff && entry.createdAt.getTime() <= nowMs; });
|
|
115
112
|
}
|
|
116
113
|
|
|
117
114
|
function summarizeHistory(entries) {
|
|
@@ -142,12 +139,19 @@
|
|
|
142
139
|
return { byDay: byDay, days: days, topModel: topModel, totalPoints: totalPoints, totalCost: hasCost ? totalCost : null, requests: entries.length };
|
|
143
140
|
}
|
|
144
141
|
|
|
145
|
-
function
|
|
146
|
-
if (!entries.length) return;
|
|
147
|
-
var summary = summarizeHistory(entries);
|
|
142
|
+
function appendSummary(lines, ctx, label, summary) {
|
|
148
143
|
var value = fmtNumber(summary.totalPoints) + " points";
|
|
149
144
|
if (summary.totalCost != null) value += " · $" + summary.totalCost.toFixed(2);
|
|
150
|
-
lines.push(ctx.line.text({ label:
|
|
145
|
+
lines.push(ctx.line.text({ label: label, value: value + " · " + summary.requests + " requests" }));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function appendHistoryLines(lines, ctx, entries, nowMs) {
|
|
149
|
+
if (!entries.length) return;
|
|
150
|
+
var summary = summarizeHistory(entries);
|
|
151
|
+
var today = dayKey(new Date(nowMs));
|
|
152
|
+
appendSummary(lines, ctx, "Today", summarizeHistory(entries.filter(function (entry) { return dayKey(entry.createdAt) === today; })));
|
|
153
|
+
appendSummary(lines, ctx, "Last 7 Days", summarizeHistory(entries.filter(function (entry) { return entry.createdAt.getTime() >= nowMs - 7 * 86400000; })));
|
|
154
|
+
appendSummary(lines, ctx, "Last 30 Days", summary);
|
|
151
155
|
if (summary.topModel) lines.push(ctx.line.text({ label: "Top Model", value: summary.topModel }));
|
|
152
156
|
|
|
153
157
|
var points = summary.days.map(function (day) {
|
|
@@ -178,7 +182,9 @@
|
|
|
178
182
|
}
|
|
179
183
|
|
|
180
184
|
try {
|
|
181
|
-
|
|
185
|
+
var nowMs = Date.parse(ctx.nowIso);
|
|
186
|
+
if (!Number.isFinite(nowMs)) nowMs = Date.now();
|
|
187
|
+
appendHistoryLines(lines, ctx, fetchHistory(ctx, key, nowMs), nowMs);
|
|
182
188
|
} catch (e) {
|
|
183
189
|
ctx.host.log.warn("poe points_history failed: " + String(e));
|
|
184
190
|
}
|
package/plugins/poe/plugin.json
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
"autoMode": "api",
|
|
14
14
|
"lines": [
|
|
15
15
|
{ "type": "text", "label": "Balance", "scope": "overview", "primaryOrder": 1 },
|
|
16
|
+
{ "type": "text", "label": "Today", "scope": "detail" },
|
|
17
|
+
{ "type": "text", "label": "Last 7 Days", "scope": "detail" },
|
|
16
18
|
{ "type": "text", "label": "Last 30 Days", "scope": "detail" },
|
|
17
19
|
{ "type": "barChart", "label": "Point History", "scope": "detail" }
|
|
18
20
|
]
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
2
|
+
<path fill="black" d="M12 2.5c5.25 0 9.5 4.25 9.5 9.5s-4.25 9.5-9.5 9.5S2.5 17.25 2.5 12 6.75 2.5 12 2.5Zm0 3.2A6.3 6.3 0 1 0 12 18.3 6.3 6.3 0 0 0 12 5.7Zm0 2.8a3.5 3.5 0 0 1 3.5 3.5c0 .75-.23 1.44-.62 2.01l1.18 1.18-1.98 1.98-1.18-1.18A3.5 3.5 0 1 1 12 8.5Zm0 2.5a1 1 0 1 0 0 2 1 1 0 0 0 0-2Z"/>
|
|
3
|
+
</svg>
|