@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,145 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var DEFAULT_API_VERSION = "2024-10-21";
|
|
3
|
+
|
|
4
|
+
function trim(value) {
|
|
5
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function env(ctx, name) {
|
|
9
|
+
try {
|
|
10
|
+
return trim(ctx.host.env.get(name));
|
|
11
|
+
} catch (_) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function settings(ctx) {
|
|
17
|
+
return ctx.provider && ctx.provider.settings ? ctx.provider.settings : {};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function parseSavedConfig(ctx, raw) {
|
|
21
|
+
var text = trim(raw);
|
|
22
|
+
if (!text) return null;
|
|
23
|
+
var parsed = ctx.util.tryParseJson(text);
|
|
24
|
+
if (parsed && typeof parsed === "object") {
|
|
25
|
+
return {
|
|
26
|
+
apiKey: trim(parsed.apiKey || parsed.api_key),
|
|
27
|
+
endpoint: trim(parsed.endpoint),
|
|
28
|
+
deployment: trim(parsed.deployment || parsed.deploymentName || parsed.deployment_name),
|
|
29
|
+
apiVersion: trim(parsed.apiVersion || parsed.api_version),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
var parts = text.split("|").map(function (part) { return part.trim(); });
|
|
33
|
+
if (parts.length >= 3) {
|
|
34
|
+
return {
|
|
35
|
+
apiKey: trim(parts[0]),
|
|
36
|
+
endpoint: trim(parts[1]),
|
|
37
|
+
deployment: trim(parts[2]),
|
|
38
|
+
apiVersion: trim(parts[3]),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return { apiKey: text };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function resolveConfig(ctx) {
|
|
45
|
+
var s = settings(ctx);
|
|
46
|
+
var saved = parseSavedConfig(ctx, ctx.provider && ctx.provider.apiKey);
|
|
47
|
+
var config = {
|
|
48
|
+
apiKey: trim(s.apiKey) || (saved && saved.apiKey) || env(ctx, "AZURE_OPENAI_API_KEY"),
|
|
49
|
+
endpoint: trim(s.endpoint) || (saved && saved.endpoint) || env(ctx, "AZURE_OPENAI_ENDPOINT"),
|
|
50
|
+
deployment: trim(s.deployment) || trim(s.deploymentName) || (saved && saved.deployment) ||
|
|
51
|
+
env(ctx, "AZURE_OPENAI_DEPLOYMENT") || env(ctx, "AZURE_OPENAI_DEPLOYMENT_NAME"),
|
|
52
|
+
apiVersion: trim(s.apiVersion) || trim(s.api_version) || (saved && saved.apiVersion) ||
|
|
53
|
+
env(ctx, "AZURE_OPENAI_API_VERSION") || DEFAULT_API_VERSION,
|
|
54
|
+
};
|
|
55
|
+
if (!config.apiKey) throw "Azure OpenAI API key not configured. Set AZURE_OPENAI_API_KEY.";
|
|
56
|
+
if (!config.endpoint) throw "Azure OpenAI endpoint not configured. Set AZURE_OPENAI_ENDPOINT.";
|
|
57
|
+
if (!config.deployment) throw "Azure OpenAI deployment not configured. Set AZURE_OPENAI_DEPLOYMENT.";
|
|
58
|
+
return config;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function endpointBase(raw) {
|
|
62
|
+
var value = String(raw || "").trim().replace(/\/+$/, "");
|
|
63
|
+
if (!/^https?:\/\//i.test(value)) value = "https://" + value;
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function stripSuffix(value, suffix) {
|
|
68
|
+
var lower = value.toLowerCase();
|
|
69
|
+
return lower.endsWith(suffix) ? value.slice(0, value.length - suffix.length) : value;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function chatUrl(config) {
|
|
73
|
+
var base = endpointBase(config.endpoint);
|
|
74
|
+
if (String(config.apiVersion).trim().toLowerCase() === "v1") {
|
|
75
|
+
base = stripSuffix(stripSuffix(base, "/openai/v1"), "/openai");
|
|
76
|
+
return base + "/openai/v1/chat/completions";
|
|
77
|
+
}
|
|
78
|
+
base = stripSuffix(base, "/openai");
|
|
79
|
+
return base + "/openai/deployments/" + encodeURIComponent(config.deployment) +
|
|
80
|
+
"/chat/completions?api-version=" + encodeURIComponent(config.apiVersion);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function validationBody(config) {
|
|
84
|
+
if (String(config.apiVersion).trim().toLowerCase() === "v1") {
|
|
85
|
+
return JSON.stringify({
|
|
86
|
+
model: config.deployment,
|
|
87
|
+
messages: [{ role: "user", content: "ping" }],
|
|
88
|
+
max_completion_tokens: 1,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return JSON.stringify({
|
|
92
|
+
messages: [{ role: "user", content: "ping" }],
|
|
93
|
+
max_tokens: 1,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function responseSummary(bodyText) {
|
|
98
|
+
var collapsed = String(bodyText || "").split(/\s+/).filter(Boolean).join(" ");
|
|
99
|
+
return collapsed.length > 240 ? collapsed.slice(0, 240) + "... [truncated]" : collapsed;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function probe(ctx) {
|
|
103
|
+
var config = resolveConfig(ctx);
|
|
104
|
+
var resp;
|
|
105
|
+
try {
|
|
106
|
+
resp = ctx.util.request({
|
|
107
|
+
method: "POST",
|
|
108
|
+
url: chatUrl(config),
|
|
109
|
+
headers: {
|
|
110
|
+
"api-key": config.apiKey,
|
|
111
|
+
Accept: "application/json",
|
|
112
|
+
"Content-Type": "application/json",
|
|
113
|
+
},
|
|
114
|
+
bodyText: validationBody(config),
|
|
115
|
+
timeoutMs: 15000,
|
|
116
|
+
});
|
|
117
|
+
} catch (_) {
|
|
118
|
+
throw "Azure OpenAI validation request failed. Check your connection.";
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (ctx.util.isAuthStatus(resp.status)) {
|
|
122
|
+
throw "Azure OpenAI API key is invalid or unauthorized.";
|
|
123
|
+
}
|
|
124
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
125
|
+
throw "Azure OpenAI API error: HTTP " + resp.status + ": " + responseSummary(resp.bodyText);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
var parsed = ctx.util.tryParseJson(resp.bodyText);
|
|
129
|
+
if (!parsed || typeof parsed !== "object") {
|
|
130
|
+
throw "Azure OpenAI response was not valid JSON.";
|
|
131
|
+
}
|
|
132
|
+
var model = trim(parsed.model);
|
|
133
|
+
var subtitle = model ? "Deployment: " + config.deployment + " / Model: " + model : "Deployment: " + config.deployment;
|
|
134
|
+
return {
|
|
135
|
+
displayName: "Azure OpenAI",
|
|
136
|
+
source: "api",
|
|
137
|
+
plan: config.deployment,
|
|
138
|
+
lines: [
|
|
139
|
+
ctx.line.badge({ label: "Deployment", text: "Validated", color: "#22c55e", subtitle: subtitle }),
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
globalThis.__openusage_plugin = { id: "azure-openai", probe: probe };
|
|
145
|
+
})();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "azure-openai",
|
|
4
|
+
"name": "Azure OpenAI",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"brandColor": "#0078D4",
|
|
8
|
+
"links": [
|
|
9
|
+
{ "label": "AI Foundry", "url": "https://ai.azure.com" },
|
|
10
|
+
{ "label": "Azure Status", "url": "https://azure.status.microsoft/en-us/status" }
|
|
11
|
+
],
|
|
12
|
+
"supportedModes": ["api"],
|
|
13
|
+
"autoMode": "api",
|
|
14
|
+
"lines": [
|
|
15
|
+
{ "type": "badge", "label": "Deployment", "scope": "overview", "primaryOrder": 1 }
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg viewBox="0 0 32 32" fill="#3184FF" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<title>Chutes</title>
|
|
3
|
+
<path d="M16 3c-6.1 0-11 4.9-11 11h5c0-3.3 2.7-6 6-6s6 2.7 6 6h5c0-6.1-4.9-11-11-11Z"/>
|
|
4
|
+
<path d="M11 14h10l-5 8-5-8Z"/>
|
|
5
|
+
<path d="M15 21h2v5h-2v-5Z"/>
|
|
6
|
+
<path d="M11 26h10v3H11v-3Z"/>
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var DEFAULT_BASE = "https://api.chutes.ai";
|
|
3
|
+
|
|
4
|
+
function env(ctx, name) {
|
|
5
|
+
try {
|
|
6
|
+
var value = ctx.host.env.get(name);
|
|
7
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
8
|
+
} catch (_) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function apiKey(ctx) {
|
|
14
|
+
var configured = ctx.provider && typeof ctx.provider.apiKey === "string" ? ctx.provider.apiKey.trim() : "";
|
|
15
|
+
return configured || env(ctx, "CHUTES_API_KEY");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function apiBase(ctx) {
|
|
19
|
+
var configured = ctx.provider && ctx.provider.settings && typeof ctx.provider.settings.apiUrl === "string"
|
|
20
|
+
? ctx.provider.settings.apiUrl.trim()
|
|
21
|
+
: "";
|
|
22
|
+
var base = configured || env(ctx, "CHUTES_API_URL") || DEFAULT_BASE;
|
|
23
|
+
base = base.replace(/\/+$/, "");
|
|
24
|
+
if (!/^https:\/\//i.test(base)) throw "Chutes API URL must be HTTPS.";
|
|
25
|
+
return base;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function numberValue(value) {
|
|
29
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
30
|
+
if (typeof value === "string" && value.trim()) {
|
|
31
|
+
var parsed = Number(value.replace(/,/g, ""));
|
|
32
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function boolValue(value) {
|
|
38
|
+
if (typeof value === "boolean") return value;
|
|
39
|
+
if (typeof value === "string") {
|
|
40
|
+
var lower = value.trim().toLowerCase();
|
|
41
|
+
if (lower === "true" || lower === "active") return true;
|
|
42
|
+
if (lower === "false" || lower === "inactive") return false;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function first(obj, keys) {
|
|
48
|
+
if (!obj || typeof obj !== "object") return undefined;
|
|
49
|
+
for (var i = 0; i < keys.length; i++) {
|
|
50
|
+
if (obj[keys[i]] !== undefined && obj[keys[i]] !== null) return obj[keys[i]];
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function requestJson(ctx, base, path, key) {
|
|
56
|
+
var resp = ctx.util.request({
|
|
57
|
+
method: "GET",
|
|
58
|
+
url: base + path,
|
|
59
|
+
headers: { Authorization: "Bearer " + key, Accept: "application/json" },
|
|
60
|
+
timeoutMs: 15000,
|
|
61
|
+
});
|
|
62
|
+
if (ctx.util.isAuthStatus(resp.status)) throw "Chutes API key was rejected.";
|
|
63
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
64
|
+
throw "Chutes API request failed (HTTP " + resp.status + ").";
|
|
65
|
+
}
|
|
66
|
+
var json = ctx.util.tryParseJson(resp.bodyText);
|
|
67
|
+
if (!json) throw "Chutes response was not valid JSON.";
|
|
68
|
+
return json;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function dataRoot(root) {
|
|
72
|
+
if (root && root.data && typeof root.data === "object" && !Array.isArray(root.data)) return root.data;
|
|
73
|
+
if (root && root.result && typeof root.result === "object" && !Array.isArray(root.result)) return root.result;
|
|
74
|
+
return root && typeof root === "object" ? root : {};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function parseDate(value) {
|
|
78
|
+
if (typeof value === "number" && Number.isFinite(value)) return new Date(value > 10000000000 ? value : value * 1000);
|
|
79
|
+
if (typeof value === "string" && value.trim()) {
|
|
80
|
+
var numeric = Number(value);
|
|
81
|
+
if (Number.isFinite(numeric)) return parseDate(numeric);
|
|
82
|
+
var ms = Date.parse(value);
|
|
83
|
+
if (Number.isFinite(ms)) return new Date(ms);
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function normalizePercent(value) {
|
|
89
|
+
var n = numberValue(value);
|
|
90
|
+
if (n == null) return null;
|
|
91
|
+
if (n <= 1 && n >= 0) n = n * 100;
|
|
92
|
+
return Math.max(0, Math.min(100, n));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function windowMinutes(payload) {
|
|
96
|
+
var minutes = numberValue(first(payload, ["window_minutes", "windowMinutes", "period_minutes", "periodMinutes"]));
|
|
97
|
+
if (minutes != null) return Math.round(minutes);
|
|
98
|
+
var hours = numberValue(first(payload, ["window_hours", "windowHours", "period_hours", "periodHours"]));
|
|
99
|
+
if (hours != null) return Math.round(hours * 60);
|
|
100
|
+
var days = numberValue(first(payload, ["window_days", "windowDays", "period_days", "periodDays"]));
|
|
101
|
+
if (days != null) return Math.round(days * 24 * 60);
|
|
102
|
+
var seconds = numberValue(first(payload, ["window_seconds", "windowSeconds", "period_seconds", "periodSeconds"]));
|
|
103
|
+
if (seconds != null) return Math.round(seconds / 60);
|
|
104
|
+
var text = first(payload, ["window", "period", "duration"]);
|
|
105
|
+
if (typeof text === "string") {
|
|
106
|
+
var match = text.trim().toLowerCase().match(/^(\d+(?:\.\d+)?)\s*(m|min|minute|minutes|h|hr|hour|hours|d|day|days|mo|month|months)/);
|
|
107
|
+
if (match) {
|
|
108
|
+
var value = Number(match[1]);
|
|
109
|
+
var unit = match[2];
|
|
110
|
+
if (unit[0] === "m" && unit !== "mo" && unit.indexOf("month") !== 0) return Math.round(value);
|
|
111
|
+
if (unit[0] === "h") return Math.round(value * 60);
|
|
112
|
+
if (unit[0] === "d") return Math.round(value * 24 * 60);
|
|
113
|
+
return Math.round(value * 30 * 24 * 60);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function parseQuota(payload, fallbackLabel, fallbackWindow) {
|
|
120
|
+
if (!payload || typeof payload !== "object") return null;
|
|
121
|
+
var limit = numberValue(first(payload, ["limit", "quota", "max", "monthly_limit", "monthlyLimit"]));
|
|
122
|
+
var used = numberValue(first(payload, ["used", "usage", "consumed", "current_usage", "currentUsage"]));
|
|
123
|
+
var remaining = numberValue(first(payload, ["remaining", "available", "left"]));
|
|
124
|
+
var percent = normalizePercent(first(payload, ["used_percent", "usedPercent", "usage_percent", "usagePercent", "percent_used", "percentUsed"]));
|
|
125
|
+
var remainingPercent = normalizePercent(first(payload, ["remaining_percent", "remainingPercent", "percent_remaining", "percentRemaining"]));
|
|
126
|
+
if (percent == null && remainingPercent != null) percent = 100 - remainingPercent;
|
|
127
|
+
if (limit == null && used != null && remaining != null) limit = used + remaining;
|
|
128
|
+
if (used == null && limit != null && remaining != null) used = Math.max(0, limit - remaining);
|
|
129
|
+
if (percent == null && used != null && limit > 0) percent = (used / limit) * 100;
|
|
130
|
+
if (percent == null) return null;
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
label: String(first(payload, ["label", "name", "quota_name", "quotaName", "chute_id", "chuteId"]) || fallbackLabel || "Quota"),
|
|
134
|
+
used: used,
|
|
135
|
+
limit: limit,
|
|
136
|
+
percent: Math.max(0, Math.min(100, percent)),
|
|
137
|
+
windowMinutes: windowMinutes(payload) || fallbackWindow || null,
|
|
138
|
+
resetsAt: parseDate(first(payload, ["resets_at", "resetsAt", "reset_at", "resetAt", "renews_at", "renewsAt", "expires_at", "expiresAt"])),
|
|
139
|
+
unit: String(first(payload, ["unit", "units"]) || "credits"),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function collectQuotaObjects(value, out) {
|
|
144
|
+
if (!value || typeof value !== "object") return;
|
|
145
|
+
if (Array.isArray(value)) {
|
|
146
|
+
for (var i = 0; i < value.length; i++) collectQuotaObjects(value[i], out);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (
|
|
150
|
+
first(value, ["limit", "quota", "used", "usage", "remaining", "used_percent", "usedPercent", "usage_percent", "usagePercent"]) !== undefined
|
|
151
|
+
) {
|
|
152
|
+
out.push(value);
|
|
153
|
+
}
|
|
154
|
+
var keys = Object.keys(value);
|
|
155
|
+
for (var j = 0; j < keys.length; j++) collectQuotaObjects(value[keys[j]], out);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function kindFor(window) {
|
|
159
|
+
var label = (window.label + " " + (window.unit || "")).toLowerCase();
|
|
160
|
+
if (label.indexOf("rolling") >= 0 || label.indexOf("4-hour") >= 0 || label.indexOf("4h") >= 0 || window.windowMinutes === 240) return "rolling";
|
|
161
|
+
if (label.indexOf("month") >= 0 || label.indexOf("billing") >= 0 || label.indexOf("subscription") >= 0 || (window.windowMinutes || 0) >= 28 * 24 * 60) return "monthly";
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function appendQuotaLine(lines, quota, label) {
|
|
166
|
+
if (!quota) return;
|
|
167
|
+
var text = "";
|
|
168
|
+
if (quota.used != null && quota.limit != null) text = fmtAmount(quota.used) + " / " + fmtAmount(quota.limit) + " " + quota.unit;
|
|
169
|
+
lines.push(ctxLineProgress(label || quota.label, quota.percent, quota.resetsAt, quota.windowMinutes));
|
|
170
|
+
if (text) lines.push({ type: "text", label: (label || quota.label) + " Used", value: text });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function ctxLineProgress(label, percent, resetsAt, windowMinutes) {
|
|
174
|
+
var line = {
|
|
175
|
+
type: "progress",
|
|
176
|
+
label: label,
|
|
177
|
+
used: Math.max(0, Math.min(100, percent)),
|
|
178
|
+
limit: 100,
|
|
179
|
+
format: { kind: "percent" },
|
|
180
|
+
};
|
|
181
|
+
if (resetsAt) line.resetsAt = resetsAt.toISOString();
|
|
182
|
+
if (windowMinutes) line.periodDurationMs = windowMinutes * 60 * 1000;
|
|
183
|
+
return line;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function fmtAmount(value) {
|
|
187
|
+
var n = Number(value) || 0;
|
|
188
|
+
if (Math.abs(n - Math.round(n)) < 0.0001) return String(Math.round(n));
|
|
189
|
+
return n.toFixed(2).replace(/\.?0+$/, "");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function parseSnapshot(root) {
|
|
193
|
+
var data = dataRoot(root);
|
|
194
|
+
var all = [];
|
|
195
|
+
collectQuotaObjects(root, all);
|
|
196
|
+
var windows = all.map(function (payload) { return parseQuota(payload, null, null); }).filter(Boolean);
|
|
197
|
+
var rolling = parseQuota(first(data, ["rolling", "rolling_window", "rollingWindow", "four_hour", "fourHour"]), "4-hour quota", 240) ||
|
|
198
|
+
windows.find(function (w) { return kindFor(w) === "rolling"; });
|
|
199
|
+
var monthly = parseQuota(first(data, ["monthly", "monthly_window", "monthlyWindow", "subscription", "subscription_usage", "subscriptionUsage"]), "Monthly quota", 30 * 24 * 60) ||
|
|
200
|
+
windows.find(function (w) { return kindFor(w) === "monthly"; });
|
|
201
|
+
var active = boolValue(first(data, ["active", "is_active", "isActive"]));
|
|
202
|
+
var status = String(first(data, ["status", "subscription_state", "subscriptionState"]) || "").trim();
|
|
203
|
+
var plan = String(first(data, ["plan", "plan_name", "planName", "tier", "subscription_tier", "subscriptionTier"]) || "").trim();
|
|
204
|
+
return { rolling: rolling, monthly: monthly, windows: windows, active: active, status: status, plan: plan };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function probe(ctx) {
|
|
208
|
+
var key = apiKey(ctx);
|
|
209
|
+
if (!key) throw "Missing Chutes API key. Set CHUTES_API_KEY or provider apiKey.";
|
|
210
|
+
var base = apiBase(ctx);
|
|
211
|
+
var snapshot = parseSnapshot(requestJson(ctx, base, "/users/me/subscription_usage", key));
|
|
212
|
+
if (!snapshot.rolling || !snapshot.monthly) {
|
|
213
|
+
try {
|
|
214
|
+
var fallback = parseSnapshot(requestJson(ctx, base, "/users/me/quotas", key));
|
|
215
|
+
snapshot.rolling = snapshot.rolling || fallback.rolling;
|
|
216
|
+
snapshot.monthly = snapshot.monthly || fallback.monthly;
|
|
217
|
+
snapshot.windows = snapshot.windows.concat(fallback.windows || []);
|
|
218
|
+
} catch (e) {
|
|
219
|
+
ctx.host.log.warn("chutes quota fallback failed: " + String(e));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
var lines = [];
|
|
224
|
+
appendQuotaLine(lines, snapshot.rolling, "4-hour quota");
|
|
225
|
+
appendQuotaLine(lines, snapshot.monthly, "Monthly quota");
|
|
226
|
+
for (var i = 0; i < snapshot.windows.length && lines.length < 8; i++) {
|
|
227
|
+
var w = snapshot.windows[i];
|
|
228
|
+
if (w === snapshot.rolling || w === snapshot.monthly) continue;
|
|
229
|
+
appendQuotaLine(lines, w, w.label);
|
|
230
|
+
}
|
|
231
|
+
if (!lines.length) lines.push({ type: "badge", label: "Status", text: snapshot.active === false ? "No active subscription" : "No usage data", color: "yellow" });
|
|
232
|
+
return { displayName: "Chutes", source: "api", plan: snapshot.plan || snapshot.status || null, lines: lines };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
globalThis.__openusage_plugin = { id: "chutes", probe: probe };
|
|
236
|
+
})();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "chutes",
|
|
4
|
+
"name": "Chutes",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"icon": "icon.svg",
|
|
8
|
+
"brandColor": "#67E8F9",
|
|
9
|
+
"links": [
|
|
10
|
+
{ "label": "Dashboard", "url": "https://chutes.ai" },
|
|
11
|
+
{ "label": "Docs", "url": "https://chutes.ai/docs/getting-started/authentication" }
|
|
12
|
+
],
|
|
13
|
+
"supportedModes": ["api"],
|
|
14
|
+
"autoMode": "api",
|
|
15
|
+
"lines": [
|
|
16
|
+
{ "type": "progress", "label": "4-hour quota", "scope": "overview", "primaryOrder": 1 },
|
|
17
|
+
{ "type": "progress", "label": "Monthly quota", "scope": "overview", "primaryOrder": 2 }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Claude</title><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z" fill="#D97757" fill-rule="nonzero"></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>Claude</title><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z"></path></svg>
|