@hashimkarim/usagestat-linux-x64-gnu 2.0.0-alpha.1 → 2.0.0-alpha.4
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 +1088 -134
- package/package.json +160 -1
- package/plugins/UPSTREAM-LICENSES.md +113 -0
- package/plugins/_provider-icons/LICENSE +21 -0
- package/plugins/_provider-icons/NOTICE +12 -0
- package/plugins/_provider-icons/licenses/CodexBar-MIT.txt +21 -0
- package/plugins/_provider-icons/licenses/LobeHub-MIT.txt +21 -0
- package/plugins/_provider-icons/licenses/UsageStat-Bar-MIT.txt +21 -0
- package/plugins/_provider-icons/manifest.json +1219 -0
- package/plugins/_provider-icons/provenance.json +269 -0
- package/plugins/_provider-icons/source.json +4 -0
- package/plugins/abacus-ai/icon-color.svg +18 -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/aixy/LICENSE +21 -0
- package/plugins/aixy/plugin.js +261 -0
- package/plugins/aixy/plugin.json +24 -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 +136 -46
- package/plugins/antigravity/plugin.json +0 -0
- package/plugins/antigravity-cli/icon-color.svg +1 -0
- package/plugins/antigravity-cli/icon.svg +1 -3
- package/plugins/antigravity-cli/plugin.js +11 -15
- package/plugins/antigravity-cli/plugin.json +0 -0
- package/plugins/antigravity-ide/icon-color.svg +1 -0
- package/plugins/antigravity-ide/icon.svg +1 -3
- package/plugins/antigravity-ide/plugin.js +0 -0
- package/plugins/antigravity-ide/plugin.json +0 -0
- package/plugins/atlascloud/LICENSE +21 -0
- package/plugins/atlascloud/icon-color.svg +1 -0
- package/plugins/atlascloud/icon.svg +1 -0
- package/plugins/atlascloud/plugin.js +49 -0
- package/plugins/atlascloud/plugin.json +23 -0
- package/plugins/augment/icon-color.svg +14 -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/bifrost/LICENSE +21 -0
- package/plugins/bifrost/plugin.js +361 -0
- package/plugins/bifrost/plugin.json +23 -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 +358 -161
- package/plugins/claude/plugin.json +1 -1
- 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 +87 -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-color.svg +92 -0
- package/plugins/codebuff/icon.svg +0 -0
- package/plugins/codebuff/plugin.js +0 -0
- package/plugins/codebuff/plugin.json +0 -0
- package/plugins/coderabbit/plugin.js +25 -0
- package/plugins/coderabbit/plugin.json +12 -0
- package/plugins/codex/icon-color.svg +0 -0
- package/plugins/codex/icon.svg +0 -0
- package/plugins/codex/plugin.js +8 -2
- package/plugins/codex/plugin.json +0 -0
- package/plugins/command-code/icon-color.svg +3 -0
- package/plugins/command-code/icon.svg +0 -0
- package/plugins/command-code/plugin.js +14 -3
- package/plugins/command-code/plugin.json +0 -0
- package/plugins/copilot/icon-color.svg +0 -0
- package/plugins/copilot/icon.svg +1 -1
- package/plugins/copilot/plugin.js +61 -9
- package/plugins/copilot/plugin.json +4 -1
- package/plugins/crof/icon-color.svg +3 -0
- 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-color.svg +3 -0
- package/plugins/crofai/icon.svg +2 -15
- package/plugins/crofai/plugin.js +0 -0
- package/plugins/crofai/plugin.json +0 -0
- package/plugins/cursor/icon-color.svg +1 -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-color.svg +1 -0
- package/plugins/deepinfra/icon.svg +1 -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 +150 -59
- package/plugins/deepseek/plugin.json +3 -1
- package/plugins/devin/icon.svg +0 -0
- package/plugins/devin/plugin.js +114 -0
- package/plugins/devin/plugin.json +2 -1
- package/plugins/devpass/LICENSE +21 -0
- package/plugins/devpass/plugin.js +115 -0
- package/plugins/devpass/plugin.json +23 -0
- 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-color.svg +4 -0
- 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-color.svg +1 -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-color.svg +1 -0
- package/plugins/fireworks-ai/icon.svg +1 -6
- 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/gemini-apps/LICENSE +22 -0
- package/plugins/gemini-apps/icon-color.svg +1 -0
- package/plugins/gemini-apps/icon.svg +1 -0
- package/plugins/gemini-apps/plugin.js +470 -0
- package/plugins/gemini-apps/plugin.json +19 -0
- package/plugins/gitkraken/LICENSE +21 -0
- package/plugins/gitkraken/plugin.js +153 -0
- package/plugins/gitkraken/plugin.json +24 -0
- package/plugins/grok/icon-color.svg +1 -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-color.svg +1 -0
- package/plugins/groqcloud/icon.svg +0 -0
- package/plugins/groqcloud/plugin.js +0 -0
- package/plugins/groqcloud/plugin.json +0 -0
- package/plugins/helmcode/LICENSE +21 -0
- package/plugins/helmcode/plugin.js +188 -0
- package/plugins/helmcode/plugin.json +24 -0
- package/plugins/huggingface/LICENSE +21 -0
- package/plugins/huggingface/icon-color.svg +1 -0
- package/plugins/huggingface/icon.svg +1 -0
- package/plugins/huggingface/plugin.js +293 -0
- package/plugins/huggingface/plugin.json +25 -0
- package/plugins/hyper/LICENSE +21 -0
- package/plugins/hyper/plugin.js +131 -0
- package/plugins/hyper/plugin.json +26 -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-color.svg +1 -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 +54 -3
- 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/llmman/LICENSE +21 -0
- package/plugins/llmman/plugin.js +133 -0
- package/plugins/llmman/plugin.json +23 -0
- package/plugins/longcat/icon-color.svg +1 -0
- package/plugins/longcat/icon.svg +1 -0
- package/plugins/longcat/plugin.js +182 -0
- package/plugins/longcat/plugin.json +23 -0
- package/plugins/manus/icon-color.svg +6 -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-color.svg +4 -0
- package/plugins/mimo/icon.svg +4 -1
- 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 +110 -5
- package/plugins/mistral/plugin.json +0 -0
- package/plugins/moonshot/icon-color.svg +1 -0
- package/plugins/moonshot/icon.svg +0 -0
- package/plugins/moonshot/plugin.js +8 -6
- package/plugins/moonshot/plugin.json +0 -0
- package/plugins/muse/LICENSE +21 -0
- package/plugins/muse/plugin.js +319 -0
- package/plugins/muse/plugin.json +26 -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/nous/LICENSE +21 -0
- package/plugins/nous/icon-color.svg +1 -0
- package/plugins/nous/icon.svg +1 -0
- package/plugins/nous/plugin.js +124 -0
- package/plugins/nous/plugin.json +24 -0
- package/plugins/ollama/icon-color.svg +1 -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-color.svg +1 -0
- 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-color.svg +1 -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-color.svg +1 -0
- package/plugins/opencode-go/icon-conflict.svg +0 -0
- package/plugins/opencode-go/icon.svg +0 -0
- package/plugins/opencode-go/plugin.js +103 -17
- package/plugins/opencode-go/plugin.json +5 -2
- package/plugins/openrouter/icon-color.svg +1 -0
- 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/pi/plugin.js +113 -0
- package/plugins/pi/plugin.json +11 -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-color.svg +1 -0
- package/plugins/qwencloud/icon.svg +1 -0
- package/plugins/qwencloud/plugin.js +677 -0
- package/plugins/qwencloud/plugin.json +29 -0
- package/plugins/raycast/LICENSE +21 -0
- package/plugins/raycast/plugin.js +174 -0
- package/plugins/raycast/plugin.json +24 -0
- package/plugins/replicate/LICENSE +21 -0
- package/plugins/replicate/icon-color.svg +1 -0
- package/plugins/replicate/icon.svg +1 -0
- package/plugins/replicate/plugin.js +165 -0
- package/plugins/replicate/plugin.json +24 -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-color.svg +14 -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/typesafe/LICENSE +21 -0
- package/plugins/typesafe/plugin.js +225 -0
- package/plugins/typesafe/plugin.json +24 -0
- package/plugins/v0/LICENSE +21 -0
- package/plugins/v0/icon-color.svg +1 -0
- package/plugins/v0/icon.svg +1 -0
- package/plugins/v0/plugin.js +214 -0
- package/plugins/v0/plugin.json +24 -0
- package/plugins/venice/icon-color.svg +0 -0
- package/plugins/venice/icon.svg +0 -0
- package/plugins/venice/plugin.js +50 -1
- package/plugins/venice/plugin.json +2 -1
- package/plugins/vercel/LICENSE +21 -0
- package/plugins/vercel/icon-color.svg +1 -0
- package/plugins/vercel/icon.svg +1 -0
- package/plugins/vercel/plugin.js +55 -0
- package/plugins/vercel/plugin.json +23 -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-color.svg +1 -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-color.svg +1 -0
- package/plugins/xai/icon.svg +1 -0
- package/plugins/xai/plugin.js +162 -0
- package/plugins/xai/plugin.json +28 -0
- package/plugins/xkiro/LICENSE +21 -0
- package/plugins/xkiro/plugin.js +99 -0
- package/plugins/xkiro/plugin.json +23 -0
- package/plugins/zai/icon-color.svg +1 -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-color.svg +1 -0
- package/plugins/zenmux/icon.svg +1 -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
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
{ "label": "Status", "url": "https://status.anthropic.com/" },
|
|
11
11
|
{ "label": "Console", "url": "https://console.anthropic.com/" }
|
|
12
12
|
],
|
|
13
|
-
"supportedModes": ["oauth", "web", "local", "api"],
|
|
13
|
+
"supportedModes": ["oauth", "cli", "web", "local", "api"],
|
|
14
14
|
"autoMode": "oauth",
|
|
15
15
|
"webUrl": "https://claude.ai",
|
|
16
16
|
"usageDashboardUrl": "https://claude.ai/settings/usage",
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<circle cx="8" cy="7" r="3" fill="currentColor" stroke="none"/>
|
|
3
|
+
<circle cx="24" cy="8" r="3" fill="currentColor" stroke="none"/>
|
|
4
|
+
<circle cx="24" cy="24" r="3" fill="currentColor" stroke="none"/>
|
|
5
|
+
<path d="M8 10v6c0 4.4 3.6 8 8 8h5"/>
|
|
6
|
+
<path d="M11 8h10"/>
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
function clean(value) { return typeof value === "string" && value.trim() ? value.trim() : null }
|
|
3
|
+
function integer(value) {
|
|
4
|
+
if (!Number.isSafeInteger(value) || value < 0) throw "Invalid ClawRouter usage counters."
|
|
5
|
+
return value
|
|
6
|
+
}
|
|
7
|
+
function money(value) { return "$" + (integer(value) / 1000000).toFixed(6) }
|
|
8
|
+
function probe(ctx) {
|
|
9
|
+
const provider = ctx.provider || {}
|
|
10
|
+
const settings = provider.settings || {}
|
|
11
|
+
const key = clean(provider.apiKey) || clean(ctx.host.env.get("CLAWROUTER_API_KEY"))
|
|
12
|
+
if (!key) throw "Set CLAWROUTER_API_KEY or the ClawRouter provider API key."
|
|
13
|
+
let base = ctx.host.http.validateBaseUrl(clean(settings.baseUrl) || clean(ctx.host.env.get("CLAWROUTER_BASE_URL")) || "https://clawrouter.openclaw.ai", false)
|
|
14
|
+
if (!base.endsWith("/v1")) base += "/v1"
|
|
15
|
+
const result = ctx.util.requestJson({ method: "GET", url: base + "/usage",
|
|
16
|
+
headers: { Authorization: "Bearer " + key, Accept: "application/json" }, timeoutMs: 10000 })
|
|
17
|
+
if (ctx.util.isAuthStatus(result.resp.status)) throw "ClawRouter rejected the API key."
|
|
18
|
+
if (result.resp.status < 200 || result.resp.status >= 300) throw "ClawRouter returned HTTP " + result.resp.status + "."
|
|
19
|
+
const data = result.json
|
|
20
|
+
if (!data || !data.budget || !data.usage || !data.usage.summary || !Array.isArray(data.usage.providers)) throw "Invalid ClawRouter usage response."
|
|
21
|
+
const budget = data.budget
|
|
22
|
+
const summary = data.usage.summary
|
|
23
|
+
const lines = [
|
|
24
|
+
ctx.line.text({ label: "Requests", value: String(integer(summary.requestCount)),
|
|
25
|
+
subtitle: integer(summary.successCount) + " succeeded; " + integer(summary.errorCount) + " failed" }),
|
|
26
|
+
ctx.line.text({ label: "Tokens", value: String(integer(summary.totalTokens)),
|
|
27
|
+
subtitle: integer(summary.inputTokens) + " input; " + integer(summary.outputTokens) + " output" }),
|
|
28
|
+
ctx.line.text({ label: "Actual cost", value: money(summary.actualCostMicros) }),
|
|
29
|
+
]
|
|
30
|
+
if (budget.spentMicros !== null && budget.spentMicros !== undefined && budget.limitMicros !== null && budget.limitMicros !== undefined) {
|
|
31
|
+
const month = typeof budget.windowKey === "string" && budget.windowKey.match(/(\d{4})-(0[1-9]|1[0-2])$/)
|
|
32
|
+
lines.unshift(ctx.line.progress({ label: "Monthly budget", used: integer(budget.spentMicros) / 1000000,
|
|
33
|
+
limit: integer(budget.limitMicros) / 1000000, format: { kind: "dollars" },
|
|
34
|
+
resetsAt: month ? new Date(Date.UTC(Number(month[1]), Number(month[2]), 1)).toISOString() : undefined,
|
|
35
|
+
periodDurationMs: 30 * 24 * 60 * 60 * 1000 }))
|
|
36
|
+
}
|
|
37
|
+
const routes = data.usage.providers.map((row) => {
|
|
38
|
+
if (!row || !clean(row.provider)) throw "Invalid ClawRouter routed provider."
|
|
39
|
+
return { label: row.provider, value: integer(row.actualCostMicros) / 1000000, valueLabel: money(row.actualCostMicros) }
|
|
40
|
+
}).sort((a, b) => b.value - a.value)
|
|
41
|
+
if (routes.length) lines.push(ctx.line.barChart({ label: "Routed provider costs", points: routes.slice(0, 20) }))
|
|
42
|
+
return { displayName: "ClawRouter", source: "api", plan: budget.configured ? "Monthly budget" : "Unmetered", lines }
|
|
43
|
+
}
|
|
44
|
+
globalThis.__openusage_plugin = { id: "clawrouter", probe }
|
|
45
|
+
})()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "clawrouter",
|
|
4
|
+
"name": "ClawRouter",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"envVars": [
|
|
9
|
+
"CLAWROUTER_API_KEY",
|
|
10
|
+
"CLAWROUTER_BASE_URL"
|
|
11
|
+
],
|
|
12
|
+
"supportedModes": [
|
|
13
|
+
"api"
|
|
14
|
+
],
|
|
15
|
+
"autoMode": "api",
|
|
16
|
+
"links": [
|
|
17
|
+
{
|
|
18
|
+
"label": "Dashboard",
|
|
19
|
+
"url": "https://clawrouter.openclaw.ai"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 466.73 487.04">
|
|
2
|
+
<!-- Official Cline bot icon: https://cline.bot/brand -->
|
|
3
|
+
<path d="M463.6,275.08l-29.26-58.75v-33.83c0-56.08-45.01-101.5-100.53-101.5h-50.01c3.62-7.43,5.61-15.79,5.61-24.61,0-31.17-25.08-56.39-56.07-56.39s-56.07,25.22-56.07,56.39c0,8.82,1.99,17.17,5.61,24.61h-50.01c-55.51,0-100.52,45.42-100.52,101.5v33.83l-29.87,58.59c-3.01,5.9-3.01,12.92,0,18.81l29.87,57.93v33.83c0,56.08,45.01,101.5,100.52,101.5h200.95c55.51,0,100.53-45.42,100.53-101.5v-33.83l29.21-58.13c2.9-5.79,2.9-12.61.05-18.46ZM202.75,322.96c0,25.48-20.54,46.14-45.88,46.14s-45.88-20.66-45.88-46.14v-82.02c0-25.48,20.54-46.14,45.88-46.14s45.88,20.66,45.88,46.14v82.02ZM350.58,322.96c0,25.48-20.54,46.14-45.88,46.14s-45.88-20.66-45.88-46.14v-82.02c0-25.48,20.54-46.14,45.88-46.14s45.88,20.66,45.88,46.14v82.02Z"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var USAGE_URL = "https://api.cline.bot/api/v1/users/me/plan/usage-limits";
|
|
3
|
+
|
|
4
|
+
function clean(value) {
|
|
5
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function env(ctx, name) {
|
|
9
|
+
try {
|
|
10
|
+
return clean(ctx.host.env.get(name));
|
|
11
|
+
} catch (_) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function apiKey(ctx) {
|
|
17
|
+
const provider = ctx.provider || {};
|
|
18
|
+
if (Object.prototype.hasOwnProperty.call(provider, "apiKey")) return clean(provider.apiKey);
|
|
19
|
+
const scoped = provider.instanceId && provider.instanceId !== 'clinepass';
|
|
20
|
+
if (scoped) return null;
|
|
21
|
+
const explicit = env(ctx, "CLINEPASS_API_KEY") || env(ctx, "CLINE_API_KEY");
|
|
22
|
+
if (explicit) return explicit;
|
|
23
|
+
const settings = provider.settings || {};
|
|
24
|
+
const dir = env(ctx, 'CLINE_DATA_DIR') || (env(ctx, 'CLINE_DIR') || ctx.host.fs.homeDir + '/.cline') + '/data';
|
|
25
|
+
const file = clean(settings.authPath) || env(ctx, 'CLINE_PROVIDER_SETTINGS_PATH') || dir + '/settings/providers.json';
|
|
26
|
+
let saved;
|
|
27
|
+
try { saved = JSON.parse(ctx.host.fs.readText(file))?.providers?.cline?.settings; } catch (_) { return null; }
|
|
28
|
+
const access = clean(saved?.auth?.accessToken);
|
|
29
|
+
if (access) {
|
|
30
|
+
ctx.clineAuthSource = 'oauth';
|
|
31
|
+
return access.startsWith('workos:') ? access : 'workos:' + access;
|
|
32
|
+
}
|
|
33
|
+
return clean(saved?.apiKey) || clean(saved?.auth?.apiKey);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function windowFor(ctx, entry) {
|
|
37
|
+
var type = String(entry && entry.type || "");
|
|
38
|
+
var minutes = type === "five_hour" ? 5 * 60 : type === "weekly" ? 7 * 24 * 60 : type === "monthly" ? 30 * 24 * 60 : null;
|
|
39
|
+
if (!minutes) return null;
|
|
40
|
+
var label = type === "five_hour" ? "5-hour" : type === "weekly" ? "Weekly" : "Monthly";
|
|
41
|
+
var raw = entry.percentUsed;
|
|
42
|
+
var percent = Number(raw);
|
|
43
|
+
if ((typeof raw !== "number" && typeof raw !== "string") || String(raw).trim() === "" || !Number.isFinite(percent) || percent < 0) throw "Invalid ClinePass usage percentage.";
|
|
44
|
+
var opts = {
|
|
45
|
+
label: label,
|
|
46
|
+
used: Math.max(0, Math.min(100, percent)),
|
|
47
|
+
limit: 100,
|
|
48
|
+
format: { kind: "percent" },
|
|
49
|
+
periodDurationMs: minutes * 60 * 1000,
|
|
50
|
+
};
|
|
51
|
+
var iso = ctx.util.toIso(entry.resetsAt);
|
|
52
|
+
if (iso) opts.resetsAt = iso;
|
|
53
|
+
return ctx.line.progress(opts);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function probe(ctx) {
|
|
57
|
+
var key = apiKey(ctx);
|
|
58
|
+
if (!key) throw "ClinePass credentials missing. Set an API key or run cline auth to sign in.";
|
|
59
|
+
|
|
60
|
+
var result = ctx.util.requestJson({
|
|
61
|
+
method: "GET",
|
|
62
|
+
url: USAGE_URL,
|
|
63
|
+
headers: { Authorization: "Bearer " + key, Accept: "application/json" },
|
|
64
|
+
timeoutMs: 15000,
|
|
65
|
+
});
|
|
66
|
+
if (ctx.util.isAuthStatus(result.resp.status)) throw "ClinePass API key invalid or expired.";
|
|
67
|
+
if (result.resp.status < 200 || result.resp.status >= 300) throw "ClinePass API error: HTTP " + result.resp.status + ".";
|
|
68
|
+
if (!result.json || !result.json.success || !result.json.data || !Array.isArray(result.json.data.limits)) {
|
|
69
|
+
throw "Failed to parse ClinePass usage.";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
var ordered = ["five_hour", "weekly", "monthly"];
|
|
73
|
+
var metrics = [];
|
|
74
|
+
for (var i = 0; i < ordered.length; i++) {
|
|
75
|
+
for (var j = 0; j < result.json.data.limits.length; j++) {
|
|
76
|
+
if (result.json.data.limits[j] && result.json.data.limits[j].type === ordered[i]) {
|
|
77
|
+
var line = windowFor(ctx, result.json.data.limits[j]);
|
|
78
|
+
if (line) metrics.push(line);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (!metrics.length) throw "ClinePass response missing five_hour window.";
|
|
83
|
+
return { displayName: "ClinePass", source: ctx.clineAuthSource || "api", plan: ctx.clineAuthSource ? "Browser" : "API key", lines: metrics };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
globalThis.__openusage_plugin = { id: "clinepass", probe: probe };
|
|
87
|
+
})();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "clinepass",
|
|
4
|
+
"name": "ClinePass",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"api"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "api",
|
|
12
|
+
"usageDashboardUrl": "https://app.cline.bot/dashboard/subscription?personal=true",
|
|
13
|
+
"links": [
|
|
14
|
+
{
|
|
15
|
+
"label": "Dashboard",
|
|
16
|
+
"url": "https://app.cline.bot/dashboard/subscription?personal=true"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"envVars": [
|
|
20
|
+
"CLINEPASS_API_KEY",
|
|
21
|
+
"CLINE_API_KEY"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var API_URL = "https://www.codebuddy.cn/billing/meter/get-user-resource";
|
|
3
|
+
var ORIGIN = "https://www.codebuddy.cn";
|
|
4
|
+
var REFERER = "https://www.codebuddy.cn/profile/plans-usage";
|
|
5
|
+
var PRODUCT_CODE = "p_tcaca";
|
|
6
|
+
var USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36";
|
|
7
|
+
var MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
|
|
8
|
+
var DEFAULT_PACKAGE_CODES = [
|
|
9
|
+
"TCACA_code_007_nzdH5h4Nl0",
|
|
10
|
+
"TCACA_code_029_6wCGEWquYy",
|
|
11
|
+
"TCACA_code_030_BjSt89qTvr",
|
|
12
|
+
"TCACA_code_008_cfWoLwvjU4",
|
|
13
|
+
"TCACA_code_002_AkiJS3ZHF5",
|
|
14
|
+
"TCACA_code_023_4xbGhMrE6q",
|
|
15
|
+
"TCACA_code_026_BaESVICNoi",
|
|
16
|
+
"TCACA_code_027_0FCGVA6vSa",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
function trim(value) {
|
|
20
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function env(ctx, name) {
|
|
24
|
+
try {
|
|
25
|
+
return trim(ctx.host.env.get(name));
|
|
26
|
+
} catch (_) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function setting(ctx, names) {
|
|
32
|
+
var settings = ctx.provider && ctx.provider.settings ? ctx.provider.settings : {};
|
|
33
|
+
for (var i = 0; i < names.length; i++) {
|
|
34
|
+
var value = trim(settings[names[i]]);
|
|
35
|
+
if (value) return value;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function normalizeCookie(raw) {
|
|
41
|
+
var header = trim(raw);
|
|
42
|
+
if (!header) return null;
|
|
43
|
+
header = header.replace(/^\uFEFF/, "").replace(/\^/g, "").trim();
|
|
44
|
+
if (header.slice(0, 7).toLowerCase() === "cookie:") header = header.slice(7).trim();
|
|
45
|
+
var pairs = [];
|
|
46
|
+
var chunks = header.split(";");
|
|
47
|
+
for (var i = 0; i < chunks.length; i++) {
|
|
48
|
+
var idx = chunks[i].indexOf("=");
|
|
49
|
+
if (idx < 0) continue;
|
|
50
|
+
var name = chunks[i].slice(0, idx).trim();
|
|
51
|
+
var value = chunks[i].slice(idx + 1).trim();
|
|
52
|
+
if (name && value) pairs.push(name + "=" + value);
|
|
53
|
+
}
|
|
54
|
+
return pairs.length ? pairs.join("; ") : null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function codebuddyHome(ctx) {
|
|
58
|
+
return env(ctx, "CODEBUDDY_HOME") || (ctx.host.fs && ctx.host.fs.homeDir ? ctx.host.fs.homeDir + "/.codebuddy" : null);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function cookieFilePath(ctx) {
|
|
62
|
+
return env(ctx, "CB_COOKIE_FILE") || (codebuddyHome(ctx) ? codebuddyHome(ctx) + "/cb_cookie.txt" : null);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function creditsCachePath(ctx) {
|
|
66
|
+
return env(ctx, "CB_CREDITS_FILE") || (codebuddyHome(ctx) ? codebuddyHome(ctx) + "/cb_credits.json" : null);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function readTextIfExists(ctx, path) {
|
|
70
|
+
if (!path || !ctx.host.fs || !ctx.host.fs.exists(path)) return null;
|
|
71
|
+
return ctx.host.fs.readText(path);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function cookieHeader(ctx) {
|
|
75
|
+
var direct = normalizeCookie(ctx.provider && ctx.provider.cookieHeader) ||
|
|
76
|
+
normalizeCookie(setting(ctx, ["cookieHeader", "cookie"])) ||
|
|
77
|
+
normalizeCookie(env(ctx, "CODEBUDDY_COOKIE")) ||
|
|
78
|
+
normalizeCookie(env(ctx, "CB_COOKIE"));
|
|
79
|
+
if (direct) return direct;
|
|
80
|
+
return normalizeCookie(readTextIfExists(ctx, cookieFilePath(ctx)));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function apiUrl(ctx) {
|
|
84
|
+
var raw = setting(ctx, ["apiUrl", "apiBase"]) || env(ctx, "CB_API_URL") || API_URL;
|
|
85
|
+
return ctx.host.http.validateBaseUrl(raw, true);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function packageCodes(ctx) {
|
|
89
|
+
var raw = env(ctx, "CB_PACKAGE_CODES");
|
|
90
|
+
if (raw) {
|
|
91
|
+
try {
|
|
92
|
+
var parsed = JSON.parse(raw);
|
|
93
|
+
if (Array.isArray(parsed)) {
|
|
94
|
+
var out = [];
|
|
95
|
+
for (var i = 0; i < parsed.length && out.length < 64; i++) {
|
|
96
|
+
var code = trim(parsed[i]);
|
|
97
|
+
if (code && code.length <= 128 && !/[\x00-\x1f\x7f]/.test(code)) out.push(code);
|
|
98
|
+
}
|
|
99
|
+
if (out.length) return out;
|
|
100
|
+
}
|
|
101
|
+
} catch (_) {}
|
|
102
|
+
ctx.host.log.warn("CodeBuddy: CB_PACKAGE_CODES had no usable entries; using defaults");
|
|
103
|
+
}
|
|
104
|
+
return DEFAULT_PACKAGE_CODES;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function requestBody(ctx) {
|
|
108
|
+
return {
|
|
109
|
+
PageNumber: 1,
|
|
110
|
+
PageSize: 200,
|
|
111
|
+
ProductCode: PRODUCT_CODE,
|
|
112
|
+
Status: [0, 3],
|
|
113
|
+
OnlyValidPeriod: true,
|
|
114
|
+
PackageCodes: packageCodes(ctx),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function number(value) {
|
|
119
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
120
|
+
if (typeof value === "string" && value.trim()) {
|
|
121
|
+
var parsed = Number(value.replace(/,/g, ""));
|
|
122
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function valueFromKeys(obj, precise, fallback) {
|
|
128
|
+
var a = number(obj && obj[precise]);
|
|
129
|
+
return a !== null ? a : number(obj && obj[fallback]);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function parseDate(ctx, value) {
|
|
133
|
+
if (value === null || value === undefined || value === "") return null;
|
|
134
|
+
return ctx.util.toIso(value);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function expireTime(ctx, account) {
|
|
138
|
+
var keys = ["ExpireTime", "expireTime", "ExpireTimeStamp", "EndTime", "endTime", "ValidEndTime"];
|
|
139
|
+
for (var i = 0; i < keys.length; i++) {
|
|
140
|
+
var iso = parseDate(ctx, account && account[keys[i]]);
|
|
141
|
+
if (iso) return iso;
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function normalizedTotals(total, used, remaining, reset) {
|
|
147
|
+
if (!Number.isFinite(total) || !Number.isFinite(used) || !Number.isFinite(remaining)) {
|
|
148
|
+
throw "CodeBuddy payload contains non-finite credit values.";
|
|
149
|
+
}
|
|
150
|
+
if (remaining > 0 && total > 0 && used <= 0) used = Math.max(0, total - remaining);
|
|
151
|
+
return {
|
|
152
|
+
total: Math.max(0, total),
|
|
153
|
+
used: Math.max(0, used),
|
|
154
|
+
remaining: remaining < 0 ? Math.max(0, total - used) : remaining,
|
|
155
|
+
resetsAt: reset,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function totalsFromPayload(ctx, value) {
|
|
160
|
+
var code = number(value && value.code);
|
|
161
|
+
if (code !== 0) {
|
|
162
|
+
var msg = String(value && value.msg || "unknown error");
|
|
163
|
+
if (/auth/i.test(msg) || msg.indexOf("登录") >= 0 || msg.indexOf("未登录") >= 0) throw { auth: true, message: "CodeBuddy login required." };
|
|
164
|
+
throw "CodeBuddy API code=" + code + ": " + msg;
|
|
165
|
+
}
|
|
166
|
+
var accounts = value && value.data && value.data.Response && value.data.Response.Data && value.data.Response.Data.Accounts;
|
|
167
|
+
if (!Array.isArray(accounts)) throw "CodeBuddy response missing data.Response.Data.Accounts.";
|
|
168
|
+
if (!accounts.length) throw "CodeBuddy returned zero packages. Set CB_PACKAGE_CODES from the browser cURL body.";
|
|
169
|
+
var total = 0;
|
|
170
|
+
var used = 0;
|
|
171
|
+
var remaining = 0;
|
|
172
|
+
var reset = null;
|
|
173
|
+
for (var i = 0; i < accounts.length; i++) {
|
|
174
|
+
var account = accounts[i] || {};
|
|
175
|
+
var capacity = valueFromKeys(account, "CapacitySizePrecise", "CapacitySize");
|
|
176
|
+
var consumed = valueFromKeys(account, "CapacityUsedPrecise", "CapacityUsed");
|
|
177
|
+
var available = valueFromKeys(account, "CapacityRemainPrecise", "CapacityRemain");
|
|
178
|
+
if (capacity === null || capacity < 0 || (consumed === null && available === null)) throw "CodeBuddy package is missing credit values.";
|
|
179
|
+
if (consumed === null) consumed = Math.max(0, capacity - available);
|
|
180
|
+
if (available === null) available = Math.max(0, capacity - consumed);
|
|
181
|
+
total += capacity;
|
|
182
|
+
used += consumed;
|
|
183
|
+
remaining += available;
|
|
184
|
+
var expiry = expireTime(ctx, account);
|
|
185
|
+
if (expiry && (!reset || expiry < reset)) reset = expiry;
|
|
186
|
+
}
|
|
187
|
+
return normalizedTotals(total, used, remaining, reset);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function totalsFromCache(ctx, cookie) {
|
|
191
|
+
var path = creditsCachePath(ctx);
|
|
192
|
+
var raw = readTextIfExists(ctx, path);
|
|
193
|
+
if (!raw) throw "No CodeBuddy cookie and no local cache at " + path + ".";
|
|
194
|
+
if (raw.length > 1024 * 1024) throw "CodeBuddy cache at " + path + " is too large.";
|
|
195
|
+
var value = ctx.util.tryParseJson(raw);
|
|
196
|
+
if (!value || typeof value !== "object") throw "Invalid CodeBuddy cache.";
|
|
197
|
+
if (cookie && value.accountHash !== ctx.host.crypto.sha256(cookie + "\n" + apiUrl(ctx))) throw "CodeBuddy cache belongs to different credentials.";
|
|
198
|
+
var updated = parseDate(ctx, value.updatedAt);
|
|
199
|
+
if (cookie && (!updated || Date.parse(ctx.nowIso) - Date.parse(updated) > 24 * 3600000 || Date.parse(updated) > Date.parse(ctx.nowIso))) throw "CodeBuddy cache is too old.";
|
|
200
|
+
var total = number(value.total);
|
|
201
|
+
if (total === null || total < 0) throw "cb_credits.json invalid total.";
|
|
202
|
+
var used = number(value.used);
|
|
203
|
+
var remaining = number(value.remaining);
|
|
204
|
+
if (used === null && remaining === null) throw "CodeBuddy cache is missing credit values.";
|
|
205
|
+
if (used === null) used = Math.max(0, total - remaining);
|
|
206
|
+
if (remaining === null) remaining = Math.max(0, total - used);
|
|
207
|
+
var totals = normalizedTotals(total, used, remaining, parseDate(ctx, value.resetsAt));
|
|
208
|
+
totals.fetchedAt = updated;
|
|
209
|
+
return totals;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function writeCache(ctx, totals, cookie) {
|
|
213
|
+
var path = creditsCachePath(ctx);
|
|
214
|
+
if (!path || !ctx.host.fs || typeof ctx.host.fs.writeText !== "function") return;
|
|
215
|
+
var value = {
|
|
216
|
+
total: totals.total,
|
|
217
|
+
used: totals.used,
|
|
218
|
+
remaining: totals.remaining,
|
|
219
|
+
source: "api",
|
|
220
|
+
updatedAt: ctx.nowIso,
|
|
221
|
+
accountHash: ctx.host.crypto.sha256(cookie + "\n" + apiUrl(ctx)),
|
|
222
|
+
};
|
|
223
|
+
if (totals.resetsAt) value.resetsAt = totals.resetsAt;
|
|
224
|
+
try {
|
|
225
|
+
ctx.host.fs.writeText(path, JSON.stringify(value, null, 2));
|
|
226
|
+
} catch (error) {
|
|
227
|
+
ctx.host.log.warn("CodeBuddy: failed to write local credits cache: " + String(error));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function looksLikeHtml(text) {
|
|
232
|
+
return /^\s*</.test(String(text || ""));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function fetchOnce(ctx, cookie) {
|
|
236
|
+
var resp = ctx.util.request({
|
|
237
|
+
method: "POST",
|
|
238
|
+
url: apiUrl(ctx),
|
|
239
|
+
headers: {
|
|
240
|
+
Cookie: cookie,
|
|
241
|
+
Accept: "application/json, text/plain, */*",
|
|
242
|
+
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.7",
|
|
243
|
+
"Content-Type": "application/json",
|
|
244
|
+
Origin: ORIGIN,
|
|
245
|
+
Referer: REFERER,
|
|
246
|
+
"User-Agent": USER_AGENT,
|
|
247
|
+
"x-client-platform": "web",
|
|
248
|
+
"sec-fetch-dest": "empty",
|
|
249
|
+
"sec-fetch-mode": "cors",
|
|
250
|
+
"sec-fetch-site": "same-origin",
|
|
251
|
+
},
|
|
252
|
+
bodyText: JSON.stringify(requestBody(ctx)),
|
|
253
|
+
timeoutMs: 20000,
|
|
254
|
+
});
|
|
255
|
+
if (ctx.util.isAuthStatus(resp.status)) throw { auth: true, message: "CodeBuddy login required." };
|
|
256
|
+
if (resp.status === 429 || resp.status >= 500) throw { transient: true, message: "CodeBuddy temporary HTTP " + resp.status + "." };
|
|
257
|
+
if (resp.status < 200 || resp.status >= 300) throw "CodeBuddy get-user-resource returned HTTP " + resp.status + ".";
|
|
258
|
+
if ((resp.bodyText || "").length > MAX_RESPONSE_BYTES) throw "CodeBuddy response exceeds " + MAX_RESPONSE_BYTES + " bytes.";
|
|
259
|
+
if (looksLikeHtml(resp.bodyText)) throw { transient: true, message: "CodeBuddy WAF/HTML response." };
|
|
260
|
+
var json = ctx.util.tryParseJson(resp.bodyText);
|
|
261
|
+
if (!json) throw { transient: true, message: "Failed to parse CodeBuddy response." };
|
|
262
|
+
return totalsFromPayload(ctx, json);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function fetchWeb(ctx, cookie) {
|
|
266
|
+
var last = null;
|
|
267
|
+
for (var attempt = 0; attempt < 2; attempt++) {
|
|
268
|
+
try {
|
|
269
|
+
var totals = fetchOnce(ctx, cookie);
|
|
270
|
+
writeCache(ctx, totals, cookie);
|
|
271
|
+
return { totals: totals, source: "web" };
|
|
272
|
+
} catch (error) {
|
|
273
|
+
if (error && error.transient && attempt === 0) {
|
|
274
|
+
last = error;
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
throw last || "CodeBuddy fetch failed.";
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function formatNumber(value) {
|
|
284
|
+
var rounded = Math.round(value * 100) / 100;
|
|
285
|
+
var text = Math.abs(rounded - Math.round(rounded)) < 0.001 ? String(Math.round(rounded)) : rounded.toFixed(2).replace(/\.?0+$/, "");
|
|
286
|
+
return text.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function resultFromTotals(ctx, totals, source) {
|
|
290
|
+
var percent = totals.total > 0 ? totals.used / totals.total * 100 : totals.used > 0 ? 100 : 0;
|
|
291
|
+
var detail = formatNumber(totals.remaining) + " / " + formatNumber(totals.total) + " left";
|
|
292
|
+
var opts = {
|
|
293
|
+
label: "Credits",
|
|
294
|
+
used: Math.max(0, Math.min(100, percent)),
|
|
295
|
+
limit: 100,
|
|
296
|
+
format: { kind: "percent" },
|
|
297
|
+
detail: detail,
|
|
298
|
+
};
|
|
299
|
+
if (totals.resetsAt) opts.resetsAt = totals.resetsAt;
|
|
300
|
+
return { displayName: "CodeBuddy", source: source, fetchedAt: totals.fetchedAt || ctx.nowIso, plan: "CodeBuddy CN", lines: [ctx.line.progress(opts)] };
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function probe(ctx) {
|
|
304
|
+
if (ctx.sourceMode === "local" || ctx.sourceMode === "cli") {
|
|
305
|
+
return resultFromTotals(ctx, totalsFromCache(ctx), "local");
|
|
306
|
+
}
|
|
307
|
+
var cookie = cookieHeader(ctx);
|
|
308
|
+
if (!cookie) {
|
|
309
|
+
try {
|
|
310
|
+
return resultFromTotals(ctx, totalsFromCache(ctx), "local");
|
|
311
|
+
} catch (_) {
|
|
312
|
+
throw "CodeBuddy session not configured. Set CODEBUDDY_COOKIE, CB_COOKIE, provider cookieHeader, or ~/.codebuddy/cb_cookie.txt.";
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
try {
|
|
316
|
+
var fetched = fetchWeb(ctx, cookie);
|
|
317
|
+
return resultFromTotals(ctx, fetched.totals, fetched.source);
|
|
318
|
+
} catch (error) {
|
|
319
|
+
if (error && error.auth) throw error.message;
|
|
320
|
+
if (error && error.transient) {
|
|
321
|
+
try {
|
|
322
|
+
return resultFromTotals(ctx, totalsFromCache(ctx, cookie), "cached");
|
|
323
|
+
} catch (_) {}
|
|
324
|
+
throw error.message;
|
|
325
|
+
}
|
|
326
|
+
throw error;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
globalThis.__openusage_plugin = { id: "codebuddy", probe: probe };
|
|
331
|
+
})();
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "codebuddy",
|
|
4
|
+
"name": "CodeBuddy",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"web",
|
|
10
|
+
"local"
|
|
11
|
+
],
|
|
12
|
+
"autoMode": "web",
|
|
13
|
+
"webUrl": "https://www.codebuddy.cn",
|
|
14
|
+
"usageDashboardUrl": "https://www.codebuddy.cn/profile/plans-usage",
|
|
15
|
+
"links": [
|
|
16
|
+
{
|
|
17
|
+
"label": "Dashboard",
|
|
18
|
+
"url": "https://www.codebuddy.cn/profile/plans-usage"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"envVars": [
|
|
22
|
+
"CODEBUDDY_HOME",
|
|
23
|
+
"CB_COOKIE_FILE",
|
|
24
|
+
"CB_CREDITS_FILE",
|
|
25
|
+
"CODEBUDDY_COOKIE",
|
|
26
|
+
"CB_COOKIE",
|
|
27
|
+
"CB_API_URL",
|
|
28
|
+
"CB_PACKAGE_CODES"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0.00 0.00 128.00 128.00">
|
|
4
|
+
<g stroke-width="2.00" fill="none" stroke-linecap="butt">
|
|
5
|
+
<path stroke="currentColor" vector-effect="non-scaling-stroke" d="
|
|
6
|
+
M 27.46 27.54
|
|
7
|
+
C 23.31 31.70 16.50 34.46 10.57 34.99
|
|
8
|
+
Q 10.24 35.02 10.04 35.39
|
|
9
|
+
Q 9.90 35.65 9.90 36.04
|
|
10
|
+
Q 9.90 36.43 10.04 36.69
|
|
11
|
+
Q 10.24 37.06 10.57 37.09
|
|
12
|
+
C 16.50 37.62 23.31 40.38 27.46 44.54
|
|
13
|
+
C 31.62 48.69 34.38 55.50 34.91 61.43
|
|
14
|
+
Q 34.94 61.76 35.31 61.97
|
|
15
|
+
Q 35.57 62.11 35.96 62.11
|
|
16
|
+
Q 36.36 62.11 36.62 61.97
|
|
17
|
+
Q 36.98 61.76 37.02 61.43
|
|
18
|
+
C 37.54 55.50 40.31 48.69 44.46 44.54
|
|
19
|
+
C 48.62 40.38 55.43 37.62 61.36 37.09
|
|
20
|
+
Q 61.69 37.06 61.89 36.69
|
|
21
|
+
Q 62.03 36.43 62.03 36.04
|
|
22
|
+
Q 62.03 35.65 61.89 35.39
|
|
23
|
+
Q 61.69 35.02 61.36 34.99
|
|
24
|
+
C 55.43 34.46 48.62 31.70 44.46 27.54
|
|
25
|
+
C 40.31 23.38 37.54 16.58 37.02 10.65
|
|
26
|
+
Q 36.98 10.32 36.62 10.11
|
|
27
|
+
Q 36.36 9.97 35.96 9.97
|
|
28
|
+
Q 35.57 9.97 35.31 10.11
|
|
29
|
+
Q 34.94 10.32 34.91 10.65
|
|
30
|
+
C 34.38 16.58 31.62 23.38 27.46 27.54"
|
|
31
|
+
/>
|
|
32
|
+
<path stroke="currentColor" vector-effect="non-scaling-stroke" d="
|
|
33
|
+
M 103.9557 64.7548
|
|
34
|
+
A 0.70 0.70 0.0 0 0 103.2569 64.0536
|
|
35
|
+
L 64.7970 63.9864
|
|
36
|
+
A 0.70 0.70 0.0 0 0 64.0958 64.6852
|
|
37
|
+
L 64.0843 75.2652
|
|
38
|
+
A 0.70 0.70 0.0 0 0 64.7831 75.9664
|
|
39
|
+
L 103.2430 76.0336
|
|
40
|
+
A 0.70 0.70 0.0 0 0 103.9442 75.3348
|
|
41
|
+
L 103.9557 64.7548"
|
|
42
|
+
/>
|
|
43
|
+
</g>
|
|
44
|
+
<path fill="currentColor" d="
|
|
45
|
+
M 113.99 0.00
|
|
46
|
+
Q 125.60 2.32 128.00 13.94
|
|
47
|
+
L 128.00 113.98
|
|
48
|
+
Q 125.72 125.58 114.06 128.00
|
|
49
|
+
L 14.00 128.00
|
|
50
|
+
Q 2.44 125.69 0.00 114.05
|
|
51
|
+
L 0.00 14.01
|
|
52
|
+
Q 2.33 2.42 13.95 0.00
|
|
53
|
+
L 113.99 0.00
|
|
54
|
+
Z
|
|
55
|
+
M 27.46 27.54
|
|
56
|
+
C 23.31 31.70 16.50 34.46 10.57 34.99
|
|
57
|
+
Q 10.24 35.02 10.04 35.39
|
|
58
|
+
Q 9.90 35.65 9.90 36.04
|
|
59
|
+
Q 9.90 36.43 10.04 36.69
|
|
60
|
+
Q 10.24 37.06 10.57 37.09
|
|
61
|
+
C 16.50 37.62 23.31 40.38 27.46 44.54
|
|
62
|
+
C 31.62 48.69 34.38 55.50 34.91 61.43
|
|
63
|
+
Q 34.94 61.76 35.31 61.97
|
|
64
|
+
Q 35.57 62.11 35.96 62.11
|
|
65
|
+
Q 36.36 62.11 36.62 61.97
|
|
66
|
+
Q 36.98 61.76 37.02 61.43
|
|
67
|
+
C 37.54 55.50 40.31 48.69 44.46 44.54
|
|
68
|
+
C 48.62 40.38 55.43 37.62 61.36 37.09
|
|
69
|
+
Q 61.69 37.06 61.89 36.69
|
|
70
|
+
Q 62.03 36.43 62.03 36.04
|
|
71
|
+
Q 62.03 35.65 61.89 35.39
|
|
72
|
+
Q 61.69 35.02 61.36 34.99
|
|
73
|
+
C 55.43 34.46 48.62 31.70 44.46 27.54
|
|
74
|
+
C 40.31 23.38 37.54 16.58 37.02 10.65
|
|
75
|
+
Q 36.98 10.32 36.62 10.11
|
|
76
|
+
Q 36.36 9.97 35.96 9.97
|
|
77
|
+
Q 35.57 9.97 35.31 10.11
|
|
78
|
+
Q 34.94 10.32 34.91 10.65
|
|
79
|
+
C 34.38 16.58 31.62 23.38 27.46 27.54
|
|
80
|
+
Z
|
|
81
|
+
M 103.9557 64.7548
|
|
82
|
+
A 0.70 0.70 0.0 0 0 103.2569 64.0536
|
|
83
|
+
L 64.7970 63.9864
|
|
84
|
+
A 0.70 0.70 0.0 0 0 64.0958 64.6852
|
|
85
|
+
L 64.0843 75.2652
|
|
86
|
+
A 0.70 0.70 0.0 0 0 64.7831 75.9664
|
|
87
|
+
L 103.2430 76.0336
|
|
88
|
+
A 0.70 0.70 0.0 0 0 103.9442 75.3348
|
|
89
|
+
L 103.9557 64.7548
|
|
90
|
+
Z"
|
|
91
|
+
/>
|
|
92
|
+
</svg>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|