sidekick-shared 0.28.2 → 0.28.3
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/CHANGELOG.md +19 -0
- package/README.md +29 -13
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +10 -1
- package/dist/codexQuota.js +17 -4
- package/dist/esm/browser.js +2 -0
- package/dist/esm/codexQuota.js +18 -5
- package/dist/esm/index.js +3 -3
- package/dist/esm/multiProviderQuotaService.js +1 -1
- package/dist/esm/quota.js +356 -24
- package/dist/esm/quotaHistory.js +33 -8
- package/dist/esm/quotaPoller.js +5 -2
- package/dist/esm/quotaResolver.js +31 -6
- package/dist/esm/quotaSnapshots.js +65 -10
- package/dist/esm/quotaThresholds.js +7 -2
- package/dist/esm/schemas/index.js +2 -2
- package/dist/esm/schemas/quota.js +30 -0
- package/dist/esm/schemas/quotaHistory.js +10 -2
- package/dist/esm/schemas/stateFile.js +9 -0
- package/dist/esm/stateFile.js +18 -3
- package/dist/esm/statusline/claudeStatuslinePayload.js +16 -4
- package/dist/esm/statusline/formatter.js +57 -18
- package/dist/esm/statusline/index.js +2 -2
- package/dist/esm/zaiQuotaApi.js +4 -2
- package/dist/index.d.ts +6 -6
- package/dist/index.js +18 -5
- package/dist/multiProviderQuotaService.js +1 -1
- package/dist/quota.d.ts +131 -1
- package/dist/quota.js +366 -24
- package/dist/quotaHistory.d.ts +10 -0
- package/dist/quotaHistory.js +34 -8
- package/dist/quotaPoller.d.ts +11 -3
- package/dist/quotaPoller.js +5 -2
- package/dist/quotaResolver.js +30 -5
- package/dist/quotaSnapshots.js +64 -9
- package/dist/quotaThresholds.js +7 -2
- package/dist/schemas/index.d.ts +3 -3
- package/dist/schemas/index.js +5 -2
- package/dist/schemas/quota.d.ts +258 -0
- package/dist/schemas/quota.js +31 -1
- package/dist/schemas/quotaHistory.d.ts +2 -0
- package/dist/schemas/quotaHistory.js +10 -2
- package/dist/schemas/stateFile.d.ts +34 -0
- package/dist/schemas/stateFile.js +10 -1
- package/dist/stateFile.d.ts +18 -0
- package/dist/stateFile.js +17 -2
- package/dist/statusline/claudeStatuslinePayload.d.ts +4 -3
- package/dist/statusline/claudeStatuslinePayload.js +16 -4
- package/dist/statusline/formatter.d.ts +5 -0
- package/dist/statusline/formatter.js +56 -17
- package/dist/statusline/index.d.ts +4 -4
- package/dist/statusline/index.js +5 -1
- package/dist/zaiQuotaApi.js +3 -1
- package/package.json +1 -1
package/dist/stateFile.js
CHANGED
|
@@ -131,14 +131,29 @@ function quotaToStateFile(quota, now = Date.now()) {
|
|
|
131
131
|
freshness ??= (0, quota_1.classifyQuotaFreshness)(ageMs);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
+
const extraLimits = (0, quota_1.extraQuotaRows)(quota).map((row) => ({
|
|
135
|
+
kind: row.kind,
|
|
136
|
+
label: row.label,
|
|
137
|
+
utilization: row.utilization,
|
|
138
|
+
resetsAt: row.resetsAt,
|
|
139
|
+
}));
|
|
134
140
|
return {
|
|
135
|
-
fiveHour:
|
|
136
|
-
sevenDay:
|
|
141
|
+
fiveHour: stateFileWindow(quota.fiveHour),
|
|
142
|
+
sevenDay: stateFileWindow(quota.sevenDay),
|
|
137
143
|
source: quota.source ?? null,
|
|
138
144
|
capturedSource: quota.capturedSource ?? null,
|
|
139
145
|
capturedAt: quota.capturedAt ?? null,
|
|
140
146
|
ageMs,
|
|
141
147
|
freshness,
|
|
148
|
+
...(quota.planLabel ? { planLabel: quota.planLabel } : {}),
|
|
149
|
+
...(extraLimits.length > 0 ? { extraLimits } : {}),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function stateFileWindow(window) {
|
|
153
|
+
return {
|
|
154
|
+
utilization: window.utilization,
|
|
155
|
+
resetsAt: window.resetsAt,
|
|
156
|
+
...(window.absent ? { absent: true } : {}),
|
|
142
157
|
};
|
|
143
158
|
}
|
|
144
159
|
/** Project a billing block onto the state-file shape (totals only). */
|
|
@@ -74,9 +74,10 @@ export interface QuotaFromStatuslineOptions {
|
|
|
74
74
|
/** Capture time; defaults to now. */
|
|
75
75
|
now?: Date;
|
|
76
76
|
/**
|
|
77
|
-
* A previously known quota (typically the persisted snapshot).
|
|
78
|
-
* payload omits
|
|
79
|
-
*
|
|
77
|
+
* A previously known quota (typically the persisted snapshot). A window the
|
|
78
|
+
* payload omits is carried over from it while the fallback window has not
|
|
79
|
+
* reset yet, or when the fallback marks it `absent` (the plan has no such
|
|
80
|
+
* window, e.g. Ultra's missing five-hour limit).
|
|
80
81
|
*/
|
|
81
82
|
fallback?: QuotaState | null;
|
|
82
83
|
}
|
|
@@ -119,14 +119,26 @@ function parseClaudeStatuslinePayload(text) {
|
|
|
119
119
|
raw,
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Claude Code leaves a window out of the document once its reset has passed,
|
|
124
|
+
* and always for a window the plan does not have (Ultra has no five-hour
|
|
125
|
+
* limit). A fallback is carried over only while it can still be current: an
|
|
126
|
+
* `absent` marker from an earlier API read, or a window that has not reset yet.
|
|
127
|
+
* An expired fallback would otherwise be re-saved as a fresh sample forever.
|
|
128
|
+
*/
|
|
129
|
+
function toWindow(live, fallback, nowMs) {
|
|
123
130
|
if (live) {
|
|
124
131
|
return {
|
|
125
132
|
utilization: Math.max(0, live.usedPercentage),
|
|
126
133
|
resetsAt: new Date(live.resetsAt * 1000).toISOString(),
|
|
127
134
|
};
|
|
128
135
|
}
|
|
129
|
-
|
|
136
|
+
if (fallback?.absent)
|
|
137
|
+
return { utilization: 0, resetsAt: '', absent: true };
|
|
138
|
+
const fallbackResetMs = fallback ? Date.parse(fallback.resetsAt) : NaN;
|
|
139
|
+
if (fallback && Number.isFinite(fallbackResetMs) && fallbackResetMs > nowMs)
|
|
140
|
+
return fallback;
|
|
141
|
+
return { utilization: 0, resetsAt: '' };
|
|
130
142
|
}
|
|
131
143
|
/**
|
|
132
144
|
* Build a `QuotaState` from the official rate-limit block. Returns `null`
|
|
@@ -141,8 +153,8 @@ function quotaFromStatuslinePayload(payload, options = {}) {
|
|
|
141
153
|
const now = options.now ?? new Date();
|
|
142
154
|
const fallback = options.fallback ?? undefined;
|
|
143
155
|
return {
|
|
144
|
-
fiveHour: toWindow(limits.fiveHour, fallback?.fiveHour),
|
|
145
|
-
sevenDay: toWindow(limits.sevenDay, fallback?.sevenDay),
|
|
156
|
+
fiveHour: toWindow(limits.fiveHour, fallback?.fiveHour, now.getTime()),
|
|
157
|
+
sevenDay: toWindow(limits.sevenDay, fallback?.sevenDay, now.getTime()),
|
|
146
158
|
available: true,
|
|
147
159
|
providerId: 'claude-code',
|
|
148
160
|
source: 'statusline',
|
|
@@ -23,6 +23,11 @@ export declare function selectStatuslineAccount(input: StatuslineInput): Statusl
|
|
|
23
23
|
* One-line status. Segments, in order, each omitted when unknown:
|
|
24
24
|
* `acct:<label> · 5h 42% resets 14:00 · ~1h20m left · 7d 61% · (2h ago) · ctx 37% · $0.42 · cache 92%`
|
|
25
25
|
*
|
|
26
|
+
* Plans without a five-hour window (Claude Ultra) lead with the weekly window
|
|
27
|
+
* instead: `acct:<label> · 7d 17% resets Fri 01:00 · ~2d3h left · …`. Window
|
|
28
|
+
* labels follow the reported window length, so a Codex weekly primary window
|
|
29
|
+
* reads `7d`, not `5h`.
|
|
30
|
+
*
|
|
26
31
|
* The age segment appears only for cached quota older than five minutes, so
|
|
27
32
|
* a snapshot from yesterday can no longer read like a live figure.
|
|
28
33
|
*/
|
|
@@ -27,6 +27,11 @@ function selectStatuslineAccount(input) {
|
|
|
27
27
|
* One-line status. Segments, in order, each omitted when unknown:
|
|
28
28
|
* `acct:<label> · 5h 42% resets 14:00 · ~1h20m left · 7d 61% · (2h ago) · ctx 37% · $0.42 · cache 92%`
|
|
29
29
|
*
|
|
30
|
+
* Plans without a five-hour window (Claude Ultra) lead with the weekly window
|
|
31
|
+
* instead: `acct:<label> · 7d 17% resets Fri 01:00 · ~2d3h left · …`. Window
|
|
32
|
+
* labels follow the reported window length, so a Codex weekly primary window
|
|
33
|
+
* reads `7d`, not `5h`.
|
|
34
|
+
*
|
|
30
35
|
* The age segment appears only for cached quota older than five minutes, so
|
|
31
36
|
* a snapshot from yesterday can no longer read like a live figure.
|
|
32
37
|
*/
|
|
@@ -41,20 +46,35 @@ function formatStatusline(input) {
|
|
|
41
46
|
if (!quota?.available) {
|
|
42
47
|
return joinSegments([`acct:${account}`, 'quota unavailable', ...liveSegments]);
|
|
43
48
|
}
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
const first = describeWindow(quota.fiveHour, '5h', quota_1.FIVE_HOUR_WINDOW_MS);
|
|
50
|
+
const second = describeWindow(quota.sevenDay, '7d', quota_1.SEVEN_DAY_WINDOW_MS);
|
|
51
|
+
// Lead with the first window whenever the plan has it (even idle); fall back
|
|
52
|
+
// to the second window when the first does not exist for this plan.
|
|
53
|
+
const leadWithFirst = (0, quota_1.quotaWindowApplies)(quota.fiveHour) || !(0, quota_1.quotaWindowHasData)(quota.sevenDay);
|
|
54
|
+
const lead = leadWithFirst ? first : second;
|
|
55
|
+
const segments = [`acct:${account}`, formatLeadSegment(lead, now)];
|
|
56
|
+
const eta = estimateWindowEta(lead, quota.capturedAt, now);
|
|
48
57
|
if (eta != null)
|
|
49
58
|
segments.push(`~${formatMinutes(eta)} left`);
|
|
50
|
-
if (quota.sevenDay
|
|
51
|
-
segments.push(
|
|
59
|
+
if (leadWithFirst && (0, quota_1.quotaWindowHasData)(quota.sevenDay) && quota.sevenDay.utilization > 0) {
|
|
60
|
+
segments.push(`${second.label} ${Math.round(clampPercent(quota.sevenDay.utilization))}%`);
|
|
52
61
|
}
|
|
53
62
|
if (quota.freshness && quota.freshness !== 'fresh') {
|
|
54
63
|
segments.push(`(${(0, quota_1.formatQuotaAge)(quota.ageMs)})`);
|
|
55
64
|
}
|
|
56
65
|
return joinSegments([...segments, ...liveSegments]);
|
|
57
66
|
}
|
|
67
|
+
function describeWindow(window, label, defaultMs) {
|
|
68
|
+
const windowMs = typeof window.windowMs === 'number' && Number.isFinite(window.windowMs) && window.windowMs > 0
|
|
69
|
+
? window.windowMs
|
|
70
|
+
: defaultMs;
|
|
71
|
+
return { label: (0, quota_1.quotaWindowShortLabel)(window.windowMs, label), window, windowMs };
|
|
72
|
+
}
|
|
73
|
+
function formatLeadSegment(lead, now) {
|
|
74
|
+
const percent = `${lead.label} ${Math.round(clampPercent(lead.window.utilization))}%`;
|
|
75
|
+
const reset = formatReset(lead.window.resetsAt, now);
|
|
76
|
+
return reset ? `${percent} resets ${reset}` : percent;
|
|
77
|
+
}
|
|
58
78
|
function formatLiveSegments(live) {
|
|
59
79
|
if (!live)
|
|
60
80
|
return [];
|
|
@@ -80,22 +100,25 @@ function formatCost(value) {
|
|
|
80
100
|
return value.toFixed(1);
|
|
81
101
|
return value.toFixed(2);
|
|
82
102
|
}
|
|
83
|
-
function estimateWindowEta(
|
|
84
|
-
const
|
|
103
|
+
function estimateWindowEta(lead, capturedAtIso, now) {
|
|
104
|
+
const { window, windowMs } = lead;
|
|
105
|
+
if (window.absent)
|
|
106
|
+
return null;
|
|
107
|
+
const resetAt = Date.parse(window.resetsAt);
|
|
85
108
|
if (!Number.isFinite(resetAt))
|
|
86
109
|
return null;
|
|
87
110
|
const nowMs = now.getTime();
|
|
88
111
|
if (resetAt <= nowMs)
|
|
89
112
|
return null;
|
|
90
|
-
const capturedAt =
|
|
113
|
+
const capturedAt = capturedAtIso ? Date.parse(capturedAtIso) : now.getTime();
|
|
91
114
|
const sampleAt = Number.isFinite(capturedAt) ? capturedAt : now.getTime();
|
|
92
115
|
if (sampleAt >= resetAt)
|
|
93
116
|
return null;
|
|
94
|
-
const elapsedMinutes = (sampleAt - (resetAt -
|
|
95
|
-
if (elapsedMinutes <= 0 ||
|
|
117
|
+
const elapsedMinutes = (sampleAt - (resetAt - windowMs)) / 60_000;
|
|
118
|
+
if (elapsedMinutes <= 0 || window.utilization <= 0)
|
|
96
119
|
return null;
|
|
97
|
-
const burnRate =
|
|
98
|
-
const eta = (0, BurnRateCalculator_1.estimateTimeToQuota)(
|
|
120
|
+
const burnRate = window.utilization / elapsedMinutes;
|
|
121
|
+
const eta = (0, BurnRateCalculator_1.estimateTimeToQuota)(window.utilization, 100, burnRate);
|
|
99
122
|
const minutesUntilReset = (resetAt - nowMs) / 60_000;
|
|
100
123
|
return eta !== null && eta < minutesUntilReset ? eta : null;
|
|
101
124
|
}
|
|
@@ -107,20 +130,36 @@ function compactLabel(value) {
|
|
|
107
130
|
function clampPercent(value) {
|
|
108
131
|
return Number.isFinite(value) ? Math.min(100, Math.max(0, value)) : 0;
|
|
109
132
|
}
|
|
110
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Reset time as `HH:MM`, or `Fri 01:00` when it is more than a day away.
|
|
135
|
+
* Returns '' for an empty or unparseable value — never the current time.
|
|
136
|
+
*/
|
|
137
|
+
function formatReset(value, now) {
|
|
138
|
+
if (!value)
|
|
139
|
+
return '';
|
|
111
140
|
const reset = new Date(value);
|
|
112
|
-
|
|
113
|
-
|
|
141
|
+
if (Number.isNaN(reset.getTime()))
|
|
142
|
+
return '';
|
|
143
|
+
const time = new Intl.DateTimeFormat(undefined, {
|
|
114
144
|
hour: '2-digit',
|
|
115
145
|
minute: '2-digit',
|
|
116
146
|
hour12: false,
|
|
117
|
-
}).format(
|
|
147
|
+
}).format(reset);
|
|
148
|
+
if (reset.getTime() - now.getTime() <= 86_400_000)
|
|
149
|
+
return time;
|
|
150
|
+
const weekday = new Intl.DateTimeFormat(undefined, { weekday: 'short' }).format(reset);
|
|
151
|
+
return `${weekday} ${time}`;
|
|
118
152
|
}
|
|
119
153
|
function formatMinutes(value) {
|
|
120
154
|
const minutes = Math.max(0, Math.round(value));
|
|
121
155
|
if (minutes < 60)
|
|
122
156
|
return `${minutes}min`;
|
|
123
157
|
const hours = Math.floor(minutes / 60);
|
|
158
|
+
if (hours >= 48) {
|
|
159
|
+
const days = Math.floor(hours / 24);
|
|
160
|
+
const remainderHours = hours % 24;
|
|
161
|
+
return remainderHours ? `${days}d${remainderHours}h` : `${days}d`;
|
|
162
|
+
}
|
|
124
163
|
const remainder = minutes % 60;
|
|
125
164
|
return remainder ? `${hours}h${remainder}m` : `${hours}h`;
|
|
126
165
|
}
|
|
@@ -2,14 +2,14 @@ export { getActiveAccountStatus } from '../accountStatus';
|
|
|
2
2
|
export type { ActiveAccountStatus, ActiveAccountStatusOptions, ActiveProviderAccountStatus, } from '../accountStatus';
|
|
3
3
|
export { readQuotaSnapshot, writeQuotaSnapshot } from '../quotaSnapshots';
|
|
4
4
|
export type { QuotaSnapshotProviderId } from '../quotaSnapshots';
|
|
5
|
-
export { appendQuotaHistorySample, getWorkspaceIdFromPath } from '../quotaHistory';
|
|
5
|
+
export { appendQuotaHistorySample, getWorkspaceIdFromPath, quotaHistoryWindow, } from '../quotaHistory';
|
|
6
6
|
export type { QuotaHistorySample } from '../quotaHistory';
|
|
7
|
-
export { classifyQuotaFreshness, formatQuotaAge } from '../quota';
|
|
8
|
-
export type { QuotaFreshness, QuotaState } from '../quota';
|
|
7
|
+
export { classifyQuotaFreshness, formatQuotaAge, quotaWindowApplies, quotaWindowHasData, quotaWindowShortLabel, } from '../quota';
|
|
8
|
+
export type { QuotaFreshness, QuotaState, QuotaWindow } from '../quota';
|
|
9
9
|
export { BurnRateCalculator, estimateTimeToQuota } from './BurnRateCalculator';
|
|
10
10
|
export { formatStatusline, selectStatuslineAccount } from './formatter';
|
|
11
11
|
export type { StatuslineInput, StatuslineSelection } from './formatter';
|
|
12
12
|
export { parseClaudeStatuslinePayload, quotaFromStatuslinePayload, } from './claudeStatuslinePayload';
|
|
13
13
|
export type { ClaudeStatuslinePayload, ClaudeStatuslineRateLimitWindow, QuotaFromStatuslineOptions, } from './claudeStatuslinePayload';
|
|
14
14
|
export { STATE_FILE_NAME, STATE_FILE_SCHEMA_VERSION, billingBlockToStateFile, getStateFilePath, quotaToStateFile, readStateFile, writeStateFile, } from '../stateFile';
|
|
15
|
-
export type { SidekickStateFile, SidekickStateInput, StateFileAccount, StateFileBillingBlock, StateFileContext, StateFileQuota, StateFileQuotaWindow, StateFileSession, StateFileWriter, WriteStateFileOptions, } from '../stateFile';
|
|
15
|
+
export type { SidekickStateFile, SidekickStateInput, StateFileAccount, StateFileBillingBlock, StateFileContext, StateFileQuota, StateFileQuotaLimit, StateFileQuotaWindow, StateFileSession, StateFileWriter, WriteStateFileOptions, } from '../stateFile';
|
package/dist/statusline/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.writeStateFile = exports.readStateFile = exports.quotaToStateFile = exports.getStateFilePath = exports.billingBlockToStateFile = exports.STATE_FILE_SCHEMA_VERSION = exports.STATE_FILE_NAME = exports.quotaFromStatuslinePayload = exports.parseClaudeStatuslinePayload = exports.selectStatuslineAccount = exports.formatStatusline = exports.estimateTimeToQuota = exports.BurnRateCalculator = exports.formatQuotaAge = exports.classifyQuotaFreshness = exports.getWorkspaceIdFromPath = exports.appendQuotaHistorySample = exports.writeQuotaSnapshot = exports.readQuotaSnapshot = exports.getActiveAccountStatus = void 0;
|
|
3
|
+
exports.writeStateFile = exports.readStateFile = exports.quotaToStateFile = exports.getStateFilePath = exports.billingBlockToStateFile = exports.STATE_FILE_SCHEMA_VERSION = exports.STATE_FILE_NAME = exports.quotaFromStatuslinePayload = exports.parseClaudeStatuslinePayload = exports.selectStatuslineAccount = exports.formatStatusline = exports.estimateTimeToQuota = exports.BurnRateCalculator = exports.quotaWindowShortLabel = exports.quotaWindowHasData = exports.quotaWindowApplies = exports.formatQuotaAge = exports.classifyQuotaFreshness = exports.quotaHistoryWindow = exports.getWorkspaceIdFromPath = exports.appendQuotaHistorySample = exports.writeQuotaSnapshot = exports.readQuotaSnapshot = exports.getActiveAccountStatus = void 0;
|
|
4
4
|
var accountStatus_1 = require("../accountStatus");
|
|
5
5
|
Object.defineProperty(exports, "getActiveAccountStatus", { enumerable: true, get: function () { return accountStatus_1.getActiveAccountStatus; } });
|
|
6
6
|
var quotaSnapshots_1 = require("../quotaSnapshots");
|
|
@@ -9,9 +9,13 @@ Object.defineProperty(exports, "writeQuotaSnapshot", { enumerable: true, get: fu
|
|
|
9
9
|
var quotaHistory_1 = require("../quotaHistory");
|
|
10
10
|
Object.defineProperty(exports, "appendQuotaHistorySample", { enumerable: true, get: function () { return quotaHistory_1.appendQuotaHistorySample; } });
|
|
11
11
|
Object.defineProperty(exports, "getWorkspaceIdFromPath", { enumerable: true, get: function () { return quotaHistory_1.getWorkspaceIdFromPath; } });
|
|
12
|
+
Object.defineProperty(exports, "quotaHistoryWindow", { enumerable: true, get: function () { return quotaHistory_1.quotaHistoryWindow; } });
|
|
12
13
|
var quota_1 = require("../quota");
|
|
13
14
|
Object.defineProperty(exports, "classifyQuotaFreshness", { enumerable: true, get: function () { return quota_1.classifyQuotaFreshness; } });
|
|
14
15
|
Object.defineProperty(exports, "formatQuotaAge", { enumerable: true, get: function () { return quota_1.formatQuotaAge; } });
|
|
16
|
+
Object.defineProperty(exports, "quotaWindowApplies", { enumerable: true, get: function () { return quota_1.quotaWindowApplies; } });
|
|
17
|
+
Object.defineProperty(exports, "quotaWindowHasData", { enumerable: true, get: function () { return quota_1.quotaWindowHasData; } });
|
|
18
|
+
Object.defineProperty(exports, "quotaWindowShortLabel", { enumerable: true, get: function () { return quota_1.quotaWindowShortLabel; } });
|
|
15
19
|
var BurnRateCalculator_1 = require("./BurnRateCalculator");
|
|
16
20
|
Object.defineProperty(exports, "BurnRateCalculator", { enumerable: true, get: function () { return BurnRateCalculator_1.BurnRateCalculator; } });
|
|
17
21
|
Object.defineProperty(exports, "estimateTimeToQuota", { enumerable: true, get: function () { return BurnRateCalculator_1.estimateTimeToQuota; } });
|
package/dist/zaiQuotaApi.js
CHANGED
|
@@ -267,7 +267,9 @@ async function resolveZaiQuota(options = {}) {
|
|
|
267
267
|
return enrichZaiQuota(apiQuota);
|
|
268
268
|
}
|
|
269
269
|
const cached = readSnapshot('zai', accountId);
|
|
270
|
-
|
|
270
|
+
// Every window of the cached sample has reset since it was taken: it would
|
|
271
|
+
// only show old percentages with "resets now", so report the API failure.
|
|
272
|
+
if (cached && !(0, quota_1.quotaSampleExpired)(cached)) {
|
|
271
273
|
return enrichZaiQuota({
|
|
272
274
|
...cached,
|
|
273
275
|
providerId: 'zai',
|