@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
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "qwencloud",
|
|
4
|
+
"name": "Qwen Cloud",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"web"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "web",
|
|
12
|
+
"webUrl": "https://home.qwencloud.com",
|
|
13
|
+
"usageDashboardUrl": "https://home.qwencloud.com/billing/subscription/token-plan-individual",
|
|
14
|
+
"statusPageUrl": "https://status.alibabacloud.com",
|
|
15
|
+
"links": [
|
|
16
|
+
{
|
|
17
|
+
"label": "Dashboard",
|
|
18
|
+
"url": "https://home.qwencloud.com/billing/subscription/token-plan-individual"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"label": "Status",
|
|
22
|
+
"url": "https://status.alibabacloud.com"
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"envVars": [
|
|
26
|
+
"QWEN_CLOUD_COOKIE",
|
|
27
|
+
"QWEN_CLOUD_COOKIE_HEADER"
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Peter Steinberger
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
|
+
globalThis.__usagestat_bundled_options = {"labels":["Credits","Plan","Additional"],"defaults":{},"autoMode":"web"};
|
|
3
|
+
function _nullishCoalesce(lhs, rhsFn) {
|
|
4
|
+
if (lhs != null) {
|
|
5
|
+
return lhs;
|
|
6
|
+
} else {
|
|
7
|
+
return rhsFn();
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
defineProvider({
|
|
11
|
+
id: "raycast",
|
|
12
|
+
name: "Raycast",
|
|
13
|
+
endpoints: ["https://www.raycast.com"],
|
|
14
|
+
settings: [{ key: "webTimeoutSeconds", title: "Web timeout", type: "plain" }],
|
|
15
|
+
capabilities: ["browser-cookies", "http-status"],
|
|
16
|
+
cookieDomains: ["raycast.com", "www.raycast.com"],
|
|
17
|
+
async fetchUsage(ctx) {
|
|
18
|
+
const sessionCookie = (value) => {
|
|
19
|
+
const match = /(?:^|;\s*)__raycast_session=([^;]*)/.exec(value);
|
|
20
|
+
return !!match && match[1].trim().length > 0;
|
|
21
|
+
};
|
|
22
|
+
const missingSession = () => {
|
|
23
|
+
throw ctx.fail.missingCredential(
|
|
24
|
+
"No Raycast session cookies found. Sign in at www.raycast.com/settings or paste a Cookie header.",
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
const domain = "www.raycast.com";
|
|
28
|
+
const policy = ctx.browser.availability(domain);
|
|
29
|
+
if (policy === "off") throw ctx.fail.missingCredential("Raycast cookies are disabled.");
|
|
30
|
+
const timeoutRaw = Number(_nullishCoalesce(ctx.settings.get("webTimeoutSeconds"), () => "15"));
|
|
31
|
+
const timeoutSeconds = Number.isFinite(timeoutRaw) ? Math.min(30, Math.max(1, Math.round(timeoutRaw))) : 15;
|
|
32
|
+
let response;
|
|
33
|
+
let rejected = false;
|
|
34
|
+
for await (const session of ctx.browser.sessions(domain)) {
|
|
35
|
+
const cookie = session.header
|
|
36
|
+
.split(";")
|
|
37
|
+
.map((part) => part.trim())
|
|
38
|
+
.filter((part) => /^(?:__raycast_session|csrf_token)=/.test(part))
|
|
39
|
+
.join("; ");
|
|
40
|
+
if (!sessionCookie(cookie)) {
|
|
41
|
+
ctx.browser.rejectCookie(domain, session);
|
|
42
|
+
if (policy === "manual") break;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const candidate = await ctx.http.get("https://www.raycast.com/frontend_api/current_user/ai_credits", {
|
|
46
|
+
timeoutSeconds,
|
|
47
|
+
headers: {
|
|
48
|
+
Cookie: cookie,
|
|
49
|
+
Accept: "application/json",
|
|
50
|
+
Origin: "https://www.raycast.com",
|
|
51
|
+
Referer: "https://www.raycast.com/settings",
|
|
52
|
+
"User-Agent":
|
|
53
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
if (candidate.status === 401) {
|
|
57
|
+
rejected = true;
|
|
58
|
+
ctx.browser.rejectCookie(domain, session);
|
|
59
|
+
if (policy === "manual") break;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
response = candidate;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
if (!response) {
|
|
66
|
+
if (rejected)
|
|
67
|
+
throw ctx.fail.authenticationExpired(
|
|
68
|
+
"Raycast website session expired. Sign in at www.raycast.com/settings or paste a fresh Cookie header.",
|
|
69
|
+
);
|
|
70
|
+
return missingSession();
|
|
71
|
+
}
|
|
72
|
+
if (response.status === 403) {
|
|
73
|
+
throw ctx.fail.permissionDenied("Raycast denied access to AI credits for this account.");
|
|
74
|
+
}
|
|
75
|
+
if (response.status === 429) throw ctx.fail.rateLimited("Raycast credits requests are rate limited.");
|
|
76
|
+
if (response.status >= 500) {
|
|
77
|
+
throw ctx.fail.providerUnavailable(`Raycast credits API returned HTTP ${response.status}.`);
|
|
78
|
+
}
|
|
79
|
+
if (response.status !== 200) {
|
|
80
|
+
throw ctx.fail.apiFailure(`Raycast credits API returned HTTP ${response.status}.`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const fail = (field) => {
|
|
84
|
+
throw ctx.fail.parseFailure(`Invalid Raycast credits response: ${field}`);
|
|
85
|
+
};
|
|
86
|
+
const object = (value, field) => {
|
|
87
|
+
if (value === undefined || value === null) return {};
|
|
88
|
+
if (typeof value !== "object" || Array.isArray(value)) return fail(field);
|
|
89
|
+
return value;
|
|
90
|
+
};
|
|
91
|
+
const number = (value, field) => {
|
|
92
|
+
if (value === undefined || value === null) return undefined;
|
|
93
|
+
if (typeof value === "boolean") return fail(field);
|
|
94
|
+
if (typeof value === "number") {
|
|
95
|
+
return Number.isFinite(value) ? value : fail(field);
|
|
96
|
+
}
|
|
97
|
+
if (typeof value !== "string") return fail(field);
|
|
98
|
+
const trimmed = value.trim();
|
|
99
|
+
if (trimmed === "") return fail(field);
|
|
100
|
+
if (!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(trimmed)) return fail(field);
|
|
101
|
+
const parsed = Number(trimmed);
|
|
102
|
+
return Number.isFinite(parsed) ? parsed : fail(field);
|
|
103
|
+
};
|
|
104
|
+
const text = (value) => (typeof value === "string" ? value.trim() || undefined : undefined);
|
|
105
|
+
// No thousands grouping. The meter footnote is this text, and a grouped number would not match the source amount.
|
|
106
|
+
const amount = (value) => {
|
|
107
|
+
if (Number.isInteger(value)) return String(value);
|
|
108
|
+
let text = value.toFixed(2);
|
|
109
|
+
while (text.endsWith("0")) text = text.slice(0, -1);
|
|
110
|
+
if (text.endsWith(".")) text = text.slice(0, -1);
|
|
111
|
+
return text;
|
|
112
|
+
};
|
|
113
|
+
const planLabel = (tier) => {
|
|
114
|
+
switch (tier) {
|
|
115
|
+
case "pro":
|
|
116
|
+
return "Pro";
|
|
117
|
+
case "pro_plus":
|
|
118
|
+
return "Pro+";
|
|
119
|
+
case "max":
|
|
120
|
+
return "Max";
|
|
121
|
+
default:
|
|
122
|
+
return tier;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
let decoded;
|
|
127
|
+
try {
|
|
128
|
+
decoded = JSON.parse(response.bodyText);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
void error;
|
|
131
|
+
return fail("expected JSON");
|
|
132
|
+
}
|
|
133
|
+
const root = object(decoded, "expected an object");
|
|
134
|
+
const remaining = number(root.remaining_balance_credits, "remaining_balance_credits");
|
|
135
|
+
const total = number(root.total_balance_credits, "total_balance_credits");
|
|
136
|
+
if (remaining === undefined && total === undefined) return fail("no credit amounts");
|
|
137
|
+
if (remaining !== undefined && remaining < 0) return fail("remaining_balance_credits");
|
|
138
|
+
if (total !== undefined && total < 0) return fail("total_balance_credits");
|
|
139
|
+
|
|
140
|
+
let renewal;
|
|
141
|
+
if (root.next_credits_at !== undefined && root.next_credits_at !== null) {
|
|
142
|
+
if (typeof root.next_credits_at !== "string") return fail("next_credits_at");
|
|
143
|
+
try {
|
|
144
|
+
renewal = ctx.date.iso(root.next_credits_at);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
void error;
|
|
147
|
+
return fail("next_credits_at");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const funding = object(root.funding_subscription, "funding_subscription");
|
|
151
|
+
const plan = planLabel(text(funding.tier));
|
|
152
|
+
const rows = [];
|
|
153
|
+
if (remaining !== undefined) rows.push({ label: "Left", value: amount(remaining) });
|
|
154
|
+
if (total !== undefined) rows.push({ label: "Total", value: amount(total) });
|
|
155
|
+
// A positive total is one Credits meter. The balance lives in resetDescription, which the shared
|
|
156
|
+
// card already prints under the bar. Left and Total rows stay only when that meter is absent,
|
|
157
|
+
// so a zero allowance still has something to show.
|
|
158
|
+
const meter = remaining !== undefined && total !== undefined && total > 0 ? { remaining, total } : undefined;
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
primary: meter
|
|
162
|
+
? {
|
|
163
|
+
usedPercent: ctx.pct(Math.max(0, meter.total - meter.remaining), meter.total),
|
|
164
|
+
resetsAt: renewal,
|
|
165
|
+
resetDescription: `${amount(meter.remaining)} / ${amount(meter.total)} credits left`,
|
|
166
|
+
}
|
|
167
|
+
: undefined,
|
|
168
|
+
details: meter || !rows.length ? undefined : [{ title: "Credits", rows }],
|
|
169
|
+
subscriptionRenewsAt: meter ? undefined : renewal,
|
|
170
|
+
identity: plan ? { loginMethod: plan } : undefined,
|
|
171
|
+
dataConfidence: "exact",
|
|
172
|
+
};
|
|
173
|
+
},
|
|
174
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "raycast",
|
|
4
|
+
"name": "Raycast",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"web"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "web",
|
|
12
|
+
"usageDashboardUrl": "https://www.raycast.com/settings",
|
|
13
|
+
"webUrl": "https://raycast.com",
|
|
14
|
+
"envVars": [
|
|
15
|
+
"RAYCAST_COOKIE"
|
|
16
|
+
],
|
|
17
|
+
"upstream": {
|
|
18
|
+
"repository": "https://github.com/steipete/CodexBar",
|
|
19
|
+
"revision": "78ba5a1e65e6859da59a21b799df95ab91bc0b89",
|
|
20
|
+
"path": "Sources/CodexBarCore/Resources/Plugins/raycast.js",
|
|
21
|
+
"sha256": "1f93bd240923c8427615b2de3a40d46f167b907864c01475754b115b804c3ee4",
|
|
22
|
+
"license": "MIT"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Peter Steinberger
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -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>Replicate</title><path d="M22 10.552v2.26h-7.932V22H11.54V10.552H22zM22 2v2.264H4.528V22H2V2h20zm0 4.276V8.54H9.296V22H6.768V6.276H22z"></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>Replicate</title><path d="M22 10.552v2.26h-7.932V22H11.54V10.552H22zM22 2v2.264H4.528V22H2V2h20zm0 4.276V8.54H9.296V22H6.768V6.276H22z"></path></svg>
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
|
+
globalThis.__usagestat_bundled_options = {"labels":["Spend","Spend","Additional"],"defaults":{},"autoMode":"web"};
|
|
3
|
+
function _optionalChain(ops) {
|
|
4
|
+
let lastAccessLHS = undefined;
|
|
5
|
+
let value = ops[0];
|
|
6
|
+
let i = 1;
|
|
7
|
+
while (i < ops.length) {
|
|
8
|
+
const op = ops[i];
|
|
9
|
+
const fn = ops[i + 1];
|
|
10
|
+
i += 2;
|
|
11
|
+
if ((op === "optionalAccess" || op === "optionalCall") && value == null) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
if (op === "access" || op === "optionalAccess") {
|
|
15
|
+
lastAccessLHS = value;
|
|
16
|
+
value = fn(value);
|
|
17
|
+
} else if (op === "call" || op === "optionalCall") {
|
|
18
|
+
value = fn((...args) => value.call(lastAccessLHS, ...args));
|
|
19
|
+
lastAccessLHS = undefined;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
defineProvider({
|
|
25
|
+
id: "replicate",
|
|
26
|
+
name: "Replicate",
|
|
27
|
+
endpoints: ["https://replicate.com"],
|
|
28
|
+
settings: [],
|
|
29
|
+
capabilities: ["browser-cookies", "http-status"],
|
|
30
|
+
cookieDomains: ["replicate.com"],
|
|
31
|
+
async fetchUsage(ctx) {
|
|
32
|
+
const fail = (field) => {
|
|
33
|
+
throw ctx.fail.parseFailure(`Replicate billing response format changed: ${field}`);
|
|
34
|
+
};
|
|
35
|
+
const record = (value) =>
|
|
36
|
+
value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
37
|
+
const parse = (body) => {
|
|
38
|
+
try {
|
|
39
|
+
return JSON.parse(body);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
void error;
|
|
42
|
+
return fail("invalid JSON");
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const money = (value) => {
|
|
46
|
+
if (typeof value !== "string" || !/^\d+(?:\.\d+)?$/.test(value.trim())) return undefined;
|
|
47
|
+
const number = Number(value.trim());
|
|
48
|
+
return Number.isFinite(number) && number >= 0 ? number : undefined;
|
|
49
|
+
};
|
|
50
|
+
const expired = () => {
|
|
51
|
+
throw ctx.fail.authenticationExpired("Replicate session expired. Sign in again or paste a fresh Cookie header.");
|
|
52
|
+
};
|
|
53
|
+
const validate = (response) => {
|
|
54
|
+
if (response.status === 401 || response.status === 403) expired();
|
|
55
|
+
const rawRetry = response.headers["retry-after"];
|
|
56
|
+
const retry = rawRetry && /^\d+(?:\.\d+)?$/.test(rawRetry.trim()) ? Number(rawRetry) : 1;
|
|
57
|
+
const retryAfterSeconds = Number.isFinite(retry) ? Math.min(10, retry) : 1;
|
|
58
|
+
if (response.status === 429) throw ctx.fail.rateLimited("Replicate rate limit reached.", { retryAfterSeconds });
|
|
59
|
+
if (response.status === 408 || response.status >= 500)
|
|
60
|
+
throw ctx.fail.providerUnavailable("Replicate billing is unavailable.", { retryAfterSeconds });
|
|
61
|
+
if (response.status < 200 || response.status >= 300)
|
|
62
|
+
throw ctx.fail.apiFailure(`Replicate returned HTTP ${response.status}.`);
|
|
63
|
+
};
|
|
64
|
+
const cookie = await ctx.browser.cookieHeader("replicate.com");
|
|
65
|
+
const response = await ctx.http.get("https://replicate.com/account/billing", {
|
|
66
|
+
headers: { Cookie: cookie, Accept: "text/html" },
|
|
67
|
+
timeoutSeconds: 8,
|
|
68
|
+
});
|
|
69
|
+
validate(response);
|
|
70
|
+
let account;
|
|
71
|
+
const scripts = /<script\b([^>]*)>([\s\S]*?)<\/script\s*>/gi;
|
|
72
|
+
let match;
|
|
73
|
+
let visited = 0;
|
|
74
|
+
while ((match = scripts.exec(response.bodyText)) && !account && visited < 4000) {
|
|
75
|
+
if (
|
|
76
|
+
!/\bid\s*=\s*(["'])react-component-props[^"']*\1/i.test(match[1]) ||
|
|
77
|
+
!/\btype\s*=\s*(["'])application\/json\1/i.test(match[1])
|
|
78
|
+
)
|
|
79
|
+
continue;
|
|
80
|
+
let payload;
|
|
81
|
+
try {
|
|
82
|
+
payload = JSON.parse(match[2]);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
void error;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const queue = [payload];
|
|
88
|
+
for (let index = 0; index < queue.length && visited < 4000; index++, visited++) {
|
|
89
|
+
const item = queue[index];
|
|
90
|
+
const object = record(item);
|
|
91
|
+
const candidate = record(_optionalChain([object, "optionalAccess", (_) => _.account]));
|
|
92
|
+
if (
|
|
93
|
+
candidate &&
|
|
94
|
+
(candidate.kind === "user" || candidate.kind === "organization") &&
|
|
95
|
+
typeof candidate.username === "string" &&
|
|
96
|
+
candidate.username.trim()
|
|
97
|
+
) {
|
|
98
|
+
account = { kind: candidate.kind, username: candidate.username.trim() };
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
const children = Array.isArray(item) ? item : object ? Object.values(object) : [];
|
|
102
|
+
for (const child of children) {
|
|
103
|
+
if (queue.length >= 4000) break;
|
|
104
|
+
if (child !== null && typeof child === "object") queue.push(child);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (!account) {
|
|
109
|
+
// These two markers identify Replicate's public signed-out billing redirect.
|
|
110
|
+
const signInTitle = /<title>\s*Sign in\s*\|\s*Replicate\s*<\/title>/i.test(response.bodyText);
|
|
111
|
+
const githubLogin = /<a\b[^>]*\bhref=["']\/login\/github\/(?:\?[^"']*)?["']/i.test(response.bodyText);
|
|
112
|
+
if (signInTitle && githubLogin) return expired();
|
|
113
|
+
return fail("unrecognized billing account props");
|
|
114
|
+
}
|
|
115
|
+
const base = `https://replicate.com/api/${account.kind === "organization" ? "organizations" : "users"}/${encodeURIComponent(account.username)}`;
|
|
116
|
+
const invoicesResponse = await ctx.http.get(`${base}/invoices`, { headers: { Cookie: cookie }, timeoutSeconds: 8 });
|
|
117
|
+
validate(invoicesResponse);
|
|
118
|
+
const invoices = _optionalChain([
|
|
119
|
+
record,
|
|
120
|
+
"call",
|
|
121
|
+
(_2) => _2(parse(invoicesResponse.bodyText)),
|
|
122
|
+
"optionalAccess",
|
|
123
|
+
(_3) => _3.invoices,
|
|
124
|
+
]);
|
|
125
|
+
if (!Array.isArray(invoices)) return fail("missing invoices");
|
|
126
|
+
const now = ctx.date.now().getTime();
|
|
127
|
+
const current = invoices.map(record).find((invoice) => {
|
|
128
|
+
if (!invoice || invoice.type !== "monthly-usage") return false;
|
|
129
|
+
if (invoice.ended_before === null || invoice.ended_before === undefined) return true;
|
|
130
|
+
if (typeof invoice.ended_before !== "string" || !invoice.ended_before.trim()) return false;
|
|
131
|
+
const end = Date.parse(invoice.ended_before);
|
|
132
|
+
return Number.isFinite(end) && end > now;
|
|
133
|
+
});
|
|
134
|
+
if (!current) return fail("no current monthly-usage invoice");
|
|
135
|
+
const used = money(current.total_cost_before_adjustments);
|
|
136
|
+
if (used === undefined) return fail("missing or invalid total_cost_before_adjustments");
|
|
137
|
+
let balance;
|
|
138
|
+
try {
|
|
139
|
+
const credit = await ctx.http.get(`${base}/unused-credit`, { headers: { Cookie: cookie }, timeoutSeconds: 2 });
|
|
140
|
+
if (credit.status >= 200 && credit.status < 300)
|
|
141
|
+
balance = money(
|
|
142
|
+
_optionalChain([
|
|
143
|
+
record,
|
|
144
|
+
"call",
|
|
145
|
+
(_4) => _4(parse(credit.bodyText)),
|
|
146
|
+
"optionalAccess",
|
|
147
|
+
(_5) => _5.unused_credit,
|
|
148
|
+
]),
|
|
149
|
+
);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
void error;
|
|
152
|
+
}
|
|
153
|
+
const rows = [{ label: "Spent this month", value: ctx.format.usd(used) }];
|
|
154
|
+
if (balance !== undefined) rows.push({ label: "Credit balance", value: ctx.format.usd(balance) });
|
|
155
|
+
return {
|
|
156
|
+
cost: { used, balance, currency: "USD", period: "This month" },
|
|
157
|
+
details: [{ title: "Billing", rows }],
|
|
158
|
+
identity: {
|
|
159
|
+
accountID: account.username,
|
|
160
|
+
organization: account.kind === "organization" ? account.username : undefined,
|
|
161
|
+
},
|
|
162
|
+
dataConfidence: "exact",
|
|
163
|
+
};
|
|
164
|
+
},
|
|
165
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "replicate",
|
|
4
|
+
"name": "Replicate",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"web"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "web",
|
|
12
|
+
"usageDashboardUrl": "https://replicate.com/account/billing",
|
|
13
|
+
"webUrl": "https://replicate.com",
|
|
14
|
+
"envVars": [
|
|
15
|
+
"REPLICATE_COOKIE"
|
|
16
|
+
],
|
|
17
|
+
"upstream": {
|
|
18
|
+
"repository": "https://github.com/steipete/CodexBar",
|
|
19
|
+
"revision": "78ba5a1e65e6859da59a21b799df95ab91bc0b89",
|
|
20
|
+
"path": "Sources/CodexBarCore/Resources/Plugins/replicate.js",
|
|
21
|
+
"sha256": "d240c36fa142ee91ce90ae52a2c6814613d2d5533a00c8a4c7ecec2f9386006c",
|
|
22
|
+
"license": "MIT"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M50 8C28.7 8 11.5 25.2 11.5 46.5C11.5 67.8 28.7 85 50 85C71.3 85 88.5 67.8 88.5 46.5C88.5 25.2 71.3 8 50 8Z" stroke="white" stroke-width="8"/>
|
|
3
|
+
<path d="M31 62C36.3 68.1 43.3 71.2 52 71.2C62.4 71.2 69.6 65.9 69.6 58.2C69.6 49.7 62.1 47.6 53.8 45.4C47.7 43.8 42.5 42.4 42.5 38.3C42.5 34.8 45.9 32.4 51.3 32.4C56.9 32.4 61.7 34.6 65.8 39" stroke="white" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
<path d="M33.2 30.4C37.1 24.8 43.9 21.5 51.8 21.5C60.5 21.5 67.3 25.1 72.2 32.2" stroke="white" stroke-width="8" stroke-linecap="round"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var BILLING_URL = "https://console.sakana.ai/billing";
|
|
3
|
+
var USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36";
|
|
4
|
+
|
|
5
|
+
function trim(value) {
|
|
6
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function env(ctx, name) {
|
|
10
|
+
try {
|
|
11
|
+
return trim(ctx.host.env.get(name));
|
|
12
|
+
} catch (_) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function setting(ctx, names) {
|
|
18
|
+
var settings = ctx.provider && ctx.provider.settings ? ctx.provider.settings : {};
|
|
19
|
+
for (var i = 0; i < names.length; i++) {
|
|
20
|
+
var value = trim(settings[names[i]]);
|
|
21
|
+
if (value) return value;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function normalizeCookie(raw) {
|
|
27
|
+
var header = trim(raw);
|
|
28
|
+
if (!header) return null;
|
|
29
|
+
if (header.slice(0, 7).toLowerCase() === "cookie:") header = header.slice(7).trim();
|
|
30
|
+
var pairs = [];
|
|
31
|
+
var chunks = header.split(";");
|
|
32
|
+
for (var i = 0; i < chunks.length; i++) {
|
|
33
|
+
var idx = chunks[i].indexOf("=");
|
|
34
|
+
if (idx < 0) continue;
|
|
35
|
+
var name = chunks[i].slice(0, idx).trim();
|
|
36
|
+
var value = chunks[i].slice(idx + 1).trim();
|
|
37
|
+
if (name && value) pairs.push(name + "=" + value);
|
|
38
|
+
}
|
|
39
|
+
return pairs.length ? pairs.join("; ") : null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function cookieHeader(ctx) {
|
|
43
|
+
return normalizeCookie(ctx.provider && ctx.provider.cookieHeader) ||
|
|
44
|
+
normalizeCookie(setting(ctx, ["cookieHeader", "cookie"])) ||
|
|
45
|
+
normalizeCookie(env(ctx, "SAKANA_COOKIE"));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function looksSignedOut(text) {
|
|
49
|
+
var lower = String(text || "").toLowerCase();
|
|
50
|
+
return lower.indexOf("sign in") >= 0 || lower.indexOf("log in") >= 0 || lower.indexOf("/auth/") >= 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function parseReset(raw) {
|
|
54
|
+
var text = String(raw || "").replace(/\bat\b/i, "").replace(/\s+/g, " ").trim();
|
|
55
|
+
var ms = Date.parse(text + " UTC");
|
|
56
|
+
return Number.isFinite(ms) ? new Date(ms).toISOString() : null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function extractResetText(segment) {
|
|
60
|
+
var patterns = [
|
|
61
|
+
/([A-Z][a-z]+ \d{1,2}, \d{4} at \d{1,2}:\d{2} [AP]M)/i,
|
|
62
|
+
/(?:reset|renews?)[^A-Z]{0,80}([A-Z][a-z]+ \d{1,2}, \d{4} at \d{1,2}:\d{2} [AP]M)/i,
|
|
63
|
+
];
|
|
64
|
+
for (var i = 0; i < patterns.length; i++) {
|
|
65
|
+
var match = patterns[i].exec(segment);
|
|
66
|
+
if (match && match[1]) return match[1];
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function extractPercent(segment) {
|
|
72
|
+
var patterns = [
|
|
73
|
+
/([0-9]+(?:\.[0-9]+)?)\s*%\s*(?:used|usage)?/i,
|
|
74
|
+
/(?:used|usage)[^0-9]{0,40}([0-9]+(?:\.[0-9]+)?)\s*%/i,
|
|
75
|
+
/"(?:usedPercent|used_percent|percent)"\s*:\s*([0-9]+(?:\.[0-9]+)?)/i,
|
|
76
|
+
];
|
|
77
|
+
for (var i = 0; i < patterns.length; i++) {
|
|
78
|
+
var match = patterns[i].exec(segment);
|
|
79
|
+
if (match && match[1]) {
|
|
80
|
+
var value = Number(match[1]);
|
|
81
|
+
if (Number.isFinite(value)) return value;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function extractWindow(ctx, text, labels, displayLabel, minutes) {
|
|
88
|
+
var lower = text.toLowerCase();
|
|
89
|
+
var index = -1;
|
|
90
|
+
for (var i = 0; i < labels.length; i++) {
|
|
91
|
+
var found = lower.indexOf(labels[i]);
|
|
92
|
+
if (found >= 0 && (index < 0 || found < index)) index = found;
|
|
93
|
+
}
|
|
94
|
+
if (index < 0) return null;
|
|
95
|
+
var end = Math.min(text.length, index + 1400);
|
|
96
|
+
var boundaries = displayLabel === "Weekly" ? ["5-hour", "5 hour", "five-hour", "session"] : ["weekly", "week"];
|
|
97
|
+
for (var b = 0; b < boundaries.length; b++) {
|
|
98
|
+
var next = lower.indexOf(boundaries[b], index + 1);
|
|
99
|
+
if (next >= 0) end = Math.min(end, next);
|
|
100
|
+
}
|
|
101
|
+
var segment = text.slice(index, end);
|
|
102
|
+
var percent = extractPercent(segment);
|
|
103
|
+
if (percent === null) return null;
|
|
104
|
+
var resetText = extractResetText(segment);
|
|
105
|
+
var opts = {
|
|
106
|
+
label: displayLabel,
|
|
107
|
+
used: Math.max(0, Math.min(100, percent)),
|
|
108
|
+
limit: 100,
|
|
109
|
+
format: { kind: "percent" },
|
|
110
|
+
periodDurationMs: minutes * 60 * 1000,
|
|
111
|
+
};
|
|
112
|
+
if (resetText) {
|
|
113
|
+
opts.resetsAt = parseReset(resetText);
|
|
114
|
+
opts.detail = resetText;
|
|
115
|
+
}
|
|
116
|
+
return ctx.line.progress(opts);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function probe(ctx) {
|
|
120
|
+
var cookie = cookieHeader(ctx);
|
|
121
|
+
if (!cookie) throw "Sakana session not configured. Set SAKANA_COOKIE or provider cookieHeader.";
|
|
122
|
+
var resp = ctx.util.request({
|
|
123
|
+
method: "GET",
|
|
124
|
+
url: BILLING_URL,
|
|
125
|
+
headers: {
|
|
126
|
+
Cookie: cookie,
|
|
127
|
+
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
128
|
+
"User-Agent": USER_AGENT,
|
|
129
|
+
},
|
|
130
|
+
timeoutMs: 15000,
|
|
131
|
+
});
|
|
132
|
+
if (ctx.util.isAuthStatus(resp.status)) throw "Sakana session expired.";
|
|
133
|
+
if (resp.status < 200 || resp.status >= 300) throw "Sakana billing returned HTTP " + resp.status + ".";
|
|
134
|
+
var primary = extractWindow(ctx, resp.bodyText || "", ["5-hour", "5 hour", "five-hour", "session"], "5-hour", 5 * 60);
|
|
135
|
+
var lines = primary ? [primary] : [];
|
|
136
|
+
var weekly = extractWindow(ctx, resp.bodyText || "", ["weekly", "week"], "Weekly", 7 * 24 * 60);
|
|
137
|
+
if (weekly) lines.push(weekly);
|
|
138
|
+
if (!lines.length) throw looksSignedOut(resp.bodyText) ? "Sakana login required." : "Missing Sakana quota windows.";
|
|
139
|
+
try {
|
|
140
|
+
var payg = ctx.util.request({ method: "GET", url: BILLING_URL + "?tab=payAsYouGo",
|
|
141
|
+
headers: { Cookie: cookie, Accept: "text/html,application/xhtml+xml", "User-Agent": USER_AGENT }, timeoutMs: 1500 });
|
|
142
|
+
if (payg.status === 200) {
|
|
143
|
+
var html = String(payg.bodyText || "").replace(/<!--[\s\S]*?-->/g, "");
|
|
144
|
+
var balance = /<h2[^>]*>\s*Credit balance\s*<\/h2>[\s\S]{0,900}?<p[^>]*tabular-nums[^>]*>\s*\$?([0-9][0-9,]*(?:\.[0-9]+)?)\s*<\/p>/i.exec(html);
|
|
145
|
+
var spent = /<h2[^>]*>\s*Usage\s*<\/h2>\s*<span[^>]*>\s*Total:\s*\$?([0-9][0-9,]*(?:\.[0-9]+)?)\s*<\/span>/i.exec(html);
|
|
146
|
+
if (balance && Number.isFinite(Number(balance[1].replace(/,/g, "")))) lines.push(ctx.line.text({ label: "PAYG Balance", value: "$" + Number(balance[1].replace(/,/g, "")).toFixed(2) }));
|
|
147
|
+
if (balance && spent && Number.isFinite(Number(spent[1].replace(/,/g, "")))) lines.push(ctx.line.text({ label: "PAYG Usage", value: "$" + Number(spent[1].replace(/,/g, "")).toFixed(2) }));
|
|
148
|
+
}
|
|
149
|
+
} catch (_) {
|
|
150
|
+
ctx.host.log.warn("Sakana PAYG balance unavailable");
|
|
151
|
+
}
|
|
152
|
+
return { displayName: "Sakana AI", source: "web", plan: "Sakana Console", lines: lines };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
globalThis.__openusage_plugin = { id: "sakana", probe: probe };
|
|
156
|
+
})();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "sakana",
|
|
4
|
+
"name": "Sakana AI",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"web"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "web",
|
|
12
|
+
"webUrl": "https://console.sakana.ai",
|
|
13
|
+
"usageDashboardUrl": "https://console.sakana.ai/billing",
|
|
14
|
+
"links": [
|
|
15
|
+
{
|
|
16
|
+
"label": "Dashboard",
|
|
17
|
+
"url": "https://console.sakana.ai/billing"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"envVars": [
|
|
21
|
+
"SAKANA_COOKIE"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
File without changes
|
package/plugins/stepfun/icon.svg
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|