@openhoo/hoopilot 0.7.4 → 0.7.5
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 +1 -1
- package/dist/cli.js +71 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +71 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +71 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -126,10 +126,16 @@ interface RequestObservation {
|
|
|
126
126
|
/** One quota category (chat, completions, or premium_interactions/credits). */
|
|
127
127
|
interface CopilotQuota {
|
|
128
128
|
entitlement?: number;
|
|
129
|
+
hasQuota?: boolean;
|
|
129
130
|
overageCount?: number;
|
|
131
|
+
overageEntitlement?: number;
|
|
130
132
|
overagePermitted?: boolean;
|
|
131
133
|
percentRemaining?: number;
|
|
134
|
+
quotaId?: string;
|
|
135
|
+
quotaResetAt?: string;
|
|
132
136
|
remaining?: number;
|
|
137
|
+
timestampUtc?: string;
|
|
138
|
+
tokenBasedBilling?: boolean;
|
|
133
139
|
unlimited?: boolean;
|
|
134
140
|
used?: number;
|
|
135
141
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -126,10 +126,16 @@ interface RequestObservation {
|
|
|
126
126
|
/** One quota category (chat, completions, or premium_interactions/credits). */
|
|
127
127
|
interface CopilotQuota {
|
|
128
128
|
entitlement?: number;
|
|
129
|
+
hasQuota?: boolean;
|
|
129
130
|
overageCount?: number;
|
|
131
|
+
overageEntitlement?: number;
|
|
130
132
|
overagePermitted?: boolean;
|
|
131
133
|
percentRemaining?: number;
|
|
134
|
+
quotaId?: string;
|
|
135
|
+
quotaResetAt?: string;
|
|
132
136
|
remaining?: number;
|
|
137
|
+
timestampUtc?: string;
|
|
138
|
+
tokenBasedBilling?: boolean;
|
|
133
139
|
unlimited?: boolean;
|
|
134
140
|
used?: number;
|
|
135
141
|
}
|
package/dist/index.js
CHANGED
|
@@ -329,22 +329,31 @@ function normalizeCopilotUsage(body) {
|
|
|
329
329
|
}
|
|
330
330
|
function normalizeQuotaDetail(detail) {
|
|
331
331
|
const entitlement = numberOrUndefined(detail.entitlement);
|
|
332
|
+
const overageCount = numberOrUndefined(detail.overage_count);
|
|
332
333
|
const remaining = numberOrUndefined(detail.remaining) ?? numberOrUndefined(detail.quota_remaining);
|
|
333
334
|
return removeUndefinedQuota({
|
|
334
335
|
entitlement,
|
|
335
|
-
|
|
336
|
+
hasQuota: typeof detail.has_quota === "boolean" ? detail.has_quota : void 0,
|
|
337
|
+
overageCount,
|
|
338
|
+
overageEntitlement: numberOrUndefined(detail.overage_entitlement),
|
|
336
339
|
overagePermitted: typeof detail.overage_permitted === "boolean" ? detail.overage_permitted : void 0,
|
|
337
340
|
percentRemaining: numberOrUndefined(detail.percent_remaining),
|
|
341
|
+
quotaId: stringOrUndefined(detail.quota_id),
|
|
342
|
+
quotaResetAt: stringOrUndefined(detail.quota_reset_at),
|
|
338
343
|
remaining,
|
|
344
|
+
timestampUtc: stringOrUndefined(detail.timestamp_utc),
|
|
345
|
+
tokenBasedBilling: typeof detail.token_based_billing === "boolean" ? detail.token_based_billing : void 0,
|
|
339
346
|
unlimited: typeof detail.unlimited === "boolean" ? detail.unlimited : void 0,
|
|
340
|
-
used: usedFrom(entitlement, remaining)
|
|
347
|
+
used: usedFrom(entitlement, remaining, overageCount)
|
|
341
348
|
});
|
|
342
349
|
}
|
|
343
|
-
function usedFrom(entitlement, remaining) {
|
|
350
|
+
function usedFrom(entitlement, remaining, overageCount) {
|
|
344
351
|
if (entitlement === void 0 || remaining === void 0) {
|
|
345
352
|
return void 0;
|
|
346
353
|
}
|
|
347
|
-
|
|
354
|
+
const base = entitlement - remaining;
|
|
355
|
+
const overage = remaining === 0 ? overageCount ?? 0 : 0;
|
|
356
|
+
return Math.max(0, base + overage);
|
|
348
357
|
}
|
|
349
358
|
function numberOrUndefined(value) {
|
|
350
359
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
@@ -1642,11 +1651,43 @@ var MetricsRegistry = class {
|
|
|
1642
1651
|
gauge("remaining", "Remaining quota for the Copilot category.", (q) => q.remaining);
|
|
1643
1652
|
gauge("entitlement", "Quota entitlement for the Copilot category.", (q) => q.entitlement);
|
|
1644
1653
|
gauge("used", "Used quota (entitlement minus remaining) for the category.", (q) => q.used);
|
|
1654
|
+
gauge("overage_count", "Overage count for the Copilot category.", (q) => q.overageCount);
|
|
1655
|
+
gauge(
|
|
1656
|
+
"overage_entitlement",
|
|
1657
|
+
"Overage entitlement for the Copilot category.",
|
|
1658
|
+
(q) => q.overageEntitlement
|
|
1659
|
+
);
|
|
1645
1660
|
gauge(
|
|
1646
1661
|
"percent_remaining",
|
|
1647
1662
|
"Percent of quota remaining for the Copilot category.",
|
|
1648
1663
|
(q) => q.percentRemaining
|
|
1649
1664
|
);
|
|
1665
|
+
booleanGauge(
|
|
1666
|
+
"unlimited",
|
|
1667
|
+
"Whether the Copilot quota category is unlimited.",
|
|
1668
|
+
(q) => q.unlimited
|
|
1669
|
+
);
|
|
1670
|
+
booleanGauge(
|
|
1671
|
+
"overage_permitted",
|
|
1672
|
+
"Whether overage is permitted for the Copilot category.",
|
|
1673
|
+
(q) => q.overagePermitted
|
|
1674
|
+
);
|
|
1675
|
+
booleanGauge("has_quota", "Whether the Copilot quota category has a quota.", (q) => q.hasQuota);
|
|
1676
|
+
booleanGauge(
|
|
1677
|
+
"token_based_billing",
|
|
1678
|
+
"Whether the Copilot quota category uses token-based billing.",
|
|
1679
|
+
(q) => q.tokenBasedBilling
|
|
1680
|
+
);
|
|
1681
|
+
dateGauge(
|
|
1682
|
+
"category_reset_timestamp_seconds",
|
|
1683
|
+
"Unix epoch of the Copilot category-specific quota reset.",
|
|
1684
|
+
(q) => q.quotaResetAt
|
|
1685
|
+
);
|
|
1686
|
+
dateGauge(
|
|
1687
|
+
"category_snapshot_timestamp_seconds",
|
|
1688
|
+
"Unix epoch of the Copilot category quota snapshot.",
|
|
1689
|
+
(q) => q.timestampUtc
|
|
1690
|
+
);
|
|
1650
1691
|
const resetMs = usage.quotaResetDate ? Date.parse(usage.quotaResetDate) : Number.NaN;
|
|
1651
1692
|
if (Number.isFinite(resetMs)) {
|
|
1652
1693
|
lines.push(
|
|
@@ -1665,6 +1706,30 @@ var MetricsRegistry = class {
|
|
|
1665
1706
|
})} 1`
|
|
1666
1707
|
);
|
|
1667
1708
|
}
|
|
1709
|
+
function booleanGauge(suffix, help, pick) {
|
|
1710
|
+
const present = categories.filter(([, quota]) => pick(quota) !== void 0);
|
|
1711
|
+
if (present.length === 0) {
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
lines.push(`# HELP hoopilot_copilot_quota_${suffix} ${help}`);
|
|
1715
|
+
lines.push(`# TYPE hoopilot_copilot_quota_${suffix} gauge`);
|
|
1716
|
+
for (const [category, quota] of present) {
|
|
1717
|
+
lines.push(
|
|
1718
|
+
`hoopilot_copilot_quota_${suffix}${labels({ category })} ${pick(quota) ? 1 : 0}`
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
function dateGauge(suffix, help, pick) {
|
|
1723
|
+
const present = categories.map(([category, quota]) => [category, Date.parse(pick(quota) ?? "")]).filter(([, timestamp]) => Number.isFinite(timestamp));
|
|
1724
|
+
if (present.length === 0) {
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
lines.push(`# HELP hoopilot_copilot_quota_${suffix} ${help}`);
|
|
1728
|
+
lines.push(`# TYPE hoopilot_copilot_quota_${suffix} gauge`);
|
|
1729
|
+
for (const [category, timestamp] of present) {
|
|
1730
|
+
lines.push(`hoopilot_copilot_quota_${suffix}${labels({ category })} ${timestamp / 1e3}`);
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1668
1733
|
}
|
|
1669
1734
|
};
|
|
1670
1735
|
function observeResponseUsage(response, fallbackModel, onUsage, signal) {
|
|
@@ -2362,8 +2427,8 @@ function metricsResponse(metrics) {
|
|
|
2362
2427
|
});
|
|
2363
2428
|
}
|
|
2364
2429
|
async function handleUsage(metrics, readUsage, signal) {
|
|
2365
|
-
const proxy = metrics.snapshot();
|
|
2366
2430
|
const { copilot, error } = await readUsage(signal);
|
|
2431
|
+
const proxy = metrics.snapshot();
|
|
2367
2432
|
const body = { copilot: copilot ?? null, object: "usage", proxy };
|
|
2368
2433
|
if (error) {
|
|
2369
2434
|
body.copilot_error = error;
|
|
@@ -2388,10 +2453,10 @@ function createUsageReader(client, metrics, now = Date.now, ttlMs = USAGE_CACHE_
|
|
|
2388
2453
|
metrics.recordCopilotQuota(value);
|
|
2389
2454
|
return { copilot: value };
|
|
2390
2455
|
} catch (error) {
|
|
2391
|
-
metrics.recordUpstream(usagePath, false);
|
|
2392
2456
|
if (error instanceof CopilotAuthError) {
|
|
2393
2457
|
return { error: error.message };
|
|
2394
2458
|
}
|
|
2459
|
+
metrics.recordUpstream(usagePath, false);
|
|
2395
2460
|
return { error: errorMessage(error) };
|
|
2396
2461
|
}
|
|
2397
2462
|
};
|