@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,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "cursor-nightly",
|
|
4
|
+
"name": "Cursor Nightly",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"icon": "icon.png",
|
|
8
|
+
"brandColor": "#E85D3A",
|
|
9
|
+
"supportedModes": ["oauth", "local"],
|
|
10
|
+
"autoMode": "local",
|
|
11
|
+
"links": [
|
|
12
|
+
{ "label": "Status", "url": "https://status.cursor.com/" },
|
|
13
|
+
{ "label": "Dashboard", "url": "https://www.cursor.com/dashboard" }
|
|
14
|
+
],
|
|
15
|
+
"lines": [
|
|
16
|
+
{ "type": "progress", "label": "Credits", "scope": "overview", "primaryOrder": 2 },
|
|
17
|
+
{ "type": "progress", "label": "Total usage", "scope": "overview", "primaryOrder": 1 },
|
|
18
|
+
{ "type": "progress", "label": "Requests", "scope": "overview", "primaryOrder": 3 },
|
|
19
|
+
{ "type": "progress", "label": "Auto usage", "scope": "detail" },
|
|
20
|
+
{ "type": "progress", "label": "API usage", "scope": "detail" },
|
|
21
|
+
{ "type": "progress", "label": "On-demand", "scope": "detail" }
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><title>Deepgram SVG Icon</title><path fill="currentColor" d="M11.203 24H1.517a.364.364 0 0 1-.258-.62l6.239-6.275a.37.37 0 0 1 .259-.108h3.52c2.723 0 5.025-2.127 5.107-4.845a5.004 5.004 0 0 0-4.999-5.148H7.613v4.646c0 .2-.164.364-.365.364H.968a.365.365 0 0 1-.363-.364V.364C.605.164.768 0 .969 0h10.416c6.684 0 12.111 5.485 12.01 12.187C23.293 18.77 17.794 24 11.202 24z"/></svg>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
function probe(ctx) {
|
|
3
|
+
var key = ctx.host.env.get("DEEPGRAM_API_KEY");
|
|
4
|
+
if (!key) throw "Deepgram API key not found. Set DEEPGRAM_API_KEY.";
|
|
5
|
+
|
|
6
|
+
var result = ctx.util.requestJson({
|
|
7
|
+
method: "GET",
|
|
8
|
+
url: "https://api.deepgram.com/v1/projects",
|
|
9
|
+
headers: { Authorization: "Token " + key, Accept: "application/json" },
|
|
10
|
+
timeoutMs: 15000,
|
|
11
|
+
});
|
|
12
|
+
if (ctx.util.isAuthStatus(result.resp.status)) throw "Deepgram API key invalid or expired.";
|
|
13
|
+
if (result.resp.status < 200 || result.resp.status >= 300) throw "Deepgram API error (HTTP " + result.resp.status + ").";
|
|
14
|
+
var projects = result.json && result.json.projects;
|
|
15
|
+
if (!Array.isArray(projects)) throw "Could not parse Deepgram projects response.";
|
|
16
|
+
return { lines: [ctx.line.text({ label: "Projects", value: String(projects.length) })] };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
globalThis.__openusage_plugin = { id: "deepgram", probe: probe };
|
|
20
|
+
})();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "deepgram",
|
|
4
|
+
"name": "Deepgram",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"brandColor": "#13EF93",
|
|
8
|
+
"links": [
|
|
9
|
+
{ "label": "Console", "url": "https://console.deepgram.com" },
|
|
10
|
+
{ "label": "Status", "url": "https://status.deepgram.com" }
|
|
11
|
+
],
|
|
12
|
+
"supportedModes": ["api"],
|
|
13
|
+
"autoMode": "api",
|
|
14
|
+
"lines": [
|
|
15
|
+
{ "type": "text", "label": "Projects", "scope": "overview", "primaryOrder": 1 }
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -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>DeepSeek</title><path d="M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z" fill="#4D6BFE"></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>DeepSeek</title><path d="M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z"></path></svg>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var API_URL = "https://api.deepseek.com/user/balance";
|
|
3
|
+
|
|
4
|
+
function loadApiKey(ctx) {
|
|
5
|
+
var names = ["DEEPSEEK_API_KEY", "DEEPSEEK_KEY"];
|
|
6
|
+
for (var i = 0; i < names.length; i++) {
|
|
7
|
+
var v = ctx.host.env.get(names[i]);
|
|
8
|
+
if (typeof v === "string" && v.trim()) return v.trim();
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function probe(ctx) {
|
|
14
|
+
var apiKey = loadApiKey(ctx);
|
|
15
|
+
if (!apiKey) {
|
|
16
|
+
throw "DeepSeek API key not found. Set DEEPSEEK_API_KEY or DEEPSEEK_KEY.";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var result = ctx.util.requestJson({
|
|
20
|
+
method: "GET",
|
|
21
|
+
url: API_URL,
|
|
22
|
+
headers: { Authorization: "Bearer " + apiKey, Accept: "application/json" },
|
|
23
|
+
timeoutMs: 15000,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (ctx.util.isAuthStatus(result.resp.status)) {
|
|
27
|
+
throw "API key invalid or expired.";
|
|
28
|
+
}
|
|
29
|
+
if (result.resp.status < 200 || result.resp.status >= 300) {
|
|
30
|
+
throw "DeepSeek API error (HTTP " + result.resp.status + ").";
|
|
31
|
+
}
|
|
32
|
+
if (!result.json) throw "Could not parse DeepSeek balance response.";
|
|
33
|
+
|
|
34
|
+
var infos = result.json.balance_infos || [];
|
|
35
|
+
var info = null;
|
|
36
|
+
for (var i = 0; i < infos.length; i++) {
|
|
37
|
+
if ((infos[i].currency || "").toUpperCase() === "USD") { info = infos[i]; break; }
|
|
38
|
+
}
|
|
39
|
+
if (!info && infos.length > 0) info = infos[0];
|
|
40
|
+
|
|
41
|
+
var lines = [];
|
|
42
|
+
if (!info) {
|
|
43
|
+
lines.push(ctx.line.badge({ label: "Balance", text: "No balance data", color: "#a3a3a3" }));
|
|
44
|
+
return { lines: lines };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
var total = parseFloat(info.total_balance) || 0;
|
|
48
|
+
var granted = parseFloat(info.granted_balance) || 0;
|
|
49
|
+
var toppedUp = parseFloat(info.topped_up_balance) || 0;
|
|
50
|
+
var symbol = (info.currency || "").toUpperCase() === "CNY" ? "¥" : "$";
|
|
51
|
+
var available = result.json.is_available !== false;
|
|
52
|
+
|
|
53
|
+
var detail;
|
|
54
|
+
if (!available) {
|
|
55
|
+
detail = "Balance unavailable for API calls";
|
|
56
|
+
} else if (total <= 0) {
|
|
57
|
+
detail = symbol + "0.00 — add credits at platform.deepseek.com";
|
|
58
|
+
} else {
|
|
59
|
+
detail = symbol + total.toFixed(2) + " (Paid: " + symbol + toppedUp.toFixed(2) + " / Granted: " + symbol + granted.toFixed(2) + ")";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
lines.push(ctx.line.text({ label: "Balance", value: detail }));
|
|
63
|
+
if (!available) {
|
|
64
|
+
lines.push(ctx.line.badge({ label: "Status", text: "Unavailable", color: "#ef4444" }));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return { lines: lines };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
globalThis.__openusage_plugin = { id: "deepseek", probe: probe };
|
|
71
|
+
})();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "deepseek",
|
|
4
|
+
"name": "DeepSeek",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"brandColor": "#4D6BFE",
|
|
8
|
+
"links": [
|
|
9
|
+
{ "label": "Platform", "url": "https://platform.deepseek.com/usage" }
|
|
10
|
+
],
|
|
11
|
+
"usageDashboardUrl": "https://platform.deepseek.com/usage",
|
|
12
|
+
"supportedModes": ["api"],
|
|
13
|
+
"autoMode": "api",
|
|
14
|
+
"lines": [
|
|
15
|
+
{ "type": "text", "label": "Balance", "scope": "overview" }
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg width="100" height="100" viewBox="0 0 44 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill="currentColor" d="M1.117,20.553l5.351,3.089c0.192,0.111,0.406,0.165,0.621,0.165c0.214,0,0.429-0.057,0.621-0.165l5.351-3.089 c0,0,0.015-0.012,0.022-0.017c0.081-0.049,0.158-0.108,0.227-0.175c0.01-0.01,0.02-0.022,0.03-0.032 c0.059-0.064,0.113-0.133,0.158-0.207c0.007-0.012,0.017-0.022,0.022-0.035c0.047-0.081,0.081-0.167,0.108-0.259 c0.005-0.02,0.01-0.039,0.015-0.059c0.022-0.094,0.039-0.19,0.039-0.291v-3.089c0-1.192,0.643-2.303,1.675-2.9s2.316-0.596,3.35,0 l2.675,1.545c0.086,0.049,0.177,0.084,0.271,0.111c0.02,0.005,0.04,0.012,0.059,0.017c0.091,0.022,0.185,0.035,0.278,0.037 c0.005,0,0.01,0,0.012,0c0.01,0,0.02-0.005,0.029-0.005c0.086,0,0.173-0.012,0.256-0.035c0.015-0.003,0.03-0.005,0.044-0.01 c0.091-0.025,0.18-0.062,0.264-0.108c0.007-0.005,0.017-0.005,0.025-0.01l5.351-3.089c0.384-0.222,0.621-0.631,0.621-1.074V4.69 c0-0.443-0.236-0.852-0.621-1.074l-5.356-3.087c-0.384-0.222-0.855-0.222-1.239,0l-5.351,3.089c0,0-0.015,0.012-0.022,0.017 c-0.081,0.049-0.158,0.108-0.227,0.175c-0.01,0.01-0.02,0.022-0.03,0.032c-0.059,0.064-0.113,0.133-0.158,0.207 c-0.007,0.012-0.017,0.022-0.022,0.034c-0.047,0.081-0.081,0.168-0.108,0.259c-0.005,0.02-0.01,0.039-0.015,0.059 c-0.022,0.094-0.039,0.19-0.039,0.291v3.089c0,1.192-0.643,2.303-1.675,2.902c-1.032,0.596-2.316,0.596-3.35,0L7.705,9.139 C7.618,9.09,7.527,9.055,7.434,9.028c-0.02-0.005-0.039-0.012-0.059-0.017C7.283,8.989,7.19,8.977,7.096,8.974 c-0.015,0-0.027,0-0.042,0c-0.089,0-0.175,0.012-0.259,0.034c-0.015,0.002-0.027,0.005-0.042,0.01 C6.663,9.043,6.574,9.08,6.49,9.127c-0.007,0.005-0.017,0.005-0.025,0.01l-5.348,3.092c-0.384,0.222-0.621,0.631-0.621,1.074v6.178 c0,0.444,0.236,0.852,0.621,1.074V20.553z"></path>
|
|
3
|
+
<path fill="currentColor" d="M30.262,22.097c1.032-0.596,2.316-0.596,3.35,0l2.675,1.545c0.086,0.049,0.177,0.084,0.271,0.111 c0.02,0.005,0.039,0.012,0.059,0.017c0.091,0.022,0.185,0.034,0.278,0.037c0.005,0,0.01,0,0.012,0c0.01,0,0.02-0.003,0.029-0.005 c0.086,0,0.173-0.012,0.256-0.034c0.015-0.003,0.03-0.005,0.044-0.01c0.091-0.025,0.177-0.062,0.264-0.108 c0.007-0.005,0.017-0.005,0.027-0.01l5.351-3.089c0.384-0.222,0.621-0.631,0.621-1.074v-6.179c0-0.443-0.237-0.852-0.621-1.074 L37.53,9.134c-0.384-0.222-0.855-0.222-1.239,0l-5.351,3.089c0,0-0.015,0.012-0.022,0.017c-0.081,0.049-0.158,0.108-0.227,0.175 c-0.01,0.01-0.02,0.022-0.029,0.032c-0.059,0.064-0.113,0.133-0.158,0.207c-0.007,0.012-0.017,0.022-0.022,0.035 c-0.047,0.081-0.081,0.168-0.108,0.259c-0.005,0.02-0.01,0.039-0.015,0.059c-0.022,0.094-0.039,0.19-0.039,0.291v3.089 c0,1.192-0.643,2.303-1.675,2.902c-1.032,0.596-2.316,0.596-3.35,0l-2.675-1.545c-0.086-0.049-0.177-0.084-0.271-0.111 c-0.02-0.005-0.039-0.012-0.059-0.017c-0.091-0.022-0.185-0.035-0.278-0.037c-0.015,0-0.027,0-0.042,0 c-0.089,0-0.175,0.012-0.259,0.035c-0.015,0.003-0.027,0.005-0.042,0.01c-0.091,0.025-0.18,0.062-0.264,0.108 c-0.007,0.005-0.017,0.005-0.025,0.01l-5.351,3.089c-0.384,0.222-0.621,0.631-0.621,1.074v6.179c0,0.443,0.236,0.852,0.621,1.074 l5.351,3.089c0,0,0.017,0.005,0.025,0.01c0.084,0.047,0.173,0.084,0.264,0.108c0.015,0.005,0.03,0.005,0.044,0.01 c0.084,0.02,0.17,0.032,0.256,0.035c0.01,0,0.02,0.005,0.03,0.005c0.005,0,0.01,0,0.012,0c0.094,0,0.185-0.015,0.278-0.037 c0.02-0.005,0.039-0.01,0.059-0.017c0.094-0.027,0.185-0.062,0.271-0.111l2.675-1.545c1.032-0.596,2.316-0.596,3.35,0 c1.032,0.596,1.675,1.707,1.675,2.9v3.089c0,0.101,0.015,0.197,0.039,0.291c0.005,0.02,0.01,0.039,0.015,0.059 c0.027,0.091,0.061,0.177,0.108,0.259c0.007,0.012,0.015,0.022,0.022,0.034c0.044,0.074,0.099,0.143,0.158,0.207 c0.01,0.01,0.02,0.022,0.029,0.032c0.067,0.066,0.143,0.123,0.227,0.175c0.007,0.005,0.012,0.012,0.022,0.017l5.351,3.089 c0.192,0.111,0.407,0.165,0.621,0.165c0.214,0,0.429-0.057,0.621-0.165l5.351-3.089c0.384-0.222,0.621-0.631,0.621-1.074v-6.179 c0-0.443-0.236-0.852-0.621-1.074l-5.351-3.089c0,0-0.017-0.005-0.025-0.01c-0.084-0.047-0.173-0.084-0.264-0.108 c-0.015-0.005-0.027-0.005-0.042-0.01c-0.086-0.02-0.172-0.032-0.261-0.035c-0.012,0-0.027,0-0.039,0 c-0.094,0-0.187,0.015-0.278,0.037c-0.02,0.005-0.037,0.01-0.057,0.017c-0.094,0.027-0.185,0.062-0.271,0.111l-2.675,1.545 c-1.032,0.596-2.316,0.596-3.348,0c-1.032-0.596-1.675-1.707-1.675-2.902c0-1.195,0.643-2.303,1.675-2.9H30.262z"></path>
|
|
4
|
+
<path fill="currentColor" d="M27.967,38.054l-5.351-3.089c0,0-0.017-0.005-0.025-0.01c-0.084-0.047-0.172-0.084-0.264-0.108 c-0.015-0.005-0.03-0.005-0.044-0.01c-0.086-0.02-0.172-0.032-0.259-0.035c-0.015,0-0.027,0-0.042,0 c-0.094,0-0.187,0.015-0.278,0.037c-0.02,0.005-0.037,0.01-0.057,0.017c-0.094,0.027-0.185,0.062-0.271,0.111l-2.675,1.545 c-1.032,0.596-2.316,0.596-3.348,0c-1.032-0.596-1.675-1.707-1.675-2.902V30.52c0-0.101-0.015-0.197-0.039-0.291 c-0.005-0.02-0.01-0.039-0.015-0.059c-0.027-0.091-0.062-0.177-0.108-0.259c-0.007-0.012-0.015-0.022-0.022-0.035 c-0.044-0.074-0.099-0.143-0.158-0.207c-0.01-0.01-0.02-0.022-0.03-0.032c-0.066-0.066-0.143-0.123-0.227-0.175 c-0.007-0.005-0.012-0.012-0.022-0.017l-5.351-3.089c-0.384-0.222-0.855-0.222-1.239,0l-5.351,3.089 c-0.384,0.222-0.621,0.631-0.621,1.074v6.179c0,0.443,0.236,0.852,0.621,1.074l5.351,3.089c0,0,0.017,0.007,0.025,0.01 c0.084,0.047,0.17,0.084,0.261,0.108c0.015,0.005,0.03,0.007,0.044,0.01c0.084,0.02,0.17,0.032,0.256,0.035 c0.01,0,0.02,0.005,0.032,0.005c0.005,0,0.01,0,0.015,0c0.094,0,0.185-0.015,0.276-0.037c0.02-0.005,0.039-0.01,0.059-0.017 c0.094-0.027,0.185-0.062,0.271-0.111l2.675-1.545c1.032-0.596,2.316-0.596,3.35,0c1.032,0.596,1.675,1.707,1.675,2.9v3.089 c0,0.101,0.015,0.197,0.039,0.291c0.005,0.02,0.01,0.039,0.015,0.059c0.027,0.091,0.062,0.177,0.108,0.259 c0.007,0.012,0.015,0.022,0.022,0.035c0.044,0.074,0.099,0.143,0.158,0.207c0.01,0.01,0.02,0.022,0.03,0.032 c0.067,0.067,0.143,0.123,0.227,0.175c0.007,0.005,0.012,0.012,0.022,0.017l5.351,3.089c0.192,0.111,0.406,0.165,0.621,0.165 s0.429-0.057,0.621-0.165l5.351-3.089c0.384-0.222,0.621-0.631,0.621-1.074V39.13c0-0.443-0.236-0.852-0.621-1.074L27.967,38.054z"></path>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var CLOUD_SERVICE = "exa.seat_management_pb.SeatManagementService"
|
|
3
|
+
var DEFAULT_API_SERVER_URL = "https://server.codeium.com"
|
|
4
|
+
var CLOUD_COMPAT_VERSION = "1.108.2"
|
|
5
|
+
var APP_STATE_VARIANTS = [
|
|
6
|
+
{id: "devin", source: "Devin app", appSupportRel: "Devin/User/globalStorage/state.vscdb"},
|
|
7
|
+
{id: "devin-next", source: "Devin - Next app", appSupportRel: "Devin - Next/User/globalStorage/state.vscdb"},
|
|
8
|
+
{id: "windsurf", source: "Devin app (legacy Windsurf)", appSupportRel: "Windsurf/User/globalStorage/state.vscdb"},
|
|
9
|
+
{id: "windsurf-next", source: "Windsurf - Next app", appSupportRel: "Windsurf - Next/User/globalStorage/state.vscdb"},
|
|
10
|
+
]
|
|
11
|
+
var LOGIN_HINT = "Run devin auth login or sign in to Devin and try again."
|
|
12
|
+
var QUOTA_HINT = "Devin quota data unavailable. Try again later."
|
|
13
|
+
var DAY_MS = 24 * 60 * 60 * 1000
|
|
14
|
+
var WEEK_MS = 7 * DAY_MS
|
|
15
|
+
|
|
16
|
+
function readFiniteNumber(value) {
|
|
17
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null
|
|
18
|
+
if (typeof value !== "string") return null
|
|
19
|
+
var trimmed = value.trim()
|
|
20
|
+
if (!trimmed) return null
|
|
21
|
+
var parsed = Number(trimmed)
|
|
22
|
+
return Number.isFinite(parsed) ? parsed : null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function clampPercent(value) {
|
|
26
|
+
if (!Number.isFinite(value)) return 0
|
|
27
|
+
if (value < 0) return 0
|
|
28
|
+
if (value > 100) return 100
|
|
29
|
+
return value
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function readTomlString(text, key) {
|
|
33
|
+
var lines = String(text || "").split(/\r?\n/)
|
|
34
|
+
var prefix = new RegExp("^\\s*" + key + "\\s*=\\s*(.*)$")
|
|
35
|
+
for (var i = 0; i < lines.length; i++) {
|
|
36
|
+
var match = prefix.exec(lines[i])
|
|
37
|
+
if (!match) continue
|
|
38
|
+
var value = match[1].trim()
|
|
39
|
+
if (!value) return null
|
|
40
|
+
if (value[0] === '"' || value[0] === "'") {
|
|
41
|
+
var quote = value[0]
|
|
42
|
+
var out = ""
|
|
43
|
+
for (var j = 1; j < value.length; j++) {
|
|
44
|
+
var ch = value[j]
|
|
45
|
+
if (ch === quote && value[j - 1] !== "\\") return out.trim() || null
|
|
46
|
+
out += ch
|
|
47
|
+
}
|
|
48
|
+
return null
|
|
49
|
+
}
|
|
50
|
+
var commentIndex = value.indexOf("#")
|
|
51
|
+
if (commentIndex >= 0) value = value.slice(0, commentIndex).trim()
|
|
52
|
+
return value || null
|
|
53
|
+
}
|
|
54
|
+
return null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function cleanApiServerUrl(value) {
|
|
58
|
+
if (typeof value !== "string") return null
|
|
59
|
+
var trimmed = value.trim().replace(/\/+$/, "")
|
|
60
|
+
if (!/^https:\/\//.test(trimmed)) return null
|
|
61
|
+
return trimmed
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function effectiveApiServerUrl(auth) {
|
|
65
|
+
return (auth && auth.apiServerUrl) || DEFAULT_API_SERVER_URL
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function hasOwn(obj, key) {
|
|
69
|
+
return Boolean(obj && Object.prototype.hasOwnProperty.call(obj, key))
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function readHost(value) {
|
|
73
|
+
if (typeof value !== "string") return null
|
|
74
|
+
var match = /^https?:\/\/([^/]+)/.exec(value.trim())
|
|
75
|
+
return match ? match[1] : null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function valueOrMissing(value) {
|
|
79
|
+
return value === null || value === undefined || value === "" ? "missing" : String(value)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function logQuotaDiagnostics(ctx, auth, userStatus) {
|
|
83
|
+
var planStatus = (userStatus && userStatus.planStatus) || {}
|
|
84
|
+
var planInfo = planStatus.planInfo || {}
|
|
85
|
+
var devinInfo = planInfo.devinInfo || {}
|
|
86
|
+
var apiServerHost = readHost(auth.apiServerUrl || DEFAULT_API_SERVER_URL)
|
|
87
|
+
var webappHost = readHost(devinInfo.webappHost) || devinInfo.webappHost || null
|
|
88
|
+
var devinApiHost = readHost(devinInfo.apiUrl)
|
|
89
|
+
|
|
90
|
+
ctx.host.log.info(
|
|
91
|
+
"Devin quota diagnostics" +
|
|
92
|
+
" source=" + auth.source +
|
|
93
|
+
" apiServerHost=" + valueOrMissing(apiServerHost) +
|
|
94
|
+
" planName=" + valueOrMissing(planInfo.planName) +
|
|
95
|
+
" teamsTier=" + valueOrMissing(userStatus && userStatus.teamsTier) +
|
|
96
|
+
" planTeamsTier=" + valueOrMissing(planInfo.teamsTier) +
|
|
97
|
+
" billingStrategy=" + valueOrMissing(planInfo.billingStrategy) +
|
|
98
|
+
" isDevin=" + String(planInfo.isDevin === true) +
|
|
99
|
+
" hideDailyQuota=" + String(planInfo.hideDailyQuota === true) +
|
|
100
|
+
" hasDailyQuotaPercent=" + String(hasOwn(planStatus, "dailyQuotaRemainingPercent")) +
|
|
101
|
+
" hasWeeklyQuotaPercent=" + String(hasOwn(planStatus, "weeklyQuotaRemainingPercent")) +
|
|
102
|
+
" hasOverageBalance=" + String(hasOwn(planStatus, "overageBalanceMicros")) +
|
|
103
|
+
" hasDailyReset=" + String(hasOwn(planStatus, "dailyQuotaResetAtUnix")) +
|
|
104
|
+
" hasWeeklyReset=" + String(hasOwn(planStatus, "weeklyQuotaResetAtUnix")) +
|
|
105
|
+
" hasTopUpStatus=" + String(hasOwn(planStatus, "topUpStatus")) +
|
|
106
|
+
" availablePromptCredits=" + valueOrMissing(planStatus.availablePromptCredits) +
|
|
107
|
+
" canUseCli=" + String(devinInfo.canUseCli === true) +
|
|
108
|
+
" canUseCascade=" + String(devinInfo.canUseCascade === true) +
|
|
109
|
+
" devinReviewEnabled=" + String(devinInfo.devinReviewEnabled === true) +
|
|
110
|
+
" webappHost=" + valueOrMissing(webappHost) +
|
|
111
|
+
" devinApiHost=" + valueOrMissing(devinApiHost)
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function settings(ctx) { return (ctx.provider && ctx.provider.settings) || {} }
|
|
116
|
+
|
|
117
|
+
function resolveCredentialsPath(ctx) {
|
|
118
|
+
var explicit = settings(ctx).credentialsPath
|
|
119
|
+
if (explicit) return ctx.host.fs.exists(explicit) ? explicit : null
|
|
120
|
+
// Carried CLI layout; credentialsPath supports other CLI versions without
|
|
121
|
+
// guessing a different account's directory. Never search Unix paths on Windows.
|
|
122
|
+
var paths = ctx.app.platform === "windows"
|
|
123
|
+
? [ctx.host.fs.localAppDataPath("devin/credentials.toml")]
|
|
124
|
+
: ["~/.local/share/devin/credentials.toml", "~/.local/share/cognition/credentials.toml"]
|
|
125
|
+
return ctx.host.fs.firstExisting(paths.filter(function(path) { return !!path })) || null
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function resolveStateDbForVariant(ctx, variant) {
|
|
129
|
+
var custom = settings(ctx).userDataDir
|
|
130
|
+
var path = custom ? custom.replace(/[\\/]+$/, "") + "/User/globalStorage/state.vscdb"
|
|
131
|
+
: ctx.host.fs.appSupportPath(variant.appSupportRel)
|
|
132
|
+
return path && ctx.host.fs.exists(path) ? path : null
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function loadCredentialsFile(ctx) {
|
|
136
|
+
var credentialsPath = resolveCredentialsPath(ctx)
|
|
137
|
+
if (!credentialsPath) return null
|
|
138
|
+
try {
|
|
139
|
+
var text = ctx.host.fs.readText(credentialsPath)
|
|
140
|
+
var apiKey = readTomlString(text, "windsurf_api_key")
|
|
141
|
+
if (!apiKey) {
|
|
142
|
+
throw {code: "credential-malformed", message: "Selected Devin credentials do not contain windsurf_api_key; select the correct credentialsPath or sign in again."}
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
apiKey: apiKey,
|
|
146
|
+
apiServerUrl: cleanApiServerUrl(readTomlString(text, "api_server_url")),
|
|
147
|
+
source: "credentials.toml",
|
|
148
|
+
}
|
|
149
|
+
} catch (e) {
|
|
150
|
+
if (e && e.code) throw e
|
|
151
|
+
throw {code: "credential-unavailable", message: "Cannot read the selected Devin credential file."}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function readAppAuth(ctx, variant) {
|
|
156
|
+
var stateDb = resolveStateDbForVariant(ctx, variant)
|
|
157
|
+
if (!stateDb) return null
|
|
158
|
+
try {
|
|
159
|
+
var rows = ctx.host.sqlite.query(
|
|
160
|
+
stateDb,
|
|
161
|
+
"SELECT value FROM ItemTable WHERE key = 'windsurfAuthStatus' LIMIT 1"
|
|
162
|
+
)
|
|
163
|
+
var parsed = ctx.util.tryParseJson(rows)
|
|
164
|
+
if (!parsed || !parsed.length || !parsed[0].value) return null
|
|
165
|
+
var auth = ctx.util.tryParseJson(parsed[0].value)
|
|
166
|
+
if (!auth || !auth.apiKey) return null
|
|
167
|
+
return {
|
|
168
|
+
apiKey: auth.apiKey,
|
|
169
|
+
apiServerUrl: null,
|
|
170
|
+
source: variant.source,
|
|
171
|
+
}
|
|
172
|
+
} catch (e) {
|
|
173
|
+
ctx.host.log.warn("failed to read " + variant.source + " auth: " + String(e))
|
|
174
|
+
return null
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function callCloud(ctx, auth) {
|
|
179
|
+
var apiServerUrl = effectiveApiServerUrl(auth)
|
|
180
|
+
try {
|
|
181
|
+
var resp = ctx.host.http.request({
|
|
182
|
+
method: "POST",
|
|
183
|
+
url: apiServerUrl + "/" + CLOUD_SERVICE + "/GetUserStatus",
|
|
184
|
+
headers: {
|
|
185
|
+
"Content-Type": "application/json",
|
|
186
|
+
"Connect-Protocol-Version": "1",
|
|
187
|
+
},
|
|
188
|
+
bodyText: JSON.stringify({
|
|
189
|
+
metadata: {
|
|
190
|
+
apiKey: auth.apiKey,
|
|
191
|
+
ideName: "devin",
|
|
192
|
+
ideVersion: CLOUD_COMPAT_VERSION,
|
|
193
|
+
extensionName: "devin",
|
|
194
|
+
extensionVersion: CLOUD_COMPAT_VERSION,
|
|
195
|
+
locale: "en",
|
|
196
|
+
},
|
|
197
|
+
}),
|
|
198
|
+
timeoutMs: 15000,
|
|
199
|
+
})
|
|
200
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
201
|
+
ctx.host.log.warn("cloud request returned status " + resp.status + " for " + auth.source)
|
|
202
|
+
if (ctx.util && typeof ctx.util.isAuthStatus === "function" && ctx.util.isAuthStatus(resp.status)) {
|
|
203
|
+
return { __openusageAuthError: true }
|
|
204
|
+
}
|
|
205
|
+
return null
|
|
206
|
+
}
|
|
207
|
+
return ctx.util.tryParseJson(resp.bodyText)
|
|
208
|
+
} catch (e) {
|
|
209
|
+
ctx.host.log.warn("cloud request failed for " + auth.source + ": " + String(e))
|
|
210
|
+
return null
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function tryAuth(ctx, auth) {
|
|
215
|
+
var data = callCloud(ctx, auth)
|
|
216
|
+
if (data && data.__openusageAuthError) {
|
|
217
|
+
return { authFailure: true }
|
|
218
|
+
}
|
|
219
|
+
if (!data || !data.userStatus) return {}
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
logQuotaDiagnostics(ctx, auth, data.userStatus)
|
|
223
|
+
return { output: buildOutput(ctx, data.userStatus) }
|
|
224
|
+
} catch (e) {
|
|
225
|
+
if (e === QUOTA_HINT) {
|
|
226
|
+
ctx.host.log.warn("quota contract unavailable for " + auth.source)
|
|
227
|
+
return {}
|
|
228
|
+
}
|
|
229
|
+
throw e
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function unixSecondsToIso(ctx, value) {
|
|
234
|
+
var seconds = readFiniteNumber(value)
|
|
235
|
+
if (seconds === null) return null
|
|
236
|
+
return ctx.util.toIso(seconds * 1000)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function formatDollarsFromMicros(value) {
|
|
240
|
+
var micros = readFiniteNumber(value)
|
|
241
|
+
if (micros === null) return null
|
|
242
|
+
if (!Number.isFinite(micros)) return null
|
|
243
|
+
if (micros < 0) micros = 0
|
|
244
|
+
return "$" + (micros / 1000000).toFixed(2)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function buildQuotaLine(ctx, label, remaining, resetsAt, periodDurationMs) {
|
|
248
|
+
if (remaining === null) return null
|
|
249
|
+
return buildUsedQuotaLine(ctx, label, 100 - remaining, resetsAt, periodDurationMs)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function buildUsedQuotaLine(ctx, label, used, resetsAt, periodDurationMs) {
|
|
253
|
+
if (used === null) return null
|
|
254
|
+
var line = {
|
|
255
|
+
label: label,
|
|
256
|
+
used: clampPercent(used),
|
|
257
|
+
limit: 100,
|
|
258
|
+
format: { kind: "percent" },
|
|
259
|
+
periodDurationMs: periodDurationMs,
|
|
260
|
+
}
|
|
261
|
+
if (resetsAt) line.resetsAt = resetsAt
|
|
262
|
+
return ctx.line.progress(line)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function buildOutput(ctx, userStatus) {
|
|
266
|
+
var planStatus = (userStatus && userStatus.planStatus) || {}
|
|
267
|
+
|
|
268
|
+
var planInfo = planStatus.planInfo || {}
|
|
269
|
+
var planName = typeof planInfo.planName === "string" && planInfo.planName.trim()
|
|
270
|
+
? planInfo.planName.trim()
|
|
271
|
+
: "Unknown"
|
|
272
|
+
|
|
273
|
+
var hideDailyQuota = planInfo.hideDailyQuota === true
|
|
274
|
+
var dailyRemaining = readFiniteNumber(planStatus.dailyQuotaRemainingPercent)
|
|
275
|
+
var weeklyRemaining = readFiniteNumber(planStatus.weeklyQuotaRemainingPercent)
|
|
276
|
+
var dailyReset = !hideDailyQuota ? unixSecondsToIso(ctx, planStatus.dailyQuotaResetAtUnix) : null
|
|
277
|
+
var weeklyReset = unixSecondsToIso(ctx, planStatus.weeklyQuotaResetAtUnix)
|
|
278
|
+
var extraUsageBalance = formatDollarsFromMicros(planStatus.overageBalanceMicros)
|
|
279
|
+
|
|
280
|
+
var dailyLine = !hideDailyQuota
|
|
281
|
+
? buildQuotaLine(ctx, "Daily quota", dailyRemaining, dailyReset, DAY_MS)
|
|
282
|
+
: null
|
|
283
|
+
var weeklyLine = weeklyRemaining !== null
|
|
284
|
+
? buildQuotaLine(ctx, "Weekly quota", weeklyRemaining, weeklyReset, WEEK_MS)
|
|
285
|
+
: hideDailyQuota
|
|
286
|
+
? buildUsedQuotaLine(ctx, "Weekly quota", dailyRemaining, weeklyReset, WEEK_MS)
|
|
287
|
+
: null
|
|
288
|
+
|
|
289
|
+
var lines = []
|
|
290
|
+
if (dailyLine) lines.push(dailyLine)
|
|
291
|
+
if (weeklyLine) lines.push(weeklyLine)
|
|
292
|
+
if (extraUsageBalance) {
|
|
293
|
+
lines.push(ctx.line.text({ label: "Extra usage balance", value: extraUsageBalance }))
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (!lines.length) throw QUOTA_HINT
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
plan: planName,
|
|
300
|
+
lines: lines,
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function authFingerprint(auth) {
|
|
305
|
+
return auth.apiKey + "\n" + effectiveApiServerUrl(auth)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function probe(ctx) {
|
|
309
|
+
var opts = settings(ctx)
|
|
310
|
+
var source = opts.authSource || (opts.credentialsPath ? "cli" : opts.ideVariant || opts.userDataDir ? "ide" : "auto")
|
|
311
|
+
if (["auto", "cli", "ide"].indexOf(source) < 0) throw {code: "failed", message: "Set Devin settings.authSource to auto, cli or ide."}
|
|
312
|
+
if ((opts.credentialsPath && source !== "cli") || ((opts.ideVariant || opts.userDataDir) && source !== "ide")) {
|
|
313
|
+
throw {code: "failed", message: "Select either a Devin CLI credential file or an IDE profile."}
|
|
314
|
+
}
|
|
315
|
+
var variants = APP_STATE_VARIANTS
|
|
316
|
+
if (opts.ideVariant) {
|
|
317
|
+
variants = variants.filter(function(variant) { return variant.id === opts.ideVariant })
|
|
318
|
+
if (!variants.length) throw {code: "failed", message: "Unknown Devin ideVariant; use devin, devin-next, windsurf or windsurf-next."}
|
|
319
|
+
}
|
|
320
|
+
if (opts.userDataDir && !opts.ideVariant) throw {code: "failed", message: "Set ideVariant when selecting a Devin userDataDir."}
|
|
321
|
+
var candidates = []
|
|
322
|
+
if (source !== "ide") {
|
|
323
|
+
var credentials = loadCredentialsFile(ctx)
|
|
324
|
+
if (credentials) candidates.push(credentials)
|
|
325
|
+
}
|
|
326
|
+
if (source !== "cli") {
|
|
327
|
+
for (var i = 0; i < variants.length; i++) {
|
|
328
|
+
var auth = readAppAuth(ctx, variants[i])
|
|
329
|
+
if (auth && !candidates.some(function(candidate) { return authFingerprint(candidate) === authFingerprint(auth) })) candidates.push(auth)
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (candidates.length > 1) throw {code: "failed", message: "Multiple Devin accounts or installations found; select settings.authSource and credentialsPath or ideVariant."}
|
|
333
|
+
if (!candidates.length) throw LOGIN_HINT
|
|
334
|
+
// Once selected, a rejected token cannot silently select another account.
|
|
335
|
+
var attempt = tryAuth(ctx, candidates[0])
|
|
336
|
+
if (attempt.output) return attempt.output
|
|
337
|
+
throw attempt.authFailure ? LOGIN_HINT : QUOTA_HINT
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
globalThis.__openusage_plugin = { id: "devin", probe: probe }
|
|
341
|
+
})()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "devin",
|
|
4
|
+
"name": "Devin",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"icon": "icon.svg",
|
|
8
|
+
"brandColor": "#000000",
|
|
9
|
+
"supportedModes": ["local"],
|
|
10
|
+
"autoMode": "local",
|
|
11
|
+
"lines": [
|
|
12
|
+
{ "type": "progress", "label": "Weekly quota", "scope": "overview", "primaryOrder": 1 },
|
|
13
|
+
{ "type": "progress", "label": "Daily quota", "scope": "overview" },
|
|
14
|
+
{ "type": "text", "label": "Extra usage balance", "scope": "detail" }
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -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>Doubao</title><path d="M5.31 15.756c.172-3.75 1.883-5.999 2.549-6.739-3.26 2.058-5.425 5.658-6.358 8.308v1.12C1.501 21.513 4.226 24 7.59 24a6.59 6.59 0 002.2-.375c.353-.12.7-.248 1.039-.378.913-.899 1.65-1.91 2.243-2.992-4.877 2.431-7.974.072-7.763-4.5l.002.001z" fill="#1E37FC"></path><path d="M22.57 10.283c-1.212-.901-4.109-2.404-7.397-2.8.295 3.792.093 8.766-2.1 12.773a12.782 12.782 0 01-2.244 2.992c3.764-1.448 6.746-3.457 8.596-5.219 2.82-2.683 3.353-5.178 3.361-6.66a2.737 2.737 0 00-.216-1.084v-.002z" fill="#37E1BE"></path><path d="M14.303 1.867C12.955.7 11.248 0 9.39 0 7.532 0 5.883.677 4.545 1.807 2.791 3.29 1.627 5.557 1.5 8.125v9.201c.932-2.65 3.097-6.25 6.357-8.307.5-.318 1.025-.595 1.569-.829 1.883-.801 3.878-.932 5.746-.706-.222-2.83-.718-5.002-.87-5.617h.001z" fill="#A569FF"></path><path d="M17.305 4.961a199.47 199.47 0 01-1.08-1.094c-.202-.213-.398-.419-.586-.622l-1.333-1.378c.151.615.648 2.786.869 5.617 3.288.395 6.185 1.898 7.396 2.8-1.306-1.275-3.475-3.487-5.266-5.323z" fill="#1E37FC"></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>Doubao</title><path d="M5.31 15.756c.172-3.75 1.883-5.999 2.549-6.739-3.26 2.058-5.425 5.658-6.358 8.308v1.12C1.501 21.513 4.226 24 7.59 24a6.59 6.59 0 002.2-.375c.353-.12.7-.248 1.039-.378.913-.899 1.65-1.91 2.243-2.992-4.877 2.431-7.974.072-7.763-4.5l.002.001z" fill-opacity=".5"></path><path d="M22.57 10.283c-1.212-.901-4.109-2.404-7.397-2.8.295 3.792.093 8.766-2.1 12.773a12.782 12.782 0 01-2.244 2.992c3.764-1.448 6.746-3.457 8.596-5.219 2.82-2.683 3.353-5.178 3.361-6.66a2.737 2.737 0 00-.216-1.084v-.002zM14.303 1.867C12.955.7 11.248 0 9.39 0 7.532 0 5.883.677 4.545 1.807 2.791 3.29 1.627 5.557 1.5 8.125v9.201c.932-2.65 3.097-6.25 6.357-8.307.5-.318 1.025-.595 1.569-.829 1.883-.801 3.878-.932 5.746-.706-.222-2.83-.718-5.002-.87-5.617h.001z"></path><path d="M17.305 4.961a199.47 199.47 0 01-1.08-1.094c-.202-.213-.398-.419-.586-.622l-1.333-1.378c.151.615.648 2.786.869 5.617 3.288.395 6.185 1.898 7.396 2.8-1.306-1.275-3.475-3.487-5.266-5.323z" fill-opacity=".5"></path></svg>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var API_URL = "https://ark.cn-beijing.volces.com/api/coding/v3/chat/completions"
|
|
3
|
+
var PROBE_MODELS = ["doubao-seed-2.0-code", "doubao-1.5-pro-32k", "doubao-lite-32k"]
|
|
4
|
+
|
|
5
|
+
function getApiKey(ctx) {
|
|
6
|
+
var key = ctx.host.env.get("ARK_API_KEY")
|
|
7
|
+
|| ctx.host.env.get("DOUBAO_API_KEY")
|
|
8
|
+
|| ctx.host.env.get("VOLCENGINE_API_KEY")
|
|
9
|
+
if (!key) throw "Set ARK_API_KEY, DOUBAO_API_KEY, or VOLCENGINE_API_KEY to use Doubao."
|
|
10
|
+
return key
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function probeModel(ctx, apiKey, model) {
|
|
14
|
+
var resp = ctx.host.http.request({
|
|
15
|
+
method: "POST",
|
|
16
|
+
url: API_URL,
|
|
17
|
+
headers: {
|
|
18
|
+
"Authorization": "Bearer " + apiKey,
|
|
19
|
+
"Content-Type": "application/json",
|
|
20
|
+
"Accept": "application/json",
|
|
21
|
+
},
|
|
22
|
+
bodyText: JSON.stringify({
|
|
23
|
+
model: model,
|
|
24
|
+
max_tokens: 1,
|
|
25
|
+
messages: [{ role: "user", content: "hi" }],
|
|
26
|
+
}),
|
|
27
|
+
timeoutMs: 20000,
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
31
|
+
throw "Invalid API key. Check ARK_API_KEY."
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Accept 200 (success) or 429 (rate-limited) — both return useful headers
|
|
35
|
+
if (resp.status !== 200 && resp.status !== 429) {
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return resp
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function parseResetMs(value) {
|
|
43
|
+
if (!value) return null
|
|
44
|
+
var trimmed = value.trim()
|
|
45
|
+
var ts = Number(trimmed)
|
|
46
|
+
if (Number.isFinite(ts) && ts > 0) return ts * 1000
|
|
47
|
+
var ms = Date.parse(trimmed)
|
|
48
|
+
return Number.isFinite(ms) ? ms : null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function probe(ctx) {
|
|
52
|
+
var apiKey = getApiKey(ctx)
|
|
53
|
+
|
|
54
|
+
var resp = null
|
|
55
|
+
for (var i = 0; i < PROBE_MODELS.length; i++) {
|
|
56
|
+
resp = probeModel(ctx, apiKey, PROBE_MODELS[i])
|
|
57
|
+
if (resp) break
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!resp) throw "All Doubao probe models failed. Check your API key and account."
|
|
61
|
+
|
|
62
|
+
var headers = resp.headers || {}
|
|
63
|
+
var remaining = parseInt(headers["x-ratelimit-remaining-requests"] || headers["X-Ratelimit-Remaining-Requests"], 10)
|
|
64
|
+
var limit = parseInt(headers["x-ratelimit-limit-requests"] || headers["X-Ratelimit-Limit-Requests"], 10)
|
|
65
|
+
var resetRaw = headers["x-ratelimit-reset-requests"] || headers["X-Ratelimit-Reset-Requests"]
|
|
66
|
+
|
|
67
|
+
var lines = []
|
|
68
|
+
|
|
69
|
+
if (Number.isFinite(remaining) && Number.isFinite(limit) && limit > 0) {
|
|
70
|
+
var used = Math.max(0, limit - remaining)
|
|
71
|
+
var resetMs = parseResetMs(resetRaw)
|
|
72
|
+
lines.push(ctx.line.progress({
|
|
73
|
+
label: "Requests",
|
|
74
|
+
used: used,
|
|
75
|
+
limit: limit,
|
|
76
|
+
format: { kind: "count", suffix: "req" },
|
|
77
|
+
resetsAt: ctx.util.toIso(resetMs ? resetMs / 1000 : null),
|
|
78
|
+
}))
|
|
79
|
+
} else {
|
|
80
|
+
var json = ctx.util.tryParseJson(resp.bodyText) || {}
|
|
81
|
+
var totalTokens = json.usage && json.usage.total_tokens
|
|
82
|
+
var detail = totalTokens
|
|
83
|
+
? "Active — " + totalTokens + " tokens observed"
|
|
84
|
+
: "Active — check dashboard for details"
|
|
85
|
+
lines.push(ctx.line.badge({ label: "Status", text: detail, color: "#22c55e" }))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return { lines: lines }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
globalThis.__openusage_plugin = { id: "doubao", probe: probe }
|
|
92
|
+
})()
|