codexuse-cli 3.9.8 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2216,6 +2216,17 @@ var SQLITE_BUSY_MAX_ATTEMPTS = 3;
2216
2216
  var SQLITE_BUSY_RETRY_DELAY_MS = 100;
2217
2217
  var writeQueueByDbPath = /* @__PURE__ */ new Map();
2218
2218
  var initializedDbPaths = /* @__PURE__ */ new Set();
2219
+ var AppStorageCorruptionError = class extends Error {
2220
+ constructor(message, options) {
2221
+ super(message);
2222
+ this.name = "AppStorageCorruptionError";
2223
+ this.dbPath = options.dbPath;
2224
+ this.namespace = options.namespace ?? null;
2225
+ if (options.cause !== void 0) {
2226
+ this.cause = options.cause;
2227
+ }
2228
+ }
2229
+ };
2219
2230
  function isRecord(value) {
2220
2231
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2221
2232
  }
@@ -2232,6 +2243,23 @@ function safeParseJson(raw) {
2232
2243
  return null;
2233
2244
  }
2234
2245
  }
2246
+ function parseJsonStrict(raw, options) {
2247
+ if (typeof raw !== "string" || raw.trim().length === 0) {
2248
+ return null;
2249
+ }
2250
+ try {
2251
+ return JSON.parse(raw);
2252
+ } catch (error) {
2253
+ throw new AppStorageCorruptionError(
2254
+ `App storage document ${options.namespace} contains invalid JSON.`,
2255
+ {
2256
+ dbPath: options.dbPath,
2257
+ namespace: options.namespace,
2258
+ cause: error
2259
+ }
2260
+ );
2261
+ }
2262
+ }
2235
2263
  function sleep(ms) {
2236
2264
  return new Promise((resolve) => setTimeout(resolve, ms));
2237
2265
  }
@@ -2240,9 +2268,32 @@ function isSqliteBusyError(error) {
2240
2268
  return false;
2241
2269
  }
2242
2270
  const sqliteError = error;
2243
- const message = typeof sqliteError.message === "string" ? sqliteError.message.toLowerCase() : "";
2271
+ if (sqliteError.cause && sqliteError.cause !== error && isSqliteBusyError(sqliteError.cause)) {
2272
+ return true;
2273
+ }
2274
+ if (sqliteError.error && sqliteError.error !== error && isSqliteBusyError(sqliteError.error)) {
2275
+ return true;
2276
+ }
2277
+ const message = typeof sqliteError.message === "string" ? sqliteError.message.toLowerCase() : String(error).toLowerCase();
2244
2278
  return sqliteError.code === "SQLITE_BUSY" || sqliteError.errno === 5 || message.includes("sqlite_busy") || message.includes("database is locked");
2245
2279
  }
2280
+ function isSqliteCorruptionError(error) {
2281
+ if (!error || typeof error !== "object") {
2282
+ return false;
2283
+ }
2284
+ const sqliteError = error;
2285
+ if (sqliteError.cause && sqliteError.cause !== error && isSqliteCorruptionError(sqliteError.cause)) {
2286
+ return true;
2287
+ }
2288
+ if (sqliteError.error && sqliteError.error !== error && isSqliteCorruptionError(sqliteError.error)) {
2289
+ return true;
2290
+ }
2291
+ const message = typeof sqliteError.message === "string" ? sqliteError.message.toLowerCase() : "";
2292
+ 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");
2293
+ }
2294
+ function isAppStorageCorruptionError(error) {
2295
+ return error instanceof AppStorageCorruptionError || isSqliteCorruptionError(error);
2296
+ }
2246
2297
  function beginImmediate(db) {
2247
2298
  db.exec("BEGIN IMMEDIATE");
2248
2299
  }
@@ -2317,19 +2368,55 @@ async function openDatabase(dbPath) {
2317
2368
  close: database.close.bind(database)
2318
2369
  };
2319
2370
  }
2371
+ function resetAppStorageInitialization(dbPath) {
2372
+ initializedDbPaths.delete(dbPath);
2373
+ }
2374
+ async function backupCorruptAppStorageDb(dbPath) {
2375
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2376
+ const backupPath = `${dbPath}.corrupt-${stamp}`;
2377
+ let moved = false;
2378
+ for (const suffix of ["", "-wal", "-shm"]) {
2379
+ const source = `${dbPath}${suffix}`;
2380
+ const destination = `${backupPath}${suffix}`;
2381
+ try {
2382
+ const stats = await import_node_fs.promises.stat(source);
2383
+ if (!stats.isFile()) {
2384
+ continue;
2385
+ }
2386
+ await import_node_fs.promises.rename(source, destination);
2387
+ moved = true;
2388
+ } catch (error) {
2389
+ if (error.code !== "ENOENT") {
2390
+ throw error;
2391
+ }
2392
+ }
2393
+ }
2394
+ resetAppStorageInitialization(dbPath);
2395
+ return moved ? backupPath : null;
2396
+ }
2320
2397
  async function withDatabase(dbPath, task) {
2321
2398
  for (let attempt = 1; attempt <= SQLITE_BUSY_MAX_ATTEMPTS; attempt += 1) {
2322
- const db = await openDatabase(dbPath);
2399
+ let db = null;
2323
2400
  try {
2401
+ db = await openDatabase(dbPath);
2324
2402
  applyConnectionPragmas(db);
2325
2403
  ensureSchema(db, dbPath);
2326
2404
  return task(db);
2327
2405
  } catch (error) {
2406
+ if (error instanceof AppStorageCorruptionError) {
2407
+ throw error;
2408
+ }
2409
+ if (isSqliteCorruptionError(error)) {
2410
+ throw new AppStorageCorruptionError(
2411
+ "App storage database is corrupt.",
2412
+ { dbPath, cause: error }
2413
+ );
2414
+ }
2328
2415
  if (!isSqliteBusyError(error) || attempt >= SQLITE_BUSY_MAX_ATTEMPTS) {
2329
2416
  throw error;
2330
2417
  }
2331
2418
  } finally {
2332
- db.close();
2419
+ db?.close();
2333
2420
  }
2334
2421
  await sleep(SQLITE_BUSY_RETRY_DELAY_MS * attempt);
2335
2422
  }
@@ -2352,6 +2439,40 @@ async function readDocument(dbPath, namespace, normalize) {
2352
2439
  return normalize(parsed);
2353
2440
  });
2354
2441
  }
2442
+ async function readDocumentStrict(dbPath, namespace, normalize) {
2443
+ return withDatabase(dbPath, (db) => {
2444
+ const row = useStatement(
2445
+ db,
2446
+ `SELECT value_json AS valueJson FROM ${APP_STORAGE_TABLE} WHERE namespace = ?`,
2447
+ (statement) => statement.get(namespace)
2448
+ );
2449
+ if (!isRecord(row)) {
2450
+ return null;
2451
+ }
2452
+ const parsed = parseJsonStrict(row.valueJson, {
2453
+ dbPath,
2454
+ namespace
2455
+ });
2456
+ if (parsed === null) {
2457
+ throw new AppStorageCorruptionError(
2458
+ `App storage document ${namespace} is empty.`,
2459
+ { dbPath, namespace }
2460
+ );
2461
+ }
2462
+ try {
2463
+ return normalize(parsed);
2464
+ } catch (error) {
2465
+ throw new AppStorageCorruptionError(
2466
+ `App storage document ${namespace} failed normalization.`,
2467
+ {
2468
+ dbPath,
2469
+ namespace,
2470
+ cause: error
2471
+ }
2472
+ );
2473
+ }
2474
+ });
2475
+ }
2355
2476
  async function writeDocument(dbPath, namespace, value) {
2356
2477
  return withWriteQueue(
2357
2478
  dbPath,
@@ -2624,7 +2745,7 @@ function normalizeAppState(raw) {
2624
2745
  merged.officialCodex.activity = Array.isArray(merged.officialCodex.activity) ? merged.officialCodex.activity.filter((entry) => isRecord2(entry)).map((entry) => ({
2625
2746
  id: asString(entry.id) ?? "",
2626
2747
  at: asString(entry.at) ?? (/* @__PURE__ */ new Date(0)).toISOString(),
2627
- kind: entry.kind === "auto-roll-eval" || entry.kind === "profile-switch" || entry.kind === "auth-verified" || entry.kind === "official-codex-restart" || entry.kind === "low-remaining-alert" ? entry.kind : "auto-roll-eval",
2748
+ kind: entry.kind === "auto-roll-eval" || entry.kind === "profile-switch" || entry.kind === "auth-verified" || entry.kind === "official-codex-restart" || entry.kind === "reset-window-activation" || entry.kind === "low-remaining-alert" ? entry.kind : "auto-roll-eval",
2628
2749
  status: asString(entry.status) ?? "unknown",
2629
2750
  reason: asString(entry.reason),
2630
2751
  decisionId: asString(entry.decisionId),
@@ -2643,7 +2764,9 @@ function normalizeAppState(raw) {
2643
2764
  restartResult: asString(entry.restartResult),
2644
2765
  observedProfileName: asString(entry.observedProfileName),
2645
2766
  observedProfileKeyHash: asString(entry.observedProfileKeyHash),
2646
- observedProfileMatchSource: asString(entry.observedProfileMatchSource)
2767
+ observedProfileMatchSource: asString(
2768
+ entry.observedProfileMatchSource
2769
+ )
2647
2770
  })).filter((entry) => entry.id && entry.at).slice(-50) : [];
2648
2771
  if (!isRecord2(merged.officialCodex.instancesByProfileName)) {
2649
2772
  merged.officialCodex.instancesByProfileName = {};
@@ -2767,7 +2890,9 @@ function normalizeAppState(raw) {
2767
2890
  merged.ui.profiles.groupBy = asString(merged.ui.profiles.groupBy);
2768
2891
  merged.ui.profiles.planFilter = asString(merged.ui.profiles.planFilter);
2769
2892
  merged.ui.profiles.healthFilter = asString(merged.ui.profiles.healthFilter);
2770
- merged.ui.profiles.customGroupFilter = asString(merged.ui.profiles.customGroupFilter);
2893
+ merged.ui.profiles.customGroupFilter = asString(
2894
+ merged.ui.profiles.customGroupFilter
2895
+ );
2771
2896
  if (typeof merged.ui.profiles.toolbarOpen !== "boolean") {
2772
2897
  merged.ui.profiles.toolbarOpen = null;
2773
2898
  }
@@ -2775,13 +2900,15 @@ function normalizeAppState(raw) {
2775
2900
  merged.ui.profiles.collapsedSections = {};
2776
2901
  } else {
2777
2902
  merged.ui.profiles.collapsedSections = Object.fromEntries(
2778
- Object.entries(merged.ui.profiles.collapsedSections).flatMap(([key, value]) => {
2779
- const normalizedKey = asString(key);
2780
- if (!normalizedKey || typeof value !== "boolean") {
2781
- return [];
2903
+ Object.entries(merged.ui.profiles.collapsedSections).flatMap(
2904
+ ([key, value]) => {
2905
+ const normalizedKey = asString(key);
2906
+ if (!normalizedKey || typeof value !== "boolean") {
2907
+ return [];
2908
+ }
2909
+ return [[normalizedKey, value]];
2782
2910
  }
2783
- return [[normalizedKey, value]];
2784
- })
2911
+ )
2785
2912
  );
2786
2913
  }
2787
2914
  if (!isRecord2(merged.ui.onboarding)) {
@@ -2810,26 +2937,30 @@ function normalizeAppState(raw) {
2810
2937
  merged.ui.onboarding.nudgeCooldowns = {};
2811
2938
  } else {
2812
2939
  merged.ui.onboarding.nudgeCooldowns = Object.fromEntries(
2813
- Object.entries(merged.ui.onboarding.nudgeCooldowns).flatMap(([key, value]) => {
2814
- const normalizedKey = asString(key);
2815
- if (!normalizedKey || !Number.isFinite(value)) {
2816
- return [];
2940
+ Object.entries(merged.ui.onboarding.nudgeCooldowns).flatMap(
2941
+ ([key, value]) => {
2942
+ const normalizedKey = asString(key);
2943
+ if (!normalizedKey || !Number.isFinite(value)) {
2944
+ return [];
2945
+ }
2946
+ return [[normalizedKey, Number(value)]];
2817
2947
  }
2818
- return [[normalizedKey, Number(value)]];
2819
- })
2948
+ )
2820
2949
  );
2821
2950
  }
2822
2951
  if (!isRecord2(merged.ui.onboarding.nudgeDismissCount)) {
2823
2952
  merged.ui.onboarding.nudgeDismissCount = {};
2824
2953
  } else {
2825
2954
  merged.ui.onboarding.nudgeDismissCount = Object.fromEntries(
2826
- Object.entries(merged.ui.onboarding.nudgeDismissCount).flatMap(([key, value]) => {
2827
- const normalizedKey = asString(key);
2828
- if (!normalizedKey || !Number.isFinite(value)) {
2829
- return [];
2955
+ Object.entries(merged.ui.onboarding.nudgeDismissCount).flatMap(
2956
+ ([key, value]) => {
2957
+ const normalizedKey = asString(key);
2958
+ if (!normalizedKey || !Number.isFinite(value)) {
2959
+ return [];
2960
+ }
2961
+ return [[normalizedKey, Number(value)]];
2830
2962
  }
2831
- return [[normalizedKey, Number(value)]];
2832
- })
2963
+ )
2833
2964
  );
2834
2965
  }
2835
2966
  if (typeof merged.ui.onboarding.proUnlockedCelebrated !== "boolean") {
@@ -2839,17 +2970,21 @@ function normalizeAppState(raw) {
2839
2970
  merged.ui.projectThreadSelections = {};
2840
2971
  } else {
2841
2972
  merged.ui.projectThreadSelections = Object.fromEntries(
2842
- Object.entries(merged.ui.projectThreadSelections).flatMap(([projectId, threadId]) => {
2843
- const normalizedProjectId = asString(projectId);
2844
- if (!normalizedProjectId) {
2845
- return [];
2973
+ Object.entries(merged.ui.projectThreadSelections).flatMap(
2974
+ ([projectId, threadId]) => {
2975
+ const normalizedProjectId = asString(projectId);
2976
+ if (!normalizedProjectId) {
2977
+ return [];
2978
+ }
2979
+ const normalizedThreadId = typeof threadId === "string" && threadId.trim().length > 0 ? threadId.trim() : null;
2980
+ return [[normalizedProjectId, normalizedThreadId]];
2846
2981
  }
2847
- const normalizedThreadId = typeof threadId === "string" && threadId.trim().length > 0 ? threadId.trim() : null;
2848
- return [[normalizedProjectId, normalizedThreadId]];
2849
- })
2982
+ )
2850
2983
  );
2851
2984
  }
2852
- merged.ui.duplicateWarningDismissedKey = asString(merged.ui.duplicateWarningDismissedKey);
2985
+ merged.ui.duplicateWarningDismissedKey = asString(
2986
+ merged.ui.duplicateWarningDismissedKey
2987
+ );
2853
2988
  if (typeof merged.ui.pendingLicenseActivation !== "boolean") {
2854
2989
  merged.ui.pendingLicenseActivation = false;
2855
2990
  }
@@ -2868,14 +3003,16 @@ function normalizeAppState(raw) {
2868
3003
  merged.profileDashboard.customGroupsByAccountKey = {};
2869
3004
  } else {
2870
3005
  merged.profileDashboard.customGroupsByAccountKey = Object.fromEntries(
2871
- Object.entries(merged.profileDashboard.customGroupsByAccountKey).flatMap(([key, value]) => {
2872
- const normalizedKey = asString(key);
2873
- const normalizedValue = asString(value);
2874
- if (!normalizedKey || !normalizedValue) {
2875
- return [];
3006
+ Object.entries(merged.profileDashboard.customGroupsByAccountKey).flatMap(
3007
+ ([key, value]) => {
3008
+ const normalizedKey = asString(key);
3009
+ const normalizedValue = asString(value);
3010
+ if (!normalizedKey || !normalizedValue) {
3011
+ return [];
3012
+ }
3013
+ return [[normalizedKey, normalizedValue]];
2876
3014
  }
2877
- return [[normalizedKey, normalizedValue]];
2878
- })
3015
+ )
2879
3016
  );
2880
3017
  }
2881
3018
  {
@@ -2942,7 +3079,9 @@ function normalizeAppState(raw) {
2942
3079
  }
2943
3080
  merged.analytics.anonymousId = asString(merged.analytics.anonymousId);
2944
3081
  if (!merged.analytics.anonymousId) {
2945
- const legacyInstallId = asString(merged.telemetry?.installId);
3082
+ const legacyInstallId = asString(
3083
+ merged.telemetry?.installId
3084
+ );
2946
3085
  merged.analytics.anonymousId = legacyInstallId;
2947
3086
  }
2948
3087
  if (typeof merged.analytics.enabled !== "boolean") {
@@ -3013,16 +3152,55 @@ async function readLegacyAppStateFromDisk() {
3013
3152
  }
3014
3153
  }
3015
3154
  async function readAppStateFromStorage() {
3016
- return readDocument(resolveStorageDbPath(), APP_STATE_DOCUMENT, normalizeAppState);
3155
+ return readDocumentStrict(
3156
+ resolveStorageDbPath(),
3157
+ APP_STATE_DOCUMENT,
3158
+ normalizeAppState
3159
+ );
3017
3160
  }
3018
3161
  async function writeAppStateToStorage(state) {
3019
- return writeDocument(resolveStorageDbPath(), APP_STATE_DOCUMENT, normalizeAppState(state));
3162
+ return writeDocument(
3163
+ resolveStorageDbPath(),
3164
+ APP_STATE_DOCUMENT,
3165
+ normalizeAppState(state)
3166
+ );
3167
+ }
3168
+ function compactRecoveryMessage(error) {
3169
+ const message = error instanceof Error ? error.message : typeof error === "string" ? error : String(error);
3170
+ return message.replace(/\s+/g, " ").trim().slice(0, 240) || "unknown corruption";
3171
+ }
3172
+ async function recoverCorruptAppStateStorage(error) {
3173
+ const dbPath = resolveStorageDbPath();
3174
+ if (error instanceof AppStorageCorruptionError && error.namespace === APP_STATE_DOCUMENT) {
3175
+ appStateCache = null;
3176
+ resetAppStorageInitialization(dbPath);
3177
+ const legacyState2 = await readLegacyAppStateFromDisk().catch(() => null);
3178
+ const recovered2 = normalizeAppState(legacyState2 ?? null);
3179
+ recovered2.migration.lastError = `Recovered app-state document after corruption (${compactRecoveryMessage(error)}). Shared storage database preserved.`;
3180
+ return writeAppStateToStorage(recovered2);
3181
+ }
3182
+ const backupPath = await backupCorruptAppStorageDb(dbPath);
3183
+ appStateCache = null;
3184
+ resetAppStorageInitialization(dbPath);
3185
+ const legacyState = await readLegacyAppStateFromDisk().catch(() => null);
3186
+ const recovered = normalizeAppState(legacyState ?? null);
3187
+ recovered.migration.lastError = backupPath ? `Recovered app-state storage after corruption (${compactRecoveryMessage(error)}). Backup: ${import_node_path2.default.basename(backupPath)}` : `Recovered app-state storage after corruption (${compactRecoveryMessage(error)}). No existing DB file was present.`;
3188
+ return writeAppStateToStorage(recovered);
3020
3189
  }
3021
3190
  async function ensureInitialized() {
3022
3191
  if (appStateCache) {
3023
3192
  return appStateCache;
3024
3193
  }
3025
- const loaded = await readAppStateFromStorage() ?? await readLegacyAppStateFromDisk();
3194
+ let loaded = null;
3195
+ try {
3196
+ loaded = await readAppStateFromStorage() ?? await readLegacyAppStateFromDisk();
3197
+ } catch (error) {
3198
+ if (!isAppStorageCorruptionError(error)) {
3199
+ throw error;
3200
+ }
3201
+ appStateCache = await recoverCorruptAppStateStorage(error);
3202
+ return clone2(appStateCache);
3203
+ }
3026
3204
  const normalized = loaded ?? normalizeAppState(null);
3027
3205
  appStateCache = await writeAppStateToStorage(normalized);
3028
3206
  return clone2(appStateCache);
@@ -3046,7 +3224,11 @@ async function withWriteLock(task) {
3046
3224
  }
3047
3225
  }
3048
3226
  async function initializeAppState(userDataDir) {
3049
- configuredUserDataDir = userDataDir;
3227
+ if (configuredUserDataDir !== userDataDir) {
3228
+ configuredUserDataDir = userDataDir;
3229
+ appStateCache = null;
3230
+ resetAppStorageInitialization(resolveStorageDbPath());
3231
+ }
3050
3232
  const state = await ensureInitialized();
3051
3233
  return clone2(state);
3052
3234
  }
@@ -4037,8 +4219,125 @@ function logInfo(...args) {
4037
4219
 
4038
4220
  // ../../packages/runtime-codex/src/codex/rpc.ts
4039
4221
  var RPC_TIMEOUT_MS = 1e4;
4222
+ var ACTIVATION_TURN_TIMEOUT_MS = 9e4;
4223
+ var ACTIVATION_PROMPT = "Reply with exactly: ok.";
4224
+ var ACTIVATION_MODEL = "gpt-5.1-codex-mini";
4040
4225
  var MAX_STDERR_CAPTURE_CHARS = 32768;
4041
4226
  var REFRESH_TOKEN_REDEEMED_SNIPPET = "refresh token was already used";
4227
+ function isRecord4(value) {
4228
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
4229
+ }
4230
+ function asString3(value) {
4231
+ return typeof value === "string" ? value : value != null ? String(value) : "";
4232
+ }
4233
+ function createRpcMessageReader(rl) {
4234
+ const queue = [];
4235
+ const waiters = [];
4236
+ let closedError = null;
4237
+ const rejectAll = (error) => {
4238
+ closedError = error;
4239
+ while (waiters.length > 0) {
4240
+ const waiter = waiters.shift();
4241
+ clearTimeout(waiter.timer);
4242
+ waiter.reject(error);
4243
+ }
4244
+ };
4245
+ const onLine = (line) => {
4246
+ let parsed;
4247
+ try {
4248
+ parsed = JSON.parse(line);
4249
+ } catch {
4250
+ rejectAll(new Error("codex RPC returned malformed JSON"));
4251
+ return;
4252
+ }
4253
+ const waiterIndex = waiters.findIndex((waiter) => waiter.predicate(parsed));
4254
+ if (waiterIndex >= 0) {
4255
+ const [waiter] = waiters.splice(waiterIndex, 1);
4256
+ clearTimeout(waiter.timer);
4257
+ waiter.resolve(parsed);
4258
+ return;
4259
+ }
4260
+ queue.push(parsed);
4261
+ };
4262
+ const onClose = () => {
4263
+ rejectAll(new Error("codex RPC stream closed before response"));
4264
+ };
4265
+ rl.on("line", onLine);
4266
+ rl.on("close", onClose);
4267
+ return {
4268
+ read(predicate, timeoutMs) {
4269
+ const queuedIndex = queue.findIndex(predicate);
4270
+ if (queuedIndex >= 0) {
4271
+ const [message] = queue.splice(queuedIndex, 1);
4272
+ return Promise.resolve(message);
4273
+ }
4274
+ if (closedError) {
4275
+ return Promise.reject(closedError);
4276
+ }
4277
+ return new Promise((resolve, reject) => {
4278
+ const waiter = {
4279
+ predicate,
4280
+ resolve,
4281
+ reject,
4282
+ timer: setTimeout(
4283
+ () => {
4284
+ const index = waiters.indexOf(waiter);
4285
+ if (index >= 0) {
4286
+ waiters.splice(index, 1);
4287
+ }
4288
+ reject(new Error("codex RPC timed out"));
4289
+ },
4290
+ Math.max(1, timeoutMs)
4291
+ )
4292
+ };
4293
+ waiters.push(waiter);
4294
+ });
4295
+ },
4296
+ dispose() {
4297
+ rl.off("line", onLine);
4298
+ rl.off("close", onClose);
4299
+ while (waiters.length > 0) {
4300
+ const waiter = waiters.shift();
4301
+ clearTimeout(waiter.timer);
4302
+ }
4303
+ }
4304
+ };
4305
+ }
4306
+ function readThreadIdFromResult(result) {
4307
+ if (!isRecord4(result)) return null;
4308
+ const thread = isRecord4(result.thread) ? result.thread : {};
4309
+ const value = asString3(thread.id ?? result.threadId).trim();
4310
+ return value.length > 0 ? value : null;
4311
+ }
4312
+ function readTurnIdFromResult(result) {
4313
+ if (!isRecord4(result)) return null;
4314
+ const turn = isRecord4(result.turn) ? result.turn : {};
4315
+ const value = asString3(turn.id ?? result.turnId).trim();
4316
+ return value.length > 0 ? value : null;
4317
+ }
4318
+ function readTurnIdFromNotification(message) {
4319
+ if (!isRecord4(message.params)) return null;
4320
+ const turn = isRecord4(message.params.turn) ? message.params.turn : {};
4321
+ const value = asString3(turn.id ?? message.params.turnId).trim();
4322
+ return value.length > 0 ? value : null;
4323
+ }
4324
+ function readTurnStatusFromNotification(message) {
4325
+ if (!isRecord4(message.params)) {
4326
+ return { status: null, reason: null };
4327
+ }
4328
+ const turn = isRecord4(message.params.turn) ? message.params.turn : {};
4329
+ const error = isRecord4(turn.error) ? turn.error : null;
4330
+ return {
4331
+ status: asString3(turn.status).trim() || null,
4332
+ reason: error ? asString3(error.message).trim() || null : null
4333
+ };
4334
+ }
4335
+ function readLegacyEventTurnId(message) {
4336
+ if (!isRecord4(message.params)) return null;
4337
+ const msg = isRecord4(message.params.msg) ? message.params.msg : {};
4338
+ const value = asString3(message.params.id ?? msg.turn_id ?? msg.turnId).trim();
4339
+ return value.length > 0 ? value : null;
4340
+ }
4042
4341
  function parseTimestamp2(value) {
4043
4342
  if (typeof value !== "string" || value.trim().length === 0) {
4044
4343
  return null;
@@ -4089,8 +4388,17 @@ function extractAuthRecencyMs(content) {
4089
4388
  const rootLastRefresh = parseTimestamp2(parsed.last_refresh);
4090
4389
  const nestedLastRefresh = parseTimestamp2(parsed.tokens?.last_refresh);
4091
4390
  const rootAccessIssuedAt = extractJwtIssuedAtMs(parsed.access_token);
4092
- const nestedAccessIssuedAt = extractJwtIssuedAtMs(parsed.tokens?.access_token);
4093
- const candidates = [rootLastRefresh, nestedLastRefresh, rootAccessIssuedAt, nestedAccessIssuedAt].filter((value) => typeof value === "number" && Number.isFinite(value));
4391
+ const nestedAccessIssuedAt = extractJwtIssuedAtMs(
4392
+ parsed.tokens?.access_token
4393
+ );
4394
+ const candidates = [
4395
+ rootLastRefresh,
4396
+ nestedLastRefresh,
4397
+ rootAccessIssuedAt,
4398
+ nestedAccessIssuedAt
4399
+ ].filter(
4400
+ (value) => typeof value === "number" && Number.isFinite(value)
4401
+ );
4094
4402
  if (candidates.length === 0) {
4095
4403
  return null;
4096
4404
  }
@@ -4141,10 +4449,13 @@ function isRpcResponseForRequest(message, requestId) {
4141
4449
  }
4142
4450
  async function readRpcResponseById(rl, requestId, timeoutMs) {
4143
4451
  return new Promise((resolve, reject) => {
4144
- const timer = setTimeout(() => {
4145
- cleanup();
4146
- reject(new Error("codex RPC timed out"));
4147
- }, Math.max(1, timeoutMs));
4452
+ const timer = setTimeout(
4453
+ () => {
4454
+ cleanup();
4455
+ reject(new Error("codex RPC timed out"));
4456
+ },
4457
+ Math.max(1, timeoutMs)
4458
+ );
4148
4459
  const cleanup = () => {
4149
4460
  clearTimeout(timer);
4150
4461
  rl.off("line", onLine);
@@ -4294,7 +4605,11 @@ async function fetchRateLimitsViaRpc(envOverride, options = {}) {
4294
4605
  throw new Error(formatRpcError("initialize", initializeResponse.error));
4295
4606
  }
4296
4607
  await sendPayload(child, { method: "initialized", params: {} });
4297
- await sendPayload(child, { id: 2, method: "account/rateLimits/read", params: {} });
4608
+ await sendPayload(child, {
4609
+ id: 2,
4610
+ method: "account/rateLimits/read",
4611
+ params: {}
4612
+ });
4298
4613
  const message = await readRpcResponseById(rl, 2, RPC_TIMEOUT_MS);
4299
4614
  if (message.error) {
4300
4615
  const base = formatRpcError("account/rateLimits/read", message.error);
@@ -4315,11 +4630,181 @@ async function fetchRateLimitsViaRpc(envOverride, options = {}) {
4315
4630
  if (shouldWriteBackAuth(initialSourceAuth, currentSourceAuth, updatedAuth)) {
4316
4631
  await import_node_fs5.promises.writeFile(sourceAuthPath, updatedAuth, "utf8");
4317
4632
  } else if (currentSourceAuth && currentSourceAuth !== updatedAuth && currentSourceAuth !== initialSourceAuth) {
4318
- logWarn("Skipped stale auth sync-back after rate-limit probe; source auth changed in flight.", {
4319
- sourceAuthPath,
4320
- currentRecencyMs: extractAuthRecencyMs(currentSourceAuth),
4321
- updatedRecencyMs: extractAuthRecencyMs(updatedAuth)
4322
- });
4633
+ logWarn(
4634
+ "Skipped stale auth sync-back after rate-limit probe; source auth changed in flight.",
4635
+ {
4636
+ sourceAuthPath,
4637
+ currentRecencyMs: extractAuthRecencyMs(currentSourceAuth),
4638
+ updatedRecencyMs: extractAuthRecencyMs(updatedAuth)
4639
+ }
4640
+ );
4641
+ }
4642
+ }
4643
+ } catch {
4644
+ }
4645
+ await import_node_fs5.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
4646
+ });
4647
+ }
4648
+ }
4649
+ async function activateResetWindowViaRpc(envOverride, options = {}) {
4650
+ const binaryPath = options.codexPath ?? await requireCodexCli();
4651
+ const tempHome = await import_node_fs5.promises.mkdtemp(
4652
+ import_node_path6.default.join(import_node_os2.default.tmpdir(), "codex-activation-")
4653
+ );
4654
+ const tempAuthPath = import_node_path6.default.join(tempHome, "auth.json");
4655
+ let initialSourceAuth = null;
4656
+ const sourceAuthPath = options.authPath ?? (envOverride?.CODEX_HOME ? import_node_path6.default.join(envOverride.CODEX_HOME, "auth.json") : import_node_path6.default.join(
4657
+ envOverride?.HOME ?? process.env.HOME ?? process.env.USERPROFILE ?? import_node_os2.default.homedir(),
4658
+ ".codex",
4659
+ "auth.json"
4660
+ ));
4661
+ try {
4662
+ initialSourceAuth = await import_node_fs5.promises.readFile(sourceAuthPath, "utf8").catch(() => null);
4663
+ if (!initialSourceAuth) {
4664
+ await import_node_fs5.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
4665
+ });
4666
+ return { status: "skipped", reason: "auth-missing" };
4667
+ }
4668
+ await import_node_fs5.promises.writeFile(tempAuthPath, initialSourceAuth, "utf8");
4669
+ } catch {
4670
+ await import_node_fs5.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
4671
+ });
4672
+ return { status: "skipped", reason: "auth-missing" };
4673
+ }
4674
+ const childEnv = {
4675
+ ...process.env,
4676
+ ...envOverride ?? {},
4677
+ HOME: tempHome,
4678
+ USERPROFILE: tempHome,
4679
+ CODEX_HOME: tempHome,
4680
+ CODEX_TELEMETRY_LABEL: "codex-reset-activation",
4681
+ ELECTRON_RUN_AS_NODE: "1"
4682
+ };
4683
+ const command = buildCodexCommand(
4684
+ binaryPath,
4685
+ ["-s", "read-only", "-a", "untrusted", "app-server"],
4686
+ childEnv
4687
+ );
4688
+ const child = (0, import_node_child_process2.spawn)(command.command, command.args, {
4689
+ stdio: ["pipe", "pipe", "pipe"],
4690
+ env: childEnv,
4691
+ shell: command.shell
4692
+ });
4693
+ const rl = import_node_readline.default.createInterface({
4694
+ input: child.stdout,
4695
+ crlfDelay: Infinity
4696
+ });
4697
+ const reader = createRpcMessageReader(rl);
4698
+ let stderrOutput = "";
4699
+ child.stderr?.on("data", (chunk) => {
4700
+ if (stderrOutput.length >= MAX_STDERR_CAPTURE_CHARS) {
4701
+ return;
4702
+ }
4703
+ const text = chunk.toString("utf8");
4704
+ const remaining = MAX_STDERR_CAPTURE_CHARS - stderrOutput.length;
4705
+ stderrOutput += text.slice(0, Math.max(0, remaining));
4706
+ });
4707
+ try {
4708
+ await sendPayload(child, {
4709
+ id: 1,
4710
+ method: "initialize",
4711
+ params: { clientInfo: { name: "codexuse", version: "0.0.0" } }
4712
+ });
4713
+ const initializeResponse = await reader.read(
4714
+ (message) => isRpcResponseForRequest(message, 1),
4715
+ RPC_TIMEOUT_MS
4716
+ );
4717
+ if (initializeResponse.error) {
4718
+ throw new Error(formatRpcError("initialize", initializeResponse.error));
4719
+ }
4720
+ await sendPayload(child, { method: "initialized", params: {} });
4721
+ await sendPayload(child, {
4722
+ id: 2,
4723
+ method: "thread/start",
4724
+ params: {
4725
+ cwd: tempHome,
4726
+ model: ACTIVATION_MODEL,
4727
+ approvalPolicy: "untrusted",
4728
+ sandbox: "read-only",
4729
+ experimentalRawEvents: false
4730
+ }
4731
+ });
4732
+ const threadResponse = await reader.read(
4733
+ (message) => isRpcResponseForRequest(message, 2),
4734
+ RPC_TIMEOUT_MS
4735
+ );
4736
+ if (threadResponse.error) {
4737
+ throw new Error(formatRpcError("thread/start", threadResponse.error));
4738
+ }
4739
+ const threadId = readThreadIdFromResult(threadResponse.result);
4740
+ if (!threadId) {
4741
+ throw new Error("thread/start response did not include a thread id.");
4742
+ }
4743
+ await sendPayload(child, {
4744
+ id: 3,
4745
+ method: "turn/start",
4746
+ params: {
4747
+ threadId,
4748
+ model: ACTIVATION_MODEL,
4749
+ effort: "low",
4750
+ input: [
4751
+ {
4752
+ type: "text",
4753
+ text: ACTIVATION_PROMPT,
4754
+ text_elements: []
4755
+ }
4756
+ ]
4757
+ }
4758
+ });
4759
+ const turnResponse = await reader.read(
4760
+ (message) => isRpcResponseForRequest(message, 3),
4761
+ RPC_TIMEOUT_MS
4762
+ );
4763
+ if (turnResponse.error) {
4764
+ const base = formatRpcError("turn/start", turnResponse.error);
4765
+ const hint = inferRefreshFailureHint(stderrOutput);
4766
+ if (hint && !base.toLowerCase().includes(hint)) {
4767
+ throw new Error(`${base}; ${hint}`);
4768
+ }
4769
+ throw new Error(base);
4770
+ }
4771
+ const turnId = readTurnIdFromResult(turnResponse.result);
4772
+ if (!turnId) {
4773
+ throw new Error("turn/start response did not include a turn id.");
4774
+ }
4775
+ const completed = await reader.read(
4776
+ (message) => message.method === "turn/completed" && readTurnIdFromNotification(message) === turnId || message.method === "codex/event/task_complete" && readLegacyEventTurnId(message) === turnId,
4777
+ ACTIVATION_TURN_TIMEOUT_MS
4778
+ );
4779
+ const turnStatus = readTurnStatusFromNotification(completed);
4780
+ if (turnStatus.status === "failed") {
4781
+ return {
4782
+ status: "failed",
4783
+ reason: turnStatus.reason ?? "turn-failed",
4784
+ threadId,
4785
+ turnId
4786
+ };
4787
+ }
4788
+ return { status: "completed", reason: null, threadId, turnId };
4789
+ } finally {
4790
+ child.kill();
4791
+ reader.dispose();
4792
+ rl.close();
4793
+ try {
4794
+ const updatedAuth = await import_node_fs5.promises.readFile(tempAuthPath, "utf8");
4795
+ if (updatedAuth.trim().length > 0) {
4796
+ const currentSourceAuth = await import_node_fs5.promises.readFile(sourceAuthPath, "utf8").catch(() => null);
4797
+ if (shouldWriteBackAuth(initialSourceAuth, currentSourceAuth, updatedAuth)) {
4798
+ await import_node_fs5.promises.writeFile(sourceAuthPath, updatedAuth, "utf8");
4799
+ } else if (currentSourceAuth && currentSourceAuth !== updatedAuth && currentSourceAuth !== initialSourceAuth) {
4800
+ logWarn(
4801
+ "Skipped stale auth sync-back after reset-window activation; source auth changed in flight.",
4802
+ {
4803
+ sourceAuthPath,
4804
+ currentRecencyMs: extractAuthRecencyMs(currentSourceAuth),
4805
+ updatedRecencyMs: extractAuthRecencyMs(updatedAuth)
4806
+ }
4807
+ );
4323
4808
  }
4324
4809
  }
4325
4810
  } catch {
@@ -5868,6 +6353,25 @@ var ProfileManager = class {
5868
6353
  });
5869
6354
  }
5870
6355
  }
6356
+ async activateResetWindow(name, options = {}) {
6357
+ const profileName = this.normalizeProfileName(name);
6358
+ try {
6359
+ return await this.enqueueProfileOperation(
6360
+ profileName,
6361
+ () => this.runWithPreparedProfileHome(
6362
+ profileName,
6363
+ (env) => activateResetWindowViaRpc(env, { codexPath: options.codexPath }),
6364
+ { syncFromActiveAuthBeforeAction: false }
6365
+ )
6366
+ );
6367
+ } finally {
6368
+ await this.enqueueAuthSwap(async () => {
6369
+ await this.syncActiveAuthFromProfileIfCurrent(profileName);
6370
+ }).catch((error) => {
6371
+ logWarn(`Failed to sync active auth after reset-window activation for '${profileName}':`, error);
6372
+ });
6373
+ }
6374
+ }
5871
6375
  /**
5872
6376
  * Rename a profile
5873
6377
  */
@@ -6320,7 +6824,7 @@ var MODEL_SLUG_ALIASES = {
6320
6824
  function asRecord2(value) {
6321
6825
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
6322
6826
  }
6323
- function asString3(value) {
6827
+ function asString4(value) {
6324
6828
  if (typeof value !== "string") {
6325
6829
  return null;
6326
6830
  }
@@ -6331,7 +6835,7 @@ function asNumber(value) {
6331
6835
  return typeof value === "number" && Number.isFinite(value) ? value : null;
6332
6836
  }
6333
6837
  function normalizeIsoString(value) {
6334
- const normalized = asString3(value);
6838
+ const normalized = asString4(value);
6335
6839
  if (!normalized) {
6336
6840
  return null;
6337
6841
  }
@@ -6343,7 +6847,7 @@ function normalizeStringArray(value) {
6343
6847
  const result = [];
6344
6848
  const seen = /* @__PURE__ */ new Set();
6345
6849
  for (const entry of input) {
6346
- const normalized = asString3(entry);
6850
+ const normalized = asString4(entry);
6347
6851
  if (!normalized || seen.has(normalized)) {
6348
6852
  continue;
6349
6853
  }
@@ -6353,7 +6857,7 @@ function normalizeStringArray(value) {
6353
6857
  return result;
6354
6858
  }
6355
6859
  function normalizeReasoningEffort(value) {
6356
- const normalized = asString3(value)?.toLowerCase() ?? null;
6860
+ const normalized = asString4(value)?.toLowerCase() ?? null;
6357
6861
  return normalized && normalized.length > 0 ? normalized : null;
6358
6862
  }
6359
6863
  function normalizeRoutingStrategy(value) {
@@ -6387,7 +6891,7 @@ function normalizeAccountPoolExposedModels(value, fallbackToDefault) {
6387
6891
  const seen = /* @__PURE__ */ new Set();
6388
6892
  const input = Array.isArray(value) ? value : [];
6389
6893
  for (const entry of input) {
6390
- const raw = asString3(entry);
6894
+ const raw = asString4(entry);
6391
6895
  const normalized = normalizeCodexModelSlug(raw) ?? raw;
6392
6896
  if (!normalized || seen.has(normalized)) {
6393
6897
  continue;
@@ -6503,8 +7007,8 @@ function normalizeSessionStatus(value) {
6503
7007
  }
6504
7008
  function normalizeApiKeyRecord(id, value) {
6505
7009
  const record = asRecord2(value);
6506
- const tokenHash = asString3(record.tokenHash);
6507
- const tokenPreview = asString3(record.tokenPreview);
7010
+ const tokenHash = asString4(record.tokenHash);
7011
+ const tokenPreview = asString4(record.tokenPreview);
6508
7012
  const createdAt = normalizeIsoString(record.createdAt);
6509
7013
  if (!tokenHash || !tokenPreview || !createdAt) {
6510
7014
  return null;
@@ -6520,7 +7024,7 @@ function normalizeApiKeyRecord(id, value) {
6520
7024
  }
6521
7025
  function normalizeLegacySessionRecord(id, value) {
6522
7026
  const record = asRecord2(value);
6523
- const profileName = asString3(record.profileName);
7027
+ const profileName = asString4(record.profileName);
6524
7028
  const createdAt = normalizeIsoString(record.createdAt);
6525
7029
  const lastUsedAt = normalizeIsoString(record.lastUsedAt);
6526
7030
  if (!profileName || !createdAt || !lastUsedAt) {
@@ -6530,16 +7034,16 @@ function normalizeLegacySessionRecord(id, value) {
6530
7034
  return {
6531
7035
  id,
6532
7036
  affinityKind,
6533
- affinityKey: asString3(record.affinityKey),
7037
+ affinityKey: asString4(record.affinityKey),
6534
7038
  profileName,
6535
- threadId: asString3(record.threadId) ?? id,
6536
- model: asString3(record.model),
7039
+ threadId: asString4(record.threadId) ?? id,
7040
+ model: asString4(record.model),
6537
7041
  status: normalizeSessionStatus(record.status),
6538
- lastError: asString3(record.lastError),
7042
+ lastError: asString4(record.lastError),
6539
7043
  createdAt,
6540
7044
  lastUsedAt,
6541
7045
  expiresAt: normalizeIsoString(record.expiresAt),
6542
- lastResponseId: asString3(record.lastResponseId),
7046
+ lastResponseId: asString4(record.lastResponseId),
6543
7047
  responseIds: normalizeStringArray(record.responseIds).slice(0, MAX_RESPONSE_IDS_PER_SESSION)
6544
7048
  };
6545
7049
  }
@@ -6561,7 +7065,7 @@ function normalizeLegacyStore(value) {
6561
7065
  }
6562
7066
  const responseIndex = {};
6563
7067
  for (const [responseId, sessionId] of Object.entries(asRecord2(record.responseIndex))) {
6564
- const normalizedSessionId = asString3(sessionId);
7068
+ const normalizedSessionId = asString4(sessionId);
6565
7069
  if (normalizedSessionId) {
6566
7070
  responseIndex[responseId] = normalizedSessionId;
6567
7071
  }
@@ -6576,7 +7080,7 @@ function normalizeLegacyStore(value) {
6576
7080
  }
6577
7081
  function normalizeSessionRecord(id, value) {
6578
7082
  const record = asRecord2(value);
6579
- const activeSegmentId = asString3(record.activeSegmentId);
7083
+ const activeSegmentId = asString4(record.activeSegmentId);
6580
7084
  const createdAt = normalizeIsoString(record.createdAt);
6581
7085
  const lastUsedAt = normalizeIsoString(record.lastUsedAt);
6582
7086
  if (!activeSegmentId || !createdAt || !lastUsedAt) {
@@ -6586,25 +7090,25 @@ function normalizeSessionRecord(id, value) {
6586
7090
  return {
6587
7091
  id,
6588
7092
  affinityKind,
6589
- affinityKey: asString3(record.affinityKey),
7093
+ affinityKey: asString4(record.affinityKey),
6590
7094
  activeSegmentId,
6591
7095
  segmentIds: normalizeStringArray(record.segmentIds),
6592
- model: asString3(record.model),
7096
+ model: asString4(record.model),
6593
7097
  status: normalizeSessionStatus(record.status),
6594
- lastError: asString3(record.lastError),
7098
+ lastError: asString4(record.lastError),
6595
7099
  createdAt,
6596
7100
  lastUsedAt,
6597
7101
  expiresAt: normalizeIsoString(record.expiresAt),
6598
- lastResponseId: asString3(record.lastResponseId),
7102
+ lastResponseId: asString4(record.lastResponseId),
6599
7103
  responseIds: normalizeStringArray(record.responseIds).slice(0, MAX_RESPONSE_IDS_PER_SESSION),
6600
7104
  rolloverCount: asNumber(record.rolloverCount) ?? 0,
6601
- lastRolloverReason: asString3(record.lastRolloverReason)
7105
+ lastRolloverReason: asString4(record.lastRolloverReason)
6602
7106
  };
6603
7107
  }
6604
7108
  function normalizeSegmentRecord(id, value) {
6605
7109
  const record = asRecord2(value);
6606
- const sessionId = asString3(record.sessionId);
6607
- const profileName = asString3(record.profileName);
7110
+ const sessionId = asString4(record.sessionId);
7111
+ const profileName = asString4(record.profileName);
6608
7112
  const createdAt = normalizeIsoString(record.createdAt);
6609
7113
  const lastUsedAt = normalizeIsoString(record.lastUsedAt);
6610
7114
  if (!sessionId || !profileName || !createdAt || !lastUsedAt) {
@@ -6620,8 +7124,8 @@ function normalizeSegmentRecord(id, value) {
6620
7124
  }
6621
7125
  function normalizeResponseIndexRecord(value) {
6622
7126
  const record = asRecord2(value);
6623
- const sessionId = asString3(record.sessionId);
6624
- const segmentId = asString3(record.segmentId);
7127
+ const sessionId = asString4(record.sessionId);
7128
+ const segmentId = asString4(record.segmentId);
6625
7129
  const createdAt = normalizeIsoString(record.createdAt) ?? (/* @__PURE__ */ new Date(0)).toISOString();
6626
7130
  if (!sessionId || !segmentId) {
6627
7131
  return null;
@@ -7296,7 +7800,7 @@ async function handleAccountPoolCommand(args, version) {
7296
7800
  params,
7297
7801
  key: "accountPoolExposedModels",
7298
7802
  defaultValues: DEFAULT_ACCOUNT_POOL_EXPOSED_MODELS,
7299
- normalizeValue: (value) => normalizeCodexModelSlug(value) ?? asString3(value)
7803
+ normalizeValue: (value) => normalizeCodexModelSlug(value) ?? asString4(value)
7300
7804
  });
7301
7805
  return;
7302
7806
  case "reasoning":
@@ -8653,228 +9157,227 @@ async function getOfficialCodexProfileInstances() {
8653
9157
  };
8654
9158
  }
8655
9159
  function launchOfficialCodexProfileInstance(options) {
8656
- return enqueueProfileAction(async () => {
8657
- if (process.platform !== "darwin") {
8658
- return {
8659
- status: "skipped",
8660
- profileName: options.profileName,
8661
- instance: null,
8662
- reason: "unsupported-platform"
8663
- };
8664
- }
8665
- const { candidate, mainPids } = await resolveCodexAppTarget();
8666
- if (!candidate) {
8667
- return {
8668
- status: "skipped",
8669
- profileName: options.profileName,
8670
- instance: null,
8671
- reason: "official-codex-app-not-found"
8672
- };
8673
- }
8674
- const existing = await readManagedInstance(options.profileName);
8675
- if (existing) {
8676
- const rows = await readProcessRows();
8677
- const runtime = await resolveInstanceRuntimeState({ instance: existing, candidate, rows });
8678
- if (runtime.running) {
8679
- const verified = {
8680
- ...existing,
8681
- profileHome: existing.profileHome ?? options.profileHome,
8682
- appServerPid: runtime.appServerPid,
8683
- lastVerifiedAt: Date.now(),
8684
- lastStatus: "already-running",
8685
- lastError: null
8686
- };
8687
- await patchManagedInstance(verified);
8688
- return {
8689
- status: "already-running",
8690
- profileName: options.profileName,
8691
- instance: managedInstanceToPayload(
8692
- verified,
8693
- true,
8694
- runtime.appServerPid,
8695
- runtime.startedAt
8696
- ),
8697
- reason: null
8698
- };
8699
- }
8700
- }
8701
- const launch = await openCodexWithProfileHome(
8702
- candidate,
8703
- options.profileHome,
8704
- options.profileName,
8705
- new Set(mainPids)
8706
- );
8707
- if (!launch.opened) {
8708
- const failed = {
8709
- profileName: options.profileName,
8710
- profileKey: options.profileKey,
8711
- profileHome: options.profileHome,
8712
- appPath: candidate.appPath,
8713
- bundleId: candidate.bundleId,
8714
- pid: null,
8715
- appServerPid: null,
8716
- launchedAt: null,
8717
- lastVerifiedAt: null,
8718
- lastStatus: "failed",
8719
- lastError: "open-failed"
8720
- };
8721
- await patchManagedInstance(failed);
8722
- return {
8723
- status: "failed",
8724
- profileName: options.profileName,
8725
- instance: managedInstanceToPayload(failed, false),
8726
- reason: "open-failed"
8727
- };
8728
- }
8729
- const launchedPid = launch.pid;
8730
- if (launchedPid === null) {
8731
- const failed = {
8732
- profileName: options.profileName,
8733
- profileKey: options.profileKey,
8734
- profileHome: options.profileHome,
8735
- appPath: candidate.appPath,
8736
- bundleId: candidate.bundleId,
8737
- pid: null,
8738
- appServerPid: null,
8739
- launchedAt: null,
8740
- lastVerifiedAt: null,
8741
- lastStatus: "failed",
8742
- lastError: "launch-timeout"
8743
- };
8744
- await patchManagedInstance(failed);
8745
- return {
8746
- status: "failed",
8747
- profileName: options.profileName,
8748
- instance: managedInstanceToPayload(failed, false),
8749
- reason: "launch-timeout"
8750
- };
8751
- }
8752
- const appServerPid = await waitForAppServerPid(
8753
- launchedPid,
8754
- options.profileHome
8755
- );
8756
- if (appServerPid === null) {
8757
- const failed = {
8758
- profileName: options.profileName,
8759
- profileKey: options.profileKey,
8760
- profileHome: options.profileHome,
8761
- appPath: candidate.appPath,
8762
- bundleId: candidate.bundleId,
8763
- pid: null,
8764
- appServerPid: null,
8765
- launchedAt: null,
9160
+ return enqueueProfileAction(() => launchOfficialCodexProfileInstanceOnce(options));
9161
+ }
9162
+ async function launchOfficialCodexProfileInstanceOnce(options) {
9163
+ if (process.platform !== "darwin") {
9164
+ return {
9165
+ status: "skipped",
9166
+ profileName: options.profileName,
9167
+ instance: null,
9168
+ reason: "unsupported-platform"
9169
+ };
9170
+ }
9171
+ const { candidate, mainPids } = await resolveCodexAppTarget();
9172
+ if (!candidate) {
9173
+ return {
9174
+ status: "skipped",
9175
+ profileName: options.profileName,
9176
+ instance: null,
9177
+ reason: "official-codex-app-not-found"
9178
+ };
9179
+ }
9180
+ const existing = await readManagedInstance(options.profileName);
9181
+ if (existing) {
9182
+ const rows = await readProcessRows();
9183
+ const runtime = await resolveInstanceRuntimeState({ instance: existing, candidate, rows });
9184
+ if (runtime.running) {
9185
+ const verified = {
9186
+ ...existing,
9187
+ profileHome: existing.profileHome ?? options.profileHome,
9188
+ appServerPid: runtime.appServerPid,
8766
9189
  lastVerifiedAt: Date.now(),
8767
- lastStatus: "failed",
8768
- lastError: "app-server-not-verified"
9190
+ lastStatus: "already-running",
9191
+ lastError: null
8769
9192
  };
8770
- await patchManagedInstance(failed);
9193
+ await patchManagedInstance(verified);
8771
9194
  return {
8772
- status: "failed",
9195
+ status: "already-running",
8773
9196
  profileName: options.profileName,
8774
- instance: managedInstanceToPayload(failed, false),
8775
- reason: "app-server-not-verified"
9197
+ instance: managedInstanceToPayload(
9198
+ verified,
9199
+ true,
9200
+ runtime.appServerPid,
9201
+ runtime.startedAt
9202
+ ),
9203
+ reason: null
8776
9204
  };
8777
9205
  }
8778
- const now = Date.now();
8779
- const instance = {
9206
+ }
9207
+ const launch = await openCodexWithProfileHome(
9208
+ candidate,
9209
+ options.profileHome,
9210
+ options.profileName,
9211
+ new Set(mainPids)
9212
+ );
9213
+ if (!launch.opened) {
9214
+ const failed = {
8780
9215
  profileName: options.profileName,
8781
9216
  profileKey: options.profileKey,
8782
9217
  profileHome: options.profileHome,
8783
9218
  appPath: candidate.appPath,
8784
9219
  bundleId: candidate.bundleId,
8785
- pid: launchedPid,
8786
- appServerPid,
8787
- launchedAt: now,
8788
- lastVerifiedAt: now,
8789
- lastStatus: "started",
8790
- lastError: null
9220
+ pid: null,
9221
+ appServerPid: null,
9222
+ launchedAt: null,
9223
+ lastVerifiedAt: null,
9224
+ lastStatus: "failed",
9225
+ lastError: "open-failed"
8791
9226
  };
8792
- await patchManagedInstance(instance);
9227
+ await patchManagedInstance(failed);
8793
9228
  return {
8794
- status: "started",
9229
+ status: "failed",
8795
9230
  profileName: options.profileName,
8796
- instance: managedInstanceToPayload(instance, true, appServerPid),
8797
- reason: null
9231
+ instance: managedInstanceToPayload(failed, false),
9232
+ reason: "open-failed"
8798
9233
  };
8799
- });
9234
+ }
9235
+ const launchedPid = launch.pid;
9236
+ if (launchedPid === null) {
9237
+ const failed = {
9238
+ profileName: options.profileName,
9239
+ profileKey: options.profileKey,
9240
+ profileHome: options.profileHome,
9241
+ appPath: candidate.appPath,
9242
+ bundleId: candidate.bundleId,
9243
+ pid: null,
9244
+ appServerPid: null,
9245
+ launchedAt: null,
9246
+ lastVerifiedAt: null,
9247
+ lastStatus: "failed",
9248
+ lastError: "launch-timeout"
9249
+ };
9250
+ await patchManagedInstance(failed);
9251
+ return {
9252
+ status: "failed",
9253
+ profileName: options.profileName,
9254
+ instance: managedInstanceToPayload(failed, false),
9255
+ reason: "launch-timeout"
9256
+ };
9257
+ }
9258
+ const appServerPid = await waitForAppServerPid(
9259
+ launchedPid,
9260
+ options.profileHome
9261
+ );
9262
+ if (appServerPid === null) {
9263
+ const failed = {
9264
+ profileName: options.profileName,
9265
+ profileKey: options.profileKey,
9266
+ profileHome: options.profileHome,
9267
+ appPath: candidate.appPath,
9268
+ bundleId: candidate.bundleId,
9269
+ pid: null,
9270
+ appServerPid: null,
9271
+ launchedAt: null,
9272
+ lastVerifiedAt: Date.now(),
9273
+ lastStatus: "failed",
9274
+ lastError: "app-server-not-verified"
9275
+ };
9276
+ await patchManagedInstance(failed);
9277
+ return {
9278
+ status: "failed",
9279
+ profileName: options.profileName,
9280
+ instance: managedInstanceToPayload(failed, false),
9281
+ reason: "app-server-not-verified"
9282
+ };
9283
+ }
9284
+ const now = Date.now();
9285
+ const instance = {
9286
+ profileName: options.profileName,
9287
+ profileKey: options.profileKey,
9288
+ profileHome: options.profileHome,
9289
+ appPath: candidate.appPath,
9290
+ bundleId: candidate.bundleId,
9291
+ pid: launchedPid,
9292
+ appServerPid,
9293
+ launchedAt: now,
9294
+ lastVerifiedAt: now,
9295
+ lastStatus: "started",
9296
+ lastError: null
9297
+ };
9298
+ await patchManagedInstance(instance);
9299
+ return {
9300
+ status: "started",
9301
+ profileName: options.profileName,
9302
+ instance: managedInstanceToPayload(instance, true, appServerPid),
9303
+ reason: null
9304
+ };
8800
9305
  }
8801
- function stopOfficialCodexProfileInstance(profileName) {
8802
- return enqueueProfileAction(async () => {
8803
- const existing = await readManagedInstance(profileName);
8804
- if (!existing) {
8805
- return {
8806
- status: "not-running",
8807
- profileName,
8808
- instance: null,
8809
- reason: "not-managed"
8810
- };
8811
- }
8812
- const { candidate } = await resolveCodexAppTarget();
8813
- if (!candidate) {
8814
- const stopped2 = {
8815
- ...existing,
8816
- pid: null,
8817
- appServerPid: null,
8818
- lastVerifiedAt: Date.now(),
8819
- lastStatus: "not-running",
8820
- lastError: "official-codex-app-not-found"
8821
- };
8822
- await patchManagedInstance(stopped2);
8823
- return {
8824
- status: "not-running",
8825
- profileName,
8826
- instance: managedInstanceToPayload(stopped2, false),
8827
- reason: "official-codex-app-not-found"
8828
- };
8829
- }
8830
- const rows = await readProcessRows();
8831
- const runtime = await resolveInstanceRuntimeState({ instance: existing, candidate, rows });
8832
- if (!runtime.running || !existing.pid) {
8833
- const stopped2 = {
8834
- ...existing,
8835
- pid: null,
8836
- appServerPid: null,
8837
- lastVerifiedAt: Date.now(),
8838
- lastStatus: "not-running",
8839
- lastError: null
8840
- };
8841
- await patchManagedInstance(stopped2);
8842
- return {
8843
- status: "not-running",
8844
- profileName,
8845
- instance: managedInstanceToPayload(stopped2, false),
8846
- reason: null
8847
- };
8848
- }
8849
- const tree = [existing.pid, ...getDescendantPids(existing.pid, rows)].filter((pid, index, all) => all.indexOf(pid) === index).sort((a, b) => b - a);
8850
- await signalPids(tree, "SIGTERM");
8851
- const exited = await waitForMainPidExit(existing.pid, 5e3);
8852
- if (!exited) {
8853
- await signalPids(tree, "SIGKILL");
8854
- await waitForMainPidExit(existing.pid, EXIT_WAIT_MS);
8855
- }
8856
- const stillRunning = (await readProcessRows()).some((row) => row.pid === existing.pid);
8857
- const stopped = {
9306
+ async function stopOfficialCodexProfileInstanceOnce(profileName) {
9307
+ const existing = await readManagedInstance(profileName);
9308
+ if (!existing) {
9309
+ return {
9310
+ status: "not-running",
9311
+ profileName,
9312
+ instance: null,
9313
+ reason: "not-managed"
9314
+ };
9315
+ }
9316
+ const { candidate } = await resolveCodexAppTarget();
9317
+ if (!candidate) {
9318
+ const stopped2 = {
8858
9319
  ...existing,
8859
- pid: stillRunning ? existing.pid : null,
8860
- appServerPid: stillRunning ? runtime.appServerPid : null,
9320
+ pid: null,
9321
+ appServerPid: null,
8861
9322
  lastVerifiedAt: Date.now(),
8862
- lastStatus: stillRunning ? "failed" : "stopped",
8863
- lastError: stillRunning ? "stop-timeout" : null
9323
+ lastStatus: "not-running",
9324
+ lastError: "official-codex-app-not-found"
8864
9325
  };
8865
- await patchManagedInstance(stopped);
9326
+ await patchManagedInstance(stopped2);
8866
9327
  return {
8867
- status: stillRunning ? "failed" : "stopped",
9328
+ status: "not-running",
8868
9329
  profileName,
8869
- instance: managedInstanceToPayload(
8870
- stopped,
8871
- stillRunning,
8872
- stopped.appServerPid,
8873
- runtime.startedAt
8874
- ),
8875
- reason: stillRunning ? "stop-timeout" : null
9330
+ instance: managedInstanceToPayload(stopped2, false),
9331
+ reason: "official-codex-app-not-found"
8876
9332
  };
8877
- });
9333
+ }
9334
+ const rows = await readProcessRows();
9335
+ const runtime = await resolveInstanceRuntimeState({ instance: existing, candidate, rows });
9336
+ if (!runtime.running || !existing.pid) {
9337
+ const stopped2 = {
9338
+ ...existing,
9339
+ pid: null,
9340
+ appServerPid: null,
9341
+ lastVerifiedAt: Date.now(),
9342
+ lastStatus: "not-running",
9343
+ lastError: null
9344
+ };
9345
+ await patchManagedInstance(stopped2);
9346
+ return {
9347
+ status: "not-running",
9348
+ profileName,
9349
+ instance: managedInstanceToPayload(stopped2, false),
9350
+ reason: null
9351
+ };
9352
+ }
9353
+ const tree = [existing.pid, ...getDescendantPids(existing.pid, rows)].filter((pid, index, all) => all.indexOf(pid) === index).sort((a, b) => b - a);
9354
+ await signalPids(tree, "SIGTERM");
9355
+ const exited = await waitForMainPidExit(existing.pid, 5e3);
9356
+ if (!exited) {
9357
+ await signalPids(tree, "SIGKILL");
9358
+ await waitForMainPidExit(existing.pid, EXIT_WAIT_MS);
9359
+ }
9360
+ const stillRunning = (await readProcessRows()).some((row) => row.pid === existing.pid);
9361
+ const stopped = {
9362
+ ...existing,
9363
+ pid: stillRunning ? existing.pid : null,
9364
+ appServerPid: stillRunning ? runtime.appServerPid : null,
9365
+ lastVerifiedAt: Date.now(),
9366
+ lastStatus: stillRunning ? "failed" : "stopped",
9367
+ lastError: stillRunning ? "stop-timeout" : null
9368
+ };
9369
+ await patchManagedInstance(stopped);
9370
+ return {
9371
+ status: stillRunning ? "failed" : "stopped",
9372
+ profileName,
9373
+ instance: managedInstanceToPayload(
9374
+ stopped,
9375
+ stillRunning,
9376
+ stopped.appServerPid,
9377
+ runtime.startedAt
9378
+ ),
9379
+ reason: stillRunning ? "stop-timeout" : null
9380
+ };
8878
9381
  }
8879
9382
  function stopOfficialCodexObservedProfileInstance(profileName, pid, appServerPid) {
8880
9383
  return enqueueProfileAction(async () => {
@@ -8930,15 +9433,17 @@ function stopOfficialCodexObservedProfileInstance(profileName, pid, appServerPid
8930
9433
  });
8931
9434
  }
8932
9435
  async function restartOfficialCodexProfileInstance(options) {
8933
- const stopped = await stopOfficialCodexProfileInstance(options.profileName);
8934
- if (stopped.status === "failed") {
8935
- return stopped;
8936
- }
8937
- const launched = await launchOfficialCodexProfileInstance(options);
8938
- return {
8939
- ...launched,
8940
- status: launched.status === "started" ? "restarted" : launched.status
8941
- };
9436
+ return enqueueProfileAction(async () => {
9437
+ const stopped = await stopOfficialCodexProfileInstanceOnce(options.profileName);
9438
+ if (stopped.status === "failed") {
9439
+ return stopped;
9440
+ }
9441
+ const launched = await launchOfficialCodexProfileInstanceOnce(options);
9442
+ return {
9443
+ ...launched,
9444
+ status: launched.status === "started" ? "restarted" : launched.status
9445
+ };
9446
+ });
8942
9447
  }
8943
9448
 
8944
9449
  // src/commands/profile.ts
@@ -9941,7 +10446,7 @@ var import_node_path15 = __toESM(require("path"), 1);
9941
10446
  var CLOUD_SYNC_SCHEMA_VERSION = 1;
9942
10447
 
9943
10448
  // ../../packages/shared/src/core/type-guards.ts
9944
- function isRecord4(value) {
10449
+ function isRecord5(value) {
9945
10450
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
9946
10451
  }
9947
10452
  function toIsoOrNull(value) {
@@ -9979,10 +10484,10 @@ function buildSyncUrl(pathname) {
9979
10484
  return `${baseUrl}${normalizedPath}`;
9980
10485
  }
9981
10486
  function normalizeSnapshot(value) {
9982
- if (!isRecord4(value)) {
10487
+ if (!isRecord5(value)) {
9983
10488
  return null;
9984
10489
  }
9985
- if (isRecord4(value.snapshot)) {
10490
+ if (isRecord5(value.snapshot)) {
9986
10491
  const nested = normalizeSnapshot(value.snapshot);
9987
10492
  if (nested) {
9988
10493
  return nested;
@@ -9997,9 +10502,9 @@ function normalizeSnapshot(value) {
9997
10502
  return null;
9998
10503
  }
9999
10504
  const rawProfiles = Array.isArray(value.profiles) ? value.profiles : [];
10000
- const profiles = rawProfiles.map((entry) => isRecord4(entry) ? entry : null).filter((entry) => Boolean(entry)).map((entry) => {
10001
- const data = isRecord4(entry.data) ? entry.data : {};
10002
- const metadata = isRecord4(entry.metadata) ? entry.metadata : void 0;
10505
+ const profiles = rawProfiles.map((entry) => isRecord5(entry) ? entry : null).filter((entry) => Boolean(entry)).map((entry) => {
10506
+ const data = isRecord5(entry.data) ? entry.data : {};
10507
+ const metadata = isRecord5(entry.metadata) ? entry.metadata : void 0;
10003
10508
  return {
10004
10509
  name: typeof entry.name === "string" ? entry.name : "",
10005
10510
  displayName: typeof entry.displayName === "string" ? entry.displayName : null,
@@ -10015,7 +10520,7 @@ function normalizeSnapshot(value) {
10015
10520
  };
10016
10521
  }).filter((entry) => entry.name.trim().length > 0);
10017
10522
  const rawSettings = value.settingsJson;
10018
- const settingsJson = isRecord4(rawSettings) ? rawSettings : null;
10523
+ const settingsJson = isRecord5(rawSettings) ? rawSettings : null;
10019
10524
  return {
10020
10525
  schemaVersion: CLOUD_SYNC_SCHEMA_VERSION,
10021
10526
  updatedAt,
@@ -10199,7 +10704,7 @@ var FALLBACK_FEATURE_KEYS = [
10199
10704
  ];
10200
10705
  var metadataCache = null;
10201
10706
  var metadataCacheAt = 0;
10202
- function isRecord5(value) {
10707
+ function isRecord6(value) {
10203
10708
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
10204
10709
  }
10205
10710
  function uniqueSorted(values) {
@@ -10264,16 +10769,16 @@ function parseFeatureCatalog(output) {
10264
10769
  }
10265
10770
  function parseSchemaKeys(schemaRaw) {
10266
10771
  const parsed = JSON.parse(schemaRaw);
10267
- if (!isRecord5(parsed)) {
10772
+ if (!isRecord6(parsed)) {
10268
10773
  return {
10269
10774
  topLevelKeys: FALLBACK_SCHEMA_TOP_LEVEL_KEYS,
10270
10775
  featureKeys: FALLBACK_FEATURE_KEYS
10271
10776
  };
10272
10777
  }
10273
- const properties = isRecord5(parsed.properties) ? parsed.properties : {};
10778
+ const properties = isRecord6(parsed.properties) ? parsed.properties : {};
10274
10779
  const topLevelKeys = uniqueSorted(Object.keys(properties));
10275
- const features = isRecord5(properties.features) ? properties.features : {};
10276
- const featureProperties = isRecord5(features.properties) ? features.properties : {};
10780
+ const features = isRecord6(properties.features) ? properties.features : {};
10781
+ const featureProperties = isRecord6(features.properties) ? features.properties : {};
10277
10782
  const featureKeys = uniqueSorted(Object.keys(featureProperties));
10278
10783
  return {
10279
10784
  topLevelKeys: topLevelKeys.length > 0 ? topLevelKeys : FALLBACK_SCHEMA_TOP_LEVEL_KEYS,
@@ -11059,15 +11564,15 @@ var SYNC_SIZE_WARN_BYTES = 1 * 1024 * 1024;
11059
11564
  var SYNC_SIZE_MAX_BYTES = 5 * 1024 * 1024;
11060
11565
  var MB_DIVISOR = 1024 * 1024;
11061
11566
  function mapProfilesFromAppState(raw) {
11062
- if (!isRecord4(raw)) {
11567
+ if (!isRecord5(raw)) {
11063
11568
  return [];
11064
11569
  }
11065
11570
  const profiles = [];
11066
11571
  for (const [name, value] of Object.entries(raw)) {
11067
- if (!isRecord4(value)) {
11572
+ if (!isRecord5(value)) {
11068
11573
  continue;
11069
11574
  }
11070
- const data = isRecord4(value.data) ? value.data : null;
11575
+ const data = isRecord5(value.data) ? value.data : null;
11071
11576
  if (!data) {
11072
11577
  continue;
11073
11578
  }
@@ -11079,7 +11584,7 @@ function mapProfilesFromAppState(raw) {
11079
11584
  name: normalizedName,
11080
11585
  displayName: typeof value.displayName === "string" ? value.displayName : null,
11081
11586
  data,
11082
- metadata: isRecord4(value.metadata) ? value.metadata : void 0,
11587
+ metadata: isRecord5(value.metadata) ? value.metadata : void 0,
11083
11588
  accountId: typeof value.accountId === "string" ? value.accountId : null,
11084
11589
  workspaceId: typeof value.workspaceId === "string" ? value.workspaceId : null,
11085
11590
  workspaceName: typeof value.workspaceName === "string" ? value.workspaceName : null,
@@ -11093,7 +11598,7 @@ function mapProfilesFromAppState(raw) {
11093
11598
  }
11094
11599
  function summarizeSnapshot(snapshot) {
11095
11600
  const configBytes = typeof snapshot.configTomlContent === "string" ? snapshot.configTomlContent.length : 0;
11096
- const settingsKeys = isRecord4(snapshot.settingsJson) ? Object.keys(snapshot.settingsJson).length : 0;
11601
+ const settingsKeys = isRecord5(snapshot.settingsJson) ? Object.keys(snapshot.settingsJson).length : 0;
11097
11602
  return {
11098
11603
  profiles: snapshot.profiles.length,
11099
11604
  configBytes,
@@ -11198,7 +11703,7 @@ async function buildLocalSnapshot(profileManager, options = {}) {
11198
11703
  const settingsJson = await readCodexSettingsJsonRaw();
11199
11704
  const hasProfiles = profiles.length > 0;
11200
11705
  const hasConfig = typeof config.content === "string" && config.content.trim().length > 0;
11201
- const hasSettings = isRecord4(settingsJson) && Object.keys(settingsJson).length > 0;
11706
+ const hasSettings = isRecord5(settingsJson) && Object.keys(settingsJson).length > 0;
11202
11707
  if (enforcePushGuards && !hasProfiles && !hasConfig && !hasSettings) {
11203
11708
  throw new Error("Refusing to push an empty cloud sync snapshot.");
11204
11709
  }
@@ -11222,7 +11727,7 @@ async function applyRemoteSnapshot(profileManager, snapshot) {
11222
11727
  codexHomePath: runtimeContext.codexHomePath
11223
11728
  });
11224
11729
  }
11225
- if (snapshot.settingsJson && isRecord4(snapshot.settingsJson)) {
11730
+ if (snapshot.settingsJson && isRecord5(snapshot.settingsJson)) {
11226
11731
  await writeCodexSettingsJsonRaw(snapshot.settingsJson);
11227
11732
  } else {
11228
11733
  await writeCodexSettingsJsonRaw({});
@@ -11475,10 +11980,10 @@ var LEGACY_SKILL_CACHE_DIR = "skill-cache";
11475
11980
  var LEGACY_SKILLS_REPOS_FILE = "repos.json";
11476
11981
  var LEGACY_SKILL_MANIFEST = ".codexuse-skill.json";
11477
11982
  var LEGACY_LICENSE_SECRET_FILE2 = "license.secret";
11478
- function isRecord6(value) {
11983
+ function isRecord7(value) {
11479
11984
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
11480
11985
  }
11481
- function asString4(value) {
11986
+ function asString5(value) {
11482
11987
  if (typeof value !== "string") {
11483
11988
  return null;
11484
11989
  }
@@ -11647,7 +12152,7 @@ function pickAutoRoll(raw) {
11647
12152
  }
11648
12153
  }
11649
12154
  function parseLegacyLicense(raw) {
11650
- if (!isRecord6(raw)) {
12155
+ if (!isRecord7(raw)) {
11651
12156
  return {
11652
12157
  licenseKey: null,
11653
12158
  purchaseEmail: null,
@@ -11658,25 +12163,25 @@ function parseLegacyLicense(raw) {
11658
12163
  signature: null
11659
12164
  };
11660
12165
  }
11661
- const statusCandidate = asString4(raw.status);
12166
+ const statusCandidate = asString5(raw.status);
11662
12167
  const status = ["inactive", "active", "grace", "error"].includes(statusCandidate ?? "") ? statusCandidate : "inactive";
11663
12168
  return {
11664
- licenseKey: asString4(raw.licenseKey ?? raw.license_key),
11665
- purchaseEmail: asString4(raw.purchaseEmail ?? raw.purchase_email),
11666
- lastVerifiedAt: asString4(raw.lastVerifiedAt ?? raw.last_verified_at),
11667
- nextCheckAt: asString4(raw.nextCheckAt ?? raw.next_check_at),
11668
- lastVerificationError: asString4(raw.lastVerificationError ?? raw.last_verification_error),
12169
+ licenseKey: asString5(raw.licenseKey ?? raw.license_key),
12170
+ purchaseEmail: asString5(raw.purchaseEmail ?? raw.purchase_email),
12171
+ lastVerifiedAt: asString5(raw.lastVerifiedAt ?? raw.last_verified_at),
12172
+ nextCheckAt: asString5(raw.nextCheckAt ?? raw.next_check_at),
12173
+ lastVerificationError: asString5(raw.lastVerificationError ?? raw.last_verification_error),
11669
12174
  status,
11670
- signature: asString4(raw.signature)
12175
+ signature: asString5(raw.signature)
11671
12176
  };
11672
12177
  }
11673
12178
  function parseLegacyProfileRecord(name, raw) {
11674
- if (!isRecord6(raw)) {
12179
+ if (!isRecord7(raw)) {
11675
12180
  return null;
11676
12181
  }
11677
12182
  const dataRaw = raw.data;
11678
12183
  let data = null;
11679
- if (isRecord6(dataRaw)) {
12184
+ if (isRecord7(dataRaw)) {
11680
12185
  data = dataRaw;
11681
12186
  } else if (typeof dataRaw === "string") {
11682
12187
  try {
@@ -11690,31 +12195,31 @@ function parseLegacyProfileRecord(name, raw) {
11690
12195
  }
11691
12196
  return {
11692
12197
  name,
11693
- displayName: asString4(raw.displayName ?? raw.display_name) ?? name,
12198
+ displayName: asString5(raw.displayName ?? raw.display_name) ?? name,
11694
12199
  data,
11695
- metadata: isRecord6(raw.metadata) ? raw.metadata : void 0,
11696
- accountId: asString4(raw.accountId ?? raw.account_id),
11697
- workspaceId: asString4(raw.workspaceId ?? raw.workspace_id),
11698
- workspaceName: asString4(raw.workspaceName ?? raw.workspace_name),
11699
- email: asString4(raw.email),
11700
- authMethod: asString4(raw.authMethod ?? raw.auth_method),
11701
- createdAt: asString4(raw.createdAt ?? raw.created_at),
11702
- updatedAt: asString4(raw.updatedAt ?? raw.updated_at)
12200
+ metadata: isRecord7(raw.metadata) ? raw.metadata : void 0,
12201
+ accountId: asString5(raw.accountId ?? raw.account_id),
12202
+ workspaceId: asString5(raw.workspaceId ?? raw.workspace_id),
12203
+ workspaceName: asString5(raw.workspaceName ?? raw.workspace_name),
12204
+ email: asString5(raw.email),
12205
+ authMethod: asString5(raw.authMethod ?? raw.auth_method),
12206
+ createdAt: asString5(raw.createdAt ?? raw.created_at),
12207
+ updatedAt: asString5(raw.updatedAt ?? raw.updated_at)
11703
12208
  };
11704
12209
  }
11705
12210
  async function loadLegacySettingsPatch() {
11706
12211
  const filePath = resolveLegacyPath(LEGACY_SETTINGS_FILE);
11707
12212
  const raw = await readJsonFileIfExists(filePath);
11708
- if (!isRecord6(raw)) {
12213
+ if (!isRecord7(raw)) {
11709
12214
  return {};
11710
12215
  }
11711
12216
  const autoRoll = pickAutoRoll(raw.autoRoll ?? raw.auto_roll);
11712
12217
  const license = parseLegacyLicense(raw.license ?? raw.license_data ?? raw.license_state);
11713
12218
  return {
11714
12219
  app: {
11715
- lastAppVersion: asString4(raw.lastAppVersion ?? raw.last_app_version),
11716
- pendingUpdateVersion: asString4(raw.pendingUpdateVersion ?? raw.pending_update_version),
11717
- lastProfileName: asString4(raw.lastProfileName ?? raw.last_profile_name)
12220
+ lastAppVersion: asString5(raw.lastAppVersion ?? raw.last_app_version),
12221
+ pendingUpdateVersion: asString5(raw.pendingUpdateVersion ?? raw.pending_update_version),
12222
+ lastProfileName: asString5(raw.lastProfileName ?? raw.last_profile_name)
11718
12223
  },
11719
12224
  license,
11720
12225
  autoRoll: autoRoll ? {
@@ -11732,22 +12237,22 @@ async function loadLegacySettingsPatch() {
11732
12237
  async function loadLegacySyncPatch() {
11733
12238
  const filePath = resolveLegacyPath(LEGACY_SYNC_STATE_FILE);
11734
12239
  const raw = await readJsonFileIfExists(filePath);
11735
- if (!isRecord6(raw)) {
12240
+ if (!isRecord7(raw)) {
11736
12241
  return {};
11737
12242
  }
11738
12243
  return {
11739
12244
  sync: {
11740
- lastPushAt: asString4(raw.lastPushAt),
11741
- lastPullAt: asString4(raw.lastPullAt),
11742
- lastError: asString4(raw.lastError),
11743
- remoteUpdatedAt: asString4(raw.remoteUpdatedAt)
12245
+ lastPushAt: asString5(raw.lastPushAt),
12246
+ lastPullAt: asString5(raw.lastPullAt),
12247
+ lastError: asString5(raw.lastError),
12248
+ remoteUpdatedAt: asString5(raw.remoteUpdatedAt)
11744
12249
  }
11745
12250
  };
11746
12251
  }
11747
12252
  async function loadLegacyAppSettingsParityPatch() {
11748
12253
  const filePath = import_node_path16.default.join(getUserDataDir(), LEGACY_APP_SETTINGS_PARITY_FILE);
11749
12254
  const raw = await readJsonFileIfExists(filePath);
11750
- if (!isRecord6(raw)) {
12255
+ if (!isRecord7(raw)) {
11751
12256
  return {};
11752
12257
  }
11753
12258
  return {
@@ -11787,21 +12292,21 @@ async function loadLegacyProfilesPatch() {
11787
12292
  return { profilesByName };
11788
12293
  }
11789
12294
  function parseSkillInstallMetadata(raw) {
11790
- if (!isRecord6(raw)) {
12295
+ if (!isRecord7(raw)) {
11791
12296
  return null;
11792
12297
  }
11793
- const id = asString4(raw.id);
12298
+ const id = asString5(raw.id);
11794
12299
  if (!id) {
11795
12300
  return null;
11796
12301
  }
11797
12302
  return {
11798
12303
  id,
11799
- repo: asString4(raw.repo),
11800
- repoPath: asString4(raw.repoPath),
11801
- sourceLabel: asString4(raw.sourceLabel),
12304
+ repo: asString5(raw.repo),
12305
+ repoPath: asString5(raw.repoPath),
12306
+ sourceLabel: asString5(raw.sourceLabel),
11802
12307
  sourceType: raw.sourceType === "official" || raw.sourceType === "community" || raw.sourceType === "local" ? raw.sourceType : void 0,
11803
- viewUrl: asString4(raw.viewUrl),
11804
- createdAt: asString4(raw.createdAt)
12308
+ viewUrl: asString5(raw.viewUrl),
12309
+ createdAt: asString5(raw.createdAt)
11805
12310
  };
11806
12311
  }
11807
12312
  async function loadLegacySkillsPatch() {
@@ -11832,7 +12337,7 @@ async function loadLegacySkillsPatch() {
11832
12337
  }
11833
12338
  installsBySlug[entry.name] = parsed;
11834
12339
  }
11835
- const sources = isRecord6(reposRaw) && Array.isArray(reposRaw.sources) ? reposRaw.sources : [];
12340
+ const sources = isRecord7(reposRaw) && Array.isArray(reposRaw.sources) ? reposRaw.sources : [];
11836
12341
  if (sources.length === 0 && Object.keys(installsBySlug).length === 0) {
11837
12342
  return {};
11838
12343
  }
@@ -11864,7 +12369,7 @@ function mergeLegacyLocalStoragePatch(payload) {
11864
12369
  }
11865
12370
  };
11866
12371
  const settingsStorage = payload["settings-storage"];
11867
- if (isRecord6(settingsStorage)) {
12372
+ if (isRecord7(settingsStorage)) {
11868
12373
  const nextExcludeFolders = Array.isArray(settingsStorage.excludeFolders) ? settingsStorage.excludeFolders.filter((item) => typeof item === "string") : void 0;
11869
12374
  const nextBeep = typeof settingsStorage.enableTaskCompleteBeep === "boolean" ? settingsStorage.enableTaskCompleteBeep : void 0;
11870
12375
  const nextSleep = typeof settingsStorage.preventSleepDuringTasks === "boolean" ? settingsStorage.preventSleepDuringTasks : void 0;
@@ -11883,15 +12388,15 @@ function mergeLegacyLocalStoragePatch(payload) {
11883
12388
  markSkippedIfPresent("provider", hasKey2("provider"));
11884
12389
  markSkippedIfPresent("sandbox-storage", hasKey2("sandbox-storage"));
11885
12390
  const projectSettings = payload["project-settings-storage"];
11886
- if (isRecord6(projectSettings) && isRecord6(projectSettings.settingsByPath)) {
12391
+ if (isRecord7(projectSettings) && isRecord7(projectSettings.settingsByPath)) {
11887
12392
  patch.workspaceSettingsByPath = projectSettings.settingsByPath;
11888
12393
  markSkippedIfPresent("project-settings-storage", true);
11889
12394
  } else {
11890
12395
  markSkippedIfPresent("project-settings-storage", false);
11891
12396
  }
11892
12397
  const folder = payload["folder-storage"];
11893
- if (isRecord6(folder)) {
11894
- const folderHistory = Array.isArray(folder.folderHistory) ? folder.folderHistory.filter(isRecord6) : void 0;
12398
+ if (isRecord7(folder)) {
12399
+ const folderHistory = Array.isArray(folder.folderHistory) ? folder.folderHistory.filter(isRecord7) : void 0;
11895
12400
  const pinnedPaths = Array.isArray(folder.pinnedPaths) ? folder.pinnedPaths.filter((item) => typeof item === "string") : void 0;
11896
12401
  patch.preferences = {
11897
12402
  ...patch.preferences ?? {},
@@ -11904,12 +12409,12 @@ function mergeLegacyLocalStoragePatch(payload) {
11904
12409
  }
11905
12410
  const categories = payload["conversation-categories-storage"];
11906
12411
  let consumedCategories = false;
11907
- if (isRecord6(categories)) {
11908
- if (isRecord6(categories.categoriesByCwd)) {
12412
+ if (isRecord7(categories)) {
12413
+ if (isRecord7(categories.categoriesByCwd)) {
11909
12414
  patch.conversationCategoriesByCwd = categories.categoriesByCwd;
11910
12415
  consumedCategories = true;
11911
12416
  }
11912
- if (isRecord6(categories.conversationCategoryByCwd)) {
12417
+ if (isRecord7(categories.conversationCategoryByCwd)) {
11913
12418
  patch.conversationCategoryAssignmentsByCwd = categories.conversationCategoryByCwd;
11914
12419
  consumedCategories = true;
11915
12420
  }
@@ -12132,7 +12637,7 @@ async function importLegacyLocalStorageOnce(payload) {
12132
12637
  if (current.migration.status === "pending") {
12133
12638
  return { completed: false, importedKeys: [], skippedKeys: [] };
12134
12639
  }
12135
- if (!payload || !isRecord6(payload)) {
12640
+ if (!payload || !isRecord7(payload)) {
12136
12641
  return { completed: true, importedKeys: [], skippedKeys: [] };
12137
12642
  }
12138
12643
  const { patch, consumedKeys, skippedKeys } = mergeLegacyLocalStoragePatch(payload);
@@ -12200,7 +12705,7 @@ async function ensureCliStorageReady() {
12200
12705
  }
12201
12706
 
12202
12707
  // src/app/main.ts
12203
- var VERSION = true ? "3.9.8" : "0.0.0";
12708
+ var VERSION = true ? "4.0.0" : "0.0.0";
12204
12709
  async function runCli() {
12205
12710
  const args = process.argv.slice(2);
12206
12711
  if (args.length === 0) {