pi-provider-qoder-cn 0.2.17 → 0.2.19
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/README.md +8 -0
- package/dist/index.js +74 -49
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -133,6 +133,14 @@ Notes:
|
|
|
133
133
|
agree with the numbers on the same row. The API's own `percentage` field is a
|
|
134
134
|
0-1 fraction (94% arrives as `0.94`) and is only used — scaled by 100 — when a
|
|
135
135
|
bucket comes back without numbers.
|
|
136
|
+
- `Add-on expiry` is only printed when a real check-in grant exists. A pool that
|
|
137
|
+
is a whole stack of daily grant packs (never more packs than the validity
|
|
138
|
+
window holds) is laid out as `Rolling 30d · earliest of N daily 100-credit
|
|
139
|
+
packs ~DATE`. A pool that is not one (a purchased top-up, or a leftover
|
|
140
|
+
remainder) prints only the expiry the campaign actually reported, `DATE ·
|
|
141
|
+
latest grant`, and an account that has never claimed prints no expiry line at
|
|
142
|
+
all, because with no grant there is nothing to date from, and inventing one
|
|
143
|
+
would show dates the API never sent.
|
|
136
144
|
- `Expires never` means the API reported the year-9999 sentinel, i.e. the
|
|
137
145
|
allowance has no expiry date.
|
|
138
146
|
- `Note plan quota is prorated` appears after a mid-cycle plan change.
|
package/dist/index.js
CHANGED
|
@@ -1785,6 +1785,27 @@ init_oauth();
|
|
|
1785
1785
|
|
|
1786
1786
|
// src/auth/usage.ts
|
|
1787
1787
|
init_region();
|
|
1788
|
+
function num(value) {
|
|
1789
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
1790
|
+
}
|
|
1791
|
+
function round2(value) {
|
|
1792
|
+
return Math.round(value * 100) / 100;
|
|
1793
|
+
}
|
|
1794
|
+
function hasAllowance(bucket) {
|
|
1795
|
+
if (!bucket) return false;
|
|
1796
|
+
return num(bucket.total ?? bucket.cap) > 0 || num(bucket.used) > 0 || num(bucket.remaining) > 0;
|
|
1797
|
+
}
|
|
1798
|
+
function resetTimestamp(expiresAt) {
|
|
1799
|
+
const ms = num(expiresAt);
|
|
1800
|
+
if (ms <= 0) return void 0;
|
|
1801
|
+
const timestamp = ms < 1e12 ? ms * 1e3 : ms;
|
|
1802
|
+
if (new Date(timestamp).getUTCFullYear() >= 9999) return void 0;
|
|
1803
|
+
return new Date(timestamp).toISOString();
|
|
1804
|
+
}
|
|
1805
|
+
function pickBucket(raw, camel) {
|
|
1806
|
+
const snake = camel.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
|
1807
|
+
return raw[snake] ?? raw[camel];
|
|
1808
|
+
}
|
|
1788
1809
|
async function fetchQoderUsageForMode(credentials, mode) {
|
|
1789
1810
|
const region = getQoderRegionConfig(mode);
|
|
1790
1811
|
const response = await fetch(getQoderUsageURL(mode), {
|
|
@@ -1799,35 +1820,27 @@ async function fetchQoderUsageForMode(credentials, mode) {
|
|
|
1799
1820
|
throw new Error(`Failed to fetch Qoder usage: ${response.status} ${response.statusText}`);
|
|
1800
1821
|
}
|
|
1801
1822
|
const raw = await response.json();
|
|
1802
|
-
const
|
|
1803
|
-
const
|
|
1804
|
-
const
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
label: "Org Resource Package",
|
|
1820
|
-
usedDisplay: org.used.toFixed(2),
|
|
1821
|
-
limitDisplay: orgLimit.toFixed(2),
|
|
1822
|
-
unit: org.unit,
|
|
1823
|
-
resetAt: raw.expiresAt ? new Date(raw.expiresAt).toISOString() : void 0
|
|
1824
|
-
});
|
|
1825
|
-
}
|
|
1826
|
-
const remainingText = userQuota ? `${userQuota.remaining.toFixed(2)} ${userQuota.unit} remaining` : org ? `${org.remaining.toFixed(2)} ${org.unit} remaining` : "";
|
|
1823
|
+
const org = pickBucket(raw, "orgResourcePackage") ?? pickBucket(raw, "sharedQuota");
|
|
1824
|
+
const resetAt = resetTimestamp(raw.expiresAt);
|
|
1825
|
+
const buckets = [
|
|
1826
|
+
{ id: "user-quota", label: "User Quota", quota: pickBucket(raw, "userQuota") },
|
|
1827
|
+
{ id: "add-on-quota", label: "Add-on", quota: pickBucket(raw, "addOnQuota") },
|
|
1828
|
+
{ id: "org-resource-package", label: "Org Resource Package", quota: org }
|
|
1829
|
+
].filter((entry) => hasAllowance(entry.quota));
|
|
1830
|
+
const usageBuckets = buckets.map(({ id, label, quota }) => ({
|
|
1831
|
+
id,
|
|
1832
|
+
label,
|
|
1833
|
+
usedDisplay: round2(num(quota?.used)).toFixed(2),
|
|
1834
|
+
limitDisplay: round2(num(quota?.total ?? quota?.cap)).toFixed(2),
|
|
1835
|
+
unit: quota?.unit || "credits",
|
|
1836
|
+
resetAt
|
|
1837
|
+
}));
|
|
1838
|
+
const remaining = buckets.reduce((sum, { quota }) => sum + Math.max(0, num(quota?.remaining)), 0);
|
|
1839
|
+
const unit = buckets[0]?.quota?.unit || "credits";
|
|
1827
1840
|
return {
|
|
1828
|
-
summary:
|
|
1841
|
+
summary: buckets.length > 0 ? `${round2(remaining)} ${unit} remaining` : "",
|
|
1829
1842
|
subscriptionTitle: region.usageTitle,
|
|
1830
|
-
resetAt
|
|
1843
|
+
resetAt,
|
|
1831
1844
|
manageUrl: region.manageUrl,
|
|
1832
1845
|
usageBuckets,
|
|
1833
1846
|
raw
|
|
@@ -2389,30 +2402,39 @@ function isCredentialExpiredError(error) {
|
|
|
2389
2402
|
|
|
2390
2403
|
// src/commands/usage.ts
|
|
2391
2404
|
init_region();
|
|
2392
|
-
|
|
2405
|
+
var DEFAULT_GRANT_CREDITS = 100;
|
|
2406
|
+
var DEFAULT_GRANT_VALIDITY_DAYS = 30;
|
|
2407
|
+
function positiveOr(value, fallback) {
|
|
2408
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
2409
|
+
}
|
|
2410
|
+
function estimateRollingAddOnExpiry(addOn, grant, now = Date.now()) {
|
|
2393
2411
|
if (!addOn || !addOn.total || addOn.total <= 0 || !addOn.remaining || addOn.remaining <= 0) {
|
|
2394
2412
|
return null;
|
|
2395
2413
|
}
|
|
2396
|
-
const
|
|
2397
|
-
const
|
|
2398
|
-
|
|
2414
|
+
const shape = typeof grant === "number" ? { expiryMs: grant } : grant ?? {};
|
|
2415
|
+
const packSize = positiveOr(shape.amount, DEFAULT_GRANT_CREDITS);
|
|
2416
|
+
const validityDays = positiveOr(shape.validityDays, DEFAULT_GRANT_VALIDITY_DAYS);
|
|
2417
|
+
const anchorMs = shape.expiryMs;
|
|
2418
|
+
if (typeof anchorMs !== "number" || !Number.isFinite(anchorMs) || anchorMs <= now) return null;
|
|
2419
|
+
if (addOn.total % packSize !== 0) return null;
|
|
2420
|
+
const totalPacks = Math.round(addOn.total / packSize);
|
|
2421
|
+
if (totalPacks < 1 || totalPacks > validityDays) return null;
|
|
2399
2422
|
const used = Math.max(0, addOn.used ?? 0);
|
|
2400
2423
|
const consumedPacks = Math.min(totalPacks - 1, Math.floor(used / packSize));
|
|
2401
|
-
const
|
|
2402
|
-
const
|
|
2403
|
-
const anchorExpiryMs = latestExpiryMs && Number.isFinite(latestExpiryMs) ? latestExpiryMs : now + 30 * 864e5;
|
|
2404
|
-
const earliestMs = anchorExpiryMs - daysAgoClaimed * 864e5;
|
|
2424
|
+
const daysAgoClaimed = totalPacks - 1 - consumedPacks;
|
|
2425
|
+
const earliestMs = anchorMs - daysAgoClaimed * 864e5;
|
|
2405
2426
|
const daysRemaining = Math.max(0, Math.round((earliestMs - now) / 864e5));
|
|
2406
2427
|
const earliestRemaining = Math.min(addOn.remaining, packSize - used % packSize);
|
|
2407
2428
|
const d = new Date(earliestMs);
|
|
2408
|
-
const earliestDate = d.toISOString().slice(0, 10);
|
|
2409
2429
|
return {
|
|
2410
|
-
earliestDate,
|
|
2430
|
+
earliestDate: d.toISOString().slice(0, 10),
|
|
2411
2431
|
earliestMs,
|
|
2412
2432
|
earliestRemaining,
|
|
2413
2433
|
totalPacks,
|
|
2414
2434
|
consumedPacks,
|
|
2415
|
-
daysRemaining
|
|
2435
|
+
daysRemaining,
|
|
2436
|
+
packSize,
|
|
2437
|
+
validityDays
|
|
2416
2438
|
};
|
|
2417
2439
|
}
|
|
2418
2440
|
var ANSI2 = {
|
|
@@ -2532,7 +2554,7 @@ function hasBucket(bucket) {
|
|
|
2532
2554
|
if (!bucket) return false;
|
|
2533
2555
|
return (bucket.total ?? 0) > 0 || (bucket.used ?? 0) > 0;
|
|
2534
2556
|
}
|
|
2535
|
-
function
|
|
2557
|
+
function pickBucket2(raw, camel) {
|
|
2536
2558
|
if (!raw) return void 0;
|
|
2537
2559
|
const snake = camel.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
|
2538
2560
|
return raw[snake] ?? raw[camel];
|
|
@@ -2542,17 +2564,17 @@ function formatQoderUsage(raw, mode, now = Date.now(), options = {}) {
|
|
|
2542
2564
|
const region = getQoderRegionConfig(mode);
|
|
2543
2565
|
const danger = Boolean(raw?.isQuotaExceeded);
|
|
2544
2566
|
const userType = raw?.userType ? ` (${raw.userType})` : "";
|
|
2545
|
-
const showUserQuota = hasBucket(
|
|
2546
|
-
const showAddOnQuota = hasBucket(
|
|
2547
|
-
const org =
|
|
2567
|
+
const showUserQuota = hasBucket(pickBucket2(raw, "userQuota"));
|
|
2568
|
+
const showAddOnQuota = hasBucket(pickBucket2(raw, "addOnQuota"));
|
|
2569
|
+
const org = pickBucket2(raw, "orgResourcePackage") ?? pickBucket2(raw, "sharedQuota");
|
|
2548
2570
|
const showOrg = hasBucket(org);
|
|
2549
2571
|
const orgPercent = typeof org?.used === "number" && typeof org?.cap === "number" && org.cap > 0 ? formatPercent(org.used / org.cap * 100) : void 0;
|
|
2550
2572
|
const overallPercent = formatPercent(
|
|
2551
2573
|
showOrg ? normalizePercent(raw?.totalUsagePercentage) || orgPercent : normalizePercent(raw?.totalUsagePercentage)
|
|
2552
2574
|
);
|
|
2553
2575
|
const rows = [{ label: "Overall", percent: overallPercent, tail: "used", danger }];
|
|
2554
|
-
if (showUserQuota) rows.push(bucketRow("Plan quota",
|
|
2555
|
-
if (showAddOnQuota) rows.push(bucketRow("Add-on",
|
|
2576
|
+
if (showUserQuota) rows.push(bucketRow("Plan quota", pickBucket2(raw, "userQuota"), danger));
|
|
2577
|
+
if (showAddOnQuota) rows.push(bucketRow("Add-on", pickBucket2(raw, "addOnQuota"), danger));
|
|
2556
2578
|
if (showOrg && org)
|
|
2557
2579
|
rows.push(bucketRow("Enterprise", { ...org, percentage: void 0, total: org.cap ?? org.total }, danger));
|
|
2558
2580
|
const isPersonalStandard = raw?.userType === "personal_standard" || raw?.userType === "free";
|
|
@@ -2592,16 +2614,19 @@ function formatQoderUsage(raw, mode, now = Date.now(), options = {}) {
|
|
|
2592
2614
|
});
|
|
2593
2615
|
}
|
|
2594
2616
|
}
|
|
2595
|
-
const addOn =
|
|
2617
|
+
const addOn = pickBucket2(raw, "addOnQuota");
|
|
2596
2618
|
if (showAddOnQuota && (addOn?.remaining ?? 0) > 0 && checkin) {
|
|
2597
|
-
const
|
|
2598
|
-
const
|
|
2619
|
+
const expiryMs = checkin.expiresAt ? Date.parse(checkin.expiresAt) : void 0;
|
|
2620
|
+
const grant = { expiryMs, amount: checkin.amount, validityDays: checkin.validityDays };
|
|
2621
|
+
const estimate = estimateRollingAddOnExpiry(addOn, grant, now);
|
|
2599
2622
|
if (estimate) {
|
|
2600
|
-
const
|
|
2623
|
+
const expiryText = estimate.totalPacks > 1 ? `earliest of ${estimate.totalPacks} daily ${estimate.packSize}-credit packs ~${estimate.earliestDate} (in ~${estimate.daysRemaining}d, ~${formatAmount(estimate.earliestRemaining)} credits)` : `${estimate.earliestDate} (in ${estimate.daysRemaining}d)`;
|
|
2601
2624
|
notes.push({
|
|
2602
2625
|
label: "Add-on expiry",
|
|
2603
|
-
value: `Rolling
|
|
2626
|
+
value: `Rolling ${estimate.validityDays}d \xB7 ${expiryText}`
|
|
2604
2627
|
});
|
|
2628
|
+
} else if (typeof expiryMs === "number" && Number.isFinite(expiryMs) && expiryMs > now) {
|
|
2629
|
+
notes.push({ label: "Add-on expiry", value: `${formatResetTime(expiryMs, now)} \xB7 latest grant` });
|
|
2605
2630
|
}
|
|
2606
2631
|
}
|
|
2607
2632
|
notes.push({ label: "Expires", value: formatResetTime(raw?.expiresAt, now) });
|
package/package.json
CHANGED