@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,261 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
|
+
globalThis.__usagestat_bundled_options = {"labels":["Budget","Secondary budget","Additional"],"defaults":{"AIXY_BASE_URL":"https://api.aixy-gateway.com"},"autoMode":"api"};
|
|
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: "aixy",
|
|
26
|
+
name: "Aixy",
|
|
27
|
+
endpoints: [{ setting: "AIXY_BASE_URL", policy: "https-or-private-network-http" }],
|
|
28
|
+
auth: { type: "bearer", secret: "AIXY_API_KEY" },
|
|
29
|
+
settings: [
|
|
30
|
+
{ key: "AIXY_API_KEY", title: "API key", type: "secure" },
|
|
31
|
+
{ key: "AIXY_BASE_URL", title: "Base URL", type: "plain" },
|
|
32
|
+
],
|
|
33
|
+
capabilities: ["http-status"],
|
|
34
|
+
async fetchUsage(ctx) {
|
|
35
|
+
const fail = (message) => {
|
|
36
|
+
throw ctx.fail.parseFailure(`Aixy: ${message}`);
|
|
37
|
+
};
|
|
38
|
+
const object = (value) => {
|
|
39
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return fail("expected an object");
|
|
40
|
+
return value;
|
|
41
|
+
};
|
|
42
|
+
const text = (value) => {
|
|
43
|
+
if (typeof value !== "string" || !value.trim()) return fail("invalid text");
|
|
44
|
+
return value.trim();
|
|
45
|
+
};
|
|
46
|
+
const bounded = (value) => Array.from(value).slice(0, 120).join("");
|
|
47
|
+
const number = (value) => {
|
|
48
|
+
if (value == null) return undefined;
|
|
49
|
+
if (typeof value === "string" && /^\d+(?:\.\d+)?$/u.test(value)) value = Number(value);
|
|
50
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return fail("invalid amount");
|
|
51
|
+
return value;
|
|
52
|
+
};
|
|
53
|
+
const count = (value) => {
|
|
54
|
+
const parsed = number(value);
|
|
55
|
+
if (parsed === undefined || !Number.isSafeInteger(parsed)) return fail("invalid count");
|
|
56
|
+
return parsed;
|
|
57
|
+
};
|
|
58
|
+
const date = (value) => {
|
|
59
|
+
if (value == null) return undefined;
|
|
60
|
+
let parsed;
|
|
61
|
+
try {
|
|
62
|
+
parsed = ctx.date.iso(text(value));
|
|
63
|
+
} catch (error) {
|
|
64
|
+
void error;
|
|
65
|
+
return fail("invalid date");
|
|
66
|
+
}
|
|
67
|
+
if (!Number.isFinite(parsed.getTime())) return fail("invalid date");
|
|
68
|
+
return parsed;
|
|
69
|
+
};
|
|
70
|
+
const base = (ctx.settings.get("AIXY_BASE_URL") || "https://api.aixy-gateway.com").replace(/\/+$/u, "");
|
|
71
|
+
if (/[?#]/u.test(base)) throw ctx.fail.apiFailure("Aixy Base URL must not contain a query or fragment.");
|
|
72
|
+
const endpoint = `${base.replace(/\/v1$/u, "")}/v1/usage`;
|
|
73
|
+
const response = await ctx.http.get(endpoint);
|
|
74
|
+
const message = `Aixy usage request failed (HTTP ${response.status}).`;
|
|
75
|
+
if (response.status === 401)
|
|
76
|
+
throw ctx.fail.authenticationExpired("Aixy rejected the API key. Check its expiry or revocation.");
|
|
77
|
+
if (response.status === 403) throw ctx.fail.permissionDenied("Aixy denied access to this key's usage.");
|
|
78
|
+
if (response.status === 404)
|
|
79
|
+
throw ctx.fail.apiFailure(
|
|
80
|
+
"This Aixy installation does not provide the usage endpoint. Update the gateway or check its Base URL.",
|
|
81
|
+
);
|
|
82
|
+
if (response.status === 429) throw ctx.fail.rateLimited(message);
|
|
83
|
+
if (response.status >= 500) throw ctx.fail.providerUnavailable(message);
|
|
84
|
+
if (response.status < 200 || response.status >= 300) throw ctx.fail.apiFailure(message);
|
|
85
|
+
let decoded;
|
|
86
|
+
try {
|
|
87
|
+
decoded = JSON.parse(response.bodyText);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
void error;
|
|
90
|
+
return fail("invalid usage JSON");
|
|
91
|
+
}
|
|
92
|
+
const root = object(decoded);
|
|
93
|
+
if (root.object !== "key.usage" || root.currency !== "USD") return fail("unsupported usage contract");
|
|
94
|
+
const asOf = date(root.as_of);
|
|
95
|
+
if (!asOf) return fail("missing observation time");
|
|
96
|
+
const key = object(root.key);
|
|
97
|
+
const keyID = text(key.id);
|
|
98
|
+
if (!Array.isArray(root.budgets)) return fail("invalid budgets");
|
|
99
|
+
const labels = {
|
|
100
|
+
organization: "Organization",
|
|
101
|
+
project: "Project",
|
|
102
|
+
team: "Team",
|
|
103
|
+
user: "User",
|
|
104
|
+
api_key: "Key",
|
|
105
|
+
daily: "Daily",
|
|
106
|
+
weekly: "Weekly",
|
|
107
|
+
monthly: "Monthly",
|
|
108
|
+
lifetime: "Lifetime",
|
|
109
|
+
};
|
|
110
|
+
if (root.budgets.length > 64) return fail("too many budgets");
|
|
111
|
+
const ids = new Set();
|
|
112
|
+
const budgets = root.budgets
|
|
113
|
+
.map((raw) => {
|
|
114
|
+
const budget = object(raw),
|
|
115
|
+
id = text(budget.id);
|
|
116
|
+
if (ids.has(id)) return fail("duplicate budget");
|
|
117
|
+
ids.add(id);
|
|
118
|
+
const scope = text(budget.scope),
|
|
119
|
+
interval = text(budget.interval);
|
|
120
|
+
if (
|
|
121
|
+
!["organization", "project", "team", "user", "api_key"].includes(scope) ||
|
|
122
|
+
!["daily", "weekly", "monthly", "lifetime"].includes(interval)
|
|
123
|
+
)
|
|
124
|
+
return fail("invalid budget scope or interval");
|
|
125
|
+
if (budget.enforcement !== "hard" && budget.enforcement !== "monitor") return fail("invalid enforcement");
|
|
126
|
+
if (typeof budget.shared !== "boolean") return fail("invalid shared scope");
|
|
127
|
+
const limit = number(budget.limit_usd);
|
|
128
|
+
if (limit === undefined || limit <= 0) return fail("invalid budget limit");
|
|
129
|
+
if (
|
|
130
|
+
!Array.isArray(budget.applies_to) ||
|
|
131
|
+
!budget.applies_to.length ||
|
|
132
|
+
budget.applies_to.some(
|
|
133
|
+
(item) => object(item).api_key_id !== keyID || object(item).project_id !== key.project_id,
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
return fail("budget belongs to another key");
|
|
137
|
+
const availability = object(budget.availability);
|
|
138
|
+
const hard = budget.enforcement === "hard";
|
|
139
|
+
if (!["available", "unavailable", "not_enforced"].includes(text(availability.status)))
|
|
140
|
+
return fail("invalid availability");
|
|
141
|
+
if (!["available", "unavailable"].includes(text(budget.spend_status))) return fail("invalid spend status");
|
|
142
|
+
const known = hard ? availability.status === "available" : budget.spend_status === "available";
|
|
143
|
+
const spent = number(hard ? availability.spent_usd : budget.spend_usd);
|
|
144
|
+
const reserved = hard ? number(availability.reserved_usd) : 0;
|
|
145
|
+
const remaining = number(hard ? availability.remaining_usd : budget.remaining_usd);
|
|
146
|
+
if (known && (spent === undefined || reserved === undefined || remaining === undefined))
|
|
147
|
+
return fail("incomplete budget balance");
|
|
148
|
+
const used = known ? spent + reserved : undefined;
|
|
149
|
+
if (used !== undefined && !Number.isFinite(used)) return fail("budget amount overflow");
|
|
150
|
+
const startsAt = date(budget.starts_at),
|
|
151
|
+
resetsAt = date(budget.resets_at);
|
|
152
|
+
if (startsAt && resetsAt && resetsAt <= startsAt) return fail("invalid budget period");
|
|
153
|
+
const minutes = startsAt && resetsAt ? (resetsAt.getTime() - startsAt.getTime()) / 60000 : undefined;
|
|
154
|
+
const title = bounded(
|
|
155
|
+
`${labels[scope]} · ${labels[interval]} · ${budget.shared ? "Shared" : "Personal"} · ${hard ? "Hard" : "Monitor"}`,
|
|
156
|
+
);
|
|
157
|
+
return {
|
|
158
|
+
id: `aixy-${id}`,
|
|
159
|
+
title,
|
|
160
|
+
known,
|
|
161
|
+
hard,
|
|
162
|
+
spent,
|
|
163
|
+
reserved,
|
|
164
|
+
remaining,
|
|
165
|
+
limit,
|
|
166
|
+
used,
|
|
167
|
+
window: {
|
|
168
|
+
usedPercent: known ? ctx.pct(used, limit) : 0,
|
|
169
|
+
windowMinutes: minutes !== undefined && Number.isSafeInteger(minutes) && minutes > 0 ? minutes : undefined,
|
|
170
|
+
resetsAt,
|
|
171
|
+
resetDescription: `${title} · ${known ? `${ctx.format.usd(remaining)} remaining` : "Unavailable"}`,
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
})
|
|
175
|
+
.sort(
|
|
176
|
+
(a, b) =>
|
|
177
|
+
Number(b.hard) - Number(a.hard) ||
|
|
178
|
+
Number(b.known) - Number(a.known) ||
|
|
179
|
+
b.window.usedPercent - a.window.usedPercent ||
|
|
180
|
+
(a.id < b.id ? -1 : a.id > b.id ? 1 : 0),
|
|
181
|
+
);
|
|
182
|
+
const known = budgets.filter((budget) => budget.known);
|
|
183
|
+
const selected = known.slice(0, 2);
|
|
184
|
+
const details = [
|
|
185
|
+
{
|
|
186
|
+
title: "Aixy key",
|
|
187
|
+
rows: [
|
|
188
|
+
{ label: "Key", value: bounded(key.name == null ? keyID : text(key.name)) },
|
|
189
|
+
{
|
|
190
|
+
label: "Project",
|
|
191
|
+
value: bounded(key.project_name == null ? text(key.project_id) : text(key.project_name)),
|
|
192
|
+
},
|
|
193
|
+
{ label: "Observed", value: asOf.toISOString() },
|
|
194
|
+
],
|
|
195
|
+
},
|
|
196
|
+
];
|
|
197
|
+
for (let offset = 0; offset < budgets.length; offset += 24)
|
|
198
|
+
details.push({
|
|
199
|
+
title: "Applicable budgets",
|
|
200
|
+
rows: budgets.slice(offset, offset + 24).map((budget) => ({
|
|
201
|
+
label: budget.title,
|
|
202
|
+
value: budget.known
|
|
203
|
+
? `${ctx.format.usd(budget.remaining)} / ${ctx.format.usd(budget.limit)} remaining`
|
|
204
|
+
: "Unavailable",
|
|
205
|
+
secondaryValue: budget.known
|
|
206
|
+
? `${ctx.format.usd(budget.spent)} spent${budget.hard ? ` · ${ctx.format.usd(budget.reserved)} reserved` : ""}`
|
|
207
|
+
: undefined,
|
|
208
|
+
progress: budget.known ? budget.window.usedPercent / 100 : undefined,
|
|
209
|
+
usageValue: budget.used,
|
|
210
|
+
})),
|
|
211
|
+
});
|
|
212
|
+
let cost;
|
|
213
|
+
let confidence = "unknown";
|
|
214
|
+
if (root.usage != null) {
|
|
215
|
+
const usage = object(root.usage);
|
|
216
|
+
if (usage.window !== "7d") return fail("unsupported reporting period");
|
|
217
|
+
const requests = count(usage.requests),
|
|
218
|
+
tokens = count(usage.total_tokens);
|
|
219
|
+
const attributed = count(usage.attributed_requests),
|
|
220
|
+
partial = count(usage.partial_requests);
|
|
221
|
+
const spend = number(usage.spend_usd);
|
|
222
|
+
if (attributed > requests || partial > attributed || (spend !== undefined && spend > 0 && attributed === 0))
|
|
223
|
+
return fail("invalid attribution coverage");
|
|
224
|
+
if (spend !== undefined) {
|
|
225
|
+
cost = { used: spend, currency: "USD", period: "Last 7 days · attributed" };
|
|
226
|
+
confidence = "estimated";
|
|
227
|
+
}
|
|
228
|
+
details.push({
|
|
229
|
+
title: "Last 7 days · this key",
|
|
230
|
+
rows: [
|
|
231
|
+
{ label: "Requests", value: ctx.format.number(requests) },
|
|
232
|
+
{ label: "Tokens", value: ctx.format.number(tokens) },
|
|
233
|
+
{ label: "Attributed spend", value: spend === undefined ? "Unavailable" : ctx.format.usd(spend) },
|
|
234
|
+
{
|
|
235
|
+
label: "Cost coverage",
|
|
236
|
+
value: `${attributed} / ${requests} requests`,
|
|
237
|
+
secondaryValue: `${partial} partial`,
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
});
|
|
241
|
+
} else {
|
|
242
|
+
details.push({ title: "Last 7 days · this key", rows: [{ label: "Usage", value: "Unavailable" }] });
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
primary: _optionalChain([selected, "access", (_) => _[0], "optionalAccess", (_2) => _2.window]),
|
|
246
|
+
secondary: _optionalChain([selected, "access", (_3) => _3[1], "optionalAccess", (_4) => _4.window]),
|
|
247
|
+
extraWindows: budgets
|
|
248
|
+
.filter((budget) => !selected.includes(budget))
|
|
249
|
+
.map((budget) => ({
|
|
250
|
+
id: budget.id,
|
|
251
|
+
title: budget.title,
|
|
252
|
+
usageKnown: budget.known,
|
|
253
|
+
window: budget.window,
|
|
254
|
+
})),
|
|
255
|
+
cost,
|
|
256
|
+
details,
|
|
257
|
+
dataConfidence: confidence,
|
|
258
|
+
identity: { accountID: keyID, loginMethod: "API key" },
|
|
259
|
+
};
|
|
260
|
+
},
|
|
261
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "aixy",
|
|
4
|
+
"name": "Aixy",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"api"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "api",
|
|
12
|
+
"usageDashboardUrl": "https://dash.aixy-gateway.com",
|
|
13
|
+
"envVars": [
|
|
14
|
+
"AIXY_API_KEY",
|
|
15
|
+
"AIXY_BASE_URL"
|
|
16
|
+
],
|
|
17
|
+
"upstream": {
|
|
18
|
+
"repository": "https://github.com/steipete/CodexBar",
|
|
19
|
+
"revision": "78ba5a1e65e6859da59a21b799df95ab91bc0b89",
|
|
20
|
+
"path": "Sources/CodexBarCore/Resources/Plugins/aixy.js",
|
|
21
|
+
"sha256": "975d98525503e286f9425c2a1d64fe00da8e2fdc0b00890e15c2cbcb9a37c125",
|
|
22
|
+
"license": "MIT"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
File without changes
|
package/plugins/alibaba/icon.svg
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/plugins/amp/icon.svg
CHANGED
|
File without changes
|
package/plugins/amp/plugin.js
CHANGED
|
File without changes
|
package/plugins/amp/plugin.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -155,6 +155,13 @@
|
|
|
155
155
|
ctx.host.log.warn("refresh skipped: no refresh token")
|
|
156
156
|
return null
|
|
157
157
|
}
|
|
158
|
+
var retryPath = ctx.app.pluginDataDir + "/oauth-retry-" + ctx.host.crypto.sha256Hex(refreshTokenValue) + ".json"
|
|
159
|
+
try {
|
|
160
|
+
if (ctx.host.fs.exists(retryPath)) {
|
|
161
|
+
var rejection = ctx.util.tryParseJson(ctx.host.fs.readText(retryPath))
|
|
162
|
+
if (rejection && rejection.retryAfterMs > Date.now()) return null
|
|
163
|
+
}
|
|
164
|
+
} catch (_) { /* A missing/corrupt cooldown must not prevent login. */ }
|
|
158
165
|
ctx.host.log.info("attempting Google OAuth token refresh")
|
|
159
166
|
try {
|
|
160
167
|
var resp = ctx.host.http.request({
|
|
@@ -169,6 +176,12 @@
|
|
|
169
176
|
timeoutMs: 15000,
|
|
170
177
|
})
|
|
171
178
|
if (resp.status < 200 || resp.status >= 300) {
|
|
179
|
+
var failure = ctx.util.tryParseJson(resp.bodyText)
|
|
180
|
+
if (resp.status === 400 && failure && failure.error === "invalid_grant") {
|
|
181
|
+
// A revoked token will not recover on the next dashboard poll. Store
|
|
182
|
+
// only a deadline under its hash; a new login bypasses this cooldown.
|
|
183
|
+
try { ctx.host.fs.writeText(retryPath, JSON.stringify({ retryAfterMs: Date.now() + 60 * 60 * 1000 })) } catch (_) {}
|
|
184
|
+
}
|
|
172
185
|
ctx.host.log.warn("Google OAuth refresh returned status: " + resp.status)
|
|
173
186
|
return null
|
|
174
187
|
}
|
|
@@ -188,22 +201,34 @@
|
|
|
188
201
|
|
|
189
202
|
// --- Token cache ---
|
|
190
203
|
|
|
204
|
+
function tokenCachePath(ctx, profileKey) {
|
|
205
|
+
// Include another hash so the filename remains bounded even on older hosts
|
|
206
|
+
// or test callers with an opaque profile key.
|
|
207
|
+
return ctx.app.pluginDataDir + "/auth-" + ctx.host.crypto.sha256Hex(profileKey) + ".json"
|
|
208
|
+
}
|
|
209
|
+
|
|
191
210
|
function loadCachedToken(ctx, profileKey) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
211
|
+
if (!profileKey) return null
|
|
212
|
+
// Read the old single-slot cache for compatibility, but write only the
|
|
213
|
+
// per-profile file so the IDE and agy cannot evict each other's token.
|
|
214
|
+
var paths = [tokenCachePath(ctx, profileKey), ctx.app.pluginDataDir + "/auth.json"]
|
|
215
|
+
for (var i = 0; i < paths.length; i++) {
|
|
216
|
+
try {
|
|
217
|
+
if (!ctx.host.fs.exists(paths[i])) continue
|
|
218
|
+
var data = ctx.util.tryParseJson(ctx.host.fs.readText(paths[i]))
|
|
219
|
+
if (!data || data.profileKey !== profileKey || !data.accessToken || !data.expiresAtMs) continue
|
|
220
|
+
if (data.expiresAtMs <= Date.now()) continue
|
|
221
|
+
return data.accessToken
|
|
222
|
+
} catch (e) {
|
|
223
|
+
ctx.host.log.warn("failed to read cached token: " + String(e))
|
|
224
|
+
}
|
|
202
225
|
}
|
|
226
|
+
return null
|
|
203
227
|
}
|
|
204
228
|
|
|
205
229
|
function cacheToken(ctx, accessToken, expiresInSeconds, profileKey) {
|
|
206
|
-
|
|
230
|
+
if (!profileKey) return
|
|
231
|
+
var path = tokenCachePath(ctx, profileKey)
|
|
207
232
|
try {
|
|
208
233
|
ctx.host.fs.writeText(path, JSON.stringify({
|
|
209
234
|
accessToken: accessToken,
|
|
@@ -238,58 +263,125 @@
|
|
|
238
263
|
return text || null
|
|
239
264
|
}
|
|
240
265
|
|
|
241
|
-
|
|
242
|
-
|
|
266
|
+
// agy stores {"token":{"access_token","refresh_token","expiry"},"id_token":...}.
|
|
267
|
+
// Search the whole payload for a bearer token before falling back to an ID
|
|
268
|
+
// token: Cloud Code rejects ID tokens, so a top-level id_token must not win.
|
|
269
|
+
var ACCESS_KEYS = ["access_token", "accessToken", "bearerToken", "auth_token", "authToken"]
|
|
270
|
+
var NESTED_KEYS = ["token", "tokens", "oauth", "oauth2", "credentials", "auth"]
|
|
243
271
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
"id_token",
|
|
249
|
-
"idToken",
|
|
250
|
-
"bearerToken",
|
|
251
|
-
"auth_token",
|
|
252
|
-
"authToken",
|
|
253
|
-
]
|
|
254
|
-
for (var i = 0; i < directKeys.length; i++) {
|
|
255
|
-
var value = obj[directKeys[i]]
|
|
272
|
+
function findStringDeep(obj, keys, depth) {
|
|
273
|
+
if (!obj || typeof obj !== "object" || depth > 4) return null
|
|
274
|
+
for (var i = 0; i < keys.length; i++) {
|
|
275
|
+
var value = obj[keys[i]]
|
|
256
276
|
if (typeof value === "string" && value.trim()) return value.trim()
|
|
257
277
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
for (var j = 0; j < nestedKeys.length; j++) {
|
|
261
|
-
var nested = extractTokenFromObject(obj[nestedKeys[j]])
|
|
278
|
+
for (var j = 0; j < NESTED_KEYS.length; j++) {
|
|
279
|
+
var nested = findStringDeep(obj[NESTED_KEYS[j]], keys, depth + 1)
|
|
262
280
|
if (nested) return nested
|
|
263
281
|
}
|
|
282
|
+
return null
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function extractTokenFromObject(obj) {
|
|
286
|
+
if (!obj || typeof obj !== "object") return null
|
|
287
|
+
return findStringDeep(obj, ACCESS_KEYS, 0) || findStringDeep(obj, ["token"], 0) ||
|
|
288
|
+
findStringDeep(obj, ["id_token", "idToken"], 0)
|
|
289
|
+
}
|
|
264
290
|
|
|
291
|
+
function parseExpiryMs(value) {
|
|
292
|
+
if (typeof value === "number" && isFinite(value)) return value < 1e12 ? value * 1000 : value
|
|
293
|
+
if (typeof value === "string" && value.trim()) {
|
|
294
|
+
var ms = Date.parse(value.trim())
|
|
295
|
+
return isFinite(ms) ? ms : null
|
|
296
|
+
}
|
|
265
297
|
return null
|
|
266
298
|
}
|
|
267
299
|
|
|
268
|
-
|
|
300
|
+
// Returns {accessToken, refreshToken, expiryMs} from agy's keyring payload.
|
|
301
|
+
function parseAgyCredentials(ctx, raw) {
|
|
269
302
|
var text = unwrapAgyKeychainText(ctx, raw)
|
|
270
303
|
if (!text) return null
|
|
271
|
-
|
|
272
304
|
var parsed = ctx.util.tryParseJson(text)
|
|
273
|
-
if (typeof parsed === "string" && parsed.trim()) return parsed.trim()
|
|
274
|
-
if (parsed
|
|
305
|
+
if (typeof parsed === "string" && parsed.trim()) return { accessToken: parsed.trim(), refreshToken: null, expiryMs: null }
|
|
306
|
+
if (parsed && typeof parsed === "object") {
|
|
307
|
+
var expiry = findStringDeep(parsed, ["expiry", "expires_at", "expiresAt"], 0)
|
|
308
|
+
var numericExpiry = parsed.token && typeof parsed.token === "object" ? parsed.token.expiry_date : null
|
|
309
|
+
return {
|
|
310
|
+
accessToken: extractTokenFromObject(parsed),
|
|
311
|
+
refreshToken: findStringDeep(parsed, ["refresh_token", "refreshToken"], 0),
|
|
312
|
+
expiryMs: parseExpiryMs(expiry) || parseExpiryMs(numericExpiry),
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (text.indexOf("Bearer ") === 0) return { accessToken: text.slice("Bearer ".length).trim() || null, refreshToken: null, expiryMs: null }
|
|
316
|
+
return { accessToken: text, refreshToken: null, expiryMs: null }
|
|
317
|
+
}
|
|
275
318
|
|
|
276
|
-
|
|
277
|
-
|
|
319
|
+
function extractAgyAccessToken(ctx, raw) {
|
|
320
|
+
var creds = parseAgyCredentials(ctx, raw)
|
|
321
|
+
return creds ? creds.accessToken : null
|
|
278
322
|
}
|
|
279
323
|
|
|
280
|
-
function
|
|
324
|
+
function loadAgyCredentials(ctx) {
|
|
281
325
|
if (!ctx.host.keychain || typeof ctx.host.keychain.readGenericPassword !== "function") {
|
|
282
326
|
return null
|
|
283
327
|
}
|
|
284
328
|
try {
|
|
285
|
-
|
|
286
|
-
return extractAgyAccessToken(ctx, raw)
|
|
329
|
+
return parseAgyCredentials(ctx, ctx.host.keychain.readGenericPassword(AGY_KEYCHAIN_SERVICE, AGY_KEYCHAIN_ACCOUNT))
|
|
287
330
|
} catch (e) {
|
|
288
331
|
ctx.host.log.info("agy keychain read failed: " + String(e))
|
|
289
332
|
return null
|
|
290
333
|
}
|
|
291
334
|
}
|
|
292
335
|
|
|
336
|
+
function loadAgyKeychainToken(ctx) {
|
|
337
|
+
var creds = loadAgyCredentials(ctx)
|
|
338
|
+
return creds ? creds.accessToken : null
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Probe Cloud Code with agy's credentials, refreshing an expired or rejected
|
|
342
|
+
// access token with agy's refresh token (same Google OAuth client).
|
|
343
|
+
function probeAgyCredentials(ctx) {
|
|
344
|
+
var creds = loadAgyCredentials(ctx)
|
|
345
|
+
if (!creds || (!creds.accessToken && !creds.refreshToken)) return null
|
|
346
|
+
var profileKey = creds.refreshToken ? ctx.host.crypto.sha256Hex("agy\n" + creds.refreshToken) : null
|
|
347
|
+
var candidates = []
|
|
348
|
+
var cached = loadCachedToken(ctx, profileKey)
|
|
349
|
+
if (cached) candidates.push(cached)
|
|
350
|
+
var expired = creds.expiryMs != null && creds.expiryMs <= Date.now() + 60000
|
|
351
|
+
if (creds.accessToken && !expired && candidates.indexOf(creds.accessToken) === -1) candidates.push(creds.accessToken)
|
|
352
|
+
var last = null
|
|
353
|
+
for (var i = 0; i < candidates.length; i++) {
|
|
354
|
+
var result = probeAgyToken(ctx, candidates[i])
|
|
355
|
+
if (result && !result._authFailed) return result
|
|
356
|
+
if (result) last = result
|
|
357
|
+
}
|
|
358
|
+
if (creds.refreshToken && (last || !candidates.length)) {
|
|
359
|
+
var refreshed = refreshAccessToken(ctx, creds.refreshToken, profileKey)
|
|
360
|
+
if (refreshed) {
|
|
361
|
+
var refreshedResult = probeAgyToken(ctx, refreshed)
|
|
362
|
+
if (refreshedResult) return refreshedResult
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return last
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Consumer agy accounts have no Cloud project, so retrieveUserQuota answers
|
|
369
|
+
// 403 "no valid license" even with a valid token. fetchAvailableModels still
|
|
370
|
+
// reports per-model quota, so use it before treating the token as rejected.
|
|
371
|
+
function probeAgyToken(ctx, token) {
|
|
372
|
+
var quota = probeAgyCloudCode(ctx, token)
|
|
373
|
+
if (quota && !quota._authFailed) return quota
|
|
374
|
+
var models = probeCloudCode(ctx, token)
|
|
375
|
+
if (models && !models._authFailed) {
|
|
376
|
+
var lines = buildModelLines(ctx, parseCloudCodeModels(models))
|
|
377
|
+
if (lines.length > 0) return { plan: null, lines: lines }
|
|
378
|
+
return null
|
|
379
|
+
}
|
|
380
|
+
// A quota 403 can mean "no license", not an invalid bearer. If the model
|
|
381
|
+
// endpoint is temporarily unavailable, don't turn that into a token refresh.
|
|
382
|
+
return models
|
|
383
|
+
}
|
|
384
|
+
|
|
293
385
|
// --- LS discovery ---
|
|
294
386
|
|
|
295
387
|
function discoverNative(ctx, options) {
|
|
@@ -682,7 +774,7 @@
|
|
|
682
774
|
|
|
683
775
|
var profileKey = dbTokenCandidates.length ? dbTokenCandidates[0].profileKey : null
|
|
684
776
|
var cached = loadCachedToken(ctx, profileKey)
|
|
685
|
-
if (cached && tokens.indexOf(cached) === -1) tokens.
|
|
777
|
+
if (cached && tokens.indexOf(cached) === -1) tokens.unshift(cached)
|
|
686
778
|
|
|
687
779
|
var ccData = null
|
|
688
780
|
var sawAuthFailure = false
|
|
@@ -717,13 +809,11 @@
|
|
|
717
809
|
}
|
|
718
810
|
}
|
|
719
811
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
if (agyResult && agyResult._authFailed) ccData = agyResult
|
|
726
|
-
}
|
|
812
|
+
// agy's own login also covers users whose IDE database is stale or absent.
|
|
813
|
+
if (!explicitDb && (!ccData || ccData._authFailed)) {
|
|
814
|
+
var agyResult = probeAgyCredentials(ctx)
|
|
815
|
+
if (agyResult && !agyResult._authFailed) return agyResult
|
|
816
|
+
if (agyResult && agyResult._authFailed) ccData = agyResult
|
|
727
817
|
}
|
|
728
818
|
|
|
729
819
|
if (ccData && !ccData._authFailed) {
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Antigravity</title><mask height="23" id="lobe-icons-antigravity-0-_R_0_" maskUnits="userSpaceOnUse" width="24" x="0" y="1"><path d="M21.751 22.607c1.34 1.005 3.35.335 1.508-1.508C17.73 15.74 18.904 1 12.037 1 5.17 1 6.342 15.74.815 21.1c-2.01 2.009.167 2.511 1.507 1.506 5.192-3.517 4.857-9.714 9.715-9.714 4.857 0 4.522 6.197 9.714 9.715z" fill="#fff"></path></mask><g mask="url(#lobe-icons-antigravity-0-_R_0_)"><g filter="url(#lobe-icons-antigravity-1-_R_0_)"><path d="M-1.018-3.992c-.408 3.591 2.686 6.89 6.91 7.37 4.225.48 7.98-2.043 8.387-5.633.408-3.59-2.686-6.89-6.91-7.37-4.225-.479-7.98 2.043-8.387 5.633z" fill="#FFE432"></path></g><g filter="url(#lobe-icons-antigravity-2-_R_0_)"><path d="M15.269 7.747c1.058 4.557 5.691 7.374 10.348 6.293 4.657-1.082 7.575-5.653 6.516-10.21-1.058-4.556-5.691-7.374-10.348-6.292-4.657 1.082-7.575 5.653-6.516 10.21z" fill="#FC413D"></path></g><g filter="url(#lobe-icons-antigravity-3-_R_0_)"><path d="M-12.443 10.804c1.338 4.703 7.36 7.11 13.453 5.378 6.092-1.733 9.947-6.95 8.61-11.652C8.282-.173 2.26-2.58-3.833-.848-9.925.884-13.78 6.1-12.443 10.804z" fill="#00B95C"></path></g><g filter="url(#lobe-icons-antigravity-4-_R_0_)"><path d="M-12.443 10.804c1.338 4.703 7.36 7.11 13.453 5.378 6.092-1.733 9.947-6.95 8.61-11.652C8.282-.173 2.26-2.58-3.833-.848-9.925.884-13.78 6.1-12.443 10.804z" fill="#00B95C"></path></g><g filter="url(#lobe-icons-antigravity-5-_R_0_)"><path d="M-7.608 14.703c3.352 3.424 9.126 3.208 12.896-.483 3.77-3.69 4.108-9.459.756-12.883C2.69-2.087-3.083-1.871-6.853 1.82c-3.77 3.69-4.108 9.458-.755 12.883z" fill="#00B95C"></path></g><g filter="url(#lobe-icons-antigravity-6-_R_0_)"><path d="M9.932 27.617c1.04 4.482 5.384 7.303 9.7 6.3 4.316-1.002 6.971-5.448 5.93-9.93-1.04-4.483-5.384-7.304-9.7-6.301-4.316 1.002-6.971 5.448-5.93 9.93z" fill="#3186FF"></path></g><g filter="url(#lobe-icons-antigravity-7-_R_0_)"><path d="M2.572-8.185C.392-3.329 2.778 2.472 7.9 4.771c5.122 2.3 11.042.227 13.222-4.63 2.18-4.855-.205-10.656-5.327-12.955-5.122-2.3-11.042-.227-13.222 4.63z" fill="#FBBC04"></path></g><g filter="url(#lobe-icons-antigravity-8-_R_0_)"><path d="M-3.267 38.686c-5.277-2.072 3.742-19.117 5.984-24.83 2.243-5.712 8.34-8.664 13.616-6.592 5.278 2.071 11.533 13.482 9.29 19.195-2.242 5.713-23.613 14.298-28.89 12.227z" fill="#3186FF"></path></g><g filter="url(#lobe-icons-antigravity-9-_R_0_)"><path d="M28.71 17.471c-1.413 1.649-5.1.808-8.236-1.878-3.135-2.687-4.531-6.201-3.118-7.85 1.412-1.649 5.1-.808 8.235 1.878s4.532 6.2 3.119 7.85z" fill="#749BFF"></path></g><g filter="url(#lobe-icons-antigravity-10-_R_0_)"><path d="M18.163 9.077c5.81 3.93 12.502 4.19 14.946.577 2.443-3.612-.287-9.727-6.098-13.658-5.81-3.931-12.502-4.19-14.946-.577-2.443 3.612.287 9.727 6.098 13.658z" fill="#FC413D"></path></g><g filter="url(#lobe-icons-antigravity-11-_R_0_)"><path d="M-.915 2.684c-1.44 3.473-.97 6.967 1.05 7.804 2.02.837 4.824-1.3 6.264-4.772 1.44-3.473.97-6.967-1.05-7.804-2.02-.837-4.824 1.3-6.264 4.772z" fill="#FFEE48"></path></g></g><defs><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="17.587" id="lobe-icons-antigravity-1-_R_0_" width="19.838" x="-3.288" y="-11.917"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="1.117"></feGaussianBlur></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="38.565" id="lobe-icons-antigravity-2-_R_0_" width="38.9" x="4.251" y="-13.493"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="5.4"></feGaussianBlur></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="36.517" id="lobe-icons-antigravity-3-_R_0_" width="40.955" x="-21.889" y="-10.592"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="4.591"></feGaussianBlur></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="36.517" id="lobe-icons-antigravity-4-_R_0_" width="40.955" x="-21.889" y="-10.592"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="4.591"></feGaussianBlur></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="36.595" id="lobe-icons-antigravity-5-_R_0_" width="36.632" x="-19.099" y="-10.278"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="4.591"></feGaussianBlur></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="34.087" id="lobe-icons-antigravity-6-_R_0_" width="33.533" x=".981" y="8.758"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="4.363"></feGaussianBlur></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="35.276" id="lobe-icons-antigravity-7-_R_0_" width="35.978" x="-6.143" y="-21.659"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="3.954"></feGaussianBlur></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="46.523" id="lobe-icons-antigravity-8-_R_0_" width="45.114" x="-11.96" y="-.46"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="3.531"></feGaussianBlur></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="24.054" id="lobe-icons-antigravity-9-_R_0_" width="25.094" x="10.485" y=".58"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="3.159"></feGaussianBlur></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="30.007" id="lobe-icons-antigravity-10-_R_0_" width="33.508" x="5.833" y="-12.467"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="2.669"></feGaussianBlur></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="26.151" id="lobe-icons-antigravity-11-_R_0_" width="22.194" x="-8.355" y="-8.876"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend><feGaussianBlur result="effect1_foregroundBlur_977_115" stdDeviation="3.303"></feGaussianBlur></filter></defs></svg>
|
|
@@ -1,3 +1 @@
|
|
|
1
|
-
<svg
|
|
2
|
-
<path d="M85.2843 88.0301C90.1329 91.6664 97.4057 89.2422 90.7389 82.5755C70.7389 63.1816 74.9813 9.84827 50.1329 9.84827C25.2843 9.84827 29.5267 63.1816 9.52673 82.5755C2.25402 89.8483 10.1328 91.6664 14.9813 88.0301C33.7692 75.3028 32.5571 52.8786 50.1329 52.8786C67.7086 52.8786 66.4965 75.3028 85.2843 88.0301Z" fill="currentColor"/>
|
|
3
|
-
</svg>
|
|
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>Antigravity</title><path d="M21.751 22.607c1.34 1.005 3.35.335 1.508-1.508C17.73 15.74 18.904 1 12.037 1 5.17 1 6.342 15.74.815 21.1c-2.01 2.009.167 2.511 1.507 1.506 5.192-3.517 4.857-9.714 9.715-9.714 4.857 0 4.522 6.197 9.714 9.715z"></path></svg>
|
|
@@ -67,27 +67,23 @@
|
|
|
67
67
|
function extractTokenFromObject(obj) {
|
|
68
68
|
if (!obj || typeof obj !== "object") return null
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"token",
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
for (var i = 0; i < directKeys.length; i += 1) {
|
|
81
|
-
var value = obj[directKeys[i]]
|
|
70
|
+
// Prefer a bearer token anywhere in the payload; an ID token is a last resort
|
|
71
|
+
// (agy stores {"token":{"access_token":...},"id_token":...}).
|
|
72
|
+
return findTokenDeep(obj, ["access_token", "accessToken", "bearerToken", "auth_token", "authToken"], 0) ||
|
|
73
|
+
findTokenDeep(obj, ["token"], 0) || findTokenDeep(obj, ["id_token", "idToken"], 0)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function findTokenDeep(obj, keys, depth) {
|
|
77
|
+
if (!obj || typeof obj !== "object" || depth > 4) return null
|
|
78
|
+
for (var i = 0; i < keys.length; i += 1) {
|
|
79
|
+
var value = obj[keys[i]]
|
|
82
80
|
if (typeof value === "string" && value.trim()) return value.trim()
|
|
83
81
|
}
|
|
84
|
-
|
|
85
82
|
var nestedKeys = ["token", "tokens", "oauth", "oauth2", "credentials", "auth"]
|
|
86
83
|
for (var j = 0; j < nestedKeys.length; j += 1) {
|
|
87
|
-
var nested =
|
|
84
|
+
var nested = findTokenDeep(obj[nestedKeys[j]], keys, depth + 1)
|
|
88
85
|
if (nested) return nested
|
|
89
86
|
}
|
|
90
|
-
|
|
91
87
|
return null
|
|
92
88
|
}
|
|
93
89
|
|
|
File without changes
|