codexuse-cli 6.0.2 → 6.0.4
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/README.md +1 -1
- package/dist/index.js +1027 -402
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2026,7 +2026,7 @@ var require_toml = __commonJS({
|
|
|
2026
2026
|
});
|
|
2027
2027
|
|
|
2028
2028
|
// src/commands/accountPool.ts
|
|
2029
|
-
var
|
|
2029
|
+
var import_node_crypto13 = require("crypto");
|
|
2030
2030
|
var import_node_path13 = __toESM(require("path"));
|
|
2031
2031
|
|
|
2032
2032
|
// ../../packages/contracts/src/settings/types.ts
|
|
@@ -2078,8 +2078,8 @@ function migrateLegacyAccountPoolExposedReasoningDefaults(efforts) {
|
|
|
2078
2078
|
|
|
2079
2079
|
// ../../packages/runtime-app-state/src/app/state.ts
|
|
2080
2080
|
var import_node_async_hooks = require("async_hooks");
|
|
2081
|
-
var
|
|
2082
|
-
var
|
|
2081
|
+
var import_node_crypto2 = require("crypto");
|
|
2082
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
2083
2083
|
var import_node_os = __toESM(require("os"), 1);
|
|
2084
2084
|
|
|
2085
2085
|
// ../../packages/contracts/src/settings/auto-roll.ts
|
|
@@ -2211,16 +2211,98 @@ function normalizeAutoRollSettings(raw) {
|
|
|
2211
2211
|
}
|
|
2212
2212
|
|
|
2213
2213
|
// ../../packages/runtime-app-state/src/storage/documents.ts
|
|
2214
|
+
var import_node_fs2 = require("fs");
|
|
2215
|
+
var import_node_fs3 = require("fs");
|
|
2216
|
+
var import_node_crypto = require("crypto");
|
|
2217
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
2218
|
+
|
|
2219
|
+
// ../../packages/runtime-app-state/src/storage/fileLock.ts
|
|
2214
2220
|
var import_node_fs = require("fs");
|
|
2215
2221
|
var import_node_path = __toESM(require("path"), 1);
|
|
2222
|
+
function isSqliteBusyError(error) {
|
|
2223
|
+
if (!error || typeof error !== "object") {
|
|
2224
|
+
return false;
|
|
2225
|
+
}
|
|
2226
|
+
const value3 = error;
|
|
2227
|
+
if (value3.cause && value3.cause !== error && isSqliteBusyError(value3.cause)) {
|
|
2228
|
+
return true;
|
|
2229
|
+
}
|
|
2230
|
+
if (value3.error && value3.error !== error && isSqliteBusyError(value3.error)) {
|
|
2231
|
+
return true;
|
|
2232
|
+
}
|
|
2233
|
+
const message = typeof value3.message === "string" ? value3.message.toLowerCase() : String(error).toLowerCase();
|
|
2234
|
+
return value3.code === "SQLITE_BUSY" || value3.errno === 5 || message.includes("sqlite_busy") || message.includes("database is locked");
|
|
2235
|
+
}
|
|
2236
|
+
async function openLockDatabase(databasePath) {
|
|
2237
|
+
await import_node_fs.promises.mkdir(import_node_path.default.dirname(databasePath), { recursive: true, mode: 448 });
|
|
2238
|
+
const sqlite = process.versions.bun ? await Function("return import('bun:sqlite')")() : await Function("return import('node:sqlite')")();
|
|
2239
|
+
const database = process.versions.bun ? new sqlite.Database(databasePath) : new sqlite.DatabaseSync(databasePath);
|
|
2240
|
+
try {
|
|
2241
|
+
if (process.platform !== "win32") {
|
|
2242
|
+
await import_node_fs.promises.chmod(databasePath, 384);
|
|
2243
|
+
}
|
|
2244
|
+
return {
|
|
2245
|
+
exec: database.exec.bind(database),
|
|
2246
|
+
close: database.close.bind(database)
|
|
2247
|
+
};
|
|
2248
|
+
} catch (error) {
|
|
2249
|
+
database.close();
|
|
2250
|
+
throw error;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
async function acquireCrossProcessFileLockTransaction(filePath, mode) {
|
|
2254
|
+
const databasePath = `${import_node_path.default.resolve(filePath)}.codexuse-lock.sqlite`;
|
|
2255
|
+
let database = null;
|
|
2256
|
+
try {
|
|
2257
|
+
database = await openLockDatabase(databasePath);
|
|
2258
|
+
database.exec(`PRAGMA busy_timeout = ${mode === "write" ? 1e3 : 0};`);
|
|
2259
|
+
database.exec("CREATE TABLE IF NOT EXISTS codexuse_file_lock (id INTEGER PRIMARY KEY);");
|
|
2260
|
+
if (mode === "write") {
|
|
2261
|
+
database.exec("BEGIN EXCLUSIVE;");
|
|
2262
|
+
} else {
|
|
2263
|
+
database.exec("BEGIN;");
|
|
2264
|
+
database.exec("SELECT COUNT(*) FROM codexuse_file_lock;");
|
|
2265
|
+
}
|
|
2266
|
+
} catch (error) {
|
|
2267
|
+
database?.close();
|
|
2268
|
+
if (isSqliteBusyError(error)) {
|
|
2269
|
+
return null;
|
|
2270
|
+
}
|
|
2271
|
+
throw error;
|
|
2272
|
+
}
|
|
2273
|
+
const acquiredDatabase = database;
|
|
2274
|
+
let released = false;
|
|
2275
|
+
return async () => {
|
|
2276
|
+
if (released) {
|
|
2277
|
+
return;
|
|
2278
|
+
}
|
|
2279
|
+
released = true;
|
|
2280
|
+
try {
|
|
2281
|
+
acquiredDatabase.exec("ROLLBACK;");
|
|
2282
|
+
} finally {
|
|
2283
|
+
acquiredDatabase.close();
|
|
2284
|
+
}
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2287
|
+
async function acquireCrossProcessFileLock(filePath) {
|
|
2288
|
+
return acquireCrossProcessFileLockTransaction(filePath, "write");
|
|
2289
|
+
}
|
|
2290
|
+
async function acquireCrossProcessFileReadLock(filePath) {
|
|
2291
|
+
return acquireCrossProcessFileLockTransaction(filePath, "read");
|
|
2292
|
+
}
|
|
2293
|
+
|
|
2294
|
+
// ../../packages/runtime-app-state/src/storage/documents.ts
|
|
2216
2295
|
var APP_STORAGE_TABLE = "app_storage_documents";
|
|
2217
2296
|
var APP_STORAGE_DB_DIR = "app-state";
|
|
2218
2297
|
var APP_STORAGE_DB_NAME = "state.sqlite";
|
|
2298
|
+
var APP_STORAGE_QUARANTINE_DIR = "quarantine";
|
|
2299
|
+
var APP_STORAGE_RECOVERY_LOG_LIMIT = 50;
|
|
2300
|
+
var APP_STORAGE_QUARANTINE_LIMIT = 3;
|
|
2219
2301
|
var SQLITE_BUSY_TIMEOUT_MS = 5e3;
|
|
2220
2302
|
var SQLITE_BUSY_MAX_ATTEMPTS = 3;
|
|
2221
2303
|
var SQLITE_BUSY_RETRY_DELAY_MS = 100;
|
|
2222
2304
|
var writeQueueByDbPath = /* @__PURE__ */ new Map();
|
|
2223
|
-
var
|
|
2305
|
+
var databaseRecoveryByDbPath = /* @__PURE__ */ new Map();
|
|
2224
2306
|
var AppStorageCorruptionError = class extends Error {
|
|
2225
2307
|
constructor(message, options) {
|
|
2226
2308
|
super(message);
|
|
@@ -2232,6 +2314,13 @@ var AppStorageCorruptionError = class extends Error {
|
|
|
2232
2314
|
}
|
|
2233
2315
|
}
|
|
2234
2316
|
};
|
|
2317
|
+
var recoveryLog = [];
|
|
2318
|
+
function recordRecovery(event) {
|
|
2319
|
+
recoveryLog.push(event);
|
|
2320
|
+
if (recoveryLog.length > APP_STORAGE_RECOVERY_LOG_LIMIT) {
|
|
2321
|
+
recoveryLog.splice(0, recoveryLog.length - APP_STORAGE_RECOVERY_LOG_LIMIT);
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2235
2324
|
function isRecord(value3) {
|
|
2236
2325
|
return Boolean(value3) && typeof value3 === "object" && !Array.isArray(value3);
|
|
2237
2326
|
}
|
|
@@ -2251,53 +2340,239 @@ function safeParseJson(raw) {
|
|
|
2251
2340
|
return null;
|
|
2252
2341
|
}
|
|
2253
2342
|
}
|
|
2254
|
-
function
|
|
2255
|
-
|
|
2256
|
-
return null;
|
|
2257
|
-
}
|
|
2258
|
-
try {
|
|
2259
|
-
return JSON.parse(raw);
|
|
2260
|
-
} catch (error) {
|
|
2261
|
-
throw new AppStorageCorruptionError(
|
|
2262
|
-
`App storage document ${options.namespace} contains invalid JSON.`,
|
|
2263
|
-
{
|
|
2264
|
-
dbPath: options.dbPath,
|
|
2265
|
-
namespace: options.namespace,
|
|
2266
|
-
cause: error
|
|
2267
|
-
}
|
|
2268
|
-
);
|
|
2269
|
-
}
|
|
2343
|
+
function describeError(error) {
|
|
2344
|
+
return error instanceof Error ? error.message : String(error);
|
|
2270
2345
|
}
|
|
2271
2346
|
function sleep(ms) {
|
|
2272
2347
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
2273
2348
|
}
|
|
2274
|
-
function
|
|
2349
|
+
function matchesErrorChain(error, predicate) {
|
|
2275
2350
|
if (!error || typeof error !== "object") {
|
|
2276
2351
|
return false;
|
|
2277
2352
|
}
|
|
2278
|
-
const
|
|
2279
|
-
if (
|
|
2353
|
+
const candidate = error;
|
|
2354
|
+
if (predicate(candidate)) {
|
|
2280
2355
|
return true;
|
|
2281
2356
|
}
|
|
2282
|
-
|
|
2283
|
-
|
|
2357
|
+
for (const key of ["cause", "error"]) {
|
|
2358
|
+
const nested = candidate[key];
|
|
2359
|
+
if (nested && nested !== error && matchesErrorChain(nested, predicate)) {
|
|
2360
|
+
return true;
|
|
2361
|
+
}
|
|
2284
2362
|
}
|
|
2285
|
-
|
|
2286
|
-
|
|
2363
|
+
return false;
|
|
2364
|
+
}
|
|
2365
|
+
function isSqliteBusyError2(error) {
|
|
2366
|
+
return matchesErrorChain(error, (candidate) => {
|
|
2367
|
+
const message = typeof candidate.message === "string" ? candidate.message.toLowerCase() : "";
|
|
2368
|
+
return candidate.code === "SQLITE_BUSY" || candidate.errno === 5 || message.includes("sqlite_busy") || message.includes("database is locked");
|
|
2369
|
+
});
|
|
2287
2370
|
}
|
|
2288
2371
|
function isSqliteCorruptionError(error) {
|
|
2289
|
-
|
|
2290
|
-
|
|
2372
|
+
return matchesErrorChain(error, (candidate) => {
|
|
2373
|
+
const message = typeof candidate.message === "string" ? candidate.message.toLowerCase() : "";
|
|
2374
|
+
return candidate.code === "SQLITE_CORRUPT" || candidate.code === "SQLITE_NOTADB" || candidate.errno === 11 || candidate.errno === 26 || message.includes("database disk image is malformed") || message.includes("file is not a database") || message.includes("database corruption") || message.includes("sqlite_corrupt") || message.includes("sqlite_notadb");
|
|
2375
|
+
});
|
|
2376
|
+
}
|
|
2377
|
+
function isSqliteCantOpenError(error) {
|
|
2378
|
+
return matchesErrorChain(error, (candidate) => {
|
|
2379
|
+
const message = typeof candidate.message === "string" ? candidate.message.toLowerCase() : "";
|
|
2380
|
+
return candidate.code === "SQLITE_CANTOPEN" || message.includes("unable to open database file");
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
var STORAGE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
|
|
2384
|
+
"EACCES",
|
|
2385
|
+
"EPERM",
|
|
2386
|
+
"EROFS",
|
|
2387
|
+
"ENOSPC",
|
|
2388
|
+
"ENOTDIR",
|
|
2389
|
+
"ENAMETOOLONG",
|
|
2390
|
+
"ENOENT",
|
|
2391
|
+
"ELOOP",
|
|
2392
|
+
"EIO",
|
|
2393
|
+
"EMFILE",
|
|
2394
|
+
"ENFILE"
|
|
2395
|
+
]);
|
|
2396
|
+
function isStorageUnavailableError(error) {
|
|
2397
|
+
return matchesErrorChain(error, (candidate) => {
|
|
2398
|
+
const message = typeof candidate.message === "string" ? candidate.message.toLowerCase() : "";
|
|
2399
|
+
return typeof candidate.code === "string" && (STORAGE_UNAVAILABLE_CODES.has(candidate.code) || candidate.code === "SQLITE_READONLY" || candidate.code === "SQLITE_CANTOPEN") || candidate.errno === 8 || message.includes("attempt to write a readonly database") || message.includes("unable to open database file");
|
|
2400
|
+
});
|
|
2401
|
+
}
|
|
2402
|
+
function isAppStorageCorruptionError(error) {
|
|
2403
|
+
return error instanceof AppStorageCorruptionError || isSqliteCorruptionError(error);
|
|
2404
|
+
}
|
|
2405
|
+
function classifyAppStorageFailure(error) {
|
|
2406
|
+
if (isAppStorageCorruptionError(error)) {
|
|
2407
|
+
return "corrupt";
|
|
2291
2408
|
}
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
return true;
|
|
2409
|
+
if (isSqliteBusyError2(error)) {
|
|
2410
|
+
return "busy";
|
|
2295
2411
|
}
|
|
2296
|
-
if (
|
|
2297
|
-
return
|
|
2412
|
+
if (isStorageUnavailableError(error)) {
|
|
2413
|
+
return "unavailable";
|
|
2414
|
+
}
|
|
2415
|
+
return "unknown";
|
|
2416
|
+
}
|
|
2417
|
+
function quarantineDirFor(dbPath) {
|
|
2418
|
+
return import_node_path2.default.join(import_node_path2.default.dirname(dbPath), APP_STORAGE_QUARANTINE_DIR);
|
|
2419
|
+
}
|
|
2420
|
+
function safeFileNamePart(value3) {
|
|
2421
|
+
const cleaned = value3.replace(/[^A-Za-z0-9._-]+/g, "_").slice(0, 80);
|
|
2422
|
+
return cleaned.length > 0 ? cleaned : "unknown";
|
|
2423
|
+
}
|
|
2424
|
+
function quarantineKey(scope2, value3) {
|
|
2425
|
+
const digest = (0, import_node_crypto.createHash)("sha256").update(value3).digest("hex").slice(0, 10);
|
|
2426
|
+
return `${scope2}-${safeFileNamePart(value3)}-${digest}`;
|
|
2427
|
+
}
|
|
2428
|
+
function uniqueQuarantinePath(dir, key, extension) {
|
|
2429
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2430
|
+
return import_node_path2.default.join(dir, `${key}-${stamp}-${(0, import_node_crypto.randomUUID)()}${extension}`);
|
|
2431
|
+
}
|
|
2432
|
+
async function pruneQuarantineCopies(input) {
|
|
2433
|
+
try {
|
|
2434
|
+
const prefix = `${input.key}-`;
|
|
2435
|
+
const names = (await import_node_fs3.promises.readdir(input.dir)).filter((name) => {
|
|
2436
|
+
if (name.startsWith(prefix) && name.endsWith(input.extension)) {
|
|
2437
|
+
return true;
|
|
2438
|
+
}
|
|
2439
|
+
if (!input.legacyPrefix || !name.startsWith(input.legacyPrefix)) {
|
|
2440
|
+
return false;
|
|
2441
|
+
}
|
|
2442
|
+
return input.databaseSidecars ? !name.endsWith("-wal") && !name.endsWith("-shm") : name.endsWith(input.extension);
|
|
2443
|
+
});
|
|
2444
|
+
const copies = await Promise.all(names.map(async (name) => ({
|
|
2445
|
+
name,
|
|
2446
|
+
modifiedAt: (await import_node_fs3.promises.stat(import_node_path2.default.join(input.dir, name))).mtimeMs
|
|
2447
|
+
})));
|
|
2448
|
+
copies.sort(
|
|
2449
|
+
(left, right) => right.modifiedAt - left.modifiedAt || right.name.localeCompare(left.name)
|
|
2450
|
+
);
|
|
2451
|
+
for (const { name } of copies.slice(APP_STORAGE_QUARANTINE_LIMIT)) {
|
|
2452
|
+
const candidate = import_node_path2.default.join(input.dir, name);
|
|
2453
|
+
await import_node_fs3.promises.rm(candidate, { force: true });
|
|
2454
|
+
if (input.databaseSidecars) {
|
|
2455
|
+
await Promise.all([
|
|
2456
|
+
import_node_fs3.promises.rm(`${candidate}-wal`, { force: true }),
|
|
2457
|
+
import_node_fs3.promises.rm(`${candidate}-shm`, { force: true })
|
|
2458
|
+
]);
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
} catch {
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
function stageDamagedDocumentRecovery(input) {
|
|
2465
|
+
let backupPath = null;
|
|
2466
|
+
const key = quarantineKey("document", input.namespace);
|
|
2467
|
+
try {
|
|
2468
|
+
const dir = quarantineDirFor(input.dbPath);
|
|
2469
|
+
(0, import_node_fs2.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
2470
|
+
if (process.platform !== "win32") {
|
|
2471
|
+
(0, import_node_fs2.chmodSync)(dir, 448);
|
|
2472
|
+
}
|
|
2473
|
+
const candidate = uniqueQuarantinePath(dir, key, ".json");
|
|
2474
|
+
(0, import_node_fs2.writeFileSync)(candidate, input.raw ?? "", { flag: "wx", mode: 384 });
|
|
2475
|
+
backupPath = candidate;
|
|
2476
|
+
} catch {
|
|
2477
|
+
}
|
|
2478
|
+
try {
|
|
2479
|
+
withStatement(
|
|
2480
|
+
input.db,
|
|
2481
|
+
`DELETE FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`,
|
|
2482
|
+
(statement) => statement.run(input.namespace)
|
|
2483
|
+
);
|
|
2484
|
+
} catch (error) {
|
|
2485
|
+
if (backupPath) {
|
|
2486
|
+
try {
|
|
2487
|
+
(0, import_node_fs2.rmSync)(backupPath, { force: true });
|
|
2488
|
+
} catch {
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
throw error;
|
|
2492
|
+
}
|
|
2493
|
+
return {
|
|
2494
|
+
event: {
|
|
2495
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2496
|
+
scope: "document",
|
|
2497
|
+
dbPath: input.dbPath,
|
|
2498
|
+
namespace: input.namespace,
|
|
2499
|
+
backupPath,
|
|
2500
|
+
reason: input.reason
|
|
2501
|
+
},
|
|
2502
|
+
quarantineKey: key
|
|
2503
|
+
};
|
|
2504
|
+
}
|
|
2505
|
+
function discardStagedDocumentRecovery(recovery) {
|
|
2506
|
+
if (!recovery?.event.backupPath) {
|
|
2507
|
+
return;
|
|
2508
|
+
}
|
|
2509
|
+
try {
|
|
2510
|
+
(0, import_node_fs2.rmSync)(recovery.event.backupPath, { force: true });
|
|
2511
|
+
} catch {
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
async function finalizeDocumentRecovery(recovery) {
|
|
2515
|
+
if (!recovery) {
|
|
2516
|
+
return;
|
|
2517
|
+
}
|
|
2518
|
+
recordRecovery(recovery.event);
|
|
2519
|
+
await pruneQuarantineCopies({
|
|
2520
|
+
dir: quarantineDirFor(recovery.event.dbPath),
|
|
2521
|
+
key: recovery.quarantineKey,
|
|
2522
|
+
extension: ".json",
|
|
2523
|
+
legacyPrefix: `${safeFileNamePart(recovery.event.namespace ?? "unknown")}-`
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2526
|
+
async function copyDatabaseToQuarantine(dbPath) {
|
|
2527
|
+
const dir = quarantineDirFor(dbPath);
|
|
2528
|
+
await import_node_fs3.promises.mkdir(dir, { recursive: true, mode: 448 });
|
|
2529
|
+
if (process.platform !== "win32") {
|
|
2530
|
+
await import_node_fs3.promises.chmod(dir, 448);
|
|
2531
|
+
}
|
|
2532
|
+
const key = quarantineKey("database", import_node_path2.default.basename(dbPath));
|
|
2533
|
+
const target = uniqueQuarantinePath(dir, key, ".sqlite");
|
|
2534
|
+
const copiedSuffixes = [];
|
|
2535
|
+
try {
|
|
2536
|
+
await import_node_fs3.promises.copyFile(dbPath, target);
|
|
2537
|
+
copiedSuffixes.push("");
|
|
2538
|
+
if (process.platform !== "win32") {
|
|
2539
|
+
await import_node_fs3.promises.chmod(target, 384);
|
|
2540
|
+
}
|
|
2541
|
+
for (const suffix of ["-wal", "-shm"]) {
|
|
2542
|
+
try {
|
|
2543
|
+
await import_node_fs3.promises.copyFile(`${dbPath}${suffix}`, `${target}${suffix}`);
|
|
2544
|
+
copiedSuffixes.push(suffix);
|
|
2545
|
+
if (process.platform !== "win32") {
|
|
2546
|
+
await import_node_fs3.promises.chmod(`${target}${suffix}`, 384);
|
|
2547
|
+
}
|
|
2548
|
+
} catch (error) {
|
|
2549
|
+
if (error.code !== "ENOENT") {
|
|
2550
|
+
throw error;
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
} catch (error) {
|
|
2555
|
+
for (const copiedSuffix of copiedSuffixes) {
|
|
2556
|
+
await import_node_fs3.promises.rm(`${target}${copiedSuffix}`, { force: true }).catch(() => void 0);
|
|
2557
|
+
}
|
|
2558
|
+
throw error;
|
|
2559
|
+
}
|
|
2560
|
+
return { backupPath: target, quarantineKey: key };
|
|
2561
|
+
}
|
|
2562
|
+
async function installReplacementDatabase(dbPath, replacementPath) {
|
|
2563
|
+
for (const suffix of ["-wal", "-shm"]) {
|
|
2564
|
+
await import_node_fs3.promises.rm(`${dbPath}${suffix}`, { force: true });
|
|
2565
|
+
}
|
|
2566
|
+
try {
|
|
2567
|
+
await import_node_fs3.promises.rename(replacementPath, dbPath);
|
|
2568
|
+
} catch (error) {
|
|
2569
|
+
const code = error.code;
|
|
2570
|
+
if (code !== "EEXIST" && code !== "EPERM") {
|
|
2571
|
+
throw error;
|
|
2572
|
+
}
|
|
2573
|
+
await import_node_fs3.promises.copyFile(replacementPath, dbPath);
|
|
2574
|
+
await import_node_fs3.promises.rm(replacementPath, { force: true }).catch(() => void 0);
|
|
2298
2575
|
}
|
|
2299
|
-
const message = typeof sqliteError.message === "string" ? sqliteError.message.toLowerCase() : "";
|
|
2300
|
-
return sqliteError.code === "SQLITE_CORRUPT" || sqliteError.code === "SQLITE_NOTADB" || sqliteError.errno === 11 || sqliteError.errno === 26 || message.includes("database disk image is malformed") || message.includes("file is not a database") || message.includes("database corruption") || message.includes("sqlite_corrupt") || message.includes("sqlite_notadb");
|
|
2301
2576
|
}
|
|
2302
2577
|
function beginImmediate(db) {
|
|
2303
2578
|
db.exec("BEGIN IMMEDIATE");
|
|
@@ -2311,7 +2586,7 @@ function rollback(db) {
|
|
|
2311
2586
|
} catch {
|
|
2312
2587
|
}
|
|
2313
2588
|
}
|
|
2314
|
-
function
|
|
2589
|
+
function withStatement(db, sql, task) {
|
|
2315
2590
|
const statement = db.prepare(sql);
|
|
2316
2591
|
try {
|
|
2317
2592
|
return task(statement);
|
|
@@ -2341,10 +2616,11 @@ function applyConnectionPragmas(db) {
|
|
|
2341
2616
|
db.exec("PRAGMA journal_mode = WAL;");
|
|
2342
2617
|
db.exec("PRAGMA foreign_keys = ON;");
|
|
2343
2618
|
}
|
|
2344
|
-
function
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2619
|
+
function applyReadConnectionPragmas(db) {
|
|
2620
|
+
db.exec(`PRAGMA busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS};`);
|
|
2621
|
+
db.exec("PRAGMA foreign_keys = ON;");
|
|
2622
|
+
}
|
|
2623
|
+
function ensureSchema(db) {
|
|
2348
2624
|
db.exec(`
|
|
2349
2625
|
CREATE TABLE IF NOT EXISTS ${APP_STORAGE_TABLE} (
|
|
2350
2626
|
namespace TEXT PRIMARY KEY,
|
|
@@ -2352,76 +2628,387 @@ function ensureSchema(db, dbPath) {
|
|
|
2352
2628
|
updated_at TEXT NOT NULL
|
|
2353
2629
|
)
|
|
2354
2630
|
`);
|
|
2355
|
-
initializedDbPaths.add(dbPath);
|
|
2356
2631
|
}
|
|
2357
2632
|
async function openDatabase(dbPath) {
|
|
2358
|
-
const dbDir =
|
|
2359
|
-
await
|
|
2633
|
+
const dbDir = import_node_path2.default.dirname(dbPath);
|
|
2634
|
+
await import_node_fs3.promises.mkdir(dbDir, { recursive: true, mode: 448 });
|
|
2360
2635
|
if (process.platform !== "win32") {
|
|
2361
|
-
await
|
|
2636
|
+
await import_node_fs3.promises.chmod(dbDir, 448);
|
|
2362
2637
|
}
|
|
2363
2638
|
if (process.versions.bun !== void 0) {
|
|
2364
2639
|
const sqlite2 = await Function("return import('bun:sqlite')")();
|
|
2365
2640
|
const database2 = new sqlite2.Database(dbPath);
|
|
2366
|
-
|
|
2641
|
+
try {
|
|
2642
|
+
if (process.platform !== "win32") {
|
|
2643
|
+
await import_node_fs3.promises.chmod(dbPath, 384);
|
|
2644
|
+
}
|
|
2645
|
+
return {
|
|
2646
|
+
exec: database2.exec.bind(database2),
|
|
2647
|
+
prepare: database2.prepare.bind(database2),
|
|
2648
|
+
close: database2.close.bind(database2)
|
|
2649
|
+
};
|
|
2650
|
+
} catch (error) {
|
|
2651
|
+
database2.close();
|
|
2652
|
+
throw error;
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
const sqlite = await Function("return import('node:sqlite')")();
|
|
2656
|
+
const database = new sqlite.DatabaseSync(dbPath);
|
|
2657
|
+
try {
|
|
2658
|
+
if (process.platform !== "win32") {
|
|
2659
|
+
await import_node_fs3.promises.chmod(dbPath, 384);
|
|
2660
|
+
}
|
|
2661
|
+
return {
|
|
2662
|
+
exec: database.exec.bind(database),
|
|
2663
|
+
prepare: database.prepare.bind(database),
|
|
2664
|
+
close: database.close.bind(database)
|
|
2665
|
+
};
|
|
2666
|
+
} catch (error) {
|
|
2667
|
+
database.close();
|
|
2668
|
+
throw error;
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
async function openReadOnlyDatabase(dbPath) {
|
|
2672
|
+
if (process.versions.bun !== void 0) {
|
|
2673
|
+
const sqlite2 = await Function("return import('bun:sqlite')")();
|
|
2674
|
+
const database2 = new sqlite2.Database(dbPath, { readonly: true });
|
|
2675
|
+
return {
|
|
2367
2676
|
exec: database2.exec.bind(database2),
|
|
2368
2677
|
prepare: database2.prepare.bind(database2),
|
|
2369
2678
|
close: database2.close.bind(database2)
|
|
2370
2679
|
};
|
|
2371
|
-
if (process.platform !== "win32") {
|
|
2372
|
-
await import_node_fs.promises.chmod(dbPath, 384);
|
|
2373
|
-
}
|
|
2374
|
-
return result3;
|
|
2375
2680
|
}
|
|
2376
2681
|
const sqlite = await Function("return import('node:sqlite')")();
|
|
2377
|
-
const database = new sqlite.DatabaseSync(dbPath);
|
|
2378
|
-
|
|
2682
|
+
const database = new sqlite.DatabaseSync(dbPath, { readOnly: true });
|
|
2683
|
+
return {
|
|
2379
2684
|
exec: database.exec.bind(database),
|
|
2380
2685
|
prepare: database.prepare.bind(database),
|
|
2381
2686
|
close: database.close.bind(database)
|
|
2382
2687
|
};
|
|
2383
|
-
|
|
2384
|
-
|
|
2688
|
+
}
|
|
2689
|
+
function sqliteBusyError(message) {
|
|
2690
|
+
return Object.assign(new Error(message), { code: "SQLITE_BUSY" });
|
|
2691
|
+
}
|
|
2692
|
+
function isMissingStorageTableError(error) {
|
|
2693
|
+
return matchesErrorChain(error, (candidate) => {
|
|
2694
|
+
const message = typeof candidate.message === "string" ? candidate.message.toLowerCase() : "";
|
|
2695
|
+
return message.includes(`no such table: ${APP_STORAGE_TABLE}`);
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
async function acquireDatabaseFileLock(dbPath, mode) {
|
|
2699
|
+
const acquire = mode === "read" ? acquireCrossProcessFileReadLock : acquireCrossProcessFileLock;
|
|
2700
|
+
for (let attempt = 1; attempt <= SQLITE_BUSY_MAX_ATTEMPTS; attempt += 1) {
|
|
2701
|
+
const release = await acquire(dbPath);
|
|
2702
|
+
if (release) {
|
|
2703
|
+
return release;
|
|
2704
|
+
}
|
|
2705
|
+
if (attempt < SQLITE_BUSY_MAX_ATTEMPTS) {
|
|
2706
|
+
await sleep(SQLITE_BUSY_RETRY_DELAY_MS * attempt);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
throw sqliteBusyError(`App storage ${mode} lock is busy.`);
|
|
2710
|
+
}
|
|
2711
|
+
async function probeDatabaseHealth(dbPath) {
|
|
2712
|
+
if (!(0, import_node_fs2.existsSync)(dbPath)) {
|
|
2713
|
+
return "healthy";
|
|
2714
|
+
}
|
|
2715
|
+
let db = null;
|
|
2716
|
+
try {
|
|
2717
|
+
db = await openReadOnlyDatabase(dbPath);
|
|
2718
|
+
applyReadConnectionPragmas(db);
|
|
2719
|
+
const row = withStatement(
|
|
2720
|
+
db,
|
|
2721
|
+
"PRAGMA quick_check(1)",
|
|
2722
|
+
(statement) => statement.get()
|
|
2723
|
+
);
|
|
2724
|
+
return isRecord(row) && Object.values(row).some((value3) => value3 === "ok") ? "healthy" : "corrupt";
|
|
2725
|
+
} catch (error) {
|
|
2726
|
+
if (isAppStorageCorruptionError(error)) {
|
|
2727
|
+
return "corrupt";
|
|
2728
|
+
}
|
|
2729
|
+
throw error;
|
|
2730
|
+
} finally {
|
|
2731
|
+
db?.close();
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
async function readSalvageableDocuments(dbPath) {
|
|
2735
|
+
let db = null;
|
|
2736
|
+
try {
|
|
2737
|
+
db = await openReadOnlyDatabase(dbPath);
|
|
2738
|
+
applyReadConnectionPragmas(db);
|
|
2739
|
+
const rows = withStatement(
|
|
2740
|
+
db,
|
|
2741
|
+
`
|
|
2742
|
+
SELECT
|
|
2743
|
+
namespace,
|
|
2744
|
+
value_json AS valueJson,
|
|
2745
|
+
updated_at AS updatedAt
|
|
2746
|
+
FROM ${APP_STORAGE_TABLE}
|
|
2747
|
+
`,
|
|
2748
|
+
(statement) => statement.all()
|
|
2749
|
+
);
|
|
2750
|
+
return rows.flatMap((row) => {
|
|
2751
|
+
if (!isRecord(row) || typeof row.namespace !== "string" || typeof row.valueJson !== "string" || typeof row.updatedAt !== "string") {
|
|
2752
|
+
return [];
|
|
2753
|
+
}
|
|
2754
|
+
return [{
|
|
2755
|
+
namespace: row.namespace,
|
|
2756
|
+
valueJson: row.valueJson,
|
|
2757
|
+
updatedAt: row.updatedAt
|
|
2758
|
+
}];
|
|
2759
|
+
});
|
|
2760
|
+
} catch (error) {
|
|
2761
|
+
if (isAppStorageCorruptionError(error) || isMissingStorageTableError(error)) {
|
|
2762
|
+
return [];
|
|
2763
|
+
}
|
|
2764
|
+
throw error;
|
|
2765
|
+
} finally {
|
|
2766
|
+
db?.close();
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
async function buildReplacementDatabase(dbPath, rows) {
|
|
2770
|
+
const replacementPath = `${dbPath}.recovery-${(0, import_node_crypto.randomUUID)()}.sqlite`;
|
|
2771
|
+
try {
|
|
2772
|
+
const db = await openDatabase(replacementPath);
|
|
2773
|
+
try {
|
|
2774
|
+
db.exec(`PRAGMA busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS};`);
|
|
2775
|
+
db.exec("PRAGMA journal_mode = DELETE;");
|
|
2776
|
+
db.exec("PRAGMA foreign_keys = ON;");
|
|
2777
|
+
ensureSchema(db);
|
|
2778
|
+
beginImmediate(db);
|
|
2779
|
+
try {
|
|
2780
|
+
for (const row of rows) {
|
|
2781
|
+
withStatement(
|
|
2782
|
+
db,
|
|
2783
|
+
`
|
|
2784
|
+
INSERT INTO ${APP_STORAGE_TABLE} (namespace, value_json, updated_at)
|
|
2785
|
+
VALUES (?, ?, ?)
|
|
2786
|
+
`,
|
|
2787
|
+
(statement) => statement.run(row.namespace, row.valueJson, row.updatedAt)
|
|
2788
|
+
);
|
|
2789
|
+
}
|
|
2790
|
+
commit(db);
|
|
2791
|
+
} catch (error) {
|
|
2792
|
+
rollback(db);
|
|
2793
|
+
throw error;
|
|
2794
|
+
}
|
|
2795
|
+
} finally {
|
|
2796
|
+
db.close();
|
|
2797
|
+
}
|
|
2798
|
+
return replacementPath;
|
|
2799
|
+
} catch (error) {
|
|
2800
|
+
await import_node_fs3.promises.rm(replacementPath, { force: true });
|
|
2801
|
+
throw error;
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
async function restoreQuarantinedDatabase(dbPath, backupPath) {
|
|
2805
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
2806
|
+
if (!(0, import_node_fs2.existsSync)(`${backupPath}${suffix}`) || (0, import_node_fs2.existsSync)(`${dbPath}${suffix}`)) {
|
|
2807
|
+
continue;
|
|
2808
|
+
}
|
|
2809
|
+
try {
|
|
2810
|
+
await import_node_fs3.promises.rename(`${backupPath}${suffix}`, `${dbPath}${suffix}`);
|
|
2811
|
+
} catch {
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
async function performDatabaseRecovery(dbPath, reason) {
|
|
2816
|
+
const release = await acquireDatabaseFileLock(dbPath, "write");
|
|
2817
|
+
try {
|
|
2818
|
+
if (await probeDatabaseHealth(dbPath) === "healthy") {
|
|
2819
|
+
return;
|
|
2820
|
+
}
|
|
2821
|
+
const salvagedRows = await readSalvageableDocuments(dbPath);
|
|
2822
|
+
const replacementPath = await buildReplacementDatabase(dbPath, salvagedRows);
|
|
2823
|
+
let backup = null;
|
|
2824
|
+
try {
|
|
2825
|
+
backup = await copyDatabaseToQuarantine(dbPath);
|
|
2826
|
+
await installReplacementDatabase(dbPath, replacementPath);
|
|
2827
|
+
} catch (error) {
|
|
2828
|
+
await import_node_fs3.promises.rm(replacementPath, { force: true });
|
|
2829
|
+
if (backup) {
|
|
2830
|
+
await restoreQuarantinedDatabase(dbPath, backup.backupPath);
|
|
2831
|
+
}
|
|
2832
|
+
throw error;
|
|
2833
|
+
}
|
|
2834
|
+
recordRecovery({
|
|
2835
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2836
|
+
scope: "database",
|
|
2837
|
+
dbPath,
|
|
2838
|
+
namespace: null,
|
|
2839
|
+
backupPath: backup.backupPath,
|
|
2840
|
+
reason: `${reason} Salvaged ${salvagedRows.length} document(s).`
|
|
2841
|
+
});
|
|
2842
|
+
await pruneQuarantineCopies({
|
|
2843
|
+
dir: quarantineDirFor(dbPath),
|
|
2844
|
+
key: backup.quarantineKey,
|
|
2845
|
+
extension: ".sqlite",
|
|
2846
|
+
databaseSidecars: true,
|
|
2847
|
+
legacyPrefix: `${safeFileNamePart(import_node_path2.default.basename(dbPath))}-`
|
|
2848
|
+
});
|
|
2849
|
+
} finally {
|
|
2850
|
+
await release();
|
|
2385
2851
|
}
|
|
2386
|
-
return result2;
|
|
2387
2852
|
}
|
|
2388
|
-
function
|
|
2389
|
-
|
|
2853
|
+
async function recoverCorruptDatabase(dbPath, reason) {
|
|
2854
|
+
const activeRecovery = databaseRecoveryByDbPath.get(dbPath);
|
|
2855
|
+
if (activeRecovery) {
|
|
2856
|
+
return activeRecovery;
|
|
2857
|
+
}
|
|
2858
|
+
const recovery = performDatabaseRecovery(dbPath, reason);
|
|
2859
|
+
databaseRecoveryByDbPath.set(dbPath, recovery);
|
|
2860
|
+
try {
|
|
2861
|
+
await recovery;
|
|
2862
|
+
} finally {
|
|
2863
|
+
if (databaseRecoveryByDbPath.get(dbPath) === recovery) {
|
|
2864
|
+
databaseRecoveryByDbPath.delete(dbPath);
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2390
2867
|
}
|
|
2391
2868
|
async function withDatabase(dbPath, task) {
|
|
2392
|
-
|
|
2869
|
+
let busyAttempts = 0;
|
|
2870
|
+
let databaseRecovered = false;
|
|
2871
|
+
for (; ; ) {
|
|
2393
2872
|
let db = null;
|
|
2873
|
+
let releaseFileLock = null;
|
|
2874
|
+
let corruption = null;
|
|
2394
2875
|
try {
|
|
2876
|
+
releaseFileLock = await acquireDatabaseFileLock(dbPath, "read");
|
|
2395
2877
|
db = await openDatabase(dbPath);
|
|
2396
2878
|
applyConnectionPragmas(db);
|
|
2397
|
-
ensureSchema(db
|
|
2879
|
+
ensureSchema(db);
|
|
2398
2880
|
return task(db);
|
|
2399
2881
|
} catch (error) {
|
|
2400
|
-
if (error
|
|
2882
|
+
if (isAppStorageCorruptionError(error)) {
|
|
2883
|
+
if (databaseRecovered) {
|
|
2884
|
+
throw error instanceof AppStorageCorruptionError ? error : new AppStorageCorruptionError("App storage database is corrupt.", {
|
|
2885
|
+
dbPath,
|
|
2886
|
+
cause: error
|
|
2887
|
+
});
|
|
2888
|
+
}
|
|
2889
|
+
databaseRecovered = true;
|
|
2890
|
+
corruption = error;
|
|
2891
|
+
} else if (!isSqliteBusyError2(error)) {
|
|
2401
2892
|
throw error;
|
|
2893
|
+
} else {
|
|
2894
|
+
busyAttempts += 1;
|
|
2895
|
+
if (busyAttempts >= SQLITE_BUSY_MAX_ATTEMPTS) {
|
|
2896
|
+
throw error;
|
|
2897
|
+
}
|
|
2402
2898
|
}
|
|
2403
|
-
|
|
2899
|
+
} finally {
|
|
2900
|
+
db?.close();
|
|
2901
|
+
await releaseFileLock?.();
|
|
2902
|
+
}
|
|
2903
|
+
if (corruption) {
|
|
2904
|
+
try {
|
|
2905
|
+
await recoverCorruptDatabase(dbPath, describeError(corruption));
|
|
2906
|
+
} catch (error) {
|
|
2907
|
+
if (isSqliteBusyError2(error) || isStorageUnavailableError(error)) {
|
|
2908
|
+
throw error;
|
|
2909
|
+
}
|
|
2404
2910
|
throw new AppStorageCorruptionError(
|
|
2405
|
-
"App storage database is corrupt.",
|
|
2911
|
+
"App storage database is corrupt and could not be moved aside.",
|
|
2406
2912
|
{ dbPath, cause: error }
|
|
2407
2913
|
);
|
|
2408
2914
|
}
|
|
2409
|
-
|
|
2915
|
+
continue;
|
|
2916
|
+
}
|
|
2917
|
+
await sleep(SQLITE_BUSY_RETRY_DELAY_MS * busyAttempts);
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
async function withReadOnlyDatabase(dbPath, task) {
|
|
2921
|
+
let busyAttempts = 0;
|
|
2922
|
+
let databaseRecovered = false;
|
|
2923
|
+
for (; ; ) {
|
|
2924
|
+
let db = null;
|
|
2925
|
+
let releaseFileLock = null;
|
|
2926
|
+
let corruption = null;
|
|
2927
|
+
let requiresReadWriteFallback = false;
|
|
2928
|
+
try {
|
|
2929
|
+
try {
|
|
2930
|
+
releaseFileLock = await acquireDatabaseFileLock(dbPath, "read");
|
|
2931
|
+
} catch (error) {
|
|
2932
|
+
if (!isStorageUnavailableError(error)) {
|
|
2933
|
+
throw error;
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
db = await openReadOnlyDatabase(dbPath);
|
|
2937
|
+
applyReadConnectionPragmas(db);
|
|
2938
|
+
return task(db);
|
|
2939
|
+
} catch (error) {
|
|
2940
|
+
if (isMissingStorageTableError(error) || isSqliteCantOpenError(error)) {
|
|
2941
|
+
requiresReadWriteFallback = true;
|
|
2942
|
+
} else if (isAppStorageCorruptionError(error)) {
|
|
2943
|
+
if (databaseRecovered) {
|
|
2944
|
+
throw error;
|
|
2945
|
+
}
|
|
2946
|
+
databaseRecovered = true;
|
|
2947
|
+
corruption = error;
|
|
2948
|
+
} else if (!isSqliteBusyError2(error)) {
|
|
2410
2949
|
throw error;
|
|
2950
|
+
} else {
|
|
2951
|
+
busyAttempts += 1;
|
|
2952
|
+
if (busyAttempts >= SQLITE_BUSY_MAX_ATTEMPTS) {
|
|
2953
|
+
throw error;
|
|
2954
|
+
}
|
|
2411
2955
|
}
|
|
2412
2956
|
} finally {
|
|
2413
2957
|
db?.close();
|
|
2958
|
+
await releaseFileLock?.();
|
|
2959
|
+
}
|
|
2960
|
+
if (requiresReadWriteFallback) {
|
|
2961
|
+
return withDatabase(dbPath, task);
|
|
2414
2962
|
}
|
|
2415
|
-
|
|
2963
|
+
if (corruption) {
|
|
2964
|
+
await recoverCorruptDatabase(dbPath, describeError(corruption));
|
|
2965
|
+
continue;
|
|
2966
|
+
}
|
|
2967
|
+
await sleep(SQLITE_BUSY_RETRY_DELAY_MS * busyAttempts);
|
|
2416
2968
|
}
|
|
2417
|
-
|
|
2969
|
+
}
|
|
2970
|
+
async function withReadableDatabase(dbPath, task) {
|
|
2971
|
+
return (0, import_node_fs2.existsSync)(dbPath) ? withReadOnlyDatabase(dbPath, task) : withDatabase(dbPath, task);
|
|
2418
2972
|
}
|
|
2419
2973
|
function resolveAppStorageDbPath(userDataDir) {
|
|
2420
|
-
return
|
|
2974
|
+
return import_node_path2.default.join(userDataDir, APP_STORAGE_DB_DIR, APP_STORAGE_DB_NAME);
|
|
2975
|
+
}
|
|
2976
|
+
function readStrictDocumentRow(input) {
|
|
2977
|
+
const row = withStatement(
|
|
2978
|
+
input.db,
|
|
2979
|
+
`SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`,
|
|
2980
|
+
(statement) => statement.get(input.namespace)
|
|
2981
|
+
);
|
|
2982
|
+
if (!isRecord(row)) {
|
|
2983
|
+
return { kind: "absent" };
|
|
2984
|
+
}
|
|
2985
|
+
const raw = typeof row.valueJson === "string" ? row.valueJson : null;
|
|
2986
|
+
if (raw === null || raw.trim().length === 0) {
|
|
2987
|
+
return { kind: "damaged", raw, reason: "Stored document is empty." };
|
|
2988
|
+
}
|
|
2989
|
+
let parsed;
|
|
2990
|
+
try {
|
|
2991
|
+
parsed = JSON.parse(raw);
|
|
2992
|
+
} catch (error) {
|
|
2993
|
+
return {
|
|
2994
|
+
kind: "damaged",
|
|
2995
|
+
raw,
|
|
2996
|
+
reason: `Stored document is not valid JSON: ${describeError(error)}`
|
|
2997
|
+
};
|
|
2998
|
+
}
|
|
2999
|
+
try {
|
|
3000
|
+
return { kind: "value", value: input.normalize(parsed) };
|
|
3001
|
+
} catch (error) {
|
|
3002
|
+
return {
|
|
3003
|
+
kind: "damaged",
|
|
3004
|
+
raw,
|
|
3005
|
+
reason: `Stored document failed validation: ${describeError(error)}`
|
|
3006
|
+
};
|
|
3007
|
+
}
|
|
2421
3008
|
}
|
|
2422
3009
|
async function readDocument(dbPath, namespace, normalize3) {
|
|
2423
|
-
return
|
|
2424
|
-
const row =
|
|
3010
|
+
return withReadableDatabase(dbPath, (db) => {
|
|
3011
|
+
const row = withStatement(
|
|
2425
3012
|
db,
|
|
2426
3013
|
`SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`,
|
|
2427
3014
|
(statement) => statement.get(namespace)
|
|
@@ -2434,38 +3021,46 @@ async function readDocument(dbPath, namespace, normalize3) {
|
|
|
2434
3021
|
});
|
|
2435
3022
|
}
|
|
2436
3023
|
async function readDocumentStrict(dbPath, namespace, normalize3) {
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
{
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
3024
|
+
const initialRead = await withReadableDatabase(
|
|
3025
|
+
dbPath,
|
|
3026
|
+
(db) => readStrictDocumentRow({ db, namespace, normalize: normalize3 })
|
|
3027
|
+
);
|
|
3028
|
+
if (initialRead.kind === "value") {
|
|
3029
|
+
return initialRead.value;
|
|
3030
|
+
}
|
|
3031
|
+
if (initialRead.kind === "absent") {
|
|
3032
|
+
return null;
|
|
3033
|
+
}
|
|
3034
|
+
const recovered = await withWriteQueue(
|
|
3035
|
+
dbPath,
|
|
3036
|
+
async () => withDatabase(dbPath, (db) => {
|
|
3037
|
+
let stagedRecovery = null;
|
|
3038
|
+
beginImmediate(db);
|
|
3039
|
+
try {
|
|
3040
|
+
const read = readStrictDocumentRow({ db, namespace, normalize: normalize3 });
|
|
3041
|
+
let value3 = null;
|
|
3042
|
+
if (read.kind === "value") {
|
|
3043
|
+
value3 = read.value;
|
|
3044
|
+
} else if (read.kind === "damaged") {
|
|
3045
|
+
stagedRecovery = stageDamagedDocumentRecovery({
|
|
3046
|
+
db,
|
|
3047
|
+
dbPath,
|
|
3048
|
+
namespace,
|
|
3049
|
+
raw: read.raw,
|
|
3050
|
+
reason: read.reason
|
|
3051
|
+
});
|
|
2465
3052
|
}
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
3053
|
+
commit(db);
|
|
3054
|
+
return { value: value3, stagedRecovery };
|
|
3055
|
+
} catch (error) {
|
|
3056
|
+
rollback(db);
|
|
3057
|
+
discardStagedDocumentRecovery(stagedRecovery);
|
|
3058
|
+
throw error;
|
|
3059
|
+
}
|
|
3060
|
+
})
|
|
3061
|
+
);
|
|
3062
|
+
await finalizeDocumentRecovery(recovered.stagedRecovery);
|
|
3063
|
+
return recovered.value;
|
|
2469
3064
|
}
|
|
2470
3065
|
async function writeDocument(dbPath, namespace, value3, options = {}) {
|
|
2471
3066
|
return withWriteQueue(
|
|
@@ -2474,7 +3069,7 @@ async function writeDocument(dbPath, namespace, value3, options = {}) {
|
|
|
2474
3069
|
const normalizedValue = options.cloneValue === false ? value3 : clone(value3);
|
|
2475
3070
|
beginImmediate(db);
|
|
2476
3071
|
try {
|
|
2477
|
-
|
|
3072
|
+
withStatement(
|
|
2478
3073
|
db,
|
|
2479
3074
|
`
|
|
2480
3075
|
INSERT INTO ${APP_STORAGE_TABLE} (namespace, value_json, updated_at)
|
|
@@ -2496,36 +3091,42 @@ async function writeDocument(dbPath, namespace, value3, options = {}) {
|
|
|
2496
3091
|
);
|
|
2497
3092
|
}
|
|
2498
3093
|
async function updateDocument(input) {
|
|
2499
|
-
|
|
3094
|
+
const updated = await withWriteQueue(
|
|
2500
3095
|
input.dbPath,
|
|
2501
3096
|
async () => withDatabase(input.dbPath, (db) => {
|
|
3097
|
+
let stagedRecovery = null;
|
|
2502
3098
|
beginImmediate(db);
|
|
2503
3099
|
try {
|
|
2504
|
-
const row = useStatement(
|
|
2505
|
-
db,
|
|
2506
|
-
`SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`,
|
|
2507
|
-
(statement) => statement.get(input.namespace)
|
|
2508
|
-
);
|
|
2509
3100
|
let current;
|
|
2510
|
-
if (
|
|
2511
|
-
const
|
|
2512
|
-
|
|
2513
|
-
namespace: input.namespace
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
3101
|
+
if (input.strictExisting) {
|
|
3102
|
+
const read = readStrictDocumentRow({
|
|
3103
|
+
db,
|
|
3104
|
+
namespace: input.namespace,
|
|
3105
|
+
normalize: input.normalize
|
|
3106
|
+
});
|
|
3107
|
+
if (read.kind === "damaged") {
|
|
3108
|
+
stagedRecovery = stageDamagedDocumentRecovery({
|
|
3109
|
+
db,
|
|
3110
|
+
dbPath: input.dbPath,
|
|
3111
|
+
namespace: input.namespace,
|
|
3112
|
+
raw: read.raw,
|
|
3113
|
+
reason: read.reason
|
|
3114
|
+
});
|
|
2520
3115
|
}
|
|
2521
|
-
current =
|
|
3116
|
+
current = read.kind === "value" ? read.value : input.fallback();
|
|
2522
3117
|
} else {
|
|
2523
|
-
|
|
3118
|
+
const row = withStatement(
|
|
3119
|
+
db,
|
|
3120
|
+
`SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`,
|
|
3121
|
+
(statement) => statement.get(input.namespace)
|
|
3122
|
+
);
|
|
3123
|
+
const parsed = isRecord(row) ? safeParseJson(row.valueJson) : null;
|
|
3124
|
+
current = input.normalize(parsed ?? input.fallback());
|
|
2524
3125
|
}
|
|
2525
3126
|
const transformInput = input.cloneBeforeTransform === false ? current : clone(current);
|
|
2526
3127
|
const transformed = input.transform(transformInput);
|
|
2527
3128
|
const next = input.normalizeResult === false ? transformed : input.normalize(transformed);
|
|
2528
|
-
|
|
3129
|
+
withStatement(
|
|
2529
3130
|
db,
|
|
2530
3131
|
`
|
|
2531
3132
|
INSERT INTO ${APP_STORAGE_TABLE} (namespace, value_json, updated_at)
|
|
@@ -2538,13 +3139,19 @@ async function updateDocument(input) {
|
|
|
2538
3139
|
(statement) => statement.run(input.namespace, JSON.stringify(next), (/* @__PURE__ */ new Date()).toISOString())
|
|
2539
3140
|
);
|
|
2540
3141
|
commit(db);
|
|
2541
|
-
return
|
|
3142
|
+
return {
|
|
3143
|
+
value: input.cloneResult === false ? next : clone(next),
|
|
3144
|
+
stagedRecovery
|
|
3145
|
+
};
|
|
2542
3146
|
} catch (error) {
|
|
2543
3147
|
rollback(db);
|
|
3148
|
+
discardStagedDocumentRecovery(stagedRecovery);
|
|
2544
3149
|
throw error;
|
|
2545
3150
|
}
|
|
2546
3151
|
})
|
|
2547
3152
|
);
|
|
3153
|
+
await finalizeDocumentRecovery(updated.stagedRecovery);
|
|
3154
|
+
return updated.value;
|
|
2548
3155
|
}
|
|
2549
3156
|
async function deleteDocument(dbPath, namespace) {
|
|
2550
3157
|
await withWriteQueue(
|
|
@@ -2552,7 +3159,7 @@ async function deleteDocument(dbPath, namespace) {
|
|
|
2552
3159
|
async () => withDatabase(dbPath, (db) => {
|
|
2553
3160
|
beginImmediate(db);
|
|
2554
3161
|
try {
|
|
2555
|
-
|
|
3162
|
+
withStatement(
|
|
2556
3163
|
db,
|
|
2557
3164
|
`DELETE FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`,
|
|
2558
3165
|
(statement) => statement.run(namespace)
|
|
@@ -2569,8 +3176,15 @@ async function deleteDocument(dbPath, namespace) {
|
|
|
2569
3176
|
// ../../packages/runtime-app-state/src/app/state.ts
|
|
2570
3177
|
var APP_STATE_DOCUMENT = "desktop.app-state";
|
|
2571
3178
|
var APP_NAME = "codexuse-desktop";
|
|
3179
|
+
var PERSISTENCE_RETRY_COOLDOWN_MS = 5e3;
|
|
3180
|
+
var PERSISTENCE_READ_DEADLINE_MS = 8e3;
|
|
3181
|
+
var READ_TOO_SLOW = /* @__PURE__ */ Symbol("app-state-read-too-slow");
|
|
2572
3182
|
var configuredUserDataDir = null;
|
|
2573
3183
|
var appStateCache = null;
|
|
3184
|
+
var ephemeralAppState = null;
|
|
3185
|
+
var persistenceFailure = null;
|
|
3186
|
+
var pendingRendererUiPatch = null;
|
|
3187
|
+
var nextPersistenceRetryAt = 0;
|
|
2574
3188
|
var writeLock = Promise.resolve();
|
|
2575
3189
|
var writeLockContext = new import_node_async_hooks.AsyncLocalStorage();
|
|
2576
3190
|
function isRecord2(value3) {
|
|
@@ -2601,7 +3215,7 @@ function resolveDefaultUserDataDir() {
|
|
|
2601
3215
|
if (!home) {
|
|
2602
3216
|
throw new Error("Unable to resolve home directory for app state.");
|
|
2603
3217
|
}
|
|
2604
|
-
return
|
|
3218
|
+
return import_node_path3.default.join(home, "Library", "Application Support", APP_NAME);
|
|
2605
3219
|
}
|
|
2606
3220
|
function getUserDataDir() {
|
|
2607
3221
|
return configuredUserDataDir ?? resolveDefaultUserDataDir();
|
|
@@ -2638,7 +3252,7 @@ function createDefaultAppState() {
|
|
|
2638
3252
|
desktopLlmEnabled: false,
|
|
2639
3253
|
desktopLlmRegistry: {
|
|
2640
3254
|
version: 3,
|
|
2641
|
-
revision: (0,
|
|
3255
|
+
revision: (0, import_node_crypto2.createHash)("sha256").update("empty").digest("hex"),
|
|
2642
3256
|
providers: [],
|
|
2643
3257
|
routes: [],
|
|
2644
3258
|
externalProfiles: []
|
|
@@ -2933,7 +3547,7 @@ function normalizeOfficialCodexRelayProfile(value3) {
|
|
|
2933
3547
|
}
|
|
2934
3548
|
function migrateDesktopLlmRegistry(profiles) {
|
|
2935
3549
|
const entries3 = Object.values(profiles).filter((profile) => Boolean(profile.model)).sort((left, right) => left.id.localeCompare(right.id));
|
|
2936
|
-
const revision = (0,
|
|
3550
|
+
const revision = (0, import_node_crypto2.createHash)("sha256").update(
|
|
2937
3551
|
JSON.stringify(
|
|
2938
3552
|
entries3.map((profile) => [
|
|
2939
3553
|
profile.id,
|
|
@@ -3257,7 +3871,7 @@ function normalizeDesktopLlmRegistry(value3, profiles) {
|
|
|
3257
3871
|
externalProfiles.sort((left, right) => left.updatedAt.localeCompare(right.updatedAt)).map((profile) => [profile.id, profile])
|
|
3258
3872
|
).values()
|
|
3259
3873
|
).sort((left, right) => left.id.localeCompare(right.id));
|
|
3260
|
-
const revision = (0,
|
|
3874
|
+
const revision = (0, import_node_crypto2.createHash)("sha256").update(
|
|
3261
3875
|
JSON.stringify({
|
|
3262
3876
|
providers: providers.map((provider) => ({
|
|
3263
3877
|
id: provider.id,
|
|
@@ -3898,10 +4512,10 @@ function normalizeAppState(raw) {
|
|
|
3898
4512
|
([rootPath, profileName]) => {
|
|
3899
4513
|
const normalizedRoot = asString(rootPath);
|
|
3900
4514
|
const normalizedProfile = asString(profileName);
|
|
3901
|
-
if (!normalizedRoot || !
|
|
4515
|
+
if (!normalizedRoot || !import_node_path3.default.isAbsolute(normalizedRoot) || !normalizedProfile) {
|
|
3902
4516
|
return [];
|
|
3903
4517
|
}
|
|
3904
|
-
return [[
|
|
4518
|
+
return [[import_node_path3.default.normalize(normalizedRoot), normalizedProfile]];
|
|
3905
4519
|
}
|
|
3906
4520
|
)
|
|
3907
4521
|
);
|
|
@@ -3942,22 +4556,85 @@ async function readAppStateFromStorage() {
|
|
|
3942
4556
|
normalizeAppState
|
|
3943
4557
|
);
|
|
3944
4558
|
}
|
|
3945
|
-
async function
|
|
3946
|
-
|
|
3947
|
-
return
|
|
4559
|
+
async function readStoredAppStateOrNull() {
|
|
4560
|
+
try {
|
|
4561
|
+
return await readStoredAppStateForInit();
|
|
4562
|
+
} catch (error) {
|
|
4563
|
+
persistenceFailure = {
|
|
4564
|
+
kind: classifyAppStorageFailure(error),
|
|
4565
|
+
message: error instanceof Error ? error.message : String(error)
|
|
4566
|
+
};
|
|
4567
|
+
nextPersistenceRetryAt = Date.now() + PERSISTENCE_RETRY_COOLDOWN_MS;
|
|
4568
|
+
return null;
|
|
3948
4569
|
}
|
|
3949
|
-
|
|
4570
|
+
}
|
|
4571
|
+
async function readStoredAppStateForInit() {
|
|
4572
|
+
const stored = await readAppStateFromStorage();
|
|
4573
|
+
if (stored && !pendingRendererUiPatch) {
|
|
4574
|
+
return stored;
|
|
4575
|
+
}
|
|
4576
|
+
const pendingUiPatch = pendingRendererUiPatch;
|
|
4577
|
+
const initialized = await updateDocument({
|
|
3950
4578
|
dbPath: resolveStorageDbPath(),
|
|
3951
4579
|
namespace: APP_STATE_DOCUMENT,
|
|
3952
4580
|
normalize: normalizeAppState,
|
|
3953
4581
|
fallback: () => normalizeAppState(null),
|
|
3954
|
-
transform: (current) => current,
|
|
4582
|
+
transform: (current) => pendingUiPatch ? deepMerge(current, { ui: pendingUiPatch }) : current,
|
|
3955
4583
|
cloneBeforeTransform: false,
|
|
3956
4584
|
cloneResult: false,
|
|
3957
4585
|
strictExisting: true
|
|
3958
4586
|
});
|
|
3959
|
-
|
|
3960
|
-
|
|
4587
|
+
if (pendingRendererUiPatch === pendingUiPatch) {
|
|
4588
|
+
pendingRendererUiPatch = null;
|
|
4589
|
+
}
|
|
4590
|
+
return initialized;
|
|
4591
|
+
}
|
|
4592
|
+
function degradeToMemory(kind, message) {
|
|
4593
|
+
persistenceFailure = { kind, message };
|
|
4594
|
+
nextPersistenceRetryAt = Date.now() + PERSISTENCE_RETRY_COOLDOWN_MS;
|
|
4595
|
+
if (appStateCache) {
|
|
4596
|
+
return appStateCache;
|
|
4597
|
+
}
|
|
4598
|
+
ephemeralAppState = ephemeralAppState ?? freezeDeep(normalizeAppState(null));
|
|
4599
|
+
return ephemeralAppState;
|
|
4600
|
+
}
|
|
4601
|
+
async function ensureInitialized() {
|
|
4602
|
+
if (appStateCache && !persistenceFailure) {
|
|
4603
|
+
return appStateCache;
|
|
4604
|
+
}
|
|
4605
|
+
const memoryState = appStateCache ?? ephemeralAppState;
|
|
4606
|
+
if (memoryState && Date.now() < nextPersistenceRetryAt) {
|
|
4607
|
+
return memoryState;
|
|
4608
|
+
}
|
|
4609
|
+
const attempt = readStoredAppStateForInit();
|
|
4610
|
+
attempt.catch(() => void 0);
|
|
4611
|
+
let deadlineTimer;
|
|
4612
|
+
const deadline = new Promise((resolve2) => {
|
|
4613
|
+
deadlineTimer = setTimeout(
|
|
4614
|
+
() => resolve2(READ_TOO_SLOW),
|
|
4615
|
+
PERSISTENCE_READ_DEADLINE_MS
|
|
4616
|
+
);
|
|
4617
|
+
});
|
|
4618
|
+
try {
|
|
4619
|
+
const outcome = await Promise.race([attempt, deadline]);
|
|
4620
|
+
if (outcome === READ_TOO_SLOW) {
|
|
4621
|
+
return degradeToMemory(
|
|
4622
|
+
"busy",
|
|
4623
|
+
`Saved app state did not load within ${PERSISTENCE_READ_DEADLINE_MS}ms.`
|
|
4624
|
+
);
|
|
4625
|
+
}
|
|
4626
|
+
appStateCache = freezeDeep(outcome);
|
|
4627
|
+
ephemeralAppState = null;
|
|
4628
|
+
persistenceFailure = null;
|
|
4629
|
+
return appStateCache;
|
|
4630
|
+
} catch (error) {
|
|
4631
|
+
return degradeToMemory(
|
|
4632
|
+
classifyAppStorageFailure(error),
|
|
4633
|
+
error instanceof Error ? error.message : String(error)
|
|
4634
|
+
);
|
|
4635
|
+
} finally {
|
|
4636
|
+
clearTimeout(deadlineTimer);
|
|
4637
|
+
}
|
|
3961
4638
|
}
|
|
3962
4639
|
async function withWriteLock(task) {
|
|
3963
4640
|
if (writeLockContext.getStore()) {
|
|
@@ -3981,7 +4658,10 @@ async function initializeAppState(userDataDir) {
|
|
|
3981
4658
|
if (configuredUserDataDir !== userDataDir) {
|
|
3982
4659
|
configuredUserDataDir = userDataDir;
|
|
3983
4660
|
appStateCache = null;
|
|
3984
|
-
|
|
4661
|
+
ephemeralAppState = null;
|
|
4662
|
+
persistenceFailure = null;
|
|
4663
|
+
pendingRendererUiPatch = null;
|
|
4664
|
+
nextPersistenceRetryAt = 0;
|
|
3985
4665
|
}
|
|
3986
4666
|
const state = await ensureInitialized();
|
|
3987
4667
|
return state;
|
|
@@ -3992,8 +4672,13 @@ async function getAppState() {
|
|
|
3992
4672
|
}
|
|
3993
4673
|
async function refreshAppStateCache() {
|
|
3994
4674
|
return withWriteLock(async () => {
|
|
3995
|
-
const
|
|
3996
|
-
|
|
4675
|
+
const stored = await readStoredAppStateOrNull();
|
|
4676
|
+
if (!stored) {
|
|
4677
|
+
return ensureInitialized();
|
|
4678
|
+
}
|
|
4679
|
+
appStateCache = freezeDeep(stored);
|
|
4680
|
+
ephemeralAppState = null;
|
|
4681
|
+
persistenceFailure = null;
|
|
3997
4682
|
return appStateCache;
|
|
3998
4683
|
});
|
|
3999
4684
|
}
|
|
@@ -4001,24 +4686,40 @@ async function updateAppState(transform3, options = {}) {
|
|
|
4001
4686
|
const mode = options.mode ?? "patch";
|
|
4002
4687
|
return withWriteLock(async () => {
|
|
4003
4688
|
const shouldNormalize = options.normalize !== false;
|
|
4004
|
-
const
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4689
|
+
const pendingUiPatch = pendingRendererUiPatch;
|
|
4690
|
+
try {
|
|
4691
|
+
const stored = await updateDocument({
|
|
4692
|
+
dbPath: resolveStorageDbPath(),
|
|
4693
|
+
namespace: APP_STATE_DOCUMENT,
|
|
4694
|
+
normalize: normalizeAppState,
|
|
4695
|
+
fallback: () => normalizeAppState(null),
|
|
4696
|
+
cloneBeforeTransform: false,
|
|
4697
|
+
normalizeResult: shouldNormalize,
|
|
4698
|
+
cloneResult: false,
|
|
4699
|
+
strictExisting: true,
|
|
4700
|
+
transform: (current) => {
|
|
4701
|
+
const transformed = transform3(
|
|
4702
|
+
options.cloneCurrent === false ? current : clone2(current)
|
|
4703
|
+
);
|
|
4704
|
+
const next = mode === "replace" ? transformed : deepMerge(current, transformed);
|
|
4705
|
+
return pendingUiPatch ? deepMerge(next, { ui: pendingUiPatch }) : next;
|
|
4706
|
+
}
|
|
4707
|
+
});
|
|
4708
|
+
if (pendingRendererUiPatch === pendingUiPatch) {
|
|
4709
|
+
pendingRendererUiPatch = null;
|
|
4018
4710
|
}
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4711
|
+
appStateCache = freezeDeep(stored);
|
|
4712
|
+
ephemeralAppState = null;
|
|
4713
|
+
persistenceFailure = null;
|
|
4714
|
+
return appStateCache;
|
|
4715
|
+
} catch (error) {
|
|
4716
|
+
persistenceFailure = {
|
|
4717
|
+
kind: classifyAppStorageFailure(error),
|
|
4718
|
+
message: error instanceof Error ? error.message : String(error)
|
|
4719
|
+
};
|
|
4720
|
+
nextPersistenceRetryAt = Date.now() + PERSISTENCE_RETRY_COOLDOWN_MS;
|
|
4721
|
+
throw error;
|
|
4722
|
+
}
|
|
4022
4723
|
});
|
|
4023
4724
|
}
|
|
4024
4725
|
async function patchAppState(patch) {
|
|
@@ -4131,7 +4832,7 @@ async function updateAppSettings(transform3, onUpdated) {
|
|
|
4131
4832
|
}
|
|
4132
4833
|
|
|
4133
4834
|
// ../../packages/runtime-profiles/src/license/service.ts
|
|
4134
|
-
var
|
|
4835
|
+
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
4135
4836
|
|
|
4136
4837
|
// ../../packages/runtime-codex/src/codex/settings.ts
|
|
4137
4838
|
function asString2(value3) {
|
|
@@ -4370,10 +5071,10 @@ async function writeCodexSettingsJsonRaw(payload) {
|
|
|
4370
5071
|
}
|
|
4371
5072
|
|
|
4372
5073
|
// ../../packages/runtime-profiles/src/license/secret.ts
|
|
4373
|
-
var
|
|
5074
|
+
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
4374
5075
|
var LICENSE_SECRET_DOCUMENT = "desktop.license-secret";
|
|
4375
5076
|
async function generateSecret() {
|
|
4376
|
-
return
|
|
5077
|
+
return import_node_crypto3.default.randomBytes(32).toString("hex");
|
|
4377
5078
|
}
|
|
4378
5079
|
function normalizeSecret(value3) {
|
|
4379
5080
|
return typeof value3 === "string" ? value3.trim() : "";
|
|
@@ -4434,10 +5135,10 @@ function buildCheckoutUrl(offer2, options) {
|
|
|
4434
5135
|
}
|
|
4435
5136
|
|
|
4436
5137
|
// ../../packages/runtime-profiles/src/license/trial.ts
|
|
4437
|
-
var
|
|
5138
|
+
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
4438
5139
|
|
|
4439
5140
|
// ../../packages/runtime-profiles/src/license/device-id.ts
|
|
4440
|
-
var
|
|
5141
|
+
var import_node_crypto4 = __toESM(require("crypto"), 1);
|
|
4441
5142
|
var import_promises = require("fs/promises");
|
|
4442
5143
|
var import_node_child_process = require("child_process");
|
|
4443
5144
|
var import_node_util = require("util");
|
|
@@ -4480,7 +5181,7 @@ async function readLinuxMachineId() {
|
|
|
4480
5181
|
return null;
|
|
4481
5182
|
}
|
|
4482
5183
|
function hashDeviceComponent(value3) {
|
|
4483
|
-
return
|
|
5184
|
+
return import_node_crypto4.default.createHash("sha256").update(`codexuse-device:${value3}`).digest("hex");
|
|
4484
5185
|
}
|
|
4485
5186
|
async function getDeviceId() {
|
|
4486
5187
|
if (memoizedDeviceId) {
|
|
@@ -4501,7 +5202,7 @@ async function getDeviceId() {
|
|
|
4501
5202
|
memoizedDeviceId = cached2;
|
|
4502
5203
|
return cached2;
|
|
4503
5204
|
}
|
|
4504
|
-
const seed =
|
|
5205
|
+
const seed = import_node_crypto4.default.randomBytes(32).toString("hex");
|
|
4505
5206
|
const deviceId = hashDeviceComponent(seed);
|
|
4506
5207
|
await writeDocument(dbPath, DEVICE_ID_DOCUMENT, deviceId);
|
|
4507
5208
|
memoizedDeviceId = deviceId;
|
|
@@ -4512,7 +5213,7 @@ function hashEmail(email) {
|
|
|
4512
5213
|
if (!normalized) {
|
|
4513
5214
|
return null;
|
|
4514
5215
|
}
|
|
4515
|
-
return
|
|
5216
|
+
return import_node_crypto4.default.createHash("sha256").update(`codexuse-email:${normalized}`).digest("hex");
|
|
4516
5217
|
}
|
|
4517
5218
|
|
|
4518
5219
|
// ../../packages/runtime-profiles/src/license/trial-client.ts
|
|
@@ -4567,17 +5268,17 @@ async function registerTrialWithServer(input) {
|
|
|
4567
5268
|
}
|
|
4568
5269
|
|
|
4569
5270
|
// ../../packages/runtime-profiles/src/license/trial-token-store.ts
|
|
4570
|
-
var
|
|
5271
|
+
var import_node_crypto5 = require("crypto");
|
|
4571
5272
|
var import_node_child_process2 = require("child_process");
|
|
4572
5273
|
var KEYCHAIN_SERVICE = "CODEXUSE_TRIAL_TOKEN";
|
|
4573
5274
|
var KEYCHAIN_ACCOUNT_PREFIX = "device-sha256:";
|
|
4574
5275
|
var FALLBACK_DOCUMENT_PREFIX = "desktop.trial-token.";
|
|
4575
5276
|
function keychainAccountForDevice(deviceId) {
|
|
4576
|
-
const digest = (0,
|
|
5277
|
+
const digest = (0, import_node_crypto5.createHash)("sha256").update(deviceId).digest("hex");
|
|
4577
5278
|
return KEYCHAIN_ACCOUNT_PREFIX + digest;
|
|
4578
5279
|
}
|
|
4579
5280
|
function fallbackDocumentForDevice(deviceId) {
|
|
4580
|
-
const digest = (0,
|
|
5281
|
+
const digest = (0, import_node_crypto5.createHash)("sha256").update(deviceId).digest("hex");
|
|
4581
5282
|
return FALLBACK_DOCUMENT_PREFIX + digest;
|
|
4582
5283
|
}
|
|
4583
5284
|
function normalizeToken(value3) {
|
|
@@ -4681,7 +5382,7 @@ function trialSignaturePayload(trial) {
|
|
|
4681
5382
|
});
|
|
4682
5383
|
}
|
|
4683
5384
|
function signTrial(trial, secret) {
|
|
4684
|
-
return
|
|
5385
|
+
return import_node_crypto6.default.createHmac("sha256", secret).update(trialSignaturePayload(trial)).digest("hex");
|
|
4685
5386
|
}
|
|
4686
5387
|
function withTrialSignature(trial, secret) {
|
|
4687
5388
|
return { ...trial, signature: signTrial(trial, secret) };
|
|
@@ -4995,7 +5696,7 @@ function licenseSignaturePayload(license) {
|
|
|
4995
5696
|
return JSON.stringify(payload);
|
|
4996
5697
|
}
|
|
4997
5698
|
function signLicense(license, secret) {
|
|
4998
|
-
return
|
|
5699
|
+
return import_node_crypto7.default.createHmac("sha256", secret).update(licenseSignaturePayload(license)).digest("hex");
|
|
4999
5700
|
}
|
|
5000
5701
|
function withSignature(license, secret) {
|
|
5001
5702
|
return {
|
|
@@ -5303,7 +6004,7 @@ var LicenseService = class {
|
|
|
5303
6004
|
throw new Error("License key is required.");
|
|
5304
6005
|
}
|
|
5305
6006
|
const secret = await getLicenseSecret();
|
|
5306
|
-
const digest =
|
|
6007
|
+
const digest = import_node_crypto7.default.createHash("sha256").update(trimmed).digest("hex");
|
|
5307
6008
|
const result2 = await requestGumroadVerify(trimmed, "activation");
|
|
5308
6009
|
ensureWithinUseLimit(result2);
|
|
5309
6010
|
const normalized = normalizeVerificationResult(result2, "activation");
|
|
@@ -5366,7 +6067,7 @@ function shouldEnforceProfileLimit(status) {
|
|
|
5366
6067
|
}
|
|
5367
6068
|
|
|
5368
6069
|
// ../../packages/runtime-profiles/src/profiles/profile-manager.ts
|
|
5369
|
-
var
|
|
6070
|
+
var import_node_crypto12 = require("crypto");
|
|
5370
6071
|
var import_fs = require("fs");
|
|
5371
6072
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
5372
6073
|
var import_path = __toESM(require("path"), 1);
|
|
@@ -5425,29 +6126,29 @@ function resolveProfileIdentityKeyFromProfile(profile) {
|
|
|
5425
6126
|
|
|
5426
6127
|
// ../../packages/runtime-codex/src/codex/rpc.ts
|
|
5427
6128
|
var import_node_child_process5 = require("child_process");
|
|
5428
|
-
var
|
|
6129
|
+
var import_node_crypto9 = require("crypto");
|
|
5429
6130
|
var import_node_readline = __toESM(require("readline"), 1);
|
|
5430
|
-
var
|
|
6131
|
+
var import_node_fs6 = require("fs");
|
|
5431
6132
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
5432
6133
|
var import_node_path9 = __toESM(require("path"), 1);
|
|
5433
6134
|
|
|
5434
6135
|
// ../../packages/runtime-codex/src/codex/cli.ts
|
|
5435
|
-
var
|
|
5436
|
-
var
|
|
6136
|
+
var import_node_fs4 = require("fs");
|
|
6137
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
5437
6138
|
var STABLE_CHANNEL = "stable";
|
|
5438
6139
|
var ENV_HINTS = ["CODEX_BINARY", "CODEX_CLI_PATH", "CODEX_PATH"];
|
|
5439
6140
|
var cachedStatus = null;
|
|
5440
6141
|
function getPathHintEntries() {
|
|
5441
6142
|
const homeDir = process.env.HOME ?? "";
|
|
5442
6143
|
const homeEntries = homeDir ? [
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
6144
|
+
import_node_path4.default.join(homeDir, ".local", "bin"),
|
|
6145
|
+
import_node_path4.default.join(homeDir, ".fnm", "aliases", "default", "bin"),
|
|
6146
|
+
import_node_path4.default.join(homeDir, ".fnm", "current", "bin"),
|
|
6147
|
+
import_node_path4.default.join(homeDir, ".volta", "bin"),
|
|
6148
|
+
import_node_path4.default.join(homeDir, ".asdf", "shims"),
|
|
6149
|
+
import_node_path4.default.join(homeDir, ".bun", "bin")
|
|
5449
6150
|
] : [];
|
|
5450
|
-
const configuredHints = (process.env.CODEX_PATH_HINTS ?? "").split(
|
|
6151
|
+
const configuredHints = (process.env.CODEX_PATH_HINTS ?? "").split(import_node_path4.default.delimiter).map((entry) => entry.trim()).filter(Boolean);
|
|
5451
6152
|
return [
|
|
5452
6153
|
"/opt/homebrew/bin",
|
|
5453
6154
|
"/usr/local/bin",
|
|
@@ -5459,9 +6160,9 @@ function fileExists(candidate) {
|
|
|
5459
6160
|
if (!candidate) {
|
|
5460
6161
|
return null;
|
|
5461
6162
|
}
|
|
5462
|
-
const normalized =
|
|
6163
|
+
const normalized = import_node_path4.default.resolve(candidate);
|
|
5463
6164
|
try {
|
|
5464
|
-
const stats = (0,
|
|
6165
|
+
const stats = (0, import_node_fs4.statSync)(normalized);
|
|
5465
6166
|
if (stats.isFile()) {
|
|
5466
6167
|
return normalized;
|
|
5467
6168
|
}
|
|
@@ -5488,12 +6189,12 @@ function resolveCodexFromPath() {
|
|
|
5488
6189
|
new Set(
|
|
5489
6190
|
[
|
|
5490
6191
|
...getPathHintEntries(),
|
|
5491
|
-
...pathValue.split(
|
|
6192
|
+
...pathValue.split(import_node_path4.default.delimiter).map((entry) => entry.trim()).filter(Boolean)
|
|
5492
6193
|
].filter(Boolean)
|
|
5493
6194
|
)
|
|
5494
6195
|
);
|
|
5495
6196
|
for (const entry of entries3) {
|
|
5496
|
-
const candidate = fileExists(
|
|
6197
|
+
const candidate = fileExists(import_node_path4.default.join(entry, "codex"));
|
|
5497
6198
|
if (candidate) {
|
|
5498
6199
|
return candidate;
|
|
5499
6200
|
}
|
|
@@ -5557,7 +6258,7 @@ async function requireCodexCli() {
|
|
|
5557
6258
|
|
|
5558
6259
|
// ../../packages/runtime-codex/src/codex/command.ts
|
|
5559
6260
|
var import_node_child_process3 = require("child_process");
|
|
5560
|
-
var
|
|
6261
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
5561
6262
|
var cachedNodeRuntime = null;
|
|
5562
6263
|
function isJavaScriptEntrypoint(binaryPath) {
|
|
5563
6264
|
const normalized = binaryPath.trim().toLowerCase();
|
|
@@ -5573,19 +6274,19 @@ function resolveNodeRuntime(env) {
|
|
|
5573
6274
|
}
|
|
5574
6275
|
const runtimeEnv = { ...process.env, ...env };
|
|
5575
6276
|
const homeDir = runtimeEnv.HOME ?? "";
|
|
5576
|
-
const pathHints = (runtimeEnv.CODEX_PATH_HINTS ?? process.env.CODEX_PATH_HINTS ?? "").split(
|
|
6277
|
+
const pathHints = (runtimeEnv.CODEX_PATH_HINTS ?? process.env.CODEX_PATH_HINTS ?? "").split(import_node_path5.default.delimiter).map((entry) => entry.trim()).filter(Boolean);
|
|
5577
6278
|
const extraPathEntries = [
|
|
5578
6279
|
"/usr/local/bin",
|
|
5579
6280
|
"/opt/homebrew/bin",
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
6281
|
+
import_node_path5.default.join(homeDir, ".local", "bin"),
|
|
6282
|
+
import_node_path5.default.join(homeDir, ".fnm", "aliases", "default", "bin"),
|
|
6283
|
+
import_node_path5.default.join(homeDir, ".fnm", "current", "bin"),
|
|
5583
6284
|
...pathHints
|
|
5584
6285
|
].filter(Boolean);
|
|
5585
6286
|
const currentPath = runtimeEnv.PATH ?? "";
|
|
5586
6287
|
runtimeEnv.PATH = Array.from(
|
|
5587
|
-
/* @__PURE__ */ new Set([...extraPathEntries, ...currentPath.split(
|
|
5588
|
-
).join(
|
|
6288
|
+
/* @__PURE__ */ new Set([...extraPathEntries, ...currentPath.split(import_node_path5.default.delimiter).filter(Boolean)])
|
|
6289
|
+
).join(import_node_path5.default.delimiter);
|
|
5589
6290
|
const candidates = Array.from(
|
|
5590
6291
|
new Set(
|
|
5591
6292
|
[
|
|
@@ -5624,11 +6325,11 @@ function buildCodexCommand(binaryPath, args2, env) {
|
|
|
5624
6325
|
}
|
|
5625
6326
|
|
|
5626
6327
|
// ../../packages/runtime-codex/src/codex/home.ts
|
|
5627
|
-
var
|
|
5628
|
-
var
|
|
6328
|
+
var import_node_crypto8 = require("crypto");
|
|
6329
|
+
var import_node_fs5 = require("fs");
|
|
5629
6330
|
var import_promises2 = require("fs/promises");
|
|
5630
6331
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
5631
|
-
var
|
|
6332
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
5632
6333
|
function resolveHomeDir() {
|
|
5633
6334
|
return process.env.HOME || import_node_os2.default.homedir();
|
|
5634
6335
|
}
|
|
@@ -5637,7 +6338,7 @@ function expandHomePrefix(input, homeDir) {
|
|
|
5637
6338
|
return homeDir;
|
|
5638
6339
|
}
|
|
5639
6340
|
if (input.startsWith("~/") || input.startsWith("~\\")) {
|
|
5640
|
-
return
|
|
6341
|
+
return import_node_path6.default.join(homeDir, input.slice(2));
|
|
5641
6342
|
}
|
|
5642
6343
|
return input;
|
|
5643
6344
|
}
|
|
@@ -5653,25 +6354,25 @@ function normalizeCodexHomePath(input) {
|
|
|
5653
6354
|
if (!configured) {
|
|
5654
6355
|
return null;
|
|
5655
6356
|
}
|
|
5656
|
-
return
|
|
6357
|
+
return import_node_path6.default.resolve(expandHomePrefix(configured, resolveHomeDir()));
|
|
5657
6358
|
}
|
|
5658
6359
|
function resolveDefaultCodexHomeDir() {
|
|
5659
|
-
return normalizeCodexHomePath(process.env.CODEX_HOME) ??
|
|
6360
|
+
return normalizeCodexHomePath(process.env.CODEX_HOME) ?? import_node_path6.default.join(resolveHomeDir(), ".codex");
|
|
5660
6361
|
}
|
|
5661
6362
|
function resolveCodexSqliteHomeDir(codexHomePath) {
|
|
5662
6363
|
return normalizeCodexHomePath(process.env.CODEX_SQLITE_HOME) ?? resolveCodexHomeDir({ codexHomePath });
|
|
5663
6364
|
}
|
|
5664
6365
|
function resolveCurrentProfileCodexHomeDir(profileHomeId) {
|
|
5665
|
-
return
|
|
6366
|
+
return import_node_path6.default.join(
|
|
5666
6367
|
resolveProfileCodexHomesRoot(),
|
|
5667
|
-
(0,
|
|
6368
|
+
(0, import_node_crypto8.createHash)("sha256").update(profileHomeId).digest("hex").slice(0, 20)
|
|
5668
6369
|
);
|
|
5669
6370
|
}
|
|
5670
6371
|
function resolveProfileCodexHomeDir(profileHomeId) {
|
|
5671
6372
|
const current = resolveCurrentProfileCodexHomeDir(profileHomeId);
|
|
5672
|
-
const legacy =
|
|
5673
|
-
const currentExists = (0,
|
|
5674
|
-
const legacyExists = (0,
|
|
6373
|
+
const legacy = import_node_path6.default.join(resolveLegacyProfileCodexHomesRoot(), profileHomeId);
|
|
6374
|
+
const currentExists = (0, import_node_fs5.existsSync)(current);
|
|
6375
|
+
const legacyExists = (0, import_node_fs5.existsSync)(legacy);
|
|
5675
6376
|
if (currentExists && legacyExists) {
|
|
5676
6377
|
return current;
|
|
5677
6378
|
}
|
|
@@ -5679,15 +6380,15 @@ function resolveProfileCodexHomeDir(profileHomeId) {
|
|
|
5679
6380
|
}
|
|
5680
6381
|
function findProfileCodexHomeLocationConflict(profileHomeId) {
|
|
5681
6382
|
const current = resolveCurrentProfileCodexHomeDir(profileHomeId);
|
|
5682
|
-
const legacy =
|
|
5683
|
-
return (0,
|
|
6383
|
+
const legacy = import_node_path6.default.join(resolveLegacyProfileCodexHomesRoot(), profileHomeId);
|
|
6384
|
+
return (0, import_node_fs5.existsSync)(current) && (0, import_node_fs5.existsSync)(legacy) ? { current, legacy } : null;
|
|
5684
6385
|
}
|
|
5685
6386
|
function resolveProfileCodexHomesRoot() {
|
|
5686
|
-
return
|
|
6387
|
+
return import_node_path6.default.join(resolveHomeDir(), ".codexuse", "p");
|
|
5687
6388
|
}
|
|
5688
6389
|
async function ensureProfileCodexHomesRoot() {
|
|
5689
6390
|
const root = resolveProfileCodexHomesRoot();
|
|
5690
|
-
const parent =
|
|
6391
|
+
const parent = import_node_path6.default.dirname(root);
|
|
5691
6392
|
await (0, import_promises2.mkdir)(parent, { recursive: true, mode: 448 });
|
|
5692
6393
|
await (0, import_promises2.mkdir)(root, { recursive: true, mode: 448 });
|
|
5693
6394
|
if (process.platform !== "win32") {
|
|
@@ -5697,13 +6398,13 @@ async function ensureProfileCodexHomesRoot() {
|
|
|
5697
6398
|
return root;
|
|
5698
6399
|
}
|
|
5699
6400
|
function resolveLegacyProfileCodexHomesRoot() {
|
|
5700
|
-
return
|
|
6401
|
+
return import_node_path6.default.join(getUserDataDir(), "profile-homes");
|
|
5701
6402
|
}
|
|
5702
6403
|
async function migrateProfileCodexHomeDir(profileHomeId) {
|
|
5703
|
-
const legacy =
|
|
6404
|
+
const legacy = import_node_path6.default.join(resolveLegacyProfileCodexHomesRoot(), profileHomeId);
|
|
5704
6405
|
const current = resolveCurrentProfileCodexHomeDir(profileHomeId);
|
|
5705
|
-
const currentExists = (0,
|
|
5706
|
-
const legacyExists = (0,
|
|
6406
|
+
const currentExists = (0, import_node_fs5.existsSync)(current);
|
|
6407
|
+
const legacyExists = (0, import_node_fs5.existsSync)(legacy);
|
|
5707
6408
|
if (currentExists && legacyExists) {
|
|
5708
6409
|
return current;
|
|
5709
6410
|
}
|
|
@@ -5779,7 +6480,7 @@ var import_toml = __toESM(require_toml(), 1);
|
|
|
5779
6480
|
// ../../packages/runtime-codex/src/codex/config-metadata.ts
|
|
5780
6481
|
var import_node_child_process4 = require("child_process");
|
|
5781
6482
|
var import_promises3 = require("fs/promises");
|
|
5782
|
-
var
|
|
6483
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
5783
6484
|
var CONFIG_SCHEMA_URL = "https://raw.githubusercontent.com/openai/codex/main/codex-rs/core/config.schema.json";
|
|
5784
6485
|
var METADATA_CACHE_TTL_MS = 6e4;
|
|
5785
6486
|
var FALLBACK_SCHEMA_TOP_LEVEL_KEYS = [
|
|
@@ -5965,8 +6666,8 @@ function parseSchemaKeys(schemaRaw) {
|
|
|
5965
6666
|
async function readSchemaFromLocal() {
|
|
5966
6667
|
const candidates = [
|
|
5967
6668
|
process.env.CODEX_CONFIG_SCHEMA_PATH,
|
|
5968
|
-
|
|
5969
|
-
|
|
6669
|
+
import_node_path7.default.join(process.cwd(), "codex-rs", "core", "config.schema.json"),
|
|
6670
|
+
import_node_path7.default.join(process.cwd(), "node_modules", "@openai", "codex", "codex-rs", "core", "config.schema.json")
|
|
5970
6671
|
].filter((candidate) => Boolean(candidate));
|
|
5971
6672
|
for (const candidate of candidates) {
|
|
5972
6673
|
try {
|
|
@@ -6071,7 +6772,7 @@ async function getCodexConfigMetadata(forceRefresh = false) {
|
|
|
6071
6772
|
|
|
6072
6773
|
// ../../packages/runtime-codex/src/codex/config-io.ts
|
|
6073
6774
|
var import_promises4 = require("fs/promises");
|
|
6074
|
-
var
|
|
6775
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
6075
6776
|
|
|
6076
6777
|
// ../../packages/runtime-codex/src/codex/config-presets.ts
|
|
6077
6778
|
var DEFAULT_CONFIG_TEMPLATE = [
|
|
@@ -6114,10 +6815,10 @@ var YOLO_PRESET = {
|
|
|
6114
6815
|
|
|
6115
6816
|
// ../../packages/runtime-codex/src/codex/config-io.ts
|
|
6116
6817
|
function getConfigPath(options) {
|
|
6117
|
-
return
|
|
6818
|
+
return import_node_path8.default.join(resolveCodexHomeDir(options), "config.toml");
|
|
6118
6819
|
}
|
|
6119
6820
|
async function ensureConfigDirExists(filePath) {
|
|
6120
|
-
const dir =
|
|
6821
|
+
const dir = import_node_path8.default.dirname(filePath);
|
|
6121
6822
|
await (0, import_promises4.mkdir)(dir, { recursive: true });
|
|
6122
6823
|
}
|
|
6123
6824
|
function normalizeLineEndings(content) {
|
|
@@ -6675,82 +7376,6 @@ async function saveCodexConfigContent(content, options) {
|
|
|
6675
7376
|
return buildSnapshot(normalized, true, options);
|
|
6676
7377
|
}
|
|
6677
7378
|
|
|
6678
|
-
// ../../packages/runtime-app-state/src/storage/fileLock.ts
|
|
6679
|
-
var import_node_fs4 = require("fs");
|
|
6680
|
-
var import_node_path8 = __toESM(require("path"), 1);
|
|
6681
|
-
function isSqliteBusyError2(error) {
|
|
6682
|
-
if (!error || typeof error !== "object") {
|
|
6683
|
-
return false;
|
|
6684
|
-
}
|
|
6685
|
-
const value3 = error;
|
|
6686
|
-
if (value3.cause && value3.cause !== error && isSqliteBusyError2(value3.cause)) {
|
|
6687
|
-
return true;
|
|
6688
|
-
}
|
|
6689
|
-
if (value3.error && value3.error !== error && isSqliteBusyError2(value3.error)) {
|
|
6690
|
-
return true;
|
|
6691
|
-
}
|
|
6692
|
-
const message = typeof value3.message === "string" ? value3.message.toLowerCase() : String(error).toLowerCase();
|
|
6693
|
-
return value3.code === "SQLITE_BUSY" || value3.errno === 5 || message.includes("sqlite_busy") || message.includes("database is locked");
|
|
6694
|
-
}
|
|
6695
|
-
async function openLockDatabase(databasePath) {
|
|
6696
|
-
await import_node_fs4.promises.mkdir(import_node_path8.default.dirname(databasePath), { recursive: true, mode: 448 });
|
|
6697
|
-
const sqlite = process.versions.bun ? await Function("return import('bun:sqlite')")() : await Function("return import('node:sqlite')")();
|
|
6698
|
-
const database = process.versions.bun ? new sqlite.Database(databasePath) : new sqlite.DatabaseSync(databasePath);
|
|
6699
|
-
try {
|
|
6700
|
-
if (process.platform !== "win32") {
|
|
6701
|
-
await import_node_fs4.promises.chmod(databasePath, 384);
|
|
6702
|
-
}
|
|
6703
|
-
return {
|
|
6704
|
-
exec: database.exec.bind(database),
|
|
6705
|
-
close: database.close.bind(database)
|
|
6706
|
-
};
|
|
6707
|
-
} catch (error) {
|
|
6708
|
-
database.close();
|
|
6709
|
-
throw error;
|
|
6710
|
-
}
|
|
6711
|
-
}
|
|
6712
|
-
async function acquireCrossProcessFileLockTransaction(filePath, mode) {
|
|
6713
|
-
const databasePath = `${import_node_path8.default.resolve(filePath)}.codexuse-lock.sqlite`;
|
|
6714
|
-
let database = null;
|
|
6715
|
-
try {
|
|
6716
|
-
database = await openLockDatabase(databasePath);
|
|
6717
|
-
database.exec("PRAGMA busy_timeout = 1000;");
|
|
6718
|
-
database.exec("CREATE TABLE IF NOT EXISTS codexuse_file_lock (id INTEGER PRIMARY KEY);");
|
|
6719
|
-
database.exec("PRAGMA busy_timeout = 0;");
|
|
6720
|
-
if (mode === "write") {
|
|
6721
|
-
database.exec("BEGIN EXCLUSIVE;");
|
|
6722
|
-
} else {
|
|
6723
|
-
database.exec("BEGIN;");
|
|
6724
|
-
database.exec("SELECT COUNT(*) FROM codexuse_file_lock;");
|
|
6725
|
-
}
|
|
6726
|
-
} catch (error) {
|
|
6727
|
-
database?.close();
|
|
6728
|
-
if (isSqliteBusyError2(error)) {
|
|
6729
|
-
return null;
|
|
6730
|
-
}
|
|
6731
|
-
throw error;
|
|
6732
|
-
}
|
|
6733
|
-
const acquiredDatabase = database;
|
|
6734
|
-
let released = false;
|
|
6735
|
-
return async () => {
|
|
6736
|
-
if (released) {
|
|
6737
|
-
return;
|
|
6738
|
-
}
|
|
6739
|
-
released = true;
|
|
6740
|
-
try {
|
|
6741
|
-
acquiredDatabase.exec("ROLLBACK;");
|
|
6742
|
-
} finally {
|
|
6743
|
-
acquiredDatabase.close();
|
|
6744
|
-
}
|
|
6745
|
-
};
|
|
6746
|
-
}
|
|
6747
|
-
async function acquireCrossProcessFileLock(filePath) {
|
|
6748
|
-
return acquireCrossProcessFileLockTransaction(filePath, "write");
|
|
6749
|
-
}
|
|
6750
|
-
async function acquireCrossProcessFileReadLock(filePath) {
|
|
6751
|
-
return acquireCrossProcessFileLockTransaction(filePath, "read");
|
|
6752
|
-
}
|
|
6753
|
-
|
|
6754
7379
|
// ../../packages/shared/src/core/logger.ts
|
|
6755
7380
|
var isTestEnv = process.env.NODE_ENV === "test" || process.env.VITEST === "true" || process.env.VITEST === "1";
|
|
6756
7381
|
function isMocked(fn2) {
|
|
@@ -23535,11 +24160,11 @@ function authWritebackPaths(filePath) {
|
|
|
23535
24160
|
};
|
|
23536
24161
|
}
|
|
23537
24162
|
function fingerprintAuth(content) {
|
|
23538
|
-
return (0,
|
|
24163
|
+
return (0, import_node_crypto9.createHash)("sha256").update(content).digest("hex");
|
|
23539
24164
|
}
|
|
23540
24165
|
async function readOptionalFile(filePath) {
|
|
23541
24166
|
try {
|
|
23542
|
-
return await
|
|
24167
|
+
return await import_node_fs6.promises.readFile(filePath, "utf8");
|
|
23543
24168
|
} catch (error) {
|
|
23544
24169
|
const code = error && typeof error === "object" && "code" in error ? error.code : null;
|
|
23545
24170
|
if (code === "ENOENT") return null;
|
|
@@ -23550,9 +24175,9 @@ async function writeAtomicPath(filePath, content) {
|
|
|
23550
24175
|
const dir = import_node_path9.default.dirname(filePath);
|
|
23551
24176
|
const tempPath = import_node_path9.default.join(
|
|
23552
24177
|
dir,
|
|
23553
|
-
`.${import_node_path9.default.basename(filePath)}.${process.pid}.${(0,
|
|
24178
|
+
`.${import_node_path9.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto9.randomUUID)()}.tmp`
|
|
23554
24179
|
);
|
|
23555
|
-
const handle = await
|
|
24180
|
+
const handle = await import_node_fs6.promises.open(tempPath, "wx", 384);
|
|
23556
24181
|
try {
|
|
23557
24182
|
await handle.writeFile(content, "utf8");
|
|
23558
24183
|
await handle.sync();
|
|
@@ -23560,9 +24185,9 @@ async function writeAtomicPath(filePath, content) {
|
|
|
23560
24185
|
await handle.close();
|
|
23561
24186
|
}
|
|
23562
24187
|
try {
|
|
23563
|
-
await
|
|
24188
|
+
await import_node_fs6.promises.rename(tempPath, filePath);
|
|
23564
24189
|
if (process.platform !== "win32") {
|
|
23565
|
-
const dirHandle = await
|
|
24190
|
+
const dirHandle = await import_node_fs6.promises.open(dir, "r");
|
|
23566
24191
|
try {
|
|
23567
24192
|
await dirHandle.sync();
|
|
23568
24193
|
} finally {
|
|
@@ -23570,16 +24195,16 @@ async function writeAtomicPath(filePath, content) {
|
|
|
23570
24195
|
}
|
|
23571
24196
|
}
|
|
23572
24197
|
} finally {
|
|
23573
|
-
await
|
|
24198
|
+
await import_node_fs6.promises.rm(tempPath, { force: true }).catch(() => void 0);
|
|
23574
24199
|
}
|
|
23575
24200
|
}
|
|
23576
24201
|
async function installAuthFileIfAbsent(filePath, content) {
|
|
23577
24202
|
const dir = import_node_path9.default.dirname(filePath);
|
|
23578
24203
|
const tempPath = import_node_path9.default.join(
|
|
23579
24204
|
dir,
|
|
23580
|
-
`.${import_node_path9.default.basename(filePath)}.${process.pid}.${(0,
|
|
24205
|
+
`.${import_node_path9.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto9.randomUUID)()}.install`
|
|
23581
24206
|
);
|
|
23582
|
-
const handle = await
|
|
24207
|
+
const handle = await import_node_fs6.promises.open(tempPath, "wx", 384);
|
|
23583
24208
|
try {
|
|
23584
24209
|
await handle.writeFile(content, "utf8");
|
|
23585
24210
|
await handle.sync();
|
|
@@ -23587,25 +24212,25 @@ async function installAuthFileIfAbsent(filePath, content) {
|
|
|
23587
24212
|
await handle.close();
|
|
23588
24213
|
}
|
|
23589
24214
|
try {
|
|
23590
|
-
await
|
|
24215
|
+
await import_node_fs6.promises.link(tempPath, filePath);
|
|
23591
24216
|
} finally {
|
|
23592
|
-
await
|
|
24217
|
+
await import_node_fs6.promises.rm(tempPath, { force: true }).catch(() => void 0);
|
|
23593
24218
|
}
|
|
23594
24219
|
}
|
|
23595
24220
|
async function linkAuthFileIfAbsent(sourcePath, targetPath) {
|
|
23596
|
-
await
|
|
24221
|
+
await import_node_fs6.promises.link(sourcePath, targetPath);
|
|
23597
24222
|
}
|
|
23598
24223
|
async function hasExternalOpenFileHandle(filePath) {
|
|
23599
24224
|
if (process.platform === "linux") {
|
|
23600
24225
|
let target;
|
|
23601
24226
|
try {
|
|
23602
|
-
target = await
|
|
24227
|
+
target = await import_node_fs6.promises.stat(filePath);
|
|
23603
24228
|
} catch {
|
|
23604
24229
|
return true;
|
|
23605
24230
|
}
|
|
23606
24231
|
let processes;
|
|
23607
24232
|
try {
|
|
23608
|
-
processes = await
|
|
24233
|
+
processes = await import_node_fs6.promises.readdir("/proc", { withFileTypes: true });
|
|
23609
24234
|
} catch {
|
|
23610
24235
|
return true;
|
|
23611
24236
|
}
|
|
@@ -23616,7 +24241,7 @@ async function hasExternalOpenFileHandle(filePath) {
|
|
|
23616
24241
|
}
|
|
23617
24242
|
const processPath = `/proc/${entry.name}`;
|
|
23618
24243
|
try {
|
|
23619
|
-
const processStats = await
|
|
24244
|
+
const processStats = await import_node_fs6.promises.stat(processPath);
|
|
23620
24245
|
if (currentUid !== void 0 && processStats.uid !== currentUid) {
|
|
23621
24246
|
continue;
|
|
23622
24247
|
}
|
|
@@ -23625,7 +24250,7 @@ async function hasExternalOpenFileHandle(filePath) {
|
|
|
23625
24250
|
}
|
|
23626
24251
|
let descriptors;
|
|
23627
24252
|
try {
|
|
23628
|
-
descriptors = await
|
|
24253
|
+
descriptors = await import_node_fs6.promises.readdir(`${processPath}/fd`);
|
|
23629
24254
|
} catch (error) {
|
|
23630
24255
|
const code = error && typeof error === "object" && "code" in error ? error.code : null;
|
|
23631
24256
|
if (code === "ENOENT" || code === "ESRCH") continue;
|
|
@@ -23633,7 +24258,7 @@ async function hasExternalOpenFileHandle(filePath) {
|
|
|
23633
24258
|
}
|
|
23634
24259
|
for (const descriptor2 of descriptors) {
|
|
23635
24260
|
try {
|
|
23636
|
-
const descriptorStats = await
|
|
24261
|
+
const descriptorStats = await import_node_fs6.promises.stat(`${processPath}/fd/${descriptor2}`);
|
|
23637
24262
|
if (descriptorStats.dev === target.dev && descriptorStats.ino === target.ino) {
|
|
23638
24263
|
return true;
|
|
23639
24264
|
}
|
|
@@ -23680,9 +24305,9 @@ async function hasExternalOpenFileHandle(filePath) {
|
|
|
23680
24305
|
async function cleanupAuthWriteback(filePath) {
|
|
23681
24306
|
const paths = authWritebackPaths(filePath);
|
|
23682
24307
|
await Promise.all([
|
|
23683
|
-
|
|
23684
|
-
|
|
23685
|
-
|
|
24308
|
+
import_node_fs6.promises.rm(paths.manifest, { force: true }),
|
|
24309
|
+
import_node_fs6.promises.rm(paths.backup, { force: true }),
|
|
24310
|
+
import_node_fs6.promises.rm(paths.replaced, { force: true })
|
|
23686
24311
|
]);
|
|
23687
24312
|
}
|
|
23688
24313
|
async function rollbackAuthWriteback(filePath, manifest) {
|
|
@@ -23703,8 +24328,8 @@ async function rollbackAuthWriteback(filePath, manifest) {
|
|
|
23703
24328
|
"Codex auth changed outside CodexUse during writeback rollback; recovery files were preserved."
|
|
23704
24329
|
);
|
|
23705
24330
|
}
|
|
23706
|
-
await
|
|
23707
|
-
if (fingerprintAuth(await
|
|
24331
|
+
await import_node_fs6.promises.rename(filePath, paths.replaced);
|
|
24332
|
+
if (fingerprintAuth(await import_node_fs6.promises.readFile(paths.replaced, "utf8")) !== manifest.targetFingerprint) {
|
|
23708
24333
|
const replaced = await readOptionalFile(paths.replaced);
|
|
23709
24334
|
if (await readOptionalFile(filePath) === null && replaced !== null) {
|
|
23710
24335
|
await installAuthFileIfAbsent(filePath, replaced);
|
|
@@ -23741,7 +24366,7 @@ async function replaceAuthFileIfCurrent(filePath, expectedCurrent, replacement)
|
|
|
23741
24366
|
await writeAtomicPath(paths.manifest, JSON.stringify(manifest));
|
|
23742
24367
|
let committed = false;
|
|
23743
24368
|
try {
|
|
23744
|
-
await
|
|
24369
|
+
await import_node_fs6.promises.rename(filePath, paths.backup);
|
|
23745
24370
|
if (await readOptionalFile(paths.backup) !== expectedCurrent) {
|
|
23746
24371
|
throw new Error("Codex auth changed while writeback began.");
|
|
23747
24372
|
}
|
|
@@ -23841,7 +24466,7 @@ async function acquireCodexAuthFileReadLock(filePath) {
|
|
|
23841
24466
|
async function readAuthFileCached(filePath) {
|
|
23842
24467
|
let stats;
|
|
23843
24468
|
try {
|
|
23844
|
-
stats = await
|
|
24469
|
+
stats = await import_node_fs6.promises.stat(filePath);
|
|
23845
24470
|
} catch {
|
|
23846
24471
|
authFileCache.delete(filePath);
|
|
23847
24472
|
return null;
|
|
@@ -23850,7 +24475,7 @@ async function readAuthFileCached(filePath) {
|
|
|
23850
24475
|
if (cached2 && cached2.mtimeMs === stats.mtimeMs && cached2.size === stats.size) {
|
|
23851
24476
|
return cached2.content;
|
|
23852
24477
|
}
|
|
23853
|
-
const content = await
|
|
24478
|
+
const content = await import_node_fs6.promises.readFile(filePath, "utf8");
|
|
23854
24479
|
authFileCache.set(filePath, {
|
|
23855
24480
|
mtimeMs: stats.mtimeMs,
|
|
23856
24481
|
size: stats.size,
|
|
@@ -23869,7 +24494,7 @@ async function writeAuthFileCached(filePath, content, expectedCurrent, options =
|
|
|
23869
24494
|
);
|
|
23870
24495
|
if (!written) return false;
|
|
23871
24496
|
try {
|
|
23872
|
-
const stats = await
|
|
24497
|
+
const stats = await import_node_fs6.promises.stat(filePath);
|
|
23873
24498
|
authFileCache.set(filePath, {
|
|
23874
24499
|
mtimeMs: stats.mtimeMs,
|
|
23875
24500
|
size: stats.size,
|
|
@@ -24008,13 +24633,13 @@ function resolveRpcAuthPath(envOverride, authPath) {
|
|
|
24008
24633
|
async function fetchRateLimitsViaRpc(envOverride, options = {}) {
|
|
24009
24634
|
const binaryPath = options.codexPath ?? await requireCodexCli();
|
|
24010
24635
|
const sourceAuthPath = resolveRpcAuthPath(envOverride, options.authPath);
|
|
24011
|
-
const tempHome = await
|
|
24636
|
+
const tempHome = await import_node_fs6.promises.mkdtemp(import_node_path9.default.join(import_node_os3.default.tmpdir(), "codex-rpc-"));
|
|
24012
24637
|
const tempAuthPath = import_node_path9.default.join(tempHome, "auth.json");
|
|
24013
24638
|
let initialSourceAuth;
|
|
24014
24639
|
try {
|
|
24015
24640
|
const authLock = await acquireCodexAuthFileReadLock(sourceAuthPath);
|
|
24016
24641
|
if (!authLock) {
|
|
24017
|
-
await
|
|
24642
|
+
await import_node_fs6.promises.rm(tempHome, { recursive: true, force: true });
|
|
24018
24643
|
return null;
|
|
24019
24644
|
}
|
|
24020
24645
|
try {
|
|
@@ -24023,15 +24648,15 @@ async function fetchRateLimitsViaRpc(envOverride, options = {}) {
|
|
|
24023
24648
|
await authLock.release();
|
|
24024
24649
|
}
|
|
24025
24650
|
if (!initialSourceAuth) {
|
|
24026
|
-
await
|
|
24651
|
+
await import_node_fs6.promises.rm(tempHome, { recursive: true, force: true });
|
|
24027
24652
|
return null;
|
|
24028
24653
|
}
|
|
24029
|
-
await
|
|
24654
|
+
await import_node_fs6.promises.writeFile(tempAuthPath, initialSourceAuth, {
|
|
24030
24655
|
encoding: "utf8",
|
|
24031
24656
|
mode: 384
|
|
24032
24657
|
});
|
|
24033
24658
|
} catch {
|
|
24034
|
-
await
|
|
24659
|
+
await import_node_fs6.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
|
|
24035
24660
|
});
|
|
24036
24661
|
return null;
|
|
24037
24662
|
}
|
|
@@ -24098,7 +24723,7 @@ async function fetchRateLimitsViaRpc(envOverride, options = {}) {
|
|
|
24098
24723
|
rl.close();
|
|
24099
24724
|
await stopChildAndWait(child);
|
|
24100
24725
|
try {
|
|
24101
|
-
const updatedAuth = await
|
|
24726
|
+
const updatedAuth = await import_node_fs6.promises.readFile(tempAuthPath, "utf8");
|
|
24102
24727
|
if (updatedAuth.trim().length > 0) {
|
|
24103
24728
|
const currentSourceAuth = await readAuthFileCached(sourceAuthPath);
|
|
24104
24729
|
if (shouldWriteBackAuth(initialSourceAuth, currentSourceAuth, updatedAuth)) {
|
|
@@ -24127,7 +24752,7 @@ async function fetchRateLimitsViaRpc(envOverride, options = {}) {
|
|
|
24127
24752
|
} catch (error) {
|
|
24128
24753
|
logWarn("Failed to sync refreshed auth after rate-limit probe:", error);
|
|
24129
24754
|
}
|
|
24130
|
-
await
|
|
24755
|
+
await import_node_fs6.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
|
|
24131
24756
|
});
|
|
24132
24757
|
}
|
|
24133
24758
|
}
|
|
@@ -24141,7 +24766,7 @@ async function activateResetWindowViaRpc(envOverride, options = {}) {
|
|
|
24141
24766
|
}
|
|
24142
24767
|
async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAuthPath) {
|
|
24143
24768
|
const binaryPath = options.codexPath ?? await requireCodexCli();
|
|
24144
|
-
const tempHome = await
|
|
24769
|
+
const tempHome = await import_node_fs6.promises.mkdtemp(
|
|
24145
24770
|
import_node_path9.default.join(import_node_os3.default.tmpdir(), "codex-activation-")
|
|
24146
24771
|
);
|
|
24147
24772
|
const tempAuthPath = import_node_path9.default.join(tempHome, "auth.json");
|
|
@@ -24149,7 +24774,7 @@ async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAut
|
|
|
24149
24774
|
try {
|
|
24150
24775
|
const authLock = await acquireCodexAuthFileReadLock(sourceAuthPath);
|
|
24151
24776
|
if (!authLock) {
|
|
24152
|
-
await
|
|
24777
|
+
await import_node_fs6.promises.rm(tempHome, { recursive: true, force: true });
|
|
24153
24778
|
return { status: "skipped", reason: "auth-busy" };
|
|
24154
24779
|
}
|
|
24155
24780
|
try {
|
|
@@ -24158,16 +24783,16 @@ async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAut
|
|
|
24158
24783
|
await authLock.release();
|
|
24159
24784
|
}
|
|
24160
24785
|
if (!initialSourceAuth) {
|
|
24161
|
-
await
|
|
24786
|
+
await import_node_fs6.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
|
|
24162
24787
|
});
|
|
24163
24788
|
return { status: "skipped", reason: "auth-missing" };
|
|
24164
24789
|
}
|
|
24165
|
-
await
|
|
24790
|
+
await import_node_fs6.promises.writeFile(tempAuthPath, initialSourceAuth, {
|
|
24166
24791
|
encoding: "utf8",
|
|
24167
24792
|
mode: 384
|
|
24168
24793
|
});
|
|
24169
24794
|
} catch {
|
|
24170
|
-
await
|
|
24795
|
+
await import_node_fs6.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
|
|
24171
24796
|
});
|
|
24172
24797
|
return { status: "skipped", reason: "auth-missing" };
|
|
24173
24798
|
}
|
|
@@ -24180,7 +24805,7 @@ async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAut
|
|
|
24180
24805
|
} catch {
|
|
24181
24806
|
}
|
|
24182
24807
|
const activationModel = resolveActivationModel(configuredModel);
|
|
24183
|
-
await
|
|
24808
|
+
await import_node_fs6.promises.writeFile(
|
|
24184
24809
|
import_node_path9.default.join(tempHome, "config.toml"),
|
|
24185
24810
|
`model = ${JSON.stringify(activationModel)}
|
|
24186
24811
|
`,
|
|
@@ -24318,7 +24943,7 @@ async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAut
|
|
|
24318
24943
|
rl.close();
|
|
24319
24944
|
await stopChildAndWait(child);
|
|
24320
24945
|
try {
|
|
24321
|
-
const updatedAuth = await
|
|
24946
|
+
const updatedAuth = await import_node_fs6.promises.readFile(tempAuthPath, "utf8");
|
|
24322
24947
|
if (updatedAuth.trim().length > 0) {
|
|
24323
24948
|
const currentSourceAuth = await readAuthFileCached(sourceAuthPath);
|
|
24324
24949
|
if (shouldWriteBackAuth(initialSourceAuth, currentSourceAuth, updatedAuth)) {
|
|
@@ -24353,7 +24978,7 @@ async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAut
|
|
|
24353
24978
|
} catch (error) {
|
|
24354
24979
|
writebackError = error instanceof Error ? error : new Error(String(error));
|
|
24355
24980
|
}
|
|
24356
|
-
await
|
|
24981
|
+
await import_node_fs6.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
|
|
24357
24982
|
});
|
|
24358
24983
|
}
|
|
24359
24984
|
if (activationError && writebackError) {
|
|
@@ -24376,13 +25001,13 @@ async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAut
|
|
|
24376
25001
|
|
|
24377
25002
|
// ../../packages/runtime-codex/src/codex/officialAppRestart.ts
|
|
24378
25003
|
var import_node_child_process6 = require("child_process");
|
|
24379
|
-
var
|
|
24380
|
-
var
|
|
25004
|
+
var import_node_crypto10 = require("crypto");
|
|
25005
|
+
var import_node_fs8 = require("fs");
|
|
24381
25006
|
var import_node_os4 = require("os");
|
|
24382
25007
|
var import_node_path11 = __toESM(require("path"), 1);
|
|
24383
25008
|
|
|
24384
25009
|
// ../../packages/runtime-codex/src/codex/threadUsage.ts
|
|
24385
|
-
var
|
|
25010
|
+
var import_node_fs7 = require("fs");
|
|
24386
25011
|
var import_node_path10 = __toESM(require("path"), 1);
|
|
24387
25012
|
var ROLLOUT_DIRS = ["sessions", "archived_sessions"];
|
|
24388
25013
|
var SQLITE_EXTENSIONS = /* @__PURE__ */ new Set([".db", ".sqlite", ".sqlite3"]);
|
|
@@ -24395,7 +25020,7 @@ async function collectRolloutFiles(root) {
|
|
|
24395
25020
|
async function visit(dir) {
|
|
24396
25021
|
let entries3;
|
|
24397
25022
|
try {
|
|
24398
|
-
entries3 = await
|
|
25023
|
+
entries3 = await import_node_fs7.promises.readdir(dir, {
|
|
24399
25024
|
withFileTypes: true,
|
|
24400
25025
|
encoding: "utf8"
|
|
24401
25026
|
});
|
|
@@ -24423,7 +25048,7 @@ async function collectRolloutFiles(root) {
|
|
|
24423
25048
|
async function collectRolloutFilesStrict(root) {
|
|
24424
25049
|
const files = [];
|
|
24425
25050
|
async function visit(dir) {
|
|
24426
|
-
const entries3 = await
|
|
25051
|
+
const entries3 = await import_node_fs7.promises.readdir(dir, {
|
|
24427
25052
|
withFileTypes: true,
|
|
24428
25053
|
encoding: "utf8"
|
|
24429
25054
|
});
|
|
@@ -24448,7 +25073,7 @@ async function readOfficialCodexRolloutActivityHeat(profileHome) {
|
|
|
24448
25073
|
for (const dirname of ROLLOUT_DIRS) {
|
|
24449
25074
|
const root = import_node_path10.default.join(profileHome, dirname);
|
|
24450
25075
|
try {
|
|
24451
|
-
await
|
|
25076
|
+
await import_node_fs7.promises.access(root);
|
|
24452
25077
|
} catch (error) {
|
|
24453
25078
|
if (error.code === "ENOENT") {
|
|
24454
25079
|
continue;
|
|
@@ -24457,7 +25082,7 @@ async function readOfficialCodexRolloutActivityHeat(profileHome) {
|
|
|
24457
25082
|
}
|
|
24458
25083
|
const files = await collectRolloutFilesStrict(root);
|
|
24459
25084
|
for (const file of files) {
|
|
24460
|
-
const stat2 = await
|
|
25085
|
+
const stat2 = await import_node_fs7.promises.stat(file);
|
|
24461
25086
|
if (Number.isFinite(stat2.mtimeMs)) {
|
|
24462
25087
|
latestUpdatedAtMs = Math.max(latestUpdatedAtMs ?? 0, stat2.mtimeMs);
|
|
24463
25088
|
}
|
|
@@ -24485,7 +25110,7 @@ async function findRolloutFileByScan(profileHome, threadId) {
|
|
|
24485
25110
|
if (!variants.some((variant) => basename.includes(variant))) {
|
|
24486
25111
|
continue;
|
|
24487
25112
|
}
|
|
24488
|
-
const stat2 = await
|
|
25113
|
+
const stat2 = await import_node_fs7.promises.stat(file).catch(() => null);
|
|
24489
25114
|
const updatedAtMs = stat2 && Number.isFinite(stat2.mtimeMs) ? stat2.mtimeMs : null;
|
|
24490
25115
|
if (!best || (updatedAtMs ?? 0) > (best.updatedAtMs ?? 0) || (updatedAtMs ?? 0) === (best.updatedAtMs ?? 0) && file > best.path) {
|
|
24491
25116
|
best = { path: file, updatedAtMs };
|
|
@@ -24563,7 +25188,7 @@ async function collectSessionDatabasePaths(profileHome, sqliteHome = profileHome
|
|
|
24563
25188
|
const paths = [];
|
|
24564
25189
|
const sqliteDir = import_node_path10.default.join(sqliteHome, "sqlite");
|
|
24565
25190
|
try {
|
|
24566
|
-
const entries3 = await
|
|
25191
|
+
const entries3 = await import_node_fs7.promises.readdir(sqliteDir, {
|
|
24567
25192
|
withFileTypes: true,
|
|
24568
25193
|
encoding: "utf8"
|
|
24569
25194
|
});
|
|
@@ -24645,7 +25270,7 @@ function queryThreadRecordFromTable(db, profileHome, threadId, config) {
|
|
|
24645
25270
|
}
|
|
24646
25271
|
async function readThreadRecordFromDb(profileHome, dbPath, threadId) {
|
|
24647
25272
|
try {
|
|
24648
|
-
await
|
|
25273
|
+
await import_node_fs7.promises.access(dbPath);
|
|
24649
25274
|
} catch {
|
|
24650
25275
|
return null;
|
|
24651
25276
|
}
|
|
@@ -25065,7 +25690,7 @@ function hashProfileKey(profileKey) {
|
|
|
25065
25690
|
if (!profileKey) {
|
|
25066
25691
|
return null;
|
|
25067
25692
|
}
|
|
25068
|
-
return (0,
|
|
25693
|
+
return (0, import_node_crypto10.createHash)("sha256").update(profileKey).digest("hex").slice(0, 12);
|
|
25069
25694
|
}
|
|
25070
25695
|
function sanitizeOfficialCodexOverlayActionTargetsForRenderer(targets) {
|
|
25071
25696
|
const sanitized = [];
|
|
@@ -28677,7 +29302,7 @@ async function runCdpCommandSequence(debuggerUrl, commands, timeoutMs = CODEX_CD
|
|
|
28677
29302
|
});
|
|
28678
29303
|
}
|
|
28679
29304
|
async function verifyCdpBindingRoundTrip(debuggerUrl) {
|
|
28680
|
-
const nonce = (0,
|
|
29305
|
+
const nonce = (0, import_node_crypto10.randomUUID)();
|
|
28681
29306
|
const expression = `(() => {
|
|
28682
29307
|
const binding = window[${JSON.stringify(CODEXUSE_BRIDGE_BINDING_NAME)}];
|
|
28683
29308
|
if (typeof binding !== "function") return false;
|
|
@@ -29100,7 +29725,7 @@ async function startOfficialCodexBridgeActionListenerOnce(args2) {
|
|
|
29100
29725
|
let closeNotified = false;
|
|
29101
29726
|
let echoReceived = false;
|
|
29102
29727
|
const requiredCommandIds = /* @__PURE__ */ new Set();
|
|
29103
|
-
const echoId = (0,
|
|
29728
|
+
const echoId = (0, import_node_crypto10.randomUUID)();
|
|
29104
29729
|
const readyTimeout = setTimeout(() => {
|
|
29105
29730
|
settleReady(false);
|
|
29106
29731
|
try {
|
|
@@ -29174,7 +29799,7 @@ async function startOfficialCodexBridgeActionListenerOnce(args2) {
|
|
|
29174
29799
|
}
|
|
29175
29800
|
};
|
|
29176
29801
|
bridgeActionListenerVerifiers.set(args2.debuggerUrl, async () => {
|
|
29177
|
-
const id2 = (0,
|
|
29802
|
+
const id2 = (0, import_node_crypto10.randomUUID)();
|
|
29178
29803
|
return await new Promise((resolve2) => {
|
|
29179
29804
|
const waiters = bridgeActionListenerHealthWaiters.get(args2.debuggerUrl) ?? /* @__PURE__ */ new Map();
|
|
29180
29805
|
bridgeActionListenerHealthWaiters.set(args2.debuggerUrl, waiters);
|
|
@@ -29722,7 +30347,7 @@ async function recordOfficialCodexActivity(input) {
|
|
|
29722
30347
|
};
|
|
29723
30348
|
const finite2 = (value3, min4, max4) => typeof value3 === "number" && Number.isFinite(value3) ? Math.max(min4, Math.min(max4, value3)) : null;
|
|
29724
30349
|
const entry = {
|
|
29725
|
-
id: (0,
|
|
30350
|
+
id: (0, import_node_crypto10.randomUUID)(),
|
|
29726
30351
|
at: now2.toISOString(),
|
|
29727
30352
|
kind: input.kind,
|
|
29728
30353
|
status: bounded(input.status, 80) ?? "unknown",
|
|
@@ -30725,7 +31350,7 @@ var devToolsActivePortPaths = (appUserDataDir) => {
|
|
|
30725
31350
|
};
|
|
30726
31351
|
var readDevToolsActivePort = async (filePath) => {
|
|
30727
31352
|
try {
|
|
30728
|
-
const text = await
|
|
31353
|
+
const text = await import_node_fs8.promises.readFile(filePath, "utf8");
|
|
30729
31354
|
const port = Number(text.split(/\r?\n/, 1)[0]);
|
|
30730
31355
|
if (!Number.isInteger(port) || port <= 0 || port >= 65536) {
|
|
30731
31356
|
return null;
|
|
@@ -30762,7 +31387,7 @@ function classifyOpenCodexLaunchFailure(error) {
|
|
|
30762
31387
|
}
|
|
30763
31388
|
async function openCodexWithProfileHome(candidate, profileHome, profileName, previousPids, options = {}) {
|
|
30764
31389
|
const executablePath = getMainExecutablePath(candidate);
|
|
30765
|
-
if (!(0,
|
|
31390
|
+
if (!(0, import_node_fs8.existsSync)(executablePath)) {
|
|
30766
31391
|
return {
|
|
30767
31392
|
opened: false,
|
|
30768
31393
|
pid: null,
|
|
@@ -30780,7 +31405,7 @@ async function openCodexWithProfileHome(candidate, profileHome, profileName, pre
|
|
|
30780
31405
|
let child;
|
|
30781
31406
|
try {
|
|
30782
31407
|
if (appUserDataDir) {
|
|
30783
|
-
(0,
|
|
31408
|
+
(0, import_node_fs8.mkdirSync)(appUserDataDir, { recursive: true });
|
|
30784
31409
|
}
|
|
30785
31410
|
child = (0, import_node_child_process6.spawn)(
|
|
30786
31411
|
"/usr/bin/open",
|
|
@@ -30935,7 +31560,7 @@ function resolveCodexLaunchHome(profileHome) {
|
|
|
30935
31560
|
}
|
|
30936
31561
|
async function readBundleString(appPath, key) {
|
|
30937
31562
|
const plistPath = import_node_path11.default.join(appPath, "Contents", "Info.plist");
|
|
30938
|
-
if (!(0,
|
|
31563
|
+
if (!(0, import_node_fs8.existsSync)(plistPath)) {
|
|
30939
31564
|
return null;
|
|
30940
31565
|
}
|
|
30941
31566
|
const result2 = await runCommand2("/usr/bin/plutil", [
|
|
@@ -30965,7 +31590,7 @@ function officialCodexAppPriority(appPath) {
|
|
|
30965
31590
|
async function collectCodexAppCandidates(rawPaths) {
|
|
30966
31591
|
const candidates = [];
|
|
30967
31592
|
for (const appPath of rawPaths) {
|
|
30968
|
-
if (!(0,
|
|
31593
|
+
if (!(0, import_node_fs8.existsSync)(appPath) || !OFFICIAL_CODEX_APP_NAMES.includes(import_node_path11.default.basename(appPath)) || !(0, import_node_fs8.existsSync)(import_node_path11.default.join(appPath, "Contents", "Resources", "codex"))) {
|
|
30969
31594
|
continue;
|
|
30970
31595
|
}
|
|
30971
31596
|
const bundleId = await readBundleString(appPath, "CFBundleIdentifier");
|
|
@@ -31077,7 +31702,7 @@ function sharedCodexLaunchOptions(useDefaultUserData, profileIdentity) {
|
|
|
31077
31702
|
const userDataDir = !useDefaultUserData && profileIdentity ? import_node_path11.default.join(
|
|
31078
31703
|
SHARED_CODEX_HOME,
|
|
31079
31704
|
"codex-app-user-data",
|
|
31080
|
-
(0,
|
|
31705
|
+
(0, import_node_crypto10.createHash)("sha256").update(profileIdentity).digest("hex").slice(0, 16)
|
|
31081
31706
|
) : void 0;
|
|
31082
31707
|
return {
|
|
31083
31708
|
useDefaultUserData,
|
|
@@ -33488,7 +34113,7 @@ async function attemptOfficialCodexManagedLiveLogin(args2) {
|
|
|
33488
34113
|
}
|
|
33489
34114
|
}
|
|
33490
34115
|
async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTrace = {
|
|
33491
|
-
operationId: (0,
|
|
34116
|
+
operationId: (0, import_node_crypto10.randomUUID)(),
|
|
33492
34117
|
attempt: 1
|
|
33493
34118
|
}) {
|
|
33494
34119
|
let expectedWindowPreflight = options.expectedWindowPreflight;
|
|
@@ -34556,7 +35181,7 @@ async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTra
|
|
|
34556
35181
|
}
|
|
34557
35182
|
function applyOfficialCodexLiveAccountSwitch(options = {}) {
|
|
34558
35183
|
return enqueueProfileAction("shared-window", async () => {
|
|
34559
|
-
const operationId = (0,
|
|
35184
|
+
const operationId = (0, import_node_crypto10.randomUUID)();
|
|
34560
35185
|
let result2 = await applyOfficialCodexLiveAccountSwitchOnce(options, {
|
|
34561
35186
|
operationId,
|
|
34562
35187
|
attempt: 1
|
|
@@ -35281,7 +35906,7 @@ async function launchOfficialCodexProfileInstanceOnce(options) {
|
|
|
35281
35906
|
}
|
|
35282
35907
|
|
|
35283
35908
|
// ../../packages/runtime-app-state/src/app/profileHomeMutationCoordinator.ts
|
|
35284
|
-
var
|
|
35909
|
+
var import_node_crypto11 = require("crypto");
|
|
35285
35910
|
|
|
35286
35911
|
// ../../packages/runtime-app-state/src/app/processOwner.ts
|
|
35287
35912
|
var import_node_child_process7 = require("child_process");
|
|
@@ -35319,12 +35944,12 @@ function isProcessEpochAlive(pid, expectedStartedAt) {
|
|
|
35319
35944
|
// ../../packages/runtime-app-state/src/app/profileHomeMutationCoordinator.ts
|
|
35320
35945
|
var PROFILE_HOME_MUTATION_TTL_MS = 10 * 60 * 1e3;
|
|
35321
35946
|
var PROFILE_HOME_MUTATION_RENEW_MS = 30 * 1e3;
|
|
35322
|
-
var PROCESS_OWNER_ID = (0,
|
|
35947
|
+
var PROCESS_OWNER_ID = (0, import_node_crypto11.randomUUID)();
|
|
35323
35948
|
var PROCESS_STARTED_AT = readProcessStartedAt(process.pid);
|
|
35324
35949
|
var activeRenewals = /* @__PURE__ */ new Map();
|
|
35325
35950
|
async function acquireProfileHomeMutationIntent(input) {
|
|
35326
35951
|
const now2 = Date.now();
|
|
35327
|
-
const operationId = (0,
|
|
35952
|
+
const operationId = (0, import_node_crypto11.randomUUID)();
|
|
35328
35953
|
const renewal = {
|
|
35329
35954
|
timer: void 0,
|
|
35330
35955
|
pending: Promise.resolve(),
|
|
@@ -35406,7 +36031,7 @@ async function releaseProfileHomeMutationIntent(homeId, operationId) {
|
|
|
35406
36031
|
}
|
|
35407
36032
|
|
|
35408
36033
|
// ../../packages/runtime-profiles/src/profiles/rate-limit-cache.ts
|
|
35409
|
-
var
|
|
36034
|
+
var import_node_fs9 = require("fs");
|
|
35410
36035
|
var import_node_path12 = __toESM(require("path"), 1);
|
|
35411
36036
|
var memorySnapshots = /* @__PURE__ */ new Map();
|
|
35412
36037
|
var persistedSnapshotWriteLock = Promise.resolve();
|
|
@@ -35420,7 +36045,7 @@ function snapshotCachePath() {
|
|
|
35420
36045
|
async function loadPersistedSnapshots() {
|
|
35421
36046
|
let raw;
|
|
35422
36047
|
try {
|
|
35423
|
-
raw = (await
|
|
36048
|
+
raw = (await import_node_fs9.promises.readFile(snapshotCachePath(), "utf8")).trim();
|
|
35424
36049
|
} catch {
|
|
35425
36050
|
return /* @__PURE__ */ new Map();
|
|
35426
36051
|
}
|
|
@@ -35464,13 +36089,13 @@ async function writePersistedSnapshots(snapshots) {
|
|
|
35464
36089
|
2
|
|
35465
36090
|
);
|
|
35466
36091
|
try {
|
|
35467
|
-
await
|
|
35468
|
-
await
|
|
36092
|
+
await import_node_fs9.promises.mkdir(import_node_path12.default.dirname(filePath), { recursive: true });
|
|
36093
|
+
await import_node_fs9.promises.writeFile(tmpPath, `${payload}
|
|
35469
36094
|
`, "utf8");
|
|
35470
|
-
await
|
|
36095
|
+
await import_node_fs9.promises.rename(tmpPath, filePath);
|
|
35471
36096
|
} catch {
|
|
35472
36097
|
try {
|
|
35473
|
-
await
|
|
36098
|
+
await import_node_fs9.promises.rm(tmpPath, { force: true });
|
|
35474
36099
|
} catch {
|
|
35475
36100
|
}
|
|
35476
36101
|
}
|
|
@@ -35535,7 +36160,7 @@ var AUTH_MUTATION_MANIFEST_NAME = ".codexuse-auth-transaction.json";
|
|
|
35535
36160
|
var AUTH_MUTATION_BACKUP_NAME = ".codexuse-auth-transaction.backup";
|
|
35536
36161
|
var AUTH_MUTATION_REPLACED_NAME = ".codexuse-auth-transaction.replaced";
|
|
35537
36162
|
var PROFILE_HOME_MUTATION_MARKER_TTL_MS = 10 * 60 * 1e3;
|
|
35538
|
-
var PROCESS_OWNER_ID2 = (0,
|
|
36163
|
+
var PROCESS_OWNER_ID2 = (0, import_node_crypto12.randomUUID)();
|
|
35539
36164
|
var PROCESS_STARTED_AT2 = readProcessStartedAt(process.pid);
|
|
35540
36165
|
var globalAuthSwapLock = Promise.resolve();
|
|
35541
36166
|
var profileOperationLocks = /* @__PURE__ */ new Map();
|
|
@@ -36381,7 +37006,7 @@ var ProfileManager = class {
|
|
|
36381
37006
|
let attempt = 0;
|
|
36382
37007
|
let homeId;
|
|
36383
37008
|
do {
|
|
36384
|
-
homeId = `legacy-${(0,
|
|
37009
|
+
homeId = `legacy-${(0, import_node_crypto12.createHash)("sha256").update(profileName).update("\0").update(String(attempt)).digest("hex").slice(0, 32)}`;
|
|
36385
37010
|
attempt += 1;
|
|
36386
37011
|
} while (profileNamesByHomeId.has(homeId.toLowerCase()));
|
|
36387
37012
|
homeIdsByProfileName.set(profileName, homeId);
|
|
@@ -36591,7 +37216,7 @@ var ProfileManager = class {
|
|
|
36591
37216
|
const dir = import_path.default.dirname(filePath);
|
|
36592
37217
|
const tempPath = import_path.default.join(
|
|
36593
37218
|
dir,
|
|
36594
|
-
`.${import_path.default.basename(filePath)}.${process.pid}.${(0,
|
|
37219
|
+
`.${import_path.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto12.randomUUID)()}.tmp`
|
|
36595
37220
|
);
|
|
36596
37221
|
await import_fs.promises.mkdir(dir, { recursive: true, mode: 448 });
|
|
36597
37222
|
if (process.platform !== "win32") {
|
|
@@ -36878,7 +37503,7 @@ var ProfileManager = class {
|
|
|
36878
37503
|
if (content === null) {
|
|
36879
37504
|
return null;
|
|
36880
37505
|
}
|
|
36881
|
-
return (0,
|
|
37506
|
+
return (0, import_node_crypto12.createHash)("sha256").update(content).digest("hex");
|
|
36882
37507
|
}
|
|
36883
37508
|
async readOptionalFile(filePath) {
|
|
36884
37509
|
try {
|
|
@@ -36936,7 +37561,7 @@ var ProfileManager = class {
|
|
|
36936
37561
|
const dir = import_path.default.dirname(filePath);
|
|
36937
37562
|
const tempPath = import_path.default.join(
|
|
36938
37563
|
dir,
|
|
36939
|
-
`.${import_path.default.basename(filePath)}.${process.pid}.${(0,
|
|
37564
|
+
`.${import_path.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto12.randomUUID)()}.install`
|
|
36940
37565
|
);
|
|
36941
37566
|
const handle = await import_fs.promises.open(tempPath, "wx", 384);
|
|
36942
37567
|
try {
|
|
@@ -37054,7 +37679,7 @@ var ProfileManager = class {
|
|
|
37054
37679
|
});
|
|
37055
37680
|
const manifest = {
|
|
37056
37681
|
version: 1,
|
|
37057
|
-
id: (0,
|
|
37682
|
+
id: (0, import_node_crypto12.randomUUID)(),
|
|
37058
37683
|
operation,
|
|
37059
37684
|
phase: "prepared",
|
|
37060
37685
|
sourceFingerprint: this.fingerprintAuthContent(sourceRaw),
|
|
@@ -37776,7 +38401,7 @@ var ProfileManager = class {
|
|
|
37776
38401
|
const displayName = typeof options?.displayName === "string" && options.displayName.trim().length > 0 ? options.displayName.trim() : existingRecord?.displayName ?? resolvedName;
|
|
37777
38402
|
const record2 = {
|
|
37778
38403
|
name: resolvedName,
|
|
37779
|
-
homeId: existingRecord?.homeId ?? (options?.homeId ? this.normalizeProfileHomeId(options.homeId, resolvedName) : (0,
|
|
38404
|
+
homeId: existingRecord?.homeId ?? (options?.homeId ? this.normalizeProfileHomeId(options.homeId, resolvedName) : (0, import_node_crypto12.randomUUID)()),
|
|
37780
38405
|
cloudHomeId: existingRecord?.cloudHomeId ?? null,
|
|
37781
38406
|
displayName,
|
|
37782
38407
|
data,
|
|
@@ -37881,7 +38506,7 @@ var ProfileManager = class {
|
|
|
37881
38506
|
const safeName = record2.name.replace(/[^A-Za-z0-9._-]+/g, "-").slice(0, 48) || "profile";
|
|
37882
38507
|
const destination = import_path.default.join(
|
|
37883
38508
|
trashRoot,
|
|
37884
|
-
`CodexUse-${safeName}-${(0,
|
|
38509
|
+
`CodexUse-${safeName}-${(0, import_node_crypto12.randomUUID)()}`
|
|
37885
38510
|
);
|
|
37886
38511
|
await import_fs.promises.rename(profileHome, destination);
|
|
37887
38512
|
return destination;
|
|
@@ -38309,7 +38934,7 @@ var ProfileManager = class {
|
|
|
38309
38934
|
async acquireProfileRuntimeLease(record2) {
|
|
38310
38935
|
const leaseDir = this.getProfileRuntimeLeaseDir(record2.homeId);
|
|
38311
38936
|
const deletingPath = (0, import_path2.join)(leaseDir, ".deleting");
|
|
38312
|
-
const leaseId = (0,
|
|
38937
|
+
const leaseId = (0, import_node_crypto12.randomUUID)();
|
|
38313
38938
|
const leasePath = (0, import_path2.join)(leaseDir, `${leaseId}.json`);
|
|
38314
38939
|
const backupPath = (0, import_path2.join)(leaseDir, `${leaseId}.auth.backup`);
|
|
38315
38940
|
const releaseIntent = await this.acquireProfileHomeWriteIntent(record2);
|
|
@@ -38520,7 +39145,7 @@ var ProfileManager = class {
|
|
|
38520
39145
|
async acquireProfileHomeMutationGuard(record2) {
|
|
38521
39146
|
const leaseDir = this.getProfileRuntimeLeaseDir(record2.homeId);
|
|
38522
39147
|
const deletingPath = (0, import_path2.join)(leaseDir, ".deleting");
|
|
38523
|
-
const mutationId = (0,
|
|
39148
|
+
const mutationId = (0, import_node_crypto12.randomUUID)();
|
|
38524
39149
|
const mutationIntent = await acquireProfileHomeMutationIntent({
|
|
38525
39150
|
homeId: record2.homeId,
|
|
38526
39151
|
profileName: record2.name
|
|
@@ -39872,8 +40497,8 @@ var ProfileManager = class {
|
|
|
39872
40497
|
}
|
|
39873
40498
|
cloudRenamesByOldName.set(renamedExisting.name, name);
|
|
39874
40499
|
}
|
|
39875
|
-
const homeId = (0,
|
|
39876
|
-
const cloudHomeId = remoteHomeId || existing?.cloudHomeId || existing?.homeId || renamedExisting?.cloudHomeId || renamedExisting?.homeId || (0,
|
|
40500
|
+
const homeId = (0, import_node_crypto12.randomUUID)();
|
|
40501
|
+
const cloudHomeId = remoteHomeId || existing?.cloudHomeId || existing?.homeId || renamedExisting?.cloudHomeId || renamedExisting?.homeId || (0, import_node_crypto12.randomUUID)();
|
|
39877
40502
|
const sourceRecord = renamedExisting ?? existing;
|
|
39878
40503
|
if (sourceRecord) {
|
|
39879
40504
|
sourceHomeIdByTargetHomeId.set(homeId, sourceRecord.homeId);
|
|
@@ -40774,13 +41399,13 @@ async function listApiKeys(stateDir) {
|
|
|
40774
41399
|
return Object.values(store.apiKeysById).filter((key) => key.revokedAt === null).sort((left, right) => right.createdAt.localeCompare(left.createdAt)).map(accountPoolApiKeyView);
|
|
40775
41400
|
}
|
|
40776
41401
|
function hashToken(token) {
|
|
40777
|
-
return (0,
|
|
41402
|
+
return (0, import_node_crypto13.createHash)("sha256").update(token).digest("hex");
|
|
40778
41403
|
}
|
|
40779
41404
|
async function createApiKey(stateDir) {
|
|
40780
|
-
const plaintextToken = `cux_pool_${(0,
|
|
41405
|
+
const plaintextToken = `cux_pool_${(0, import_node_crypto13.randomBytes)(24).toString("hex")}`;
|
|
40781
41406
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
40782
41407
|
const keyRecord = {
|
|
40783
|
-
id: (0,
|
|
41408
|
+
id: (0, import_node_crypto13.randomUUID)(),
|
|
40784
41409
|
tokenHash: hashToken(plaintextToken),
|
|
40785
41410
|
tokenPreview: `${plaintextToken.slice(0, 8)}...${plaintextToken.slice(-6)}`,
|
|
40786
41411
|
createdAt: now2,
|
|
@@ -41405,14 +42030,14 @@ async function assertProfileAccessAllowed(profileManager, profileName) {
|
|
|
41405
42030
|
}
|
|
41406
42031
|
|
|
41407
42032
|
// ../../packages/runtime-app-state/src/app/workspaceBindings.ts
|
|
41408
|
-
var
|
|
42033
|
+
var import_node_fs10 = require("fs");
|
|
41409
42034
|
var import_node_path14 = __toESM(require("path"), 1);
|
|
41410
42035
|
async function canonicalizeWorkspacePath(input, options = {}) {
|
|
41411
42036
|
const resolved = import_node_path14.default.resolve(input || process.cwd());
|
|
41412
42037
|
try {
|
|
41413
|
-
const canonical = await
|
|
42038
|
+
const canonical = await import_node_fs10.promises.realpath(resolved);
|
|
41414
42039
|
if (options.requireDirectory !== false) {
|
|
41415
|
-
const stats = await
|
|
42040
|
+
const stats = await import_node_fs10.promises.stat(canonical);
|
|
41416
42041
|
if (!stats.isDirectory()) {
|
|
41417
42042
|
throw new Error(`Workspace path is not a directory: ${resolved}`);
|
|
41418
42043
|
}
|
|
@@ -41497,14 +42122,14 @@ async function resolveWorkspaceProfileBinding(requestedPath) {
|
|
|
41497
42122
|
|
|
41498
42123
|
// src/platform/codexCli.ts
|
|
41499
42124
|
var import_node_child_process8 = require("child_process");
|
|
41500
|
-
var
|
|
42125
|
+
var import_node_fs11 = require("fs");
|
|
41501
42126
|
var import_node_path15 = __toESM(require("path"));
|
|
41502
42127
|
var ENV_HINTS2 = ["CODEX_BINARY", "CODEX_CLI_PATH", "CODEX_PATH"];
|
|
41503
42128
|
function fileExists2(candidate) {
|
|
41504
42129
|
if (!candidate) return null;
|
|
41505
42130
|
const resolved = import_node_path15.default.resolve(candidate);
|
|
41506
42131
|
try {
|
|
41507
|
-
const stat2 = (0,
|
|
42132
|
+
const stat2 = (0, import_node_fs11.statSync)(resolved);
|
|
41508
42133
|
if (stat2.isFile()) return resolved;
|
|
41509
42134
|
} catch {
|
|
41510
42135
|
return null;
|
|
@@ -41963,17 +42588,17 @@ async function handleLicense(args2, version) {
|
|
|
41963
42588
|
}
|
|
41964
42589
|
|
|
41965
42590
|
// src/commands/profile.ts
|
|
41966
|
-
var
|
|
42591
|
+
var import_node_fs13 = require("fs");
|
|
41967
42592
|
var import_node_os7 = __toESM(require("os"));
|
|
41968
42593
|
var import_node_path17 = __toESM(require("path"));
|
|
41969
42594
|
|
|
41970
42595
|
// ../../packages/runtime-app-state/src/app/officialCodexSwitchCoordinator.ts
|
|
41971
|
-
var
|
|
41972
|
-
var
|
|
42596
|
+
var import_node_crypto14 = require("crypto");
|
|
42597
|
+
var import_node_fs12 = require("fs");
|
|
41973
42598
|
var import_node_path16 = __toESM(require("path"), 1);
|
|
41974
42599
|
var DEFAULT_SWITCH_INTENT_TTL_MS = 10 * 60 * 1e3;
|
|
41975
42600
|
var SWITCH_INTENT_RENEW_MS = 30 * 1e3;
|
|
41976
|
-
var PROCESS_OWNER_ID3 = (0,
|
|
42601
|
+
var PROCESS_OWNER_ID3 = (0, import_node_crypto14.randomUUID)();
|
|
41977
42602
|
var PROCESS_STARTED_AT3 = readProcessStartedAt(process.pid);
|
|
41978
42603
|
var localIntentDepth = /* @__PURE__ */ new Map();
|
|
41979
42604
|
var pendingLocalIntentAcquisitions = /* @__PURE__ */ new Map();
|
|
@@ -41983,7 +42608,7 @@ function nextSwitchIntentGeneration(current) {
|
|
|
41983
42608
|
}
|
|
41984
42609
|
async function acquireOfficialCodexSwitchIntent(input) {
|
|
41985
42610
|
const now2 = Date.now();
|
|
41986
|
-
const operationId = input.operationId?.trim() || (0,
|
|
42611
|
+
const operationId = input.operationId?.trim() || (0, import_node_crypto14.randomUUID)();
|
|
41987
42612
|
const targetProfileName = input.targetProfileName.trim();
|
|
41988
42613
|
if (!targetProfileName) {
|
|
41989
42614
|
throw new Error("Profile name is required");
|
|
@@ -42477,7 +43102,7 @@ function formatProfileLabel(name, displayName) {
|
|
|
42477
43102
|
}
|
|
42478
43103
|
var AUTO_ROLL_ACCESS_REQUIRED_MESSAGE = "Auto-roll requires a Pro license or an active trial.";
|
|
42479
43104
|
async function withIsolatedCodexLogin(mode, action) {
|
|
42480
|
-
const home = await
|
|
43105
|
+
const home = await import_node_fs13.promises.mkdtemp(import_node_path17.default.join(import_node_os7.default.tmpdir(), "codexuse-cli-login-"));
|
|
42481
43106
|
try {
|
|
42482
43107
|
await runCodexLogin(mode, {
|
|
42483
43108
|
HOME: home,
|
|
@@ -42487,7 +43112,7 @@ async function withIsolatedCodexLogin(mode, action) {
|
|
|
42487
43112
|
});
|
|
42488
43113
|
return await action(import_node_path17.default.join(home, "auth.json"));
|
|
42489
43114
|
} finally {
|
|
42490
|
-
await
|
|
43115
|
+
await import_node_fs13.promises.rm(home, { recursive: true, force: true }).catch(() => void 0);
|
|
42491
43116
|
}
|
|
42492
43117
|
}
|
|
42493
43118
|
async function assertOfficialCodexProfileStopped(profileName) {
|
|
@@ -44005,7 +44630,7 @@ async function pushRemoteSnapshot(access, snapshot2, options) {
|
|
|
44005
44630
|
|
|
44006
44631
|
// ../../packages/runtime-profiles/src/cloud-sync/encryption.ts
|
|
44007
44632
|
var import_node_child_process10 = require("child_process");
|
|
44008
|
-
var
|
|
44633
|
+
var import_node_crypto15 = require("crypto");
|
|
44009
44634
|
var KEYCHAIN_SERVICE2 = "CODEXUSE_CLOUD_SYNC_PASSPHRASE";
|
|
44010
44635
|
var KEYCHAIN_ACCOUNT_PREFIX2 = "license-sha256:";
|
|
44011
44636
|
var ENCRYPTION_AAD = Buffer.from("codexuse-cloud-sync-v2", "utf8");
|
|
@@ -44030,7 +44655,7 @@ function requireCloudSyncPassphrase(value3) {
|
|
|
44030
44655
|
}
|
|
44031
44656
|
async function deriveKey(passphrase, salt, params = SCRYPT_PARAMS) {
|
|
44032
44657
|
return new Promise((resolve2, reject) => {
|
|
44033
|
-
(0,
|
|
44658
|
+
(0, import_node_crypto15.scrypt)(passphrase, salt, params.keyLength, {
|
|
44034
44659
|
N: params.N,
|
|
44035
44660
|
r: params.r,
|
|
44036
44661
|
p: params.p,
|
|
@@ -44067,10 +44692,10 @@ function normalizeDecryptedSnapshot(value3) {
|
|
|
44067
44692
|
};
|
|
44068
44693
|
}
|
|
44069
44694
|
async function encryptCloudSyncSnapshot(snapshot2, passphrase) {
|
|
44070
|
-
const salt = (0,
|
|
44071
|
-
const iv = (0,
|
|
44695
|
+
const salt = (0, import_node_crypto15.randomBytes)(16);
|
|
44696
|
+
const iv = (0, import_node_crypto15.randomBytes)(12);
|
|
44072
44697
|
const key = await deriveKey(requireCloudSyncPassphrase(passphrase), salt);
|
|
44073
|
-
const cipher = (0,
|
|
44698
|
+
const cipher = (0, import_node_crypto15.createCipheriv)("aes-256-gcm", key, iv);
|
|
44074
44699
|
cipher.setAAD(ENCRYPTION_AAD);
|
|
44075
44700
|
const plaintext = Buffer.from(JSON.stringify(snapshot2), "utf8");
|
|
44076
44701
|
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
@@ -44097,7 +44722,7 @@ async function decryptCloudSyncSnapshot(snapshot2, passphrase) {
|
|
|
44097
44722
|
const tag2 = fromBase64(snapshot2.encryption.tag);
|
|
44098
44723
|
const ciphertext = fromBase64(snapshot2.encryption.ciphertext);
|
|
44099
44724
|
const key = await deriveKey(requireCloudSyncPassphrase(passphrase), salt, snapshot2.encryption.kdfParams);
|
|
44100
|
-
const decipher = (0,
|
|
44725
|
+
const decipher = (0, import_node_crypto15.createDecipheriv)("aes-256-gcm", key, iv);
|
|
44101
44726
|
decipher.setAAD(ENCRYPTION_AAD);
|
|
44102
44727
|
decipher.setAuthTag(tag2);
|
|
44103
44728
|
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
@@ -44112,7 +44737,7 @@ async function decryptCloudSyncSnapshot(snapshot2, passphrase) {
|
|
|
44112
44737
|
}
|
|
44113
44738
|
}
|
|
44114
44739
|
function keychainAccountForLicense(licenseKey) {
|
|
44115
|
-
const digest = (0,
|
|
44740
|
+
const digest = (0, import_node_crypto15.createHash)("sha256").update(licenseKey).digest("hex");
|
|
44116
44741
|
return KEYCHAIN_ACCOUNT_PREFIX2 + digest;
|
|
44117
44742
|
}
|
|
44118
44743
|
function runSecurityCommand2(args2) {
|
|
@@ -44678,7 +45303,7 @@ async function handleSync(args2, version) {
|
|
|
44678
45303
|
}
|
|
44679
45304
|
|
|
44680
45305
|
// src/commands/workspace.ts
|
|
44681
|
-
var
|
|
45306
|
+
var import_node_fs14 = require("fs");
|
|
44682
45307
|
function printWorkspaceHelp() {
|
|
44683
45308
|
console.log(`Usage:
|
|
44684
45309
|
codexuse workspace bind <path> <profile>
|
|
@@ -44708,7 +45333,7 @@ async function handleWorkspaceCommand(args2) {
|
|
|
44708
45333
|
return;
|
|
44709
45334
|
}
|
|
44710
45335
|
for (const binding of bindings) {
|
|
44711
|
-
const pathState = await
|
|
45336
|
+
const pathState = await import_node_fs14.promises.stat(binding.rootPath).then(() => "").catch(() => " (path missing)");
|
|
44712
45337
|
const profileState = profiles.has(binding.profileName) ? "" : " (profile missing)";
|
|
44713
45338
|
console.log(`${binding.rootPath} -> ${binding.profileName}${pathState}${profileState}`);
|
|
44714
45339
|
}
|
|
@@ -44772,7 +45397,7 @@ async function ensureCliStorageReady() {
|
|
|
44772
45397
|
}
|
|
44773
45398
|
|
|
44774
45399
|
// src/app/main.ts
|
|
44775
|
-
var VERSION = true ? "6.0.
|
|
45400
|
+
var VERSION = true ? "6.0.4" : "0.0.0";
|
|
44776
45401
|
async function runCli() {
|
|
44777
45402
|
const args2 = process.argv.slice(2);
|
|
44778
45403
|
if (args2.length === 0) {
|