@cad0p/pi-usage 0.11.5 → 0.11.6
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 +22 -0
- package/README.md +81 -39
- package/bin/piquota.js +12 -2
- package/extensions/quota-panel.ts +532 -184
- package/package.json +1 -1
- package/src/cache.js +128 -31
- package/src/cli/commands/omarchy.js +21 -3
- package/src/engine.js +98 -7
- package/src/local/pi-sessions.js +28 -1
- package/src/local/stats-worker.js +27 -0
- package/src/local/worker.js +157 -0
- package/src/model.js +39 -5
- package/src/omarchy/publish.js +9 -8
- package/src/overlay-keys.js +257 -0
- package/src/providers/antigravity-oauth.js +43 -3
- package/src/providers/antigravity.js +44 -5
- package/src/refresh.js +4 -1
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* Response shape: `groups[].buckets[]` with
|
|
12
12
|
* `{ bucketId, displayName, window, resetTime, remainingFraction, description }`.
|
|
13
13
|
*
|
|
14
|
-
* Google does not rotate this refresh token,
|
|
15
|
-
*
|
|
14
|
+
* Google does not rotate this refresh token, so an expired access token may be
|
|
15
|
+
* renewed in memory. The renewed value is cached only for this process lifetime.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { buildWindow, clampPercent, degradedResult, displayIdentity, finiteNumber, stringValue, windowFromName } from "../model.js";
|
|
18
|
+
import { buildWindow, clampPercent, degradedResult, displayIdentity, finiteNumber, identityKind, stringValue, windowFromName } from "../model.js";
|
|
19
19
|
import { requestJson } from "../http.js";
|
|
20
20
|
import { describeOAuthClient, ensureFreshAccessToken } from "./antigravity-oauth.js";
|
|
21
21
|
|
|
@@ -109,6 +109,24 @@ function windowFromBucket(bucket, context, now) {
|
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* The account line for a resolved project.
|
|
114
|
+
*
|
|
115
|
+
* Pi stores no e-mail for Antigravity, so the project id *is* the display
|
|
116
|
+
* identity; appending it again printed "project rising-f… · rising-f…". An
|
|
117
|
+
* account that has a better identity (an e-mail or an id) still gets the
|
|
118
|
+
* project, because the same login can hold several.
|
|
119
|
+
*
|
|
120
|
+
* @param {import("../auth/pi-auth.js").PiCredential} credential
|
|
121
|
+
* @param {string | null} projectId
|
|
122
|
+
* @returns {string}
|
|
123
|
+
*/
|
|
124
|
+
function accountLabel(credential, projectId) {
|
|
125
|
+
const identity = displayIdentity(credential);
|
|
126
|
+
if (!projectId || identityKind(credential) === "projectId") return identity;
|
|
127
|
+
return `${identity} · ${projectId.slice(0, 8)}…`;
|
|
128
|
+
}
|
|
129
|
+
|
|
112
130
|
/**
|
|
113
131
|
* @param {import("../auth/pi-auth.js").PiCredential} credential
|
|
114
132
|
* @param {{ now?: number, fetchFn?: typeof fetch, timeoutMs?: number, expiresInMin?: number | null, env?: Record<string, string | undefined>, refresh?: boolean }} [options]
|
|
@@ -139,7 +157,20 @@ export async function fetchQuota(credential, options = {}) {
|
|
|
139
157
|
timeoutMs: options.timeoutMs,
|
|
140
158
|
now,
|
|
141
159
|
enabled: options.refresh,
|
|
160
|
+
env: options.env,
|
|
161
|
+
cacheKey: `${credential.source}\\u0000${credential.identity}`,
|
|
142
162
|
});
|
|
163
|
+
// `expiresInMin` arrives from the engine as the freshness of the *stored*
|
|
164
|
+
// credential, and that is only the truth about this run when the refresh
|
|
165
|
+
// above did not happen: a token renewed in memory expires in an hour, so
|
|
166
|
+
// repeating the stored value made every surface print "token expired" (and
|
|
167
|
+
// the engine warn about it) next to healthy windows. A refresh that failed
|
|
168
|
+
// keeps the stored value — then the expiry claim is what the user must see.
|
|
169
|
+
const renewed = freshness.refreshed === true;
|
|
170
|
+
const expiresInMin = renewed ? null : options.expiresInMin ?? null;
|
|
171
|
+
// Present only when a renewal happened: an always-false field would be one
|
|
172
|
+
// more thing the JSON feed promises to keep.
|
|
173
|
+
const renewal = renewed ? { tokenRenewedInMemory: true } : {};
|
|
143
174
|
let projectId = credential.projectId ?? null;
|
|
144
175
|
|
|
145
176
|
/** @type {string | null} */
|
|
@@ -211,7 +242,9 @@ export async function fetchQuota(credential, options = {}) {
|
|
|
211
242
|
|
|
212
243
|
return {
|
|
213
244
|
...base,
|
|
214
|
-
account:
|
|
245
|
+
account: accountLabel(credential, projectId),
|
|
246
|
+
expiresInMin,
|
|
247
|
+
...renewal,
|
|
215
248
|
plan: stringValue(body.paidTier) ?? stringValue(body.currentTier),
|
|
216
249
|
windows,
|
|
217
250
|
error: null,
|
|
@@ -221,5 +254,11 @@ export async function fetchQuota(credential, options = {}) {
|
|
|
221
254
|
}
|
|
222
255
|
|
|
223
256
|
const suffix = authFailed ? ` (${describeOAuthClient({ env: options.env })})` : "";
|
|
224
|
-
return degradedResult({
|
|
257
|
+
return degradedResult({
|
|
258
|
+
...base,
|
|
259
|
+
account: accountLabel(credential, projectId),
|
|
260
|
+
expiresInMin,
|
|
261
|
+
...renewal,
|
|
262
|
+
error: `${lastError ?? "Antigravity quota unavailable"}${suffix}`,
|
|
263
|
+
});
|
|
225
264
|
}
|
package/src/refresh.js
CHANGED
|
@@ -278,7 +278,10 @@ export async function collectWithCadence(options) {
|
|
|
278
278
|
: null;
|
|
279
279
|
|
|
280
280
|
const report = mergeReports([cachedPart, fresh], { families, now, reused });
|
|
281
|
-
|
|
281
|
+
// The cache carries the same per-family clocks this layer decided on, so a
|
|
282
|
+
// reader that only sees the cache (the CLI, the extension's first frame)
|
|
283
|
+
// judges each family by the time it was actually fetched.
|
|
284
|
+
writeCache(report, { path: cachePath, now, fetchedAtMs });
|
|
282
285
|
writeRefreshState({ fetchedAtMs }, { statePath });
|
|
283
286
|
|
|
284
287
|
/** @type {Record<string, number>} */
|