@cortexkit/anthropic-auth-core 1.1.2 → 1.1.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.
@@ -89,6 +89,14 @@ export type AccountRefreshError = {
89
89
  export declare function getAccountStoragePath(): string;
90
90
  export declare function loadAccounts(path?: string): Promise<AccountStorage | null>;
91
91
  export declare function saveAccounts(storage: AccountStorage, path?: string): Promise<void>;
92
+ export declare function acquireRefreshFileLock(options: {
93
+ name: string;
94
+ ttlMs: number;
95
+ path?: string;
96
+ now?: () => number;
97
+ }): Promise<{
98
+ release: () => Promise<void>;
99
+ } | null>;
92
100
  export declare function isCache1hPersistentlyEnabled(storage: AccountStorage | null): boolean;
93
101
  export declare function getCache1hPersistentMode(storage: AccountStorage | null): Cache1hMode;
94
102
  export declare function setCache1hPersistentEnabled(enabled: boolean, mode?: Cache1hMode, path?: string): Promise<AccountStorage>;
package/dist/accounts.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomUUID } from 'node:crypto';
2
- import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
2
+ import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
3
3
  import { homedir } from 'node:os';
4
4
  import { dirname, join } from 'node:path';
5
5
  import { ClaudeOAuthRefreshError, refreshClaudeOAuthToken } from "./auth.js";
@@ -8,7 +8,8 @@ import { log } from "./logger.js";
8
8
  export const ACCOUNT_FILE_NAME = 'anthropic-auth.json';
9
9
  export const QUOTA_URL = 'https://api.anthropic.com/api/oauth/usage';
10
10
  const DEFAULT_FALLBACK_ON = [401, 403, 429];
11
- const DEFAULT_REFRESH_BEFORE_EXPIRY_MINUTES = 30;
11
+ const MIN_REFRESH_BEFORE_EXPIRY_MINUTES = 240;
12
+ const DEFAULT_REFRESH_BEFORE_EXPIRY_MINUTES = MIN_REFRESH_BEFORE_EXPIRY_MINUTES;
12
13
  const DEFAULT_REFRESH_INTERVAL_MINUTES = 10;
13
14
  const MIN_REFRESH_RETRY_DELAY_MS = 5 * 60_000;
14
15
  const MAX_REFRESH_RETRY_DELAY_MS = 60 * 60_000;
@@ -159,6 +160,51 @@ export async function saveAccounts(storage, path = getAccountStoragePath()) {
159
160
  });
160
161
  await rename(tempPath, path);
161
162
  }
163
+ export async function acquireRefreshFileLock(options) {
164
+ const accountPath = options.path ?? getAccountStoragePath();
165
+ const lockDir = `${accountPath}.${options.name}.lock`;
166
+ const ownerPath = join(lockDir, 'owner.json');
167
+ const ownerId = randomUUID();
168
+ const now = options.now ?? Date.now;
169
+ async function tryAcquire() {
170
+ try {
171
+ await mkdir(lockDir, { mode: 0o700 });
172
+ await writeFile(ownerPath, `${JSON.stringify({ ownerId, expiresAt: now() + options.ttlMs })}\n`, { encoding: 'utf8', mode: 0o600 });
173
+ return true;
174
+ }
175
+ catch (error) {
176
+ if (error.code !== 'EEXIST')
177
+ throw error;
178
+ return false;
179
+ }
180
+ }
181
+ if (!(await tryAcquire())) {
182
+ try {
183
+ const owner = JSON.parse(await readFile(ownerPath, 'utf8'));
184
+ if (Number(owner?.expiresAt) > now())
185
+ return null;
186
+ }
187
+ catch {
188
+ // Broken owner metadata is treated as stale.
189
+ }
190
+ await rm(lockDir, { recursive: true, force: true }).catch(() => { });
191
+ if (!(await tryAcquire()))
192
+ return null;
193
+ }
194
+ return {
195
+ release: async () => {
196
+ try {
197
+ const owner = JSON.parse(await readFile(ownerPath, 'utf8'));
198
+ if (owner?.ownerId !== ownerId)
199
+ return;
200
+ }
201
+ catch {
202
+ return;
203
+ }
204
+ await rm(lockDir, { recursive: true, force: true }).catch(() => { });
205
+ },
206
+ };
207
+ }
162
208
  export function isCache1hPersistentlyEnabled(storage) {
163
209
  return storage?.claudeCache?.enabled === true;
164
210
  }
@@ -284,7 +330,7 @@ function refreshEnabled(storage) {
284
330
  function refreshBeforeExpiryMs(storage) {
285
331
  const minutes = storage?.refresh?.refreshBeforeExpiryMinutes ??
286
332
  DEFAULT_REFRESH_BEFORE_EXPIRY_MINUTES;
287
- return Math.max(0, minutes) * 60_000;
333
+ return Math.max(MIN_REFRESH_BEFORE_EXPIRY_MINUTES, minutes) * 60_000;
288
334
  }
289
335
  export function getRefreshIntervalMs(storage) {
290
336
  const minutes = storage?.refresh?.intervalMinutes ?? DEFAULT_REFRESH_INTERVAL_MINUTES;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/anthropic-auth-core",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",