@cortexkit/antigravity-auth-core 1.1.0 → 2.0.0
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/dist/account-manager.d.ts +281 -0
- package/dist/account-manager.d.ts.map +1 -0
- package/dist/account-manager.js +1378 -0
- package/dist/account-manager.js.map +1 -0
- package/dist/account-storage.d.ts +162 -0
- package/dist/account-storage.d.ts.map +1 -0
- package/dist/account-storage.js +635 -0
- package/dist/account-storage.js.map +1 -0
- package/dist/account-types.d.ts +136 -0
- package/dist/account-types.d.ts.map +1 -0
- package/dist/account-types.js +9 -0
- package/dist/account-types.js.map +1 -0
- package/dist/agy-request-metadata.d.ts +12 -5
- package/dist/agy-request-metadata.d.ts.map +1 -1
- package/dist/agy-request-metadata.js +64 -38
- package/dist/agy-request-metadata.js.map +1 -1
- package/dist/agy-transport.d.ts +2 -2
- package/dist/agy-transport.d.ts.map +1 -1
- package/dist/agy-transport.js +87 -74
- package/dist/agy-transport.js.map +1 -1
- package/dist/antigravity/oauth.d.ts +3 -2
- package/dist/antigravity/oauth.d.ts.map +1 -1
- package/dist/antigravity/oauth.js +65 -55
- package/dist/antigravity/oauth.js.map +1 -1
- package/dist/atomic-write.d.ts +23 -0
- package/dist/atomic-write.d.ts.map +1 -0
- package/dist/atomic-write.js +47 -0
- package/dist/atomic-write.js.map +1 -0
- package/dist/auth-types.d.ts +2 -2
- package/dist/auth-types.d.ts.map +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +9 -6
- package/dist/auth.js.map +1 -1
- package/dist/constants.d.ts +19 -12
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +51 -39
- package/dist/constants.js.map +1 -1
- package/dist/fetch-timeout.d.ts +26 -0
- package/dist/fetch-timeout.d.ts.map +1 -0
- package/dist/fetch-timeout.js +43 -0
- package/dist/fetch-timeout.js.map +1 -0
- package/dist/file-lock.d.ts +79 -0
- package/dist/file-lock.d.ts.map +1 -0
- package/dist/file-lock.js +438 -0
- package/dist/file-lock.js.map +1 -0
- package/dist/fingerprint.d.ts +9 -3
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +28 -20
- package/dist/fingerprint.js.map +1 -1
- package/dist/index.d.ts +23 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -9
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +10 -10
- package/dist/logger.js.map +1 -1
- package/dist/model-registry.d.ts +5 -5
- package/dist/model-registry.d.ts.map +1 -1
- package/dist/model-registry.js +107 -106
- package/dist/model-registry.js.map +1 -1
- package/dist/project.d.ts +1 -1
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +53 -25
- package/dist/project.js.map +1 -1
- package/dist/quota-manager.d.ts +140 -0
- package/dist/quota-manager.d.ts.map +1 -0
- package/dist/quota-manager.js +481 -0
- package/dist/quota-manager.js.map +1 -0
- package/dist/quota-types.d.ts +49 -0
- package/dist/quota-types.d.ts.map +1 -0
- package/dist/quota-types.js +10 -0
- package/dist/quota-types.js.map +1 -0
- package/dist/rotation.d.ts +175 -0
- package/dist/rotation.d.ts.map +1 -0
- package/dist/rotation.js +391 -0
- package/dist/rotation.js.map +1 -0
- package/dist/transform/claude.d.ts +1 -1
- package/dist/transform/claude.d.ts.map +1 -1
- package/dist/transform/claude.js +63 -41
- package/dist/transform/claude.js.map +1 -1
- package/dist/transform/cross-model-sanitizer.d.ts +1 -1
- package/dist/transform/cross-model-sanitizer.d.ts.map +1 -1
- package/dist/transform/cross-model-sanitizer.js +19 -16
- package/dist/transform/cross-model-sanitizer.js.map +1 -1
- package/dist/transform/gemini.d.ts +1 -1
- package/dist/transform/gemini.d.ts.map +1 -1
- package/dist/transform/gemini.js +111 -85
- package/dist/transform/gemini.js.map +1 -1
- package/dist/transform/index.d.ts +9 -9
- package/dist/transform/index.d.ts.map +1 -1
- package/dist/transform/index.js +6 -6
- package/dist/transform/index.js.map +1 -1
- package/dist/transform/model-resolver.d.ts +5 -5
- package/dist/transform/model-resolver.d.ts.map +1 -1
- package/dist/transform/model-resolver.js +97 -75
- package/dist/transform/model-resolver.js.map +1 -1
- package/dist/transform/types.d.ts +5 -5
- package/dist/transform/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +14 -16
- package/dist/version.js.map +1 -1
- package/package.json +16 -10
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renewable fenced file lock.
|
|
3
|
+
*
|
|
4
|
+
* The lock file at `${path}.${name}.lock` holds the JSON
|
|
5
|
+
* `{ ownerId, expiresAt }`. Acquiring it uses an exclusive `wx` write so
|
|
6
|
+
* concurrent processes race deterministically — only one wins.
|
|
7
|
+
*
|
|
8
|
+
* A contended, live lock (ownerId present, expiresAt > now) returns
|
|
9
|
+
* `null` immediately; no eviction is attempted and no destructive op
|
|
10
|
+
* touches the file. A contended, stale lock (no owner, expired, or
|
|
11
|
+
* malformed-but-old) opens an eviction protocol that uses an exclusive
|
|
12
|
+
* "evicting" marker directory at `${lockPath}.evicting/owner.json` as a
|
|
13
|
+
* fence: the file holds the in-progress evicter's ownerId. The marker
|
|
14
|
+
* is verified before every destructive seam (re-read, unlink,
|
|
15
|
+
* re-acquire) so a contender whose marker has been hijacked will see
|
|
16
|
+
* ownership has changed and back off without touching the winner's lock.
|
|
17
|
+
*
|
|
18
|
+
* The renewal timer is `setInterval(...).unref()`-ed so it does not
|
|
19
|
+
* keep the Node/Bun runtime alive. Default renewal interval is
|
|
20
|
+
* `max(1000, floor(ttlMs / 3))`.
|
|
21
|
+
*/
|
|
22
|
+
import { randomUUID } from 'node:crypto';
|
|
23
|
+
import { mkdir, readFile, rename, rm, stat, unlink, writeFile, } from 'node:fs/promises';
|
|
24
|
+
import { dirname, join } from 'node:path';
|
|
25
|
+
const RENEW_MIN_INTERVAL_MS = 1_000;
|
|
26
|
+
const MARKER_CLAIM_MAX_ATTEMPTS = 8;
|
|
27
|
+
const MARKER_CLAIM_BACKOFF_MS = 25;
|
|
28
|
+
/**
|
|
29
|
+
* Thrown by `assertOwned` when the lock file no longer carries our
|
|
30
|
+
* ownerId or has expired.
|
|
31
|
+
*/
|
|
32
|
+
export class FileLockOwnershipError extends Error {
|
|
33
|
+
details;
|
|
34
|
+
constructor(message, details) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = 'FileLockOwnershipError';
|
|
37
|
+
this.details = details;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const MARKER_TTL_MS = 30_000;
|
|
41
|
+
async function readLockPayload(path) {
|
|
42
|
+
try {
|
|
43
|
+
const text = await readFile(path, 'utf8');
|
|
44
|
+
const parsed = JSON.parse(text);
|
|
45
|
+
if (typeof parsed === 'object' &&
|
|
46
|
+
parsed !== null &&
|
|
47
|
+
typeof parsed.ownerId === 'string' &&
|
|
48
|
+
typeof parsed.expiresAt === 'number') {
|
|
49
|
+
return parsed;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function readMarkerPayload(path) {
|
|
58
|
+
try {
|
|
59
|
+
const text = await readFile(path, 'utf8');
|
|
60
|
+
const parsed = JSON.parse(text);
|
|
61
|
+
if (typeof parsed === 'object' &&
|
|
62
|
+
parsed !== null &&
|
|
63
|
+
typeof parsed.ownerId === 'string' &&
|
|
64
|
+
typeof parsed.pid === 'number' &&
|
|
65
|
+
typeof parsed.createdAt === 'number') {
|
|
66
|
+
return parsed;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Best-effort liveness check for a PID. Returns `true` when the process
|
|
76
|
+
* is alive or when the platform lacks a reliable probe (Windows), so
|
|
77
|
+
* the marker is only reclaimed when we have positive evidence of death.
|
|
78
|
+
*/
|
|
79
|
+
function isProcessAlive(pid) {
|
|
80
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
81
|
+
return false;
|
|
82
|
+
try {
|
|
83
|
+
process.kill(pid, 0);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
const code = err.code;
|
|
88
|
+
if (code === 'ESRCH')
|
|
89
|
+
return false;
|
|
90
|
+
// EPERM (process exists but we cannot signal it) still counts as alive.
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function rmEvictingDir(evictingPath) {
|
|
95
|
+
await rm(evictingPath, { force: true }).catch(() => { });
|
|
96
|
+
await rm(dirname(evictingPath), { recursive: true, force: true }).catch(() => { });
|
|
97
|
+
}
|
|
98
|
+
async function sleep(ms) {
|
|
99
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
100
|
+
}
|
|
101
|
+
export async function acquireFencedFileLock(options) {
|
|
102
|
+
const lockPath = `${options.path}.${options.name}.lock`;
|
|
103
|
+
const evictingDir = `${lockPath}.evicting`;
|
|
104
|
+
const evictingPath = join(evictingDir, 'owner.json');
|
|
105
|
+
const ownerId = randomUUID();
|
|
106
|
+
const now = options.now ?? Date.now;
|
|
107
|
+
const tryAcquire = async (expiresAt) => {
|
|
108
|
+
const payload = JSON.stringify({ ownerId, expiresAt });
|
|
109
|
+
try {
|
|
110
|
+
await mkdir(dirname(lockPath), { recursive: true });
|
|
111
|
+
await writeFile(lockPath, payload, {
|
|
112
|
+
flag: 'wx',
|
|
113
|
+
encoding: 'utf8',
|
|
114
|
+
mode: 0o600,
|
|
115
|
+
});
|
|
116
|
+
return buildLock(lockPath, evictingPath, ownerId, options, now);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
if (err.code === 'EEXIST') {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
throw err;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
// Outer loop: each iteration represents one full attempt to acquire
|
|
126
|
+
// (fresh OR after eviction). We may need to retry if the contender
|
|
127
|
+
// creates a new lock between our unlink and our re-acquire.
|
|
128
|
+
for (;;) {
|
|
129
|
+
const firstTry = await tryAcquire(now() + options.ttlMs);
|
|
130
|
+
if (firstTry)
|
|
131
|
+
return firstTry;
|
|
132
|
+
const observed = await readLockPayload(lockPath);
|
|
133
|
+
const lockStats = await stat(lockPath).catch(() => null);
|
|
134
|
+
if (!lockStats)
|
|
135
|
+
continue; // lock vanished between attempts
|
|
136
|
+
const currentTime = now();
|
|
137
|
+
const looksLive = observed !== null &&
|
|
138
|
+
typeof observed.ownerId === 'string' &&
|
|
139
|
+
observed.expiresAt > currentTime;
|
|
140
|
+
if (looksLive) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
// malformed fail-closed: only proceed when mtime proves staleness.
|
|
144
|
+
const looksValid = observed !== null;
|
|
145
|
+
if (!looksValid) {
|
|
146
|
+
const ageMs = currentTime - lockStats.mtimeMs;
|
|
147
|
+
if (ageMs < options.ttlMs)
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
// Past this point we have decided the lock is stale and we will
|
|
151
|
+
// attempt eviction.
|
|
152
|
+
await options.onStep?.('stale-marker-stat');
|
|
153
|
+
// Claim the exclusive evicting marker (bounded retries so a stuck
|
|
154
|
+
// contender cannot trap us in an infinite loop). Before each retry,
|
|
155
|
+
// inspect the existing marker: if its PID is dead or the marker is
|
|
156
|
+
// older than MARKER_TTL_MS, it is abandoned and we reclaim it.
|
|
157
|
+
let markerClaimed = false;
|
|
158
|
+
for (let attempt = 0; attempt < MARKER_CLAIM_MAX_ATTEMPTS; attempt++) {
|
|
159
|
+
try {
|
|
160
|
+
await mkdir(evictingDir, { recursive: true, mode: 0o700 });
|
|
161
|
+
await writeFile(evictingPath, JSON.stringify({
|
|
162
|
+
ownerId,
|
|
163
|
+
pid: process.pid,
|
|
164
|
+
createdAt: now(),
|
|
165
|
+
}), {
|
|
166
|
+
flag: 'wx',
|
|
167
|
+
encoding: 'utf8',
|
|
168
|
+
mode: 0o600,
|
|
169
|
+
});
|
|
170
|
+
markerClaimed = true;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
if (err.code !== 'EEXIST')
|
|
175
|
+
throw err;
|
|
176
|
+
// Existing marker — check whether it is reclaimed-able.
|
|
177
|
+
const existing = await readMarkerPayload(evictingPath);
|
|
178
|
+
if (existing) {
|
|
179
|
+
const ageMs = now() - existing.createdAt;
|
|
180
|
+
const deadPid = !isProcessAlive(existing.pid);
|
|
181
|
+
if (deadPid || ageMs > MARKER_TTL_MS) {
|
|
182
|
+
// Stale marker — recycle the directory and retry the claim.
|
|
183
|
+
await rmEvictingDir(evictingPath);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
await sleep(MARKER_CLAIM_BACKOFF_MS);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (!markerClaimed) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
await options.onStep?.('stale-marker-claimed');
|
|
194
|
+
// First re-check boundary: confirm the marker is still ours AND
|
|
195
|
+
// the lock still looks stale (its real owner may have refreshed).
|
|
196
|
+
let markerPayload = await readMarkerPayload(evictingPath);
|
|
197
|
+
if (markerPayload?.ownerId !== ownerId)
|
|
198
|
+
continue;
|
|
199
|
+
const observedAgain = await readLockPayload(lockPath);
|
|
200
|
+
const refreshed = observedAgain !== null &&
|
|
201
|
+
observedAgain.ownerId !== ownerId &&
|
|
202
|
+
observedAgain.expiresAt > now();
|
|
203
|
+
if (refreshed) {
|
|
204
|
+
await rmEvictingDir(evictingPath);
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
await options.onStep?.('stale-lock-confirmed');
|
|
208
|
+
// Second re-check boundary: marker must still be ours before
|
|
209
|
+
// unlinking. If we lost ownership between the previous check and
|
|
210
|
+
// this one, the winner is now responsible for the lock file.
|
|
211
|
+
markerPayload = await readMarkerPayload(evictingPath);
|
|
212
|
+
if (markerPayload?.ownerId !== ownerId)
|
|
213
|
+
continue;
|
|
214
|
+
try {
|
|
215
|
+
await unlink(lockPath);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
const code = err.code;
|
|
219
|
+
if (code !== 'ENOENT') {
|
|
220
|
+
await rmEvictingDir(evictingPath);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
await options.onStep?.('eviction-marker-acquired');
|
|
225
|
+
// Re-acquire while still holding the marker as the new lock's
|
|
226
|
+
// "we evicted this" witness. If another contender grabs between our
|
|
227
|
+
// unlink and our re-acquire, drop the marker and loop back.
|
|
228
|
+
const reentry = await tryAcquire(now() + options.ttlMs);
|
|
229
|
+
if (reentry) {
|
|
230
|
+
await rmEvictingDir(evictingPath);
|
|
231
|
+
return reentry;
|
|
232
|
+
}
|
|
233
|
+
await rmEvictingDir(evictingPath);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function buildLock(lockPath, evictingPath, ownerId, options, now) {
|
|
237
|
+
let renewTimer = null;
|
|
238
|
+
let inFlightRenew = null;
|
|
239
|
+
let released = false;
|
|
240
|
+
let lost = false;
|
|
241
|
+
let lostResolve = null;
|
|
242
|
+
let lostPromise = new Promise((resolve) => {
|
|
243
|
+
lostResolve = resolve;
|
|
244
|
+
});
|
|
245
|
+
const markLost = () => {
|
|
246
|
+
if (lost)
|
|
247
|
+
return;
|
|
248
|
+
lost = true;
|
|
249
|
+
if (renewTimer !== null) {
|
|
250
|
+
clearInterval(renewTimer);
|
|
251
|
+
renewTimer = null;
|
|
252
|
+
}
|
|
253
|
+
const resolve = lostResolve;
|
|
254
|
+
lostResolve = null;
|
|
255
|
+
resolve?.();
|
|
256
|
+
};
|
|
257
|
+
const setupRenew = () => {
|
|
258
|
+
if (options.renew === false)
|
|
259
|
+
return;
|
|
260
|
+
const interval = options.renewIntervalMs ??
|
|
261
|
+
Math.max(RENEW_MIN_INTERVAL_MS, Math.floor(options.ttlMs / 3));
|
|
262
|
+
const renew = async () => {
|
|
263
|
+
if (released || lost)
|
|
264
|
+
return;
|
|
265
|
+
try {
|
|
266
|
+
const observed = await readLockPayload(lockPath);
|
|
267
|
+
if (released || lost)
|
|
268
|
+
return;
|
|
269
|
+
await options.onStep?.('renew-read');
|
|
270
|
+
if (released || lost)
|
|
271
|
+
return;
|
|
272
|
+
// If the lock file is gone or carries a different ownerId, the
|
|
273
|
+
// lock has been taken over (e.g. owner B evicted and replaced
|
|
274
|
+
// the lock while this renewal was paused). Mark it lost so the
|
|
275
|
+
// next iteration stops renewing.
|
|
276
|
+
if (observed === null) {
|
|
277
|
+
markLost();
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (observed.ownerId !== ownerId) {
|
|
281
|
+
markLost();
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (observed.expiresAt > now()) {
|
|
285
|
+
if (released || lost)
|
|
286
|
+
return;
|
|
287
|
+
// Rename cannot compare-and-swap ownership. Re-read after the
|
|
288
|
+
// rename and mark this lock lost if another owner replaced it;
|
|
289
|
+
// writers call assertOwned() before mutating shared state, so a
|
|
290
|
+
// hijack in this seam is detected and stops future renewals.
|
|
291
|
+
const tempPath = `${lockPath}.${ownerId}.tmp`;
|
|
292
|
+
let shouldCommit = false;
|
|
293
|
+
try {
|
|
294
|
+
await writeFile(tempPath, JSON.stringify({
|
|
295
|
+
ownerId,
|
|
296
|
+
expiresAt: now() + options.ttlMs,
|
|
297
|
+
}), { encoding: 'utf8', mode: 0o600 });
|
|
298
|
+
if (released || lost) {
|
|
299
|
+
await unlink(tempPath).catch(() => { });
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
const currentObserved = await readLockPayload(lockPath);
|
|
303
|
+
if (released || lost) {
|
|
304
|
+
await unlink(tempPath).catch(() => { });
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (!currentObserved || currentObserved.ownerId !== ownerId) {
|
|
308
|
+
// Another owner slipped in — leave their content intact,
|
|
309
|
+
// mark lost, drop our temp draft.
|
|
310
|
+
markLost();
|
|
311
|
+
await unlink(tempPath).catch(() => { });
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
shouldCommit = true;
|
|
315
|
+
await rename(tempPath, lockPath);
|
|
316
|
+
await options.onStep?.('renew-committed');
|
|
317
|
+
if (released || lost)
|
|
318
|
+
return;
|
|
319
|
+
// Verify-after-commit: a replacement owner may have arrived
|
|
320
|
+
// between the re-read above and the rename — our rename then
|
|
321
|
+
// just overwrote their fresh lock — or may land a microsecond
|
|
322
|
+
// after our rename. Re-read and, if the file no longer carries
|
|
323
|
+
// our ownerId, mark lost and stop renewing so the double-owner
|
|
324
|
+
// window collapses to this seam; the fresh owner's next
|
|
325
|
+
// renewal/acquire attempt re-acquires.
|
|
326
|
+
const committed = await readLockPayload(lockPath);
|
|
327
|
+
if (released || lost)
|
|
328
|
+
return;
|
|
329
|
+
if (!committed || committed.ownerId !== ownerId) {
|
|
330
|
+
markLost();
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// Lost the race against a rename/evict — mark lost so the
|
|
336
|
+
// next iteration stops renewing, and clean up any temp draft.
|
|
337
|
+
markLost();
|
|
338
|
+
if (!shouldCommit) {
|
|
339
|
+
await unlink(tempPath).catch(() => { });
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
// best-effort renewal; nothing to do on failure
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
// The timer callback is small: it only schedules a renew if one is not
|
|
349
|
+
// already in flight and the lock has not been released. The renew
|
|
350
|
+
// Promise itself runs to completion; its in-flight state is tracked
|
|
351
|
+
// so release() can await it before unlinking.
|
|
352
|
+
const tick = () => {
|
|
353
|
+
if (released)
|
|
354
|
+
return;
|
|
355
|
+
if (inFlightRenew)
|
|
356
|
+
return;
|
|
357
|
+
inFlightRenew = renew().finally(() => {
|
|
358
|
+
inFlightRenew = null;
|
|
359
|
+
});
|
|
360
|
+
};
|
|
361
|
+
renewTimer = setInterval(tick, interval);
|
|
362
|
+
if (renewTimer &&
|
|
363
|
+
typeof renewTimer.unref === 'function') {
|
|
364
|
+
;
|
|
365
|
+
renewTimer.unref();
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
const release = async () => {
|
|
369
|
+
if (released)
|
|
370
|
+
return;
|
|
371
|
+
released = true;
|
|
372
|
+
if (renewTimer !== null) {
|
|
373
|
+
clearInterval(renewTimer);
|
|
374
|
+
renewTimer = null;
|
|
375
|
+
}
|
|
376
|
+
const pendingRenew = inFlightRenew;
|
|
377
|
+
inFlightRenew = null;
|
|
378
|
+
if (pendingRenew) {
|
|
379
|
+
try {
|
|
380
|
+
await pendingRenew;
|
|
381
|
+
}
|
|
382
|
+
catch {
|
|
383
|
+
// renewal swallows its own errors; awaiting is just a fence
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
try {
|
|
387
|
+
const observed = await readLockPayload(lockPath);
|
|
388
|
+
if (!observed || observed.ownerId !== ownerId) {
|
|
389
|
+
// Not ours anymore — refuse to delete.
|
|
390
|
+
await rmEvictingDir(evictingPath).catch(() => { });
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
try {
|
|
394
|
+
await unlink(lockPath);
|
|
395
|
+
}
|
|
396
|
+
catch (err) {
|
|
397
|
+
if (err.code !== 'ENOENT')
|
|
398
|
+
throw err;
|
|
399
|
+
}
|
|
400
|
+
await rmEvictingDir(evictingPath).catch(() => { });
|
|
401
|
+
}
|
|
402
|
+
finally {
|
|
403
|
+
markLost();
|
|
404
|
+
renewTimer = null;
|
|
405
|
+
inFlightRenew = null;
|
|
406
|
+
lostResolve = null;
|
|
407
|
+
lostPromise = null;
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
const assertOwned = async () => {
|
|
411
|
+
const observed = await readLockPayload(lockPath);
|
|
412
|
+
if (!observed || observed.ownerId !== ownerId) {
|
|
413
|
+
throw new FileLockOwnershipError(`file lock ${lockPath} is not owned by ${ownerId}`, {
|
|
414
|
+
path: lockPath,
|
|
415
|
+
expectedOwner: ownerId,
|
|
416
|
+
observedOwner: observed?.ownerId,
|
|
417
|
+
observedExpiresAt: observed?.expiresAt,
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
if (observed.expiresAt <= now()) {
|
|
421
|
+
throw new FileLockOwnershipError(`file lock ${lockPath} has expired`, {
|
|
422
|
+
path: lockPath,
|
|
423
|
+
expectedOwner: ownerId,
|
|
424
|
+
observedOwner: observed.ownerId,
|
|
425
|
+
observedExpiresAt: observed.expiresAt,
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
setupRenew();
|
|
430
|
+
return {
|
|
431
|
+
ownerId,
|
|
432
|
+
assertOwned,
|
|
433
|
+
release,
|
|
434
|
+
whenLost: () => lostPromise ?? Promise.resolve(),
|
|
435
|
+
hasLost: () => lost,
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
//# sourceMappingURL=file-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-lock.js","sourceRoot":"","sources":["../src/file-lock.ts"],"names":[],"mappings":"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"}
|
package/dist/fingerprint.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Device Fingerprint Generator for Rate Limit Mitigation
|
|
3
3
|
*
|
|
4
|
-
* Uses the agy CLI 1.1.
|
|
4
|
+
* Uses the agy CLI 1.1.6 content-request identity captured with mitmproxy:
|
|
5
5
|
* an Antigravity CLI User-Agent with explicit client, OS, architecture, and auth metadata.
|
|
6
6
|
* The stored deviceId/sessionToken fields are
|
|
7
7
|
* retained for account history, but content requests only send User-Agent.
|
|
8
8
|
*/
|
|
9
|
-
export declare const AGY_CLI_VERSION = "1.1.
|
|
9
|
+
export declare const AGY_CLI_VERSION = "1.1.6";
|
|
10
10
|
export interface ClientMetadata {
|
|
11
11
|
ideType: string;
|
|
12
12
|
platform: string;
|
|
@@ -32,7 +32,7 @@ export interface FingerprintVersion {
|
|
|
32
32
|
/** Maximum number of fingerprint versions to keep per account */
|
|
33
33
|
export declare const MAX_FINGERPRINT_HISTORY = 5;
|
|
34
34
|
export interface FingerprintHeaders {
|
|
35
|
-
|
|
35
|
+
'User-Agent': string;
|
|
36
36
|
}
|
|
37
37
|
export declare function buildAntigravityHarnessPlatformArch(platform?: NodeJS.Platform, arch?: NodeJS.Architecture): string;
|
|
38
38
|
export declare function buildAntigravityHarnessUserAgent(version?: string, platform?: NodeJS.Platform, arch?: NodeJS.Architecture, authMethod?: string): string;
|
|
@@ -70,4 +70,10 @@ export declare function getSessionFingerprint(): Fingerprint;
|
|
|
70
70
|
* Call this to get a fresh identity (e.g., after rate limiting).
|
|
71
71
|
*/
|
|
72
72
|
export declare function regenerateSessionFingerprint(): Fingerprint;
|
|
73
|
+
/**
|
|
74
|
+
* Clear the cached session fingerprint so the next `getSessionFingerprint`
|
|
75
|
+
* call generates a fresh one. Test-only escape hatch — production code should
|
|
76
|
+
* use `regenerateSessionFingerprint` to also return the new value.
|
|
77
|
+
*/
|
|
78
|
+
export declare function clearSessionFingerprint(): void;
|
|
73
79
|
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,eAAO,MAAM,eAAe,UAAU,
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,eAAO,MAAM,eAAe,UAAU,CAAA;AAGtC,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,cAAc,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;CAClB;AACD;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,WAAW,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,UAAU,CAAA;CAC/C;AAED,iEAAiE;AACjE,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAA;CACrB;AAiBD,wBAAgB,mCAAmC,CACjD,QAAQ,kBAAmB,EAC3B,IAAI,sBAAe,GAClB,MAAM,CAER;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,SAAkB,EACzB,QAAQ,kBAAmB,EAC3B,IAAI,sBAAe,EACnB,UAAU,SAAa,GACtB,MAAM,CAIR;AAED,wBAAgB,8CAA8C,CAC5D,OAAO,SAAkB,GACxB,MAAM,CAER;AAQD,wBAAgB,sCAAsC,IAAI,MAAM,CAC9D,MAAM,EACN,MAAM,CACP,CAEA;AAED,wBAAgB,uCAAuC,CACrD,WAAW,EAAE,MAAM,GAClB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAUD;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,WAAW,CAajD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,WAAW,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAQ1E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,WAAW,GAAG,IAAI,GAC9B,OAAO,CAAC,kBAAkB,CAAC,CAQ7B;AAQD;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,WAAW,CAKnD;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,IAAI,WAAW,CAG1D;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
|
package/dist/fingerprint.js
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Device Fingerprint Generator for Rate Limit Mitigation
|
|
3
3
|
*
|
|
4
|
-
* Uses the agy CLI 1.1.
|
|
4
|
+
* Uses the agy CLI 1.1.6 content-request identity captured with mitmproxy:
|
|
5
5
|
* an Antigravity CLI User-Agent with explicit client, OS, architecture, and auth metadata.
|
|
6
6
|
* The stored deviceId/sessionToken fields are
|
|
7
7
|
* retained for account history, but content requests only send User-Agent.
|
|
8
8
|
*/
|
|
9
|
-
import * as crypto from
|
|
10
|
-
export const AGY_CLI_VERSION =
|
|
11
|
-
const ANTIGRAVITY_API_CLIENT =
|
|
9
|
+
import * as crypto from 'node:crypto';
|
|
10
|
+
export const AGY_CLI_VERSION = '1.1.6';
|
|
11
|
+
const ANTIGRAVITY_API_CLIENT = 'antigravity-cli';
|
|
12
12
|
/** Maximum number of fingerprint versions to keep per account */
|
|
13
13
|
export const MAX_FINGERPRINT_HISTORY = 5;
|
|
14
14
|
function normalizeHarnessPlatform(platform = process.platform) {
|
|
15
|
-
return platform ===
|
|
15
|
+
return platform === 'win32' ? 'windows' : platform || 'unknown';
|
|
16
16
|
}
|
|
17
17
|
function normalizeHarnessArch(arch = process.arch) {
|
|
18
18
|
switch (arch) {
|
|
19
|
-
case
|
|
20
|
-
return
|
|
21
|
-
case
|
|
22
|
-
return
|
|
19
|
+
case 'x64':
|
|
20
|
+
return 'amd64';
|
|
21
|
+
case 'ia32':
|
|
22
|
+
return '386';
|
|
23
23
|
default:
|
|
24
|
-
return arch ||
|
|
24
|
+
return arch || 'unknown';
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
export function buildAntigravityHarnessPlatformArch(platform = process.platform, arch = process.arch) {
|
|
28
28
|
return `${normalizeHarnessPlatform(platform)}/${normalizeHarnessArch(arch)}`;
|
|
29
29
|
}
|
|
30
|
-
export function buildAntigravityHarnessUserAgent(version = AGY_CLI_VERSION, platform = process.platform, arch = process.arch, authMethod =
|
|
30
|
+
export function buildAntigravityHarnessUserAgent(version = AGY_CLI_VERSION, platform = process.platform, arch = process.arch, authMethod = 'consumer') {
|
|
31
31
|
const osType = normalizeHarnessPlatform(platform);
|
|
32
32
|
const normalizedArch = normalizeHarnessArch(arch);
|
|
33
33
|
return `antigravity/cli/${version} (aidev_client; os_type=${osType}; arch=${normalizedArch}; auth_method=${authMethod})`;
|
|
@@ -36,24 +36,24 @@ export function buildAntigravityHarnessLoadCodeAssistUserAgent(version = AGY_CLI
|
|
|
36
36
|
return buildAntigravityHarnessUserAgent(version);
|
|
37
37
|
}
|
|
38
38
|
function platformToMetadataPlatform(platform = process.platform) {
|
|
39
|
-
return platform ===
|
|
39
|
+
return platform === 'win32' ? 'WINDOWS' : 'MACOS';
|
|
40
40
|
}
|
|
41
41
|
export function buildAntigravityLoadCodeAssistMetadata() {
|
|
42
|
-
return { ideType:
|
|
42
|
+
return { ideType: 'ANTIGRAVITY' };
|
|
43
43
|
}
|
|
44
44
|
export function buildAntigravityHarnessBootstrapHeaders(accessToken) {
|
|
45
45
|
return {
|
|
46
|
-
|
|
46
|
+
'User-Agent': buildAntigravityHarnessLoadCodeAssistUserAgent(),
|
|
47
47
|
Authorization: `Bearer ${accessToken}`,
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
'Content-Type': 'application/json',
|
|
49
|
+
'Accept-Encoding': 'gzip',
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
52
|
function generateDeviceId() {
|
|
53
53
|
return crypto.randomUUID();
|
|
54
54
|
}
|
|
55
55
|
function generateSessionToken() {
|
|
56
|
-
return crypto.randomBytes(16).toString(
|
|
56
|
+
return crypto.randomBytes(16).toString('hex');
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
59
|
* Generate the per-account content-request fingerprint.
|
|
@@ -66,9 +66,9 @@ export function generateFingerprint() {
|
|
|
66
66
|
userAgent: buildAntigravityHarnessUserAgent(),
|
|
67
67
|
apiClient: ANTIGRAVITY_API_CLIENT,
|
|
68
68
|
clientMetadata: {
|
|
69
|
-
ideType:
|
|
69
|
+
ideType: 'ANTIGRAVITY',
|
|
70
70
|
platform: platformToMetadataPlatform(),
|
|
71
|
-
pluginType:
|
|
71
|
+
pluginType: 'GEMINI',
|
|
72
72
|
},
|
|
73
73
|
createdAt: Date.now(),
|
|
74
74
|
};
|
|
@@ -102,7 +102,7 @@ export function buildFingerprintHeaders(fingerprint) {
|
|
|
102
102
|
return {};
|
|
103
103
|
}
|
|
104
104
|
return {
|
|
105
|
-
|
|
105
|
+
'User-Agent': fingerprint.userAgent,
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
@@ -128,4 +128,12 @@ export function regenerateSessionFingerprint() {
|
|
|
128
128
|
sessionFingerprint = generateFingerprint();
|
|
129
129
|
return sessionFingerprint;
|
|
130
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Clear the cached session fingerprint so the next `getSessionFingerprint`
|
|
133
|
+
* call generates a fresh one. Test-only escape hatch — production code should
|
|
134
|
+
* use `regenerateSessionFingerprint` to also return the new value.
|
|
135
|
+
*/
|
|
136
|
+
export function clearSessionFingerprint() {
|
|
137
|
+
sessionFingerprint = null;
|
|
138
|
+
}
|
|
131
139
|
//# sourceMappingURL=fingerprint.js.map
|
package/dist/fingerprint.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"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"}
|