@cortexkit/anthropic-auth-core 1.13.0 → 1.15.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/accounts.d.ts +1 -0
- package/dist/accounts.js +17 -5
- package/dist/cachekeep.d.ts +22 -0
- package/dist/cachekeep.js +54 -24
- package/package.json +1 -1
package/dist/accounts.d.ts
CHANGED
|
@@ -68,6 +68,7 @@ export type AccountScopedQuotaWindow = AccountQuotaWindow & {
|
|
|
68
68
|
};
|
|
69
69
|
export type OAuthQuotaSnapshot = Partial<Record<QuotaWindowName, AccountQuotaWindow>> & {
|
|
70
70
|
scoped?: AccountScopedQuotaWindow[];
|
|
71
|
+
checkedAt?: number;
|
|
71
72
|
};
|
|
72
73
|
export type RoutingMode = 'main-first' | 'fallback-first';
|
|
73
74
|
export type KillswitchThresholds = Partial<Record<QuotaWindowName | '5h' | '1w' | 'scoped', number>>;
|
package/dist/accounts.js
CHANGED
|
@@ -178,6 +178,14 @@ function normalizeQuota(value) {
|
|
|
178
178
|
if (normalized)
|
|
179
179
|
quota[key] = normalized;
|
|
180
180
|
}
|
|
181
|
+
// Persist a top-level snapshot checkedAt through normalize so the
|
|
182
|
+
// mergeAccountRuntimeState freshness comparison stays meaningful when the
|
|
183
|
+
// snapshot has no per-window checkedAt (e.g. {scoped:[]}). Pre-feature
|
|
184
|
+
// inputs without this key are unaffected — only on-disk snapshots that
|
|
185
|
+
// already carry it reach this branch.
|
|
186
|
+
if (typeof value.checkedAt === 'number' && Number.isFinite(value.checkedAt)) {
|
|
187
|
+
quota.checkedAt = value.checkedAt;
|
|
188
|
+
}
|
|
181
189
|
if (Array.isArray(value.scoped)) {
|
|
182
190
|
const scoped = value.scoped
|
|
183
191
|
.map((entry) => {
|
|
@@ -206,8 +214,11 @@ function normalizeQuota(value) {
|
|
|
206
214
|
};
|
|
207
215
|
})
|
|
208
216
|
.filter((entry) => entry != null);
|
|
209
|
-
|
|
210
|
-
|
|
217
|
+
// Preserve empty `[]` so a downstream reader can distinguish "scoped
|
|
218
|
+
// owned by anthropic-auth, none visible" from "no scoped data on this
|
|
219
|
+
// snapshot". Pre-feature inputs without a `scoped` key are not affected
|
|
220
|
+
// — only inputs that already carried an array reach this line.
|
|
221
|
+
quota.scoped = scoped;
|
|
211
222
|
}
|
|
212
223
|
return Object.keys(quota).length ? quota : undefined;
|
|
213
224
|
}
|
|
@@ -384,7 +395,7 @@ function accountRuntimeState(account) {
|
|
|
384
395
|
});
|
|
385
396
|
}
|
|
386
397
|
function quotaSnapshotCheckedAt(quota) {
|
|
387
|
-
return Math.max(quota?.five_hour?.checkedAt ?? 0, quota?.seven_day?.checkedAt ?? 0, ...(quota?.scoped?.map((window) => window.checkedAt) ?? []));
|
|
398
|
+
return Math.max(quota?.five_hour?.checkedAt ?? 0, quota?.seven_day?.checkedAt ?? 0, ...(quota?.scoped?.map((window) => window.checkedAt) ?? []), quota?.checkedAt ?? 0);
|
|
388
399
|
}
|
|
389
400
|
function mergeAccountRuntimeState(existing, incoming) {
|
|
390
401
|
if (!isRecord(existing))
|
|
@@ -1404,7 +1415,7 @@ function slugForQuotaIdentity(value) {
|
|
|
1404
1415
|
}
|
|
1405
1416
|
function mapScopedWeeklyLimits(limits, checkedAt) {
|
|
1406
1417
|
if (!Array.isArray(limits))
|
|
1407
|
-
return
|
|
1418
|
+
return [];
|
|
1408
1419
|
const seen = new Set();
|
|
1409
1420
|
const scoped = [];
|
|
1410
1421
|
for (const limit of limits) {
|
|
@@ -1437,7 +1448,7 @@ function mapScopedWeeklyLimits(limits, checkedAt) {
|
|
|
1437
1448
|
checkedAt,
|
|
1438
1449
|
});
|
|
1439
1450
|
}
|
|
1440
|
-
return scoped
|
|
1451
|
+
return scoped;
|
|
1441
1452
|
}
|
|
1442
1453
|
function mapUsageWindow(window, checkedAt) {
|
|
1443
1454
|
if (typeof window?.utilization !== 'number')
|
|
@@ -1478,6 +1489,7 @@ export async function fetchOAuthQuotaSnapshot(input) {
|
|
|
1478
1489
|
five_hour: mapUsageWindow(usage.five_hour, checkedAt),
|
|
1479
1490
|
seven_day: mapUsageWindow(usage.seven_day, checkedAt),
|
|
1480
1491
|
scoped: mapScopedWeeklyLimits(usage.limits, checkedAt),
|
|
1492
|
+
checkedAt,
|
|
1481
1493
|
};
|
|
1482
1494
|
}
|
|
1483
1495
|
function updateStoredAccount(storage, account) {
|
package/dist/cachekeep.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare const CACHE_KEEP_EXTENDED_TTL_BETA = "extended-cache-ttl-2025-04-
|
|
|
7
7
|
export declare const CACHE_KEEP_MAX_TARGETS = 32;
|
|
8
8
|
export declare const CACHE_KEEP_MAX_BODY_BYTES: number;
|
|
9
9
|
export declare const CACHE_KEEP_STALE_TARGET_MS: number;
|
|
10
|
+
export declare const CACHE_KEEP_PREWARM_TIMEOUT_MS = 30000;
|
|
10
11
|
export type CacheKeepWindow = {
|
|
11
12
|
startHour: number;
|
|
12
13
|
endHour: number;
|
|
@@ -63,6 +64,18 @@ export type CacheKeepTarget = {
|
|
|
63
64
|
dayKey: string;
|
|
64
65
|
oauthAccountId?: string;
|
|
65
66
|
};
|
|
67
|
+
export type CacheKeepPrewarmResult = {
|
|
68
|
+
ok: true;
|
|
69
|
+
usage?: {
|
|
70
|
+
input_tokens?: number;
|
|
71
|
+
cache_creation_input_tokens?: number;
|
|
72
|
+
cache_read_input_tokens?: number;
|
|
73
|
+
};
|
|
74
|
+
} | {
|
|
75
|
+
ok: false;
|
|
76
|
+
reason: string;
|
|
77
|
+
status?: number;
|
|
78
|
+
};
|
|
66
79
|
export declare class CacheKeepManager {
|
|
67
80
|
private readonly options;
|
|
68
81
|
private readonly targets;
|
|
@@ -71,6 +84,7 @@ export declare class CacheKeepManager {
|
|
|
71
84
|
loadStorage: () => Promise<AccountStorage | null>;
|
|
72
85
|
fetchImpl?: typeof fetch;
|
|
73
86
|
now?: () => number;
|
|
87
|
+
prewarmTimeoutMs?: number;
|
|
74
88
|
prepareHeaders?: (headers: Headers, target: CacheKeepTarget) => Promise<Headers> | Headers;
|
|
75
89
|
});
|
|
76
90
|
start(): void;
|
|
@@ -98,6 +112,14 @@ export declare class CacheKeepManager {
|
|
|
98
112
|
tracked: boolean;
|
|
99
113
|
reason?: undefined;
|
|
100
114
|
};
|
|
115
|
+
prewarmNow(input: {
|
|
116
|
+
sessionId: string;
|
|
117
|
+
url: string;
|
|
118
|
+
headers: Headers;
|
|
119
|
+
bodyText: string;
|
|
120
|
+
oauthAccountId?: string;
|
|
121
|
+
}): Promise<CacheKeepPrewarmResult>;
|
|
101
122
|
tick(): Promise<void>;
|
|
123
|
+
private sendPrewarm;
|
|
102
124
|
private prewarm;
|
|
103
125
|
}
|
package/dist/cachekeep.js
CHANGED
|
@@ -9,6 +9,7 @@ export const CACHE_KEEP_EXTENDED_TTL_BETA = 'extended-cache-ttl-2025-04-11';
|
|
|
9
9
|
export const CACHE_KEEP_MAX_TARGETS = 32;
|
|
10
10
|
export const CACHE_KEEP_MAX_BODY_BYTES = 16 * 1024 * 1024;
|
|
11
11
|
export const CACHE_KEEP_STALE_TARGET_MS = 2 * CACHE_KEEP_TTL_MS;
|
|
12
|
+
export const CACHE_KEEP_PREWARM_TIMEOUT_MS = 30_000;
|
|
12
13
|
const STATUS_TITLE = '## Claude Cache Keep Status';
|
|
13
14
|
const ENABLED_TITLE = '## Claude Cache Keep Enabled';
|
|
14
15
|
const DISABLED_TITLE = '## Claude Cache Keep Disabled';
|
|
@@ -293,6 +294,22 @@ export class CacheKeepManager {
|
|
|
293
294
|
this.start();
|
|
294
295
|
return { tracked: true };
|
|
295
296
|
}
|
|
297
|
+
async prewarmNow(input) {
|
|
298
|
+
const headers = {};
|
|
299
|
+
input.headers.forEach((value, key) => {
|
|
300
|
+
headers[key] = value;
|
|
301
|
+
});
|
|
302
|
+
const target = {
|
|
303
|
+
id: input.sessionId,
|
|
304
|
+
url: input.url,
|
|
305
|
+
headers,
|
|
306
|
+
bodyText: input.bodyText,
|
|
307
|
+
cacheExpiresAt: this.options.now?.() ?? Date.now(),
|
|
308
|
+
dayKey: '',
|
|
309
|
+
oauthAccountId: input.oauthAccountId,
|
|
310
|
+
};
|
|
311
|
+
return this.sendPrewarm(target);
|
|
312
|
+
}
|
|
296
313
|
async tick() {
|
|
297
314
|
const storage = await this.options.loadStorage();
|
|
298
315
|
const window = getCacheKeepWindow(storage);
|
|
@@ -315,16 +332,10 @@ export class CacheKeepManager {
|
|
|
315
332
|
await this.prewarm(target, now);
|
|
316
333
|
}
|
|
317
334
|
}
|
|
318
|
-
async
|
|
335
|
+
async sendPrewarm(target) {
|
|
319
336
|
const prewarm = await buildCacheKeepPrewarmBody(target.bodyText);
|
|
320
|
-
if (!prewarm.ok)
|
|
321
|
-
|
|
322
|
-
session: target.id,
|
|
323
|
-
reason: prewarm.reason,
|
|
324
|
-
});
|
|
325
|
-
this.targets.delete(target.id);
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
337
|
+
if (!prewarm.ok)
|
|
338
|
+
return prewarm;
|
|
328
339
|
const fetchImpl = this.options.fetchImpl ?? fetch;
|
|
329
340
|
const prewarmTarget = { ...target, bodyText: prewarm.bodyText };
|
|
330
341
|
const headers = this.options.prepareHeaders
|
|
@@ -336,27 +347,46 @@ export class CacheKeepManager {
|
|
|
336
347
|
method: 'POST',
|
|
337
348
|
headers,
|
|
338
349
|
body: prewarm.bodyText,
|
|
350
|
+
signal: AbortSignal.timeout(this.options.prewarmTimeoutMs ?? CACHE_KEEP_PREWARM_TIMEOUT_MS),
|
|
339
351
|
});
|
|
340
352
|
if (!response.ok) {
|
|
341
|
-
|
|
342
|
-
|
|
353
|
+
return {
|
|
354
|
+
ok: false,
|
|
355
|
+
reason: await response
|
|
356
|
+
.text()
|
|
357
|
+
.catch(() => '')
|
|
358
|
+
.then((body) => body || `HTTP ${response.status}`),
|
|
343
359
|
status: response.status,
|
|
344
|
-
|
|
345
|
-
});
|
|
346
|
-
target.cacheExpiresAt = now + CACHE_KEEP_PREWARM_LEAD_MS + 5 * 60_000;
|
|
347
|
-
return;
|
|
360
|
+
};
|
|
348
361
|
}
|
|
349
362
|
const data = (await response.json().catch(() => null));
|
|
350
363
|
const usage = data?.usage;
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
364
|
+
return { ok: true, ...(usage && { usage }) };
|
|
365
|
+
}
|
|
366
|
+
async prewarm(target, now) {
|
|
367
|
+
const result = await this.sendPrewarm(target);
|
|
368
|
+
if (!result.ok) {
|
|
369
|
+
if (result.status == null) {
|
|
370
|
+
logger.debug('cachekeep', 'prewarm skipped', {
|
|
371
|
+
session: target.id,
|
|
372
|
+
reason: result.reason,
|
|
373
|
+
});
|
|
374
|
+
this.targets.delete(target.id);
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
logger.warn('cachekeep', 'prewarm failed', {
|
|
378
|
+
session: target.id,
|
|
379
|
+
status: result.status,
|
|
380
|
+
reason: result.reason,
|
|
381
|
+
});
|
|
382
|
+
target.cacheExpiresAt = now + CACHE_KEEP_PREWARM_LEAD_MS + 5 * 60_000;
|
|
383
|
+
}
|
|
384
|
+
return;
|
|
360
385
|
}
|
|
386
|
+
target.cacheExpiresAt = now + CACHE_KEEP_TTL_MS;
|
|
387
|
+
logger.debug('cachekeep', 'prewarm succeeded', {
|
|
388
|
+
session: target.id,
|
|
389
|
+
...(result.usage && { usage: result.usage }),
|
|
390
|
+
});
|
|
361
391
|
}
|
|
362
392
|
}
|