@hashimkarim/usagestat-linux-x64-gnu 2.0.2 → 2.1.0
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/native-manifest.json +685 -133
- package/package.json +94 -2
- package/plugins/abliteration/LICENSE +21 -0
- package/plugins/abliteration/icon.svg +5 -0
- package/plugins/abliteration/plugin.js +89 -0
- package/plugins/abliteration/plugin.json +24 -0
- package/plugins/aerostack/LICENSE +21 -0
- package/plugins/aerostack/icon.svg +1 -0
- package/plugins/aerostack/plugin.js +94 -0
- package/plugins/aerostack/plugin.json +24 -0
- package/plugins/aixy/icon.svg +1 -0
- package/plugins/aixy/plugin.js +5 -0
- package/plugins/aixy/plugin.json +9 -1
- package/plugins/antigravity/plugin.js +19 -10
- package/plugins/antigravity-cli/plugin.js +8 -3
- package/plugins/antigravity-ide/plugin.js +8 -5
- package/plugins/atlascloud/plugin.js +5 -0
- package/plugins/atlascloud/plugin.json +2 -1
- package/plugins/bifrost/icon.svg +3 -0
- package/plugins/bifrost/plugin.js +5 -0
- package/plugins/bifrost/plugin.json +9 -1
- package/plugins/chatbox/LICENSE +21 -0
- package/plugins/chatbox/icon.svg +4 -0
- package/plugins/chatbox/plugin.js +208 -0
- package/plugins/chatbox/plugin.json +24 -0
- package/plugins/claude/plugin.js +39 -2
- package/plugins/claudeplatform/LICENSE +21 -0
- package/plugins/claudeplatform/icon.svg +3 -0
- package/plugins/claudeplatform/plugin.js +244 -0
- package/plugins/claudeplatform/plugin.json +25 -0
- package/plugins/codex/plugin.js +3 -2
- package/plugins/codex/plugin.json +1 -1
- package/plugins/cosmic/LICENSE +21 -0
- package/plugins/cosmic/icon.svg +1 -0
- package/plugins/cosmic/plugin.js +134 -0
- package/plugins/cosmic/plugin.json +32 -0
- package/plugins/cursor/plugin.js +9 -2
- package/plugins/cursor-nightly/plugin.json +1 -1
- package/plugins/devpass/icon.svg +3 -0
- package/plugins/devpass/plugin.js +5 -0
- package/plugins/devpass/plugin.json +2 -1
- package/plugins/exa/LICENSE +21 -0
- package/plugins/exa/icon-color.svg +1 -0
- package/plugins/exa/icon.svg +1 -0
- package/plugins/exa/plugin.js +75 -0
- package/plugins/exa/plugin.json +32 -0
- package/plugins/fal/LICENSE +21 -0
- package/plugins/fal/icon-color.svg +1 -0
- package/plugins/fal/icon.svg +1 -0
- package/plugins/fal/plugin.js +74 -0
- package/plugins/fal/plugin.json +24 -0
- package/plugins/flora/LICENSE +21 -0
- package/plugins/flora/icon.svg +4 -0
- package/plugins/flora/plugin.js +93 -0
- package/plugins/flora/plugin.json +32 -0
- package/plugins/futureagi/LICENSE +21 -0
- package/plugins/futureagi/icon.svg +24 -0
- package/plugins/futureagi/plugin.js +139 -0
- package/plugins/futureagi/plugin.json +32 -0
- package/plugins/gemini-apps/LICENSE +1 -2
- package/plugins/gemini-apps/plugin.js +136 -465
- package/plugins/gemini-apps/plugin.json +13 -7
- package/plugins/gitkraken/icon.svg +2 -0
- package/plugins/gitkraken/plugin.js +5 -0
- package/plugins/gitkraken/plugin.json +9 -1
- package/plugins/helmcode/icon.svg +5 -0
- package/plugins/helmcode/plugin.js +48 -40
- package/plugins/helmcode/plugin.json +10 -2
- package/plugins/huggingface/plugin.js +6 -1
- package/plugins/huggingface/plugin.json +4 -3
- package/plugins/hyper/plugin.js +53 -47
- package/plugins/hyper/plugin.json +3 -2
- package/plugins/kimi/plugin.js +39 -14
- package/plugins/langdock/LICENSE +21 -0
- package/plugins/langdock/icon.svg +4 -0
- package/plugins/langdock/plugin.js +106 -0
- package/plugins/langdock/plugin.json +25 -0
- package/plugins/linkup/LICENSE +21 -0
- package/plugins/linkup/icon.svg +10 -0
- package/plugins/linkup/plugin.js +46 -0
- package/plugins/linkup/plugin.json +24 -0
- package/plugins/lithosai/plugin.js +5 -0
- package/plugins/lithosai/plugin.json +2 -1
- package/plugins/llmman/icon.svg +4 -0
- package/plugins/llmman/plugin.js +5 -0
- package/plugins/llmman/plugin.json +9 -1
- package/plugins/munito/LICENSE +21 -0
- package/plugins/munito/icon.svg +7 -0
- package/plugins/munito/plugin.js +171 -0
- package/plugins/munito/plugin.json +24 -0
- package/plugins/muse/icon.svg +3 -0
- package/plugins/muse/plugin.js +5 -0
- package/plugins/muse/plugin.json +9 -1
- package/plugins/museai/plugin.js +5 -0
- package/plugins/museai/plugin.json +2 -1
- package/plugins/nous/plugin.js +5 -0
- package/plugins/nous/plugin.json +9 -1
- package/plugins/ollama/plugin.js +58 -0
- package/plugins/opencode-go/plugin.js +17 -6
- package/plugins/parallel/LICENSE +21 -0
- package/plugins/parallel/icon.svg +11 -0
- package/plugins/parallel/plugin.js +97 -0
- package/plugins/parallel/plugin.json +25 -0
- package/plugins/qwencloud/LICENSE +21 -0
- package/plugins/qwencloud/plugin.js +197 -0
- package/plugins/qwencloud/plugin.json +17 -0
- package/plugins/raycast/icon.svg +4 -0
- package/plugins/raycast/plugin.js +5 -0
- package/plugins/raycast/plugin.json +9 -1
- package/plugins/replicate/plugin.js +5 -0
- package/plugins/replicate/plugin.json +2 -1
- package/plugins/sailresearch/LICENSE +21 -0
- package/plugins/sailresearch/icon.svg +4 -0
- package/plugins/sailresearch/plugin.js +104 -0
- package/plugins/sailresearch/plugin.json +24 -0
- package/plugins/sofya/LICENSE +21 -0
- package/plugins/sofya/icon.svg +3 -0
- package/plugins/sofya/plugin.js +86 -0
- package/plugins/sofya/plugin.json +24 -0
- package/plugins/soniox/LICENSE +21 -0
- package/plugins/soniox/icon.svg +3 -0
- package/plugins/soniox/plugin.js +103 -0
- package/plugins/soniox/plugin.json +24 -0
- package/plugins/tavily/LICENSE +21 -0
- package/plugins/tavily/icon.svg +3 -0
- package/plugins/tavily/plugin.js +61 -0
- package/plugins/tavily/plugin.json +24 -0
- package/plugins/tinyapi/LICENSE +21 -0
- package/plugins/tinyapi/icon.svg +4 -0
- package/plugins/tinyapi/plugin.js +73 -0
- package/plugins/tinyapi/plugin.json +25 -0
- package/plugins/traecn/LICENSE +21 -0
- package/plugins/traecn/icon.svg +3 -0
- package/plugins/traecn/plugin.js +104 -0
- package/plugins/traecn/plugin.json +25 -0
- package/plugins/typesafe/icon.svg +4 -0
- package/plugins/typesafe/plugin.js +30 -25
- package/plugins/typesafe/plugin.json +3 -2
- package/plugins/v0/plugin.js +5 -0
- package/plugins/v0/plugin.json +9 -1
- package/plugins/vercel/plugin.js +147 -0
- package/plugins/vercel/plugin.json +34 -3
- package/plugins/workbuddy/icon.svg +1 -1
- package/plugins/workbuddy/plugin.js +9 -4
- package/plugins/workbuddy/plugin.json +20 -2
- package/plugins/xai/plugin.js +9 -0
- package/plugins/xapi/LICENSE +21 -0
- package/plugins/xapi/icon.svg +1 -0
- package/plugins/xapi/plugin.js +90 -0
- package/plugins/xapi/plugin.json +25 -0
- package/plugins/xkiro/icon.svg +1 -0
- package/plugins/xkiro/plugin.js +5 -0
- package/plugins/xkiro/plugin.json +2 -1
- package/usagestat +0 -0
- package/usagestatd +0 -0
- package/plugins/cursor-nightly/plugin.js +0 -1416
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
monthly: 60,
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
const TABLES_SQL = "SELECT name FROM sqlite_master WHERE type = 'table' AND name IN ('message','session_message','credential')";
|
|
15
|
+
const TABLES_SQL = "SELECT name FROM sqlite_master WHERE type = 'table' AND name IN ('message','session_message','credential','migration')";
|
|
16
|
+
const CREDENTIALS_IMPORTED_SQL = "SELECT 1 AS imported FROM migration WHERE id = '20260805200742_import_legacy_credentials' LIMIT 1";
|
|
16
17
|
const CREDENTIAL_SQL = `SELECT value FROM credential
|
|
17
18
|
WHERE integration_id = 'opencode-go' AND (active IS NULL OR active = 1)
|
|
18
19
|
ORDER BY active DESC, time_updated DESC, id DESC LIMIT 1`;
|
|
@@ -328,15 +329,19 @@
|
|
|
328
329
|
const configured = trim(ctx.provider && ctx.provider.apiKey) || env(ctx, "OPENCODE_GO_API_KEY");
|
|
329
330
|
if (configured) return configured;
|
|
330
331
|
const inline = ctx.host.env.get("OPENCODE_AUTH_CONTENT");
|
|
331
|
-
//
|
|
332
|
-
//
|
|
332
|
+
// OpenCode 1 also creates credential tables, but still signs in through
|
|
333
|
+
// auth.json. Only the completed v2 import makes database logout authoritative.
|
|
333
334
|
if (!inline) {
|
|
334
335
|
const database = databasePath(ctx);
|
|
335
336
|
if (ctx.host.fs.exists(database)) {
|
|
336
337
|
try {
|
|
337
338
|
const tables = ctx.util.tryParseJson(ctx.host.sqlite.query(database, TABLES_SQL));
|
|
338
339
|
if (!Array.isArray(tables)) throw new Error('Invalid schema');
|
|
339
|
-
|
|
340
|
+
const imported = tables.some(table => table.name === 'migration')
|
|
341
|
+
? ctx.util.tryParseJson(ctx.host.sqlite.query(database, CREDENTIALS_IMPORTED_SQL)) : [];
|
|
342
|
+
if (!Array.isArray(imported)) throw new Error('Invalid migration result');
|
|
343
|
+
if (imported.length) {
|
|
344
|
+
if (!tables.some(table => table.name === 'credential')) throw new Error('Imported credential storage is missing');
|
|
340
345
|
const rows = ctx.util.tryParseJson(ctx.host.sqlite.query(database, CREDENTIAL_SQL));
|
|
341
346
|
if (!Array.isArray(rows)) throw new Error('Invalid credential result');
|
|
342
347
|
if (!rows.length) return null;
|
|
@@ -622,6 +627,9 @@
|
|
|
622
627
|
if (ctx.util.isAuthStatus(result.resp.status)) throw "OpenCode Go key was rejected. Sign into OpenCode Go again.";
|
|
623
628
|
if (result.resp.status < 200 || result.resp.status >= 300) throw "OpenCode Go usage API returned HTTP " + result.resp.status + ".";
|
|
624
629
|
const usage = result.json && result.json.usage;
|
|
630
|
+
const dateHeader = Object.entries(result.resp.headers || {}).find(([key]) => key.toLowerCase() === 'date');
|
|
631
|
+
const serverTime = dateHeader && Date.parse(dateHeader[1]);
|
|
632
|
+
const referenceTime = Number.isFinite(serverTime) ? serverTime : Date.parse(ctx.nowIso);
|
|
625
633
|
const specs = [["rolling", "Session", FIVE_HOURS_MS], ["weekly", "Weekly", WEEK_MS], ["monthly", "Monthly", null]];
|
|
626
634
|
const lines = [];
|
|
627
635
|
for (const spec of specs) {
|
|
@@ -630,8 +638,11 @@
|
|
|
630
638
|
const percent = window && readNumber(window.percent);
|
|
631
639
|
if (!Number.isFinite(percent)) throw "OpenCode Go usage API returned an invalid quota.";
|
|
632
640
|
const resetInSec = readNumber(window.resetInSec);
|
|
633
|
-
|
|
634
|
-
? ctx.util.toIso(
|
|
641
|
+
let resetsAt = ctx.util.toIso(window.resetsAt) || (resetInSec !== null && resetInSec >= 0
|
|
642
|
+
? ctx.util.toIso(referenceTime + resetInSec * 1000) : null);
|
|
643
|
+
if (window.resetsAt != null && !ctx.util.toIso(window.resetsAt)) throw 'OpenCode Go usage API returned an invalid reset.';
|
|
644
|
+
if (spec[0] === 'rolling' && percent === 0 && resetsAt && Math.abs(Date.parse(resetsAt)-referenceTime-FIVE_HOURS_MS)<=2000)
|
|
645
|
+
resetsAt = null;
|
|
635
646
|
lines.push(ctx.line.progress({ label: spec[1], used: Math.max(0, Math.min(100, percent)), limit: 100,
|
|
636
647
|
format: { kind: "percent" }, resetsAt, periodDurationMs: spec[2] }));
|
|
637
648
|
}
|
|
@@ -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,11 @@
|
|
|
1
|
+
<svg fill="currentColor" viewBox="-10 -10.5 291 291" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<title>Parallel</title>
|
|
3
|
+
<path d="M267.804 105.65H193.828C194.026 106.814 194.187 107.996 194.349 109.178H76.6703C76.4546 110.736 76.2388 112.312 76.0591 113.87H1.63342C1.27387 116.198 0.950289 118.543 0.698608 120.925H75.3759C75.2501 122.483 75.1602 124.059 75.0703 125.617H195.949C196.003 126.781 196.057 127.962 196.093 129.144H270.68V125.384C270.195 118.651 269.242 112.061 267.804 105.65Z"/>
|
|
4
|
+
<path d="M195.949 144.401H75.0703C75.1422 145.977 75.2501 147.535 75.3759 149.093H0.698608C0.950289 151.457 1.2559 153.802 1.63342 156.148H76.0591C76.2388 157.724 76.4366 159.282 76.6703 160.84H194.349C194.187 162.022 194.008 163.186 193.828 164.367H267.804C269.242 157.957 270.195 151.367 270.68 144.634V140.874H196.093C196.057 142.055 196.003 143.219 195.949 144.401Z"/>
|
|
5
|
+
<path d="M190.628 179.642H80.3559C80.7514 181.218 81.1828 182.776 81.6143 184.334H9.30994C10.2448 186.715 11.2515 189.061 12.3121 191.389H83.7536C84.2749 192.965 84.7962 194.523 85.3535 196.08H185.594C185.163 197.262 184.732 198.426 184.282 199.608H254.519C258.6 192.177 261.98 184.316 264.604 176.114H191.455C191.185 177.296 190.898 178.46 190.61 179.642H190.628Z"/>
|
|
6
|
+
<path d="M177.666 214.883H93.3352C94.1082 216.458 94.9172 218.034 95.7441 219.574H29.8756C31.8351 221.992 33.8666 224.337 35.9699 226.63H99.6632C100.598 228.205 101.551 229.781 102.522 231.321H168.498C167.761 232.503 167.006 233.685 166.233 234.849H226.762C234.474 227.847 241.36 219.95 247.292 211.355H179.356C178.799 212.537 178.26 213.719 177.684 214.883H177.666Z"/>
|
|
7
|
+
<path d="M154.943 250.106H116.058C117.371 251.699 118.701 253.257 120.067 254.797H73.021C91.6094 264.431 112.715 269.946 135.096 270C135.24 270 135.366 270 135.492 270C135.618 270 135.761 270 135.887 270C164.04 269.911 190.178 261.28 211.805 246.56H157.748C156.813 247.742 155.878 248.924 154.925 250.088L154.943 250.106Z"/>
|
|
8
|
+
<path d="M116.059 19.9124H154.943C155.896 21.0764 156.831 22.2582 157.766 23.4401H211.823C190.179 8.72065 164.058 0.0895344 135.906 0C135.762 0 135.636 0 135.51 0C135.384 0 135.24 0 135.115 0C112.715 0.0716275 91.6277 5.56904 73.0393 15.2029H120.086C118.719 16.7429 117.389 18.3187 116.077 19.8945L116.059 19.9124Z"/>
|
|
9
|
+
<path d="M93.3356 55.1532H177.667C178.242 56.3171 178.799 57.499 179.339 58.6808H247.274C241.342 50.0855 234.457 42.1886 226.744 35.187H166.215C166.988 36.351 167.743 37.5328 168.48 38.7147H102.504C101.533 40.2726 100.58 41.8305 99.6456 43.4063H35.9523C33.831 45.6804 31.7996 48.0262 29.858 50.4616H95.7265C94.8996 52.0195 94.1086 53.5774 93.3176 55.1532H93.3356Z"/>
|
|
10
|
+
<path d="M80.3736 90.3758H190.646C190.933 91.5398 191.221 92.7216 191.491 93.9035H264.64C262.015 85.7021 258.636 77.841 254.555 70.4097H184.318C184.767 71.5736 185.199 72.7555 185.63 73.9373H85.3893C84.832 75.4952 84.2927 77.0531 83.7893 78.6289H12.3479C11.2872 80.9389 10.2805 83.2847 9.3457 85.6842H81.65C81.2186 87.2421 80.7871 88.8 80.3916 90.3758H80.3736Z"/>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
|
+
globalThis.__usagestat_bundled_options = {"labels":["Balance","Additional","Additional"],"defaults":{},"autoMode":"web","balanceOnly":true};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/parallel.js
|
|
5
|
+
function _nullishCoalesce(lhs, rhsFn) {
|
|
6
|
+
if (lhs != null) {
|
|
7
|
+
return lhs;
|
|
8
|
+
} else {
|
|
9
|
+
return rhsFn();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
defineProvider({
|
|
13
|
+
id: "parallel",
|
|
14
|
+
name: "Parallel",
|
|
15
|
+
endpoints: ["https://platform.parallel.ai"],
|
|
16
|
+
settings: [],
|
|
17
|
+
capabilities: ["browser-cookies", "http-status"],
|
|
18
|
+
cookieDomains: ["platform.parallel.ai"],
|
|
19
|
+
async fetchUsage(ctx) {
|
|
20
|
+
const domain = "platform.parallel.ai";
|
|
21
|
+
const policy = ctx.browser.availability(domain);
|
|
22
|
+
if (policy === "off") throw ctx.fail.missingCredential("Parallel cookies are disabled.");
|
|
23
|
+
// Internal dashboard RPC with no public contract; every shape check below fails closed.
|
|
24
|
+
const request = (cookie) =>
|
|
25
|
+
ctx.http.post(`https://${domain}/api/rpc/billing/payments/refresh-balance`, {
|
|
26
|
+
body: {},
|
|
27
|
+
headers: { Cookie: cookie, Origin: `https://${domain}` },
|
|
28
|
+
});
|
|
29
|
+
const signedOut = (response) =>
|
|
30
|
+
response.status === 401 ||
|
|
31
|
+
response.status === 403 ||
|
|
32
|
+
(response.status >= 300 && response.status < 400) ||
|
|
33
|
+
(response.status === 200 &&
|
|
34
|
+
_nullishCoalesce(response.headers["content-type"], () => "")
|
|
35
|
+
.toLowerCase()
|
|
36
|
+
.includes("text/html"));
|
|
37
|
+
|
|
38
|
+
let response;
|
|
39
|
+
let rejected = false;
|
|
40
|
+
for await (const session of ctx.browser.sessions(domain)) {
|
|
41
|
+
const candidate = await request(_nullishCoalesce(session.header, () => ""));
|
|
42
|
+
if (signedOut(candidate)) {
|
|
43
|
+
rejected = true;
|
|
44
|
+
ctx.browser.rejectCookie(domain, session);
|
|
45
|
+
if (policy === "manual") break;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
response = candidate;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
if (!response) {
|
|
52
|
+
throw rejected
|
|
53
|
+
? ctx.fail.authenticationExpired(
|
|
54
|
+
"Parallel session expired. Sign in to platform.parallel.ai again or paste a fresh Cookie header.",
|
|
55
|
+
)
|
|
56
|
+
: ctx.fail.missingCredential(
|
|
57
|
+
`No Parallel session found. Sign in to platform.parallel.ai. Supported browsers: ${ctx.browser.supportedBrowsers}. Or paste a Cookie header.`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const message = `Parallel returned HTTP ${response.status}.`;
|
|
62
|
+
if (response.status === 429) {
|
|
63
|
+
const delay = Number(_nullishCoalesce(response.headers["retry-after"], () => 1));
|
|
64
|
+
throw ctx.fail.rateLimited(message, {
|
|
65
|
+
retryAfterSeconds: Number.isFinite(delay) && delay >= 0 ? Math.min(delay, 10) : 1,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (response.status === 408 || response.status >= 500) throw ctx.fail.providerUnavailable(message);
|
|
69
|
+
if (response.status !== 200) throw ctx.fail.apiFailure(message);
|
|
70
|
+
|
|
71
|
+
const formatChanged = () => {
|
|
72
|
+
throw ctx.fail.parseFailure("Parallel billing response format changed.");
|
|
73
|
+
};
|
|
74
|
+
const finite = (value) => typeof value === "number" && Number.isFinite(value);
|
|
75
|
+
let payload;
|
|
76
|
+
try {
|
|
77
|
+
payload = JSON.parse(response.bodyText);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
void error;
|
|
80
|
+
return formatChanged();
|
|
81
|
+
}
|
|
82
|
+
const data = payload && typeof payload === "object" && payload.kind === "ok" ? payload.data : undefined;
|
|
83
|
+
if (!data || typeof data !== "object" || !finite(data.balance)) return formatChanged();
|
|
84
|
+
const rows = [{ label: "Balance", value: ctx.format.currency(data.balance / 100, "USD") }];
|
|
85
|
+
if (finite(data.pendingDebitBalanceCents) && data.pendingDebitBalanceCents !== 0) {
|
|
86
|
+
rows.push({ label: "Pending debit", value: ctx.format.currency(data.pendingDebitBalanceCents / 100, "USD") });
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
details: [{ title: "Account balance", rows }],
|
|
90
|
+
identity: { loginMethod: "Browser session" },
|
|
91
|
+
dataConfidence: "exact",
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// END UPSTREAM
|
|
97
|
+
})(globalThis.defineProvider);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "parallel",
|
|
4
|
+
"name": "Parallel",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"enabledByDefault": false,
|
|
8
|
+
"supportedModes": [
|
|
9
|
+
"web"
|
|
10
|
+
],
|
|
11
|
+
"autoMode": "web",
|
|
12
|
+
"usageDashboardUrl": "https://platform.parallel.ai",
|
|
13
|
+
"webUrl": "https://platform.parallel.ai",
|
|
14
|
+
"envVars": [
|
|
15
|
+
"PARALLEL_COOKIE"
|
|
16
|
+
],
|
|
17
|
+
"setupFields": [],
|
|
18
|
+
"upstream": {
|
|
19
|
+
"repository": "https://github.com/steipete/CodexBar",
|
|
20
|
+
"revision": "6070b29a1a5d51193a634dc1b0a14a67c39d0ccc",
|
|
21
|
+
"path": "Sources/CodexBarCore/Resources/Plugins/parallel.js",
|
|
22
|
+
"sha256": "854d5faa2b6c01b96cf009295fabe85cbdc28d07911d7c7e1da970c8cc77e5e8",
|
|
23
|
+
"license": "MIT"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -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.
|
|
@@ -1,3 +1,191 @@
|
|
|
1
|
+
// Generated by tools/vendor-codexbar-providers.cjs from individual.js and reviewed upstream; see LICENSE.
|
|
2
|
+
(function() { let team;
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/qwencloud-team.js
|
|
5
|
+
function _nullishCoalesce(lhs, rhsFn) {
|
|
6
|
+
if (lhs != null) {
|
|
7
|
+
return lhs;
|
|
8
|
+
} else {
|
|
9
|
+
return rhsFn();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function _optionalChain(ops) {
|
|
13
|
+
let lastAccessLHS = undefined;
|
|
14
|
+
let value = ops[0];
|
|
15
|
+
let i = 1;
|
|
16
|
+
while (i < ops.length) {
|
|
17
|
+
const op = ops[i];
|
|
18
|
+
const fn = ops[i + 1];
|
|
19
|
+
i += 2;
|
|
20
|
+
if ((op === "optionalAccess" || op === "optionalCall") && value == null) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
if (op === "access" || op === "optionalAccess") {
|
|
24
|
+
lastAccessLHS = value;
|
|
25
|
+
value = fn(value);
|
|
26
|
+
} else if (op === "call" || op === "optionalCall") {
|
|
27
|
+
value = fn((...args) => value.call(lastAccessLHS, ...args));
|
|
28
|
+
lastAccessLHS = undefined;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
defineProvider({
|
|
34
|
+
id: "qwencloud",
|
|
35
|
+
name: "Qwen Cloud",
|
|
36
|
+
endpoints: ["https://home.qwencloud.com"],
|
|
37
|
+
settings: [],
|
|
38
|
+
capabilities: ["browser-cookies", "http-status"],
|
|
39
|
+
cookieDomains: ["home.qwencloud.com"],
|
|
40
|
+
cookiePolicy: { selection: "request-url", cache: "nonpersistent" },
|
|
41
|
+
async fetchUsage(ctx) {
|
|
42
|
+
const base = "https://home.qwencloud.com";
|
|
43
|
+
const fail = (field) => {
|
|
44
|
+
throw ctx.fail.parseFailure(`Unsupported Qwen Cloud Team ${field}. Check Usage Dashboard.`);
|
|
45
|
+
};
|
|
46
|
+
const record = (value) =>
|
|
47
|
+
value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
48
|
+
const number = (value) => {
|
|
49
|
+
if (typeof value !== "number" && (typeof value !== "string" || !/^\d+(?:\.\d+)?$/.test(value)))
|
|
50
|
+
return fail("credit count");
|
|
51
|
+
const parsed = Number(value);
|
|
52
|
+
return Number.isFinite(parsed) && parsed >= 0 && parsed <= Number.MAX_SAFE_INTEGER
|
|
53
|
+
? parsed
|
|
54
|
+
: fail("credit count");
|
|
55
|
+
};
|
|
56
|
+
const json = (response) => {
|
|
57
|
+
if (response.status === 401 || response.status === 403)
|
|
58
|
+
throw ctx.fail.authenticationExpired("Qwen Cloud Team session expired. Sign in again.");
|
|
59
|
+
if (response.status === 429) throw ctx.fail.rateLimited("Qwen Cloud Team rate limit reached.");
|
|
60
|
+
if (response.status !== 200) throw ctx.fail.apiFailure(`Qwen Cloud Team returned HTTP ${response.status}.`);
|
|
61
|
+
let payload;
|
|
62
|
+
try {
|
|
63
|
+
payload = JSON.parse(response.bodyText);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
void error;
|
|
66
|
+
return fail("response");
|
|
67
|
+
}
|
|
68
|
+
const root = _nullishCoalesce(record(payload), () => fail("response"));
|
|
69
|
+
if (
|
|
70
|
+
typeof root.code === "string" &&
|
|
71
|
+
["ConsoleNeedLogin", "BailianGateway.Login.NotLogined", "NO_LOGIN"].includes(root.code)
|
|
72
|
+
)
|
|
73
|
+
throw ctx.fail.authenticationExpired("Qwen Cloud Team login required.");
|
|
74
|
+
return root;
|
|
75
|
+
};
|
|
76
|
+
for await (const session of ctx.browser.sessions("home.qwencloud.com")) {
|
|
77
|
+
const options = {
|
|
78
|
+
cookieSession: session.id,
|
|
79
|
+
timeoutSeconds: 8,
|
|
80
|
+
headers: { Accept: "application/json", Referer: `${base}/analytics/token-plan/team` },
|
|
81
|
+
};
|
|
82
|
+
const info = json(await ctx.http.get(`${base}/tool/user/info.json`, options));
|
|
83
|
+
const token = _optionalChain([record, "call", (_) => _(info.data), "optionalAccess", (_2) => _2.secToken]);
|
|
84
|
+
if (typeof token !== "string" || !token.trim())
|
|
85
|
+
throw ctx.fail.authenticationExpired("Qwen Cloud Team login required.");
|
|
86
|
+
const rpc = async (product, action, params, region) => {
|
|
87
|
+
const form = {
|
|
88
|
+
product,
|
|
89
|
+
action,
|
|
90
|
+
sec_token: token,
|
|
91
|
+
region,
|
|
92
|
+
params: JSON.stringify(params),
|
|
93
|
+
};
|
|
94
|
+
if (action === "GetSeatSubscriptionSummary") form.language = "zh-CN";
|
|
95
|
+
const root = json(
|
|
96
|
+
await ctx.http.post(`${base}/data/api.json?product=${product}&action=${action}`, {
|
|
97
|
+
...options,
|
|
98
|
+
headers: { ...options.headers, Origin: base },
|
|
99
|
+
form,
|
|
100
|
+
}),
|
|
101
|
+
);
|
|
102
|
+
const result = record(root.data);
|
|
103
|
+
if (root.successResponse === false || _optionalChain([result, "optionalAccess", (_3) => _3.Success]) === false)
|
|
104
|
+
throw ctx.fail.apiFailure(`Qwen Cloud Team ${action} failed.`);
|
|
105
|
+
if ((root.successResponse !== true && root.code !== "200") || !result) return fail("gateway envelope");
|
|
106
|
+
return result;
|
|
107
|
+
};
|
|
108
|
+
// The console discovers this billing selector; it is not the login UID or a saved workspace ID.
|
|
109
|
+
const human = await rpc("ea-service", "LoadHumanInfo", {}, "ap-southeast-1");
|
|
110
|
+
const nbid = _optionalChain([
|
|
111
|
+
record,
|
|
112
|
+
"call",
|
|
113
|
+
(_4) =>
|
|
114
|
+
_4(_optionalChain([record, "call", (_5) => _5(human.Data), "optionalAccess", (_6) => _6.SellerInfoDto])),
|
|
115
|
+
"optionalAccess",
|
|
116
|
+
(_7) => _7.Nbid,
|
|
117
|
+
]);
|
|
118
|
+
const params = { productCode: "sfm_tokenplanteams_dp_intl" };
|
|
119
|
+
if (nbid !== undefined && nbid !== null && nbid !== "") {
|
|
120
|
+
if (typeof nbid !== "string" || !nbid.trim()) return fail("billing selector");
|
|
121
|
+
params.Nbid = nbid;
|
|
122
|
+
}
|
|
123
|
+
const summary = await rpc("BssOpenAPI-V3", "GetSeatSubscriptionSummary", params, "cn-hangzhou");
|
|
124
|
+
const data = _nullishCoalesce(record(summary.Data === null ? {} : summary.Data), () => fail("subscription"));
|
|
125
|
+
if (Object.keys(data).length === 0) return { empty: true };
|
|
126
|
+
const groups = data.SubscriptionGroupList;
|
|
127
|
+
if (!Array.isArray(groups)) return fail("subscription groups");
|
|
128
|
+
if (!groups.length) return { empty: true };
|
|
129
|
+
const start = number(data.StartTime);
|
|
130
|
+
const end = number(data.EndTime);
|
|
131
|
+
if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start <= 0 || end <= start)
|
|
132
|
+
return fail("subscription period");
|
|
133
|
+
const now = ctx.date.now().getTime();
|
|
134
|
+
if (now < start || now >= end) return { empty: true };
|
|
135
|
+
if (data.ProductCode !== "sfm_tokenplanteams_dp_intl") return fail("subscription product");
|
|
136
|
+
if (groups.length !== 1) return fail("multiple credit pools");
|
|
137
|
+
const group = _nullishCoalesce(record(groups[0]), () => fail("subscription group"));
|
|
138
|
+
if (!Array.isArray(group.EquityList)) return fail("credit equity");
|
|
139
|
+
const equities = group.EquityList.map(record).filter(
|
|
140
|
+
(equity) => _optionalChain([equity, "optionalAccess", (_8) => _8.EquityCode]) === "credit_value",
|
|
141
|
+
);
|
|
142
|
+
if (equities.length !== 1) return fail("credit equity");
|
|
143
|
+
const total = number(
|
|
144
|
+
_optionalChain([equities, "access", (_9) => _9[0], "optionalAccess", (_10) => _10.TotalValue]),
|
|
145
|
+
);
|
|
146
|
+
const remaining = number(
|
|
147
|
+
_optionalChain([equities, "access", (_11) => _11[0], "optionalAccess", (_12) => _12.SurplusValue]),
|
|
148
|
+
);
|
|
149
|
+
if (total <= 0 || remaining > total) return fail("credit count");
|
|
150
|
+
const used = total - remaining;
|
|
151
|
+
const format = (value) => ctx.format.number(value, { maximumFractionDigits: 2 });
|
|
152
|
+
const rows = [
|
|
153
|
+
{ label: "Credits", value: `${format(used)} / ${format(total)} credits used` },
|
|
154
|
+
{ label: "Remaining", value: `${format(remaining)} credits` },
|
|
155
|
+
];
|
|
156
|
+
const assigned = group.SubscriptionAssignedNumber;
|
|
157
|
+
const seats = group.SubscriptionTotalNumber;
|
|
158
|
+
if (
|
|
159
|
+
typeof assigned === "number" &&
|
|
160
|
+
typeof seats === "number" &&
|
|
161
|
+
Number.isSafeInteger(assigned) &&
|
|
162
|
+
Number.isSafeInteger(seats) &&
|
|
163
|
+
assigned >= 0 &&
|
|
164
|
+
seats >= assigned
|
|
165
|
+
)
|
|
166
|
+
rows.push({ label: "Seats", value: `${assigned} / ${seats}` });
|
|
167
|
+
let reset;
|
|
168
|
+
if (group.NextCycleFlushTime !== undefined && group.NextCycleFlushTime !== null) {
|
|
169
|
+
const millis = number(group.NextCycleFlushTime);
|
|
170
|
+
if (!Number.isSafeInteger(millis) || millis <= 0) return fail("cycle reset");
|
|
171
|
+
reset = ctx.date.unixMillis(millis);
|
|
172
|
+
}
|
|
173
|
+
const spec =
|
|
174
|
+
typeof group.SpecType === "string" && /^[a-z][a-z0-9_-]{0,39}$/.test(group.SpecType)
|
|
175
|
+
? `${group.SpecType[0].toUpperCase()}${group.SpecType.slice(1)} Team`
|
|
176
|
+
: "Team Token Plan";
|
|
177
|
+
return {
|
|
178
|
+
primary: { usedPercent: ctx.pct(used, total), resetsAt: reset, resetDescription: "Team" },
|
|
179
|
+
identity: { loginMethod: spec },
|
|
180
|
+
details: [{ title: "Team Token Plan", rows }],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
throw ctx.fail.missingCredential("No Qwen Cloud Team session cookies available.");
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// END UPSTREAM
|
|
188
|
+
})(definition => { team=globalThis.__usagestat_bundledProvider(definition,{labels:['Team credits','Additional','Additional'],autoMode:'web'}); });
|
|
1
189
|
(function () {
|
|
2
190
|
var GATEWAY_BASE_URL = "https://home.qwencloud.com";
|
|
3
191
|
var DATA_GATEWAY_BASE_URL = "https://cs-data.qwencloud.com";
|
|
@@ -52,6 +240,7 @@
|
|
|
52
240
|
}
|
|
53
241
|
|
|
54
242
|
function env(ctx, name) {
|
|
243
|
+
if (ctx.provider && ctx.provider.instanceId && ctx.provider.instanceId !== 'qwencloud') return null;
|
|
55
244
|
try {
|
|
56
245
|
return clean(ctx.host.env.get(name));
|
|
57
246
|
} catch (_) {
|
|
@@ -675,3 +864,11 @@
|
|
|
675
864
|
|
|
676
865
|
globalThis.__openusage_plugin = { id: "qwencloud", probe: probe };
|
|
677
866
|
})();
|
|
867
|
+
|
|
868
|
+
const individual=globalThis.__openusage_plugin;
|
|
869
|
+
globalThis.__usagestat_plugin = {id:"qwencloud",probe(ctx) {
|
|
870
|
+
const selected=ctx.provider?.settings?.teamTokenPlan;
|
|
871
|
+
if(selected!==undefined && typeof selected!=='boolean') throw new Error('teamTokenPlan must be a boolean.');
|
|
872
|
+
return (selected===true ? team : individual).probe(ctx);
|
|
873
|
+
}};
|
|
874
|
+
})();
|
|
@@ -25,5 +25,22 @@
|
|
|
25
25
|
"envVars": [
|
|
26
26
|
"QWEN_CLOUD_COOKIE",
|
|
27
27
|
"QWEN_CLOUD_COOKIE_HEADER"
|
|
28
|
+
],
|
|
29
|
+
"upstreamSources": [
|
|
30
|
+
{
|
|
31
|
+
"repository": "https://github.com/steipete/CodexBar",
|
|
32
|
+
"revision": "6070b29a1a5d51193a634dc1b0a14a67c39d0ccc",
|
|
33
|
+
"path": "Sources/CodexBarCore/Resources/Plugins/qwencloud-team.js",
|
|
34
|
+
"sha256": "11a7e231c1705a83f29b4509102abaa656b9888f63cfc132de0a520d94ee9301",
|
|
35
|
+
"license": "MIT"
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"setupFields": [
|
|
39
|
+
{
|
|
40
|
+
"key": "teamTokenPlan",
|
|
41
|
+
"title": "Team Token Plan",
|
|
42
|
+
"type": "boolean",
|
|
43
|
+
"description": "Read the Team subscription for this cookie; otherwise read the Individual subscription. No fallback between scopes."
|
|
44
|
+
}
|
|
28
45
|
]
|
|
29
46
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<title>Raycast</title>
|
|
3
|
+
<path d="M6.004 15.492v2.504L0 11.992l1.258-1.249Zm2.504 2.504H6.004L12.008 24l1.253-1.253zm14.24-4.747L24 11.997 12.003 0 10.75 1.251 15.491 6h-2.865L9.317 2.692 8.065 3.944l2.06 2.06H8.691v9.31H18v-1.432l2.06 2.06 1.252-1.252-3.312-3.32V8.506ZM6.63 5.372 5.38 6.625l1.342 1.343 1.251-1.253Zm10.655 10.655-1.247 1.251 1.342 1.343 1.253-1.251zM3.944 8.059 2.692 9.31l3.312 3.314v-2.506zm9.936 9.937h-2.504l3.314 3.312 1.25-1.252z"/>
|
|
4
|
+
</svg>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
2
|
globalThis.__usagestat_bundled_options = {"labels":["Credits","Plan","Additional"],"defaults":{},"autoMode":"web"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/raycast.js
|
|
3
5
|
function _nullishCoalesce(lhs, rhsFn) {
|
|
4
6
|
if (lhs != null) {
|
|
5
7
|
return lhs;
|
|
@@ -172,3 +174,6 @@ defineProvider({
|
|
|
172
174
|
};
|
|
173
175
|
},
|
|
174
176
|
});
|
|
177
|
+
|
|
178
|
+
// END UPSTREAM
|
|
179
|
+
})(globalThis.defineProvider);
|
|
@@ -14,9 +14,17 @@
|
|
|
14
14
|
"envVars": [
|
|
15
15
|
"RAYCAST_COOKIE"
|
|
16
16
|
],
|
|
17
|
+
"setupFields": [
|
|
18
|
+
{
|
|
19
|
+
"key": "webTimeoutSeconds",
|
|
20
|
+
"title": "Web timeout",
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Provider-specific account or source selection."
|
|
23
|
+
}
|
|
24
|
+
],
|
|
17
25
|
"upstream": {
|
|
18
26
|
"repository": "https://github.com/steipete/CodexBar",
|
|
19
|
-
"revision": "
|
|
27
|
+
"revision": "6070b29a1a5d51193a634dc1b0a14a67c39d0ccc",
|
|
20
28
|
"path": "Sources/CodexBarCore/Resources/Plugins/raycast.js",
|
|
21
29
|
"sha256": "df8f6d185cb67fd9ec9b622d2321a6d4e5395576b9ab54b1725aac272c95ecb7",
|
|
22
30
|
"license": "MIT"
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Generated by tools/vendor-codexbar-providers.cjs; see LICENSE.
|
|
2
2
|
globalThis.__usagestat_bundled_options = {"labels":["Spend","Spend","Additional"],"defaults":{},"autoMode":"web"};
|
|
3
|
+
(function(defineProvider) {
|
|
4
|
+
// BEGIN UPSTREAM Sources/CodexBarCore/Resources/Plugins/replicate.js
|
|
3
5
|
function _optionalChain(ops) {
|
|
4
6
|
let lastAccessLHS = undefined;
|
|
5
7
|
let value = ops[0];
|
|
@@ -163,3 +165,6 @@ defineProvider({
|
|
|
163
165
|
};
|
|
164
166
|
},
|
|
165
167
|
});
|
|
168
|
+
|
|
169
|
+
// END UPSTREAM
|
|
170
|
+
})(globalThis.defineProvider);
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
"envVars": [
|
|
15
15
|
"REPLICATE_COOKIE"
|
|
16
16
|
],
|
|
17
|
+
"setupFields": [],
|
|
17
18
|
"upstream": {
|
|
18
19
|
"repository": "https://github.com/steipete/CodexBar",
|
|
19
|
-
"revision": "
|
|
20
|
+
"revision": "6070b29a1a5d51193a634dc1b0a14a67c39d0ccc",
|
|
20
21
|
"path": "Sources/CodexBarCore/Resources/Plugins/replicate.js",
|
|
21
22
|
"sha256": "d240c36fa142ee91ce90ae52a2c6814613d2d5533a00c8a4c7ecec2f9386006c",
|
|
22
23
|
"license": "MIT"
|
|
@@ -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,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 167 149">
|
|
2
|
+
<path fill="#000" d="M165.371.267c-6.511 13.076-45.948 89.68-104.083 147.779-.316.315-.093.856.354.856h104.182a.5.5 0 0 0 .5-.5V.528c0-.532-.716-.737-.953 0Z"/>
|
|
3
|
+
<path fill="#000" d="M87.497 49.707C81.025 58.66 40.157 114.303.178 148.022c-.357.301-.141.88.327.88h87.428c.276 0 .45-.224.45-.5V50.041c0-.487-.601-.728-.886-.334Z"/>
|
|
4
|
+
</svg>
|