codex-multi-auth 2.7.0 → 2.8.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/.codex-plugin/plugin.json +9 -9
- package/README.md +435 -433
- package/dist/lib/cli.d.ts +2 -0
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/codex-cli/writer.d.ts +51 -0
- package/dist/lib/codex-cli/writer.d.ts.map +1 -1
- package/dist/lib/codex-cli/writer.js +89 -8
- package/dist/lib/codex-manager/login-menu-actions.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-menu-actions.js +12 -1
- package/dist/lib/codex-manager/login-menu-data.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-menu-data.js +19 -8
- package/dist/lib/codex-manager/repair-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/repair-commands.js +57 -8
- package/dist/lib/forecast.d.ts.map +1 -1
- package/dist/lib/forecast.js +30 -4
- package/dist/lib/policy/runtime-policy.d.ts.map +1 -1
- package/dist/lib/policy/runtime-policy.js +12 -3
- package/dist/lib/quota-readiness.d.ts +1 -0
- package/dist/lib/quota-readiness.d.ts.map +1 -1
- package/dist/lib/quota-readiness.js +12 -2
- package/dist/lib/refresh-lease.d.ts +12 -0
- package/dist/lib/refresh-lease.d.ts.map +1 -1
- package/dist/lib/refresh-lease.js +24 -2
- package/dist/lib/refresh-queue.d.ts.map +1 -1
- package/dist/lib/refresh-queue.js +29 -3
- package/dist/lib/request/request-transformer.d.ts.map +1 -1
- package/dist/lib/request/request-transformer.js +13 -2
- package/dist/lib/request/response-handler.d.ts.map +1 -1
- package/dist/lib/request/response-handler.js +10 -1
- package/dist/lib/rotation.d.ts.map +1 -1
- package/dist/lib/rotation.js +8 -1
- package/dist/lib/runtime/account-check.d.ts +1 -1
- package/dist/lib/runtime/account-check.d.ts.map +1 -1
- package/dist/lib/runtime/account-check.js +8 -0
- package/dist/lib/runtime/first-run.d.ts +12 -6
- package/dist/lib/runtime/first-run.d.ts.map +1 -1
- package/dist/lib/runtime/first-run.js +140 -9
- package/dist/lib/runtime/rotation-storage-meta.d.ts.map +1 -1
- package/dist/lib/runtime/rotation-storage-meta.js +8 -2
- package/dist/lib/storage/account-port.d.ts +2 -0
- package/dist/lib/storage/account-port.d.ts.map +1 -1
- package/dist/lib/storage/account-port.js +1 -0
- package/dist/lib/storage/import-export.d.ts +1 -0
- package/dist/lib/storage/import-export.d.ts.map +1 -1
- package/dist/lib/storage/import-export.js +25 -0
- package/dist/lib/storage/project-migration.d.ts +1 -1
- package/dist/lib/storage/project-migration.d.ts.map +1 -1
- package/dist/lib/storage/project-migration.js +28 -2
- package/dist/lib/storage.d.ts +10 -0
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +16 -1
- package/dist/lib/ui/auth-menu-builder.d.ts +10 -0
- package/dist/lib/ui/auth-menu-builder.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu-builder.js +29 -4
- package/package.json +1 -1
- package/scripts/codex.js +126 -13
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { promises as fs } from "node:fs";
|
|
2
2
|
import type { TokenResult } from "./types.js";
|
|
3
|
+
export declare const DEFAULT_WAIT_TIMEOUT_MS = 35000;
|
|
3
4
|
type LeaseFsOps = Pick<typeof fs, "mkdir" | "open" | "writeFile" | "rename" | "unlink" | "readFile" | "stat" | "readdir"> & Partial<Pick<typeof fs, "chmod">>;
|
|
4
5
|
export interface RefreshLeaseCoordinatorOptions {
|
|
5
6
|
enabled?: boolean;
|
|
@@ -24,6 +25,17 @@ export declare class RefreshLeaseCoordinator {
|
|
|
24
25
|
private readonly resultTtlMs;
|
|
25
26
|
private readonly fsOps;
|
|
26
27
|
constructor(options?: RefreshLeaseCoordinatorOptions);
|
|
28
|
+
/**
|
|
29
|
+
* Resolved maximum time `acquire()` may block waiting for a lease.
|
|
30
|
+
*
|
|
31
|
+
* Exposed so the refresh queue can size its acquire-stage eviction threshold
|
|
32
|
+
* against the budget this coordinator ACTUALLY uses. The budget is
|
|
33
|
+
* configurable (constructor option / `CODEX_AUTH_REFRESH_LEASE_WAIT_MS`), so
|
|
34
|
+
* sizing eviction off the static `DEFAULT_WAIT_TIMEOUT_MS` would evict an
|
|
35
|
+
* acquire that is still legitimately waiting under a larger budget, spawning
|
|
36
|
+
* the duplicate refresh (→ `invalid_grant`) the lease exists to prevent.
|
|
37
|
+
*/
|
|
38
|
+
get configuredWaitTimeoutMs(): number;
|
|
27
39
|
static fromEnvironment(): RefreshLeaseCoordinator;
|
|
28
40
|
acquire(refreshToken: string): Promise<RefreshLeaseHandle>;
|
|
29
41
|
private createBypassHandle;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh-lease.d.ts","sourceRoot":"","sources":["../../lib/refresh-lease.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAMrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"refresh-lease.d.ts","sourceRoot":"","sources":["../../lib/refresh-lease.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AAMrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAQ9C,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAsB9C,KAAK,UAAU,GAAG,IAAI,CACrB,OAAO,EAAE,EACT,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CACtF,GACA,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;AAEnC,MAAM,WAAW,8BAA8B;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;IACtC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAyGD,qBAAa,uBAAuB;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;gBAEvB,OAAO,GAAE,8BAAmC;IAUxD;;;;;;;;;OASG;IACH,IAAI,uBAAuB,IAAI,MAAM,CAEpC;IAED,MAAM,CAAC,eAAe,IAAI,uBAAuB;IAgB3C,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA+FhE,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,iBAAiB;YA0CX,QAAQ;YAkBR,WAAW;YAwBX,eAAe;YAiBf,mBAAmB;YAuCnB,qBAAqB;CAsBnC"}
|
|
@@ -8,7 +8,9 @@ import { safeParseTokenResult } from "./schemas.js";
|
|
|
8
8
|
import { isRecord } from "./utils.js";
|
|
9
9
|
const log = createLogger("refresh-lease");
|
|
10
10
|
const DEFAULT_LEASE_TTL_MS = 30_000;
|
|
11
|
-
|
|
11
|
+
// Exported so the refresh queue can size its acquire-stage eviction threshold
|
|
12
|
+
// above the maximum time a lease acquire() may legitimately block waiting.
|
|
13
|
+
export const DEFAULT_WAIT_TIMEOUT_MS = 35_000;
|
|
12
14
|
const DEFAULT_POLL_INTERVAL_MS = 150;
|
|
13
15
|
const DEFAULT_RESULT_TTL_MS = 20_000;
|
|
14
16
|
const RETRYABLE_IO_ERRORS = new Set(["EBUSY", "EPERM", "EMFILE", "ENFILE"]);
|
|
@@ -120,6 +122,19 @@ export class RefreshLeaseCoordinator {
|
|
|
120
122
|
this.resultTtlMs = Math.max(1_000, Math.floor(options.resultTtlMs ?? DEFAULT_RESULT_TTL_MS));
|
|
121
123
|
this.fsOps = options.fsOps ?? fs;
|
|
122
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Resolved maximum time `acquire()` may block waiting for a lease.
|
|
127
|
+
*
|
|
128
|
+
* Exposed so the refresh queue can size its acquire-stage eviction threshold
|
|
129
|
+
* against the budget this coordinator ACTUALLY uses. The budget is
|
|
130
|
+
* configurable (constructor option / `CODEX_AUTH_REFRESH_LEASE_WAIT_MS`), so
|
|
131
|
+
* sizing eviction off the static `DEFAULT_WAIT_TIMEOUT_MS` would evict an
|
|
132
|
+
* acquire that is still legitimately waiting under a larger budget, spawning
|
|
133
|
+
* the duplicate refresh (→ `invalid_grant`) the lease exists to prevent.
|
|
134
|
+
*/
|
|
135
|
+
get configuredWaitTimeoutMs() {
|
|
136
|
+
return this.waitTimeoutMs;
|
|
137
|
+
}
|
|
123
138
|
static fromEnvironment() {
|
|
124
139
|
const testMode = process.env.VITEST === "true" || process.env.NODE_ENV === "test";
|
|
125
140
|
const enabled = parseBooleanEnv(process.env.CODEX_AUTH_REFRESH_LEASE) ??
|
|
@@ -243,7 +258,14 @@ export class RefreshLeaseCoordinator {
|
|
|
243
258
|
return;
|
|
244
259
|
released = true;
|
|
245
260
|
try {
|
|
246
|
-
|
|
261
|
+
// Only ever cache a SUCCESSFUL refresh in the cross-process lease.
|
|
262
|
+
// A `failed` result carries no token material to share; caching it
|
|
263
|
+
// would make readFreshResult serve the failure verbatim to every
|
|
264
|
+
// follower for the whole result TTL (DEFAULT_RESULT_TTL_MS), blocking
|
|
265
|
+
// a real refresh and even escalating to cooldowns. On failure we skip
|
|
266
|
+
// the cache and still unlink the lock in `finally`, so the next caller
|
|
267
|
+
// becomes owner and retries immediately.
|
|
268
|
+
if (result?.type === "success") {
|
|
247
269
|
await this.writeResult(resultPath, tokenHash, result);
|
|
248
270
|
}
|
|
249
271
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh-queue.d.ts","sourceRoot":"","sources":["../../lib/refresh-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"refresh-queue.d.ts","sourceRoot":"","sources":["../../lib/refresh-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,uBAAuB,EAA2B,MAAM,oBAAoB,CAAC;AAqCtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;IAC3D,OAAO,CAAC,cAAc,CAAK;IAE3B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAAkC;IAE1D;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IAEvC;;;OAGG;gBAED,aAAa,GAAE,MAAe,EAC9B,gBAAgB,GAAE,uBAAmE;IAMvF;;;;;;;;OAQG;IACG,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAuHzD,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,sBAAsB;YAShB,kCAAkC;IAchD;;OAEG;YACW,cAAc;IAsE5B;;;OAGG;IACH,OAAO,CAAC,OAAO;IA8Cf;;;;OAIG;IACH,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAI3C;;;OAGG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;CAId;AAQD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,CAKpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAE9E"}
|
|
@@ -10,9 +10,16 @@
|
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
11
|
import { refreshAccessToken } from "./auth/auth.js";
|
|
12
12
|
import { createLogger } from "./logger.js";
|
|
13
|
-
import { RefreshLeaseCoordinator } from "./refresh-lease.js";
|
|
13
|
+
import { RefreshLeaseCoordinator, DEFAULT_WAIT_TIMEOUT_MS } from "./refresh-lease.js";
|
|
14
14
|
import { isAbortError } from "./utils.js";
|
|
15
15
|
const log = createLogger("refresh-queue");
|
|
16
|
+
/**
|
|
17
|
+
* Extra headroom beyond the lease wait budget before an acquire-stage entry is
|
|
18
|
+
* treated as genuinely stuck. A lease acquire() polls on an interval and does
|
|
19
|
+
* filesystem work, so it can overshoot its wait deadline slightly; this slack
|
|
20
|
+
* keeps cleanup from evicting an acquire that is still legitimately waiting.
|
|
21
|
+
*/
|
|
22
|
+
const ACQUIRE_EVICTION_SLACK_MS = 5_000;
|
|
16
23
|
/**
|
|
17
24
|
* Non-reversible correlation fingerprint for a token, for logs.
|
|
18
25
|
*
|
|
@@ -311,11 +318,28 @@ export class RefreshQueue {
|
|
|
311
318
|
*/
|
|
312
319
|
cleanup() {
|
|
313
320
|
const now = Date.now();
|
|
321
|
+
// A lease acquire() can legitimately block up to the coordinator's wait
|
|
322
|
+
// budget. Evicting an acquire-stage entry before that budget elapses would
|
|
323
|
+
// spawn a duplicate refresh whose refresh token OpenAI has already rotated on
|
|
324
|
+
// first use (invalid_grant). So an acquire-stage entry is only evicted once it
|
|
325
|
+
// exceeds BOTH the configured max age AND the lease wait budget plus slack —
|
|
326
|
+
// never merely maxEntryAgeMs, which can be shorter than the wait budget.
|
|
327
|
+
//
|
|
328
|
+
// Read the budget the coordinator was actually CONFIGURED with (constructor
|
|
329
|
+
// option / CODEX_AUTH_REFRESH_LEASE_WAIT_MS) rather than the static default:
|
|
330
|
+
// under a larger configured budget the default would evict too early. An
|
|
331
|
+
// injected test double may not expose the getter, so fall back to the default.
|
|
332
|
+
const configuredWaitTimeoutMs = this.leaseCoordinator.configuredWaitTimeoutMs;
|
|
333
|
+
const leaseWaitTimeoutMs = typeof configuredWaitTimeoutMs === "number" &&
|
|
334
|
+
Number.isFinite(configuredWaitTimeoutMs)
|
|
335
|
+
? configuredWaitTimeoutMs
|
|
336
|
+
: DEFAULT_WAIT_TIMEOUT_MS;
|
|
337
|
+
const acquireEvictionAgeMs = Math.max(this.maxEntryAgeMs, leaseWaitTimeoutMs + ACQUIRE_EVICTION_SLACK_MS);
|
|
314
338
|
for (const [token, entry] of this.pending.entries()) {
|
|
315
339
|
const ageMs = now - entry.startedAt;
|
|
316
|
-
if (ageMs <= this.maxEntryAgeMs)
|
|
317
|
-
continue;
|
|
318
340
|
if (entry.stage === "acquire") {
|
|
341
|
+
if (ageMs <= acquireEvictionAgeMs)
|
|
342
|
+
continue;
|
|
319
343
|
log.warn("Evicting stale refresh entry during lease acquire stage", {
|
|
320
344
|
tokenSuffix: tokenFingerprint(token),
|
|
321
345
|
ageMs,
|
|
@@ -324,6 +348,8 @@ export class RefreshQueue {
|
|
|
324
348
|
this.cleanupRotationMapping(token);
|
|
325
349
|
continue;
|
|
326
350
|
}
|
|
351
|
+
if (ageMs <= this.maxEntryAgeMs)
|
|
352
|
+
continue;
|
|
327
353
|
if (!entry.staleWarningLogged) {
|
|
328
354
|
log.warn("Refresh entry exceeded stale warning threshold", {
|
|
329
355
|
tokenSuffix: tokenFingerprint(token),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-transformer.d.ts","sourceRoot":"","sources":["../../../lib/request/request-transformer.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACX,aAAa,EACb,SAAS,EACT,eAAe,EACf,WAAW,EAEX,UAAU,EACV,MAAM,aAAa,CAAC;AAGrB,KAAK,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAO/C,MAAM,WAAW,0BAA0B;IAC1C,IAAI,EAAE,WAAW,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,6BAA6B,CAAC,EAAE,OAAO,CAAC;IACxC,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACnC;AAID,OAAO,EACN,kBAAkB,EAClB,uCAAuC,GACvC,MAAM,0BAA0B,CAAC;AAElC;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEhE;AAkBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC7B,SAAS,EAAE,MAAM,EACjB,UAAU,GAAE,UAAuC,GACjD,aAAa,CAqEf;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACvC,UAAU,GAAE,UAAuC,GACjD,UAAU,CAUZ;AA4QD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,UAAU,GAAE,aAAkB,GAC5B,eAAe,CAuBjB;AA2DD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,WAAW,CAC1B,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,EAC9B,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9B,SAAS,EAAE,GAAG,SAAS,CAsBzB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,EAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1C,SAAS,EAAE,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"request-transformer.d.ts","sourceRoot":"","sources":["../../../lib/request/request-transformer.ts"],"names":[],"mappings":"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"}
|
|
@@ -487,7 +487,8 @@ export function trimInputForFastSession(input, maxItems, options) {
|
|
|
487
487
|
}
|
|
488
488
|
break;
|
|
489
489
|
}
|
|
490
|
-
|
|
490
|
+
const tailStart = Math.max(0, input.length - safeMax);
|
|
491
|
+
for (let i = tailStart; i < input.length; i++) {
|
|
491
492
|
if (excludedHeadIndexes.has(i))
|
|
492
493
|
continue;
|
|
493
494
|
keepIndexes.add(i);
|
|
@@ -499,7 +500,17 @@ export function trimInputForFastSession(input, maxItems, options) {
|
|
|
499
500
|
return input;
|
|
500
501
|
if (trimmed.length <= safeMax)
|
|
501
502
|
return trimmed;
|
|
502
|
-
|
|
503
|
+
// Kept head items are always the LOWEST kept indexes, so they occupy the first
|
|
504
|
+
// `keptHead` entries of `trimmed`. Reserve budget for exactly that many.
|
|
505
|
+
// Recounting the kept indexes below `tailStart` instead would miss a head
|
|
506
|
+
// instruction that ALSO falls inside the tail window (input.length only just
|
|
507
|
+
// over safeMax), and the tail slice would then drop it. The two slices cannot
|
|
508
|
+
// overlap here: keptHead + tailBudget === safeMax < trimmed.length.
|
|
509
|
+
const tailBudget = Math.max(1, safeMax - keptHead);
|
|
510
|
+
return [
|
|
511
|
+
...trimmed.slice(0, keptHead),
|
|
512
|
+
...trimmed.slice(trimmed.length - tailBudget),
|
|
513
|
+
];
|
|
503
514
|
}
|
|
504
515
|
function isTrivialLatestPrompt(text) {
|
|
505
516
|
const normalized = text.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-handler.d.ts","sourceRoot":"","sources":["../../../lib/request/response-handler.ts"],"names":[],"mappings":"AAwwBA;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;IACT,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B,GACC,OAAO,CAAC,QAAQ,CAAC,CA2HnB;AA6DD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAQ3D;AA2BD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"response-handler.d.ts","sourceRoot":"","sources":["../../../lib/request/response-handler.ts"],"names":[],"mappings":"AAwwBA;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;IACT,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B,GACC,OAAO,CAAC,QAAQ,CAAC,CA2HnB;AA6DD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAQ3D;AA2BD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CA4CtD;AAED,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,GACzC,QAAQ,CAiBV"}
|
|
@@ -787,7 +787,16 @@ export function isEmptyResponse(body) {
|
|
|
787
787
|
const obj = body;
|
|
788
788
|
if (Object.keys(obj).length === 0)
|
|
789
789
|
return true;
|
|
790
|
-
const hasOutput = "output" in obj &&
|
|
790
|
+
const hasOutput = "output" in obj &&
|
|
791
|
+
obj.output !== null &&
|
|
792
|
+
obj.output !== undefined &&
|
|
793
|
+
(Array.isArray(obj.output)
|
|
794
|
+
? obj.output.some((o) => o !== null &&
|
|
795
|
+
o !== undefined &&
|
|
796
|
+
(typeof o !== "object" || Object.keys(o).length > 0))
|
|
797
|
+
: typeof obj.output === "string"
|
|
798
|
+
? obj.output.trim() !== ""
|
|
799
|
+
: true);
|
|
791
800
|
const hasChoices = "choices" in obj &&
|
|
792
801
|
Array.isArray(obj.choices) &&
|
|
793
802
|
obj.choices.some((c) => c !== null &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../lib/rotation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,MAAM,WAAW,iBAAiB;IACjC,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,sBAAsB,EAAE,MAAM,CAAC;CAC/B;AAED,eAAO,MAAM,2BAA2B,EAAE,iBAOzC,CAAC;AAQF,KAAK,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAWlC;;;GAGG;AACH,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,MAAM,CAAoB;gBAEtB,MAAM,GAAE,OAAO,CAAC,iBAAiB,CAAM;IAInD,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,oBAAoB;IAO5B,QAAQ,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IAO3D,sBAAsB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IAMzE,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAiB9D,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAiBhE,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAiB9D,KAAK,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAKtD,KAAK,IAAI,IAAI;IAIb,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAanD;;;;OAIG;IACH,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;CAW7C;AAMD,MAAM,WAAW,iBAAiB;IACjC,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,eAAe,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,2BAA2B,EAAE,iBAGzC,CAAC;
|
|
1
|
+
{"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../lib/rotation.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/rotation.js
CHANGED
|
@@ -132,7 +132,14 @@ export const DEFAULT_TOKEN_BUCKET_CONFIG = {
|
|
|
132
132
|
maxTokens: 50,
|
|
133
133
|
tokensPerMinute: 6,
|
|
134
134
|
};
|
|
135
|
-
|
|
135
|
+
// Must cover the full request lifetime so a token consumed at request start can
|
|
136
|
+
// still be refunded when the request fails at the very end. The runtime proxy
|
|
137
|
+
// refunds on network error / upstream timeout, and the default fetch timeout is
|
|
138
|
+
// 60_000ms (config.ts fetchTimeoutMs) — measured AFTER token consumption and a
|
|
139
|
+
// token refresh. 90_000ms = that 60s timeout plus slack for the refresh and
|
|
140
|
+
// processing, so a genuinely timed-out request's token is reversed instead of
|
|
141
|
+
// leaking (gradual token-bucket starvation -> spurious token-exhausted skips).
|
|
142
|
+
const TOKEN_REFUND_WINDOW_MS = 90_000;
|
|
136
143
|
/**
|
|
137
144
|
* Client-side token bucket for rate limiting requests per account.
|
|
138
145
|
* Prevents sending requests to accounts that are likely to be rate-limited.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ModelFamily } from "../prompts/codex.js";
|
|
2
|
-
import type
|
|
2
|
+
import { type AccountStorageV3, type FlaggedAccountMetadataV1 } from "../storage.js";
|
|
3
3
|
import type { AccountIdSource, TokenResult } from "../types.js";
|
|
4
4
|
import type { AccountCheckWorkingState } from "./account-check-types.js";
|
|
5
5
|
import type { CodexQuotaSnapshot } from "./quota-headers.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-check.d.ts","sourceRoot":"","sources":["../../../lib/runtime/account-check.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"account-check.d.ts","sourceRoot":"","sources":["../../../lib/runtime/account-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { maskEmail } from "../logger.js";
|
|
2
2
|
import { CODEX_UNAVAILABLE_PROBE_NOTE } from "../quota-probe.js";
|
|
3
3
|
import { isCodexUnavailableError } from "../errors.js";
|
|
4
|
+
import { reconcilePinnedAccountIndex, } from "../storage.js";
|
|
4
5
|
export async function runRuntimeAccountCheck(deepProbe, deps) {
|
|
5
6
|
const loadedStorage = await deps.hydrateEmails(await deps.loadAccounts());
|
|
6
7
|
const workingStorage = loadedStorage
|
|
@@ -185,8 +186,15 @@ export async function runRuntimeAccountCheck(deepProbe, deps) {
|
|
|
185
186
|
}
|
|
186
187
|
}
|
|
187
188
|
if (state.removeFromActive.size > 0) {
|
|
189
|
+
// Follow the manual pin by identity across the removal: the filter can drop
|
|
190
|
+
// several accounts at once, so a raw index would point at the wrong account
|
|
191
|
+
// (or out of range, wedging the pool). See #474.
|
|
192
|
+
const pinnedAccount = typeof workingStorage.pinnedAccountIndex === "number"
|
|
193
|
+
? workingStorage.accounts[workingStorage.pinnedAccountIndex]
|
|
194
|
+
: undefined;
|
|
188
195
|
workingStorage.accounts = workingStorage.accounts.filter((account) => !state.removeFromActive.has(account.refreshToken));
|
|
189
196
|
deps.clampRuntimeActiveIndices(workingStorage, deps.MODEL_FAMILIES);
|
|
197
|
+
workingStorage.pinnedAccountIndex = reconcilePinnedAccountIndex(pinnedAccount, workingStorage.accounts);
|
|
190
198
|
state.storageChanged = true;
|
|
191
199
|
}
|
|
192
200
|
const persistAccountAndFlaggedStorage = deps.persistAccountAndFlaggedStorage;
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
export declare const FIRST_RUN_MARKER_VERSION =
|
|
2
|
-
type FirstRunStepStatus = "completed" | "skipped" | "failed";
|
|
1
|
+
export declare const FIRST_RUN_MARKER_VERSION = 2;
|
|
2
|
+
export type FirstRunStepStatus = "completed" | "skipped" | "failed";
|
|
3
3
|
interface FirstRunSetupOutcome {
|
|
4
4
|
appBind: FirstRunStepStatus;
|
|
5
5
|
launcher: FirstRunStepStatus;
|
|
6
|
+
authStore: FirstRunStepStatus;
|
|
6
7
|
}
|
|
7
8
|
type FirstRunSkipReason = "ci" | "not-installed" | "already-done" | "claim-race" | "error";
|
|
8
9
|
export type FirstRunResult = {
|
|
9
10
|
ran: false;
|
|
10
11
|
reason: FirstRunSkipReason;
|
|
12
|
+
} | {
|
|
13
|
+
ran: false;
|
|
14
|
+
reason: "migrated";
|
|
15
|
+
authStore: FirstRunStepStatus;
|
|
11
16
|
} | ({
|
|
12
17
|
ran: true;
|
|
13
18
|
} & FirstRunSetupOutcome);
|
|
@@ -19,6 +24,7 @@ export interface FirstRunSetupDeps {
|
|
|
19
24
|
resolveRotation?: () => boolean;
|
|
20
25
|
bindCodexApp?: () => Promise<FirstRunStepStatus>;
|
|
21
26
|
installLauncher?: () => Promise<FirstRunStepStatus>;
|
|
27
|
+
enforceAuthStore?: () => Promise<FirstRunStepStatus>;
|
|
22
28
|
notify?: (message: string) => void;
|
|
23
29
|
now?: () => number;
|
|
24
30
|
}
|
|
@@ -68,10 +74,10 @@ type LauncherInstallFn = (options: {
|
|
|
68
74
|
*/
|
|
69
75
|
export declare function loadLauncherInstall(candidateOverride?: readonly string[]): Promise<LauncherInstallFn | null>;
|
|
70
76
|
/**
|
|
71
|
-
* Runs the lazily deferred install setup (Codex
|
|
72
|
-
* exactly once per runtime root. Never throws and
|
|
73
|
-
* failure: every error path resolves with a
|
|
74
|
-
* debug-logs sanitized messages.
|
|
77
|
+
* Runs the lazily deferred install setup (Codex auth-store enforcement + app
|
|
78
|
+
* bind + launcher routing) exactly once per runtime root. Never throws and
|
|
79
|
+
* never blocks a command on failure: every error path resolves with a
|
|
80
|
+
* skip/failed status and only debug-logs sanitized messages.
|
|
75
81
|
*/
|
|
76
82
|
export declare function ensureFirstRunSetup(deps?: FirstRunSetupDeps): Promise<FirstRunResult>;
|
|
77
83
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"first-run.d.ts","sourceRoot":"","sources":["../../../lib/runtime/first-run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"first-run.d.ts","sourceRoot":"","sources":["../../../lib/runtime/first-run.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
// a failure is debug-logged (messages only — never tokens or emails) and the
|
|
10
10
|
// command proceeds normally.
|
|
11
11
|
import { randomBytes } from "node:crypto";
|
|
12
|
-
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, } from "node:fs";
|
|
13
13
|
import { open, rename, unlink } from "node:fs/promises";
|
|
14
14
|
import { homedir } from "node:os";
|
|
15
15
|
import { basename, dirname, isAbsolute, join, relative, sep } from "node:path";
|
|
16
16
|
import process from "node:process";
|
|
17
17
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
|
+
import { ensureCodexCliFileAuthStore } from "../codex-cli/writer.js";
|
|
18
19
|
import { getCodexRuntimeRotationProxy, loadPluginConfig } from "../config.js";
|
|
19
20
|
import { withFileOperationRetry } from "../fs-retry.js";
|
|
20
21
|
import { createLogger } from "../logger.js";
|
|
@@ -22,7 +23,8 @@ import { getCodexMultiAuthDir } from "../runtime-paths.js";
|
|
|
22
23
|
import { bindCodexAppRuntimeRotation, getAppBindStatus } from "./app-bind.js";
|
|
23
24
|
const log = createLogger("first-run");
|
|
24
25
|
const FIRST_RUN_MARKER_FILE = "first-run-setup.json";
|
|
25
|
-
|
|
26
|
+
// v2 adds the `authStore` step to the marker payload.
|
|
27
|
+
export const FIRST_RUN_MARKER_VERSION = 2;
|
|
26
28
|
const TRUE_VALUES = new Set(["1", "true", "yes"]);
|
|
27
29
|
const FALSE_VALUES = new Set(["0", "false", "no"]);
|
|
28
30
|
const CI_ENV_KEYS = [
|
|
@@ -202,12 +204,16 @@ async function atomicWriteMarker(target, content) {
|
|
|
202
204
|
});
|
|
203
205
|
}
|
|
204
206
|
async function finalizeFirstRunMarker(markerPath, startedAt, outcome, now) {
|
|
207
|
+
// A failed auth-store step records a pre-v2 version so the next invocation
|
|
208
|
+
// replays it through the migration path — which reruns only that step, never
|
|
209
|
+
// app bind or launcher install.
|
|
205
210
|
const payload = `${JSON.stringify({
|
|
206
|
-
version:
|
|
211
|
+
version: markerVersionFor(outcome.authStore, undefined),
|
|
207
212
|
startedAt,
|
|
208
213
|
completedAt: now(),
|
|
209
214
|
appBind: outcome.appBind,
|
|
210
215
|
launcher: outcome.launcher,
|
|
216
|
+
authStore: outcome.authStore,
|
|
211
217
|
}, null, "\t")}\n`;
|
|
212
218
|
try {
|
|
213
219
|
await atomicWriteMarker(markerPath, payload);
|
|
@@ -254,6 +260,110 @@ async function defaultBindCodexApp(env, rotationEnabled, detectDesktopApp, notif
|
|
|
254
260
|
}
|
|
255
261
|
return "completed";
|
|
256
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Pins the official Codex CLI to the file-backed credential store.
|
|
265
|
+
*
|
|
266
|
+
* Enforcement used to be lazy — it only happened when something called
|
|
267
|
+
* `setCodexCliActiveSelection` (switch, login, health check, repair). A user who
|
|
268
|
+
* installed the package and drove Codex through a third-party front-end could
|
|
269
|
+
* therefore stay on `cli_auth_credentials_store = "keychain"` indefinitely and
|
|
270
|
+
* keep getting macOS login-keychain prompts (issue #641). Doing it at first run
|
|
271
|
+
* closes that window before the official CLI ever reads its store.
|
|
272
|
+
*
|
|
273
|
+
* Deliberately not gated on `isCodexCliSyncEnabled()`: turning CLI sync off is a
|
|
274
|
+
* statement about account mirroring, not a request to re-enable keychain
|
|
275
|
+
* prompts. The `CODEX_MULTI_AUTH_ENFORCE_CLI_FILE_AUTH_STORE=0` opt-out is
|
|
276
|
+
* honored inside `ensureCodexCliFileAuthStore` itself.
|
|
277
|
+
*/
|
|
278
|
+
async function defaultEnforceAuthStore() {
|
|
279
|
+
return (await ensureCodexCliFileAuthStore()) ? "completed" : "skipped";
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Decides the version to persist after an auth-store attempt.
|
|
283
|
+
*
|
|
284
|
+
* Recording the current version after a *failed* step would strand the user:
|
|
285
|
+
* `ensureFirstRunSetup` short-circuits on version alone, so a single transient
|
|
286
|
+
* Windows `EPERM`/`EBUSY` on a locked `config.toml` would leave the CLI on
|
|
287
|
+
* keychain mode permanently — the exact symptom this whole change exists to
|
|
288
|
+
* remove. Staying pre-v2 costs one extra marker read per invocation and
|
|
289
|
+
* self-heals as soon as the write succeeds, because the step is idempotent.
|
|
290
|
+
*
|
|
291
|
+
* `"skipped"` deliberately does bump. It is the normal outcome for a config
|
|
292
|
+
* already pinned to `"file"`, so treating it as unfinished would mean the
|
|
293
|
+
* marker never reaches the current version for healthy installs. It also covers
|
|
294
|
+
* an explicit `CODEX_MULTI_AUTH_ENFORCE_CLI_FILE_AUTH_STORE=0` opt-out — a user
|
|
295
|
+
* choice, not a failure — and if that opt-out is later removed, the
|
|
296
|
+
* wrapper-startup guard and `doctor --fix` both still reconcile the config.
|
|
297
|
+
*/
|
|
298
|
+
function markerVersionFor(authStore, previousVersion) {
|
|
299
|
+
if (authStore === "failed")
|
|
300
|
+
return previousVersion ?? 1;
|
|
301
|
+
return FIRST_RUN_MARKER_VERSION;
|
|
302
|
+
}
|
|
303
|
+
function readFirstRunMarker(markerPath) {
|
|
304
|
+
try {
|
|
305
|
+
const parsed = JSON.parse(readFileSync(markerPath, "utf8"));
|
|
306
|
+
return typeof parsed === "object" && parsed !== null
|
|
307
|
+
? parsed
|
|
308
|
+
: null;
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
// An unreadable or truncated marker is treated as pre-v2 and migrated;
|
|
312
|
+
// the migration only replays the idempotent auth-store step.
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Brings a marker written before the auth-store step existed up to the current
|
|
318
|
+
* version.
|
|
319
|
+
*
|
|
320
|
+
* `ensureFirstRunSetup` short-circuits on marker existence, so bumping
|
|
321
|
+
* `FIRST_RUN_MARKER_VERSION` on its own would leave every already-installed
|
|
322
|
+
* user — precisely the population reporting repeated keychain prompts — without
|
|
323
|
+
* the enforcement step forever.
|
|
324
|
+
*
|
|
325
|
+
* Only the auth-store step is replayed. Rerunning app bind or launcher install
|
|
326
|
+
* would reinstall shortcuts and rebind the desktop app, which the user may have
|
|
327
|
+
* deliberately removed since.
|
|
328
|
+
*
|
|
329
|
+
* No exclusive claim is taken, unlike the initial setup. Both operations here
|
|
330
|
+
* are idempotent and atomic — `ensureCodexCliFileAuthStore` skips a config
|
|
331
|
+
* already on `"file"`, and `atomicWriteMarker` renames into place — so
|
|
332
|
+
* concurrent invocations converge on the same result instead of racing.
|
|
333
|
+
*/
|
|
334
|
+
async function migrateFirstRunMarker(markerPath, marker, deps, now) {
|
|
335
|
+
let authStore;
|
|
336
|
+
try {
|
|
337
|
+
authStore = await (deps.enforceAuthStore
|
|
338
|
+
? deps.enforceAuthStore()
|
|
339
|
+
: defaultEnforceAuthStore());
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
authStore = "failed";
|
|
343
|
+
log.debug("first-run marker migration auth store step skipped", {
|
|
344
|
+
error: errorMessage(error),
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
const payload = `${JSON.stringify({
|
|
348
|
+
version: markerVersionFor(authStore, marker.version),
|
|
349
|
+
startedAt: marker.startedAt ?? now(),
|
|
350
|
+
completedAt: marker.completedAt ?? now(),
|
|
351
|
+
appBind: marker.appBind ?? "skipped",
|
|
352
|
+
launcher: marker.launcher ?? "skipped",
|
|
353
|
+
authStore,
|
|
354
|
+
}, null, "\t")}\n`;
|
|
355
|
+
try {
|
|
356
|
+
await atomicWriteMarker(markerPath, payload);
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
// Leaving the marker at v1 just means the idempotent step runs again on
|
|
360
|
+
// the next invocation, so this is safe to swallow.
|
|
361
|
+
log.debug("first-run marker migration write failed", {
|
|
362
|
+
error: errorMessage(error),
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
return authStore;
|
|
366
|
+
}
|
|
257
367
|
async function defaultInstallLauncher(env, rotationEnabled, notify) {
|
|
258
368
|
if (!shouldInstallCodexAppLauncherOnFirstRun({ env, rotationEnabled })) {
|
|
259
369
|
return "skipped";
|
|
@@ -265,10 +375,10 @@ async function defaultInstallLauncher(env, rotationEnabled, notify) {
|
|
|
265
375
|
return "completed";
|
|
266
376
|
}
|
|
267
377
|
/**
|
|
268
|
-
* Runs the lazily deferred install setup (Codex
|
|
269
|
-
* exactly once per runtime root. Never throws and
|
|
270
|
-
* failure: every error path resolves with a
|
|
271
|
-
* debug-logs sanitized messages.
|
|
378
|
+
* Runs the lazily deferred install setup (Codex auth-store enforcement + app
|
|
379
|
+
* bind + launcher routing) exactly once per runtime root. Never throws and
|
|
380
|
+
* never blocks a command on failure: every error path resolves with a
|
|
381
|
+
* skip/failed status and only debug-logs sanitized messages.
|
|
272
382
|
*/
|
|
273
383
|
export async function ensureFirstRunSetup(deps = {}) {
|
|
274
384
|
try {
|
|
@@ -279,9 +389,18 @@ export async function ensureFirstRunSetup(deps = {}) {
|
|
|
279
389
|
if (!installed)
|
|
280
390
|
return { ran: false, reason: "not-installed" };
|
|
281
391
|
const markerPath = deps.markerPath ?? getFirstRunMarkerPath();
|
|
282
|
-
if (existsSync(markerPath))
|
|
283
|
-
return { ran: false, reason: "already-done" };
|
|
284
392
|
const now = deps.now ?? Date.now;
|
|
393
|
+
if (existsSync(markerPath)) {
|
|
394
|
+
const marker = readFirstRunMarker(markerPath);
|
|
395
|
+
if ((marker?.version ?? 1) >= FIRST_RUN_MARKER_VERSION) {
|
|
396
|
+
return { ran: false, reason: "already-done" };
|
|
397
|
+
}
|
|
398
|
+
return {
|
|
399
|
+
ran: false,
|
|
400
|
+
reason: "migrated",
|
|
401
|
+
authStore: await migrateFirstRunMarker(markerPath, marker ?? {}, deps, now),
|
|
402
|
+
};
|
|
403
|
+
}
|
|
285
404
|
const startedAt = now();
|
|
286
405
|
if (!claimFirstRunMarker(markerPath, startedAt)) {
|
|
287
406
|
return { ran: false, reason: "claim-race" };
|
|
@@ -296,7 +415,19 @@ export async function ensureFirstRunSetup(deps = {}) {
|
|
|
296
415
|
const outcome = {
|
|
297
416
|
appBind: "skipped",
|
|
298
417
|
launcher: "skipped",
|
|
418
|
+
authStore: "skipped",
|
|
299
419
|
};
|
|
420
|
+
try {
|
|
421
|
+
outcome.authStore = await (deps.enforceAuthStore
|
|
422
|
+
? deps.enforceAuthStore()
|
|
423
|
+
: defaultEnforceAuthStore());
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
outcome.authStore = "failed";
|
|
427
|
+
log.debug("first-run codex auth store enforcement skipped", {
|
|
428
|
+
error: errorMessage(error),
|
|
429
|
+
});
|
|
430
|
+
}
|
|
300
431
|
try {
|
|
301
432
|
outcome.appBind = await (deps.bindCodexApp
|
|
302
433
|
? deps.bindCodexApp()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rotation-storage-meta.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-storage-meta.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAqCnE,MAAM,WAAW,WAAW;IAC3B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,kBAAkB,EAAE,MAAM,CAAC;CAC3B;AA8BD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CACtC,WAAW,GAAE,MAAyB,GACpC,WAAW,
|
|
1
|
+
{"version":3,"file":"rotation-storage-meta.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-storage-meta.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAqCnE,MAAM,WAAW,WAAW;IAC3B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,kBAAkB,EAAE,MAAM,CAAC;CAC3B;AA8BD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CACtC,WAAW,GAAE,MAAyB,GACpC,WAAW,CAmFb;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC7C,WAAW,GAAE,MAAyB,GACpC,MAAM,GAAG,IAAI,CAEf;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC9C,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,EACjD,sBAAsB,EAAE,MAAM,EAC9B,WAAW,GAAE,MAAyB,GACpC,MAAM,CAOR"}
|
|
@@ -78,9 +78,15 @@ export function readStorageMetaFromDisk(storagePath = getStoragePath()) {
|
|
|
78
78
|
return metaFromSnapshot(refreshed);
|
|
79
79
|
}
|
|
80
80
|
const parsed = JSON.parse(bytes.toString("utf8"));
|
|
81
|
+
// Validate exactly like readPinAndGenFromDisk / the loader / the zod schema:
|
|
82
|
+
// a non-integer or negative pin is rejected (null), never truncated. This is
|
|
83
|
+
// the value the proxy actually routes on, so a malformed disk pin must not
|
|
84
|
+
// slip past here and reach chooseAccount (a negative index wedges the pool).
|
|
81
85
|
const pinnedAccountIndex = typeof parsed.pinnedAccountIndex === "number" &&
|
|
82
|
-
Number.isFinite(parsed.pinnedAccountIndex)
|
|
83
|
-
|
|
86
|
+
Number.isFinite(parsed.pinnedAccountIndex) &&
|
|
87
|
+
Number.isInteger(parsed.pinnedAccountIndex) &&
|
|
88
|
+
parsed.pinnedAccountIndex >= 0
|
|
89
|
+
? parsed.pinnedAccountIndex
|
|
84
90
|
: null;
|
|
85
91
|
const affinityGeneration = typeof parsed.affinityGeneration === "number" &&
|
|
86
92
|
Number.isFinite(parsed.affinityGeneration) &&
|
|
@@ -33,6 +33,7 @@ export declare function importAccountsSnapshot(params: {
|
|
|
33
33
|
imported: AccountStorageV3;
|
|
34
34
|
maxAccounts: number;
|
|
35
35
|
deduplicateAccounts: (accounts: AccountStorageV3["accounts"]) => AccountStorageV3["accounts"];
|
|
36
|
+
findMatchingAccountIndex: (accounts: AccountStorageV3["accounts"], candidate: AccountStorageV3["accounts"][number]) => number | undefined;
|
|
36
37
|
}) => {
|
|
37
38
|
newStorage: AccountStorageV3;
|
|
38
39
|
imported: number;
|
|
@@ -41,6 +42,7 @@ export declare function importAccountsSnapshot(params: {
|
|
|
41
42
|
};
|
|
42
43
|
maxAccounts: number;
|
|
43
44
|
deduplicateAccounts: (accounts: AccountStorageV3["accounts"]) => AccountStorageV3["accounts"];
|
|
45
|
+
findMatchingAccountIndex: (accounts: AccountStorageV3["accounts"], candidate: AccountStorageV3["accounts"][number]) => number | undefined;
|
|
44
46
|
logInfo: (message: string, details: Record<string, unknown>) => void;
|
|
45
47
|
}): Promise<{
|
|
46
48
|
imported: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-port.d.ts","sourceRoot":"","sources":["../../../lib/storage/account-port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,wBAAsB,sBAAsB,CAAC,MAAM,EAAE;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EACb;QACA,MAAM,EAAE,OAAO,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;KACjC,GACD,SAAS,CAAC;IACb,0BAA0B,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACnE,kBAAkB,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC3D,oBAAoB,EAAE,CAAC,IAAI,EAAE;QAC5B,YAAY,EAAE,MAAM,CAAC;QACrB,KAAK,EAAE,OAAO,CAAC;QACf,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;QACjC,YAAY,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAC9D,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;KACrE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9D,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACrE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBhB;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,CAAC,IAAI,EAAE;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,uBAAuB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,gBAAgB,GAAG,IAAI,CAAC;KACrE,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAChC,uBAAuB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,gBAAgB,GAAG,IAAI,CAAC;IACrE,6BAA6B,EAAE,CAAC,CAAC,EAChC,OAAO,EAAE,CACR,OAAO,EAAE,gBAAgB,GAAG,IAAI,EAChC,OAAO,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,KACjD,OAAO,CAAC,CAAC,CAAC,KACX,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB,qBAAqB,EAAE,CAAC,IAAI,EAAE;QAC7B,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;QAClC,QAAQ,EAAE,gBAAgB,CAAC;QAC3B,WAAW,EAAE,MAAM,CAAC;QACpB,mBAAmB,EAAE,CACpB,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,KAClC,gBAAgB,CAAC,UAAU,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"account-port.d.ts","sourceRoot":"","sources":["../../../lib/storage/account-port.ts"],"names":[],"mappings":"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"}
|