pi-provider-qoder-cn 0.2.17 → 0.2.18

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.
Files changed (2) hide show
  1. package/dist/index.js +47 -34
  2. package/package.json +1 -1
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 usageBuckets = [];
1803
- const userQuota = raw.user_quota ?? raw.userQuota;
1804
- const org = raw.org_resource_package ?? raw.orgResourcePackage ?? raw.shared_quota ?? raw.sharedQuota;
1805
- if (userQuota) {
1806
- usageBuckets.push({
1807
- id: "user-quota",
1808
- label: "User Quota",
1809
- usedDisplay: userQuota.used.toFixed(2),
1810
- limitDisplay: (userQuota.total ?? userQuota.cap ?? 0).toFixed(2),
1811
- unit: userQuota.unit,
1812
- resetAt: raw.expiresAt ? new Date(raw.expiresAt).toISOString() : void 0
1813
- });
1814
- }
1815
- const orgLimit = org?.cap ?? org?.total ?? 0;
1816
- if (org && orgLimit > 0) {
1817
- usageBuckets.push({
1818
- id: "org-resource-package",
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: remainingText,
1841
+ summary: buckets.length > 0 ? `${round2(remaining)} ${unit} remaining` : "",
1829
1842
  subscriptionTitle: region.usageTitle,
1830
- resetAt: raw.expiresAt ? new Date(raw.expiresAt).toISOString() : void 0,
1843
+ resetAt,
1831
1844
  manageUrl: region.manageUrl,
1832
1845
  usageBuckets,
1833
1846
  raw
@@ -2532,7 +2545,7 @@ function hasBucket(bucket) {
2532
2545
  if (!bucket) return false;
2533
2546
  return (bucket.total ?? 0) > 0 || (bucket.used ?? 0) > 0;
2534
2547
  }
2535
- function pickBucket(raw, camel) {
2548
+ function pickBucket2(raw, camel) {
2536
2549
  if (!raw) return void 0;
2537
2550
  const snake = camel.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
2538
2551
  return raw[snake] ?? raw[camel];
@@ -2542,17 +2555,17 @@ function formatQoderUsage(raw, mode, now = Date.now(), options = {}) {
2542
2555
  const region = getQoderRegionConfig(mode);
2543
2556
  const danger = Boolean(raw?.isQuotaExceeded);
2544
2557
  const userType = raw?.userType ? ` (${raw.userType})` : "";
2545
- const showUserQuota = hasBucket(pickBucket(raw, "userQuota"));
2546
- const showAddOnQuota = hasBucket(pickBucket(raw, "addOnQuota"));
2547
- const org = pickBucket(raw, "orgResourcePackage") ?? pickBucket(raw, "sharedQuota");
2558
+ const showUserQuota = hasBucket(pickBucket2(raw, "userQuota"));
2559
+ const showAddOnQuota = hasBucket(pickBucket2(raw, "addOnQuota"));
2560
+ const org = pickBucket2(raw, "orgResourcePackage") ?? pickBucket2(raw, "sharedQuota");
2548
2561
  const showOrg = hasBucket(org);
2549
2562
  const orgPercent = typeof org?.used === "number" && typeof org?.cap === "number" && org.cap > 0 ? formatPercent(org.used / org.cap * 100) : void 0;
2550
2563
  const overallPercent = formatPercent(
2551
2564
  showOrg ? normalizePercent(raw?.totalUsagePercentage) || orgPercent : normalizePercent(raw?.totalUsagePercentage)
2552
2565
  );
2553
2566
  const rows = [{ label: "Overall", percent: overallPercent, tail: "used", danger }];
2554
- if (showUserQuota) rows.push(bucketRow("Plan quota", pickBucket(raw, "userQuota"), danger));
2555
- if (showAddOnQuota) rows.push(bucketRow("Add-on", pickBucket(raw, "addOnQuota"), danger));
2567
+ if (showUserQuota) rows.push(bucketRow("Plan quota", pickBucket2(raw, "userQuota"), danger));
2568
+ if (showAddOnQuota) rows.push(bucketRow("Add-on", pickBucket2(raw, "addOnQuota"), danger));
2556
2569
  if (showOrg && org)
2557
2570
  rows.push(bucketRow("Enterprise", { ...org, percentage: void 0, total: org.cap ?? org.total }, danger));
2558
2571
  const isPersonalStandard = raw?.userType === "personal_standard" || raw?.userType === "free";
@@ -2592,7 +2605,7 @@ function formatQoderUsage(raw, mode, now = Date.now(), options = {}) {
2592
2605
  });
2593
2606
  }
2594
2607
  }
2595
- const addOn = pickBucket(raw, "addOnQuota");
2608
+ const addOn = pickBucket2(raw, "addOnQuota");
2596
2609
  if (showAddOnQuota && (addOn?.remaining ?? 0) > 0 && checkin) {
2597
2610
  const latestExpiryMs = checkin.expiresAt ? Date.parse(checkin.expiresAt) : void 0;
2598
2611
  const estimate = estimateRollingAddOnExpiry(addOn, latestExpiryMs, now);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-provider-qoder-cn",
3
- "version": "0.2.17",
3
+ "version": "0.2.18",
4
4
  "description": "Pi extension for Qoder CN — PAT/OAuth auth, /qoder-cn.usage quota command, and enterprise VPC endpoint support",
5
5
  "type": "module",
6
6
  "license": "MIT",