codexuse-cli 5.1.8 → 5.2.1

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 CHANGED
@@ -8,13 +8,10 @@ npm install -g codexuse-cli
8
8
  Commands:
9
9
  ```bash
10
10
  codexuse account-pool status [--runtime=desktop] [--state-dir=/abs/path]
11
- codexuse account-pool enable
12
- codexuse account-pool disable
13
11
  codexuse account-pool routing <least-used|round-robin>
14
12
  codexuse account-pool profiles <list|set|add|remove|reset> [names...]
15
13
  codexuse account-pool models <list|add|remove|reset> [model-ids...]
16
14
  codexuse account-pool reasoning <list|add|remove|reset> [values...]
17
- codexuse account-pool fast-mode <list|add|remove|reset> [values...]
18
15
  codexuse account-pool keys <list|create|revoke> [id]
19
16
  codexuse account-pool sessions list [--runtime=desktop] [--state-dir=/abs/path]
20
17
 
package/dist/index.js CHANGED
@@ -2027,6 +2027,11 @@ var import_node_path7 = __toESM(require("path"));
2027
2027
 
2028
2028
  // ../../packages/contracts/src/settings/types.ts
2029
2029
  var DEFAULT_ACCOUNT_POOL_EXPOSED_MODELS = [
2030
+ "gpt-5.5",
2031
+ "gpt-5.3-codex-spark",
2032
+ "gpt-5.4-mini"
2033
+ ];
2034
+ var LEGACY_ACCOUNT_POOL_EXPOSED_MODELS_DEFAULT = [
2030
2035
  "gpt-5.5",
2031
2036
  "gpt-5.4",
2032
2037
  "gpt-5.4-mini",
@@ -2034,15 +2039,27 @@ var DEFAULT_ACCOUNT_POOL_EXPOSED_MODELS = [
2034
2039
  ];
2035
2040
  var DEFAULT_ACCOUNT_POOL_EXPOSED_REASONING_EFFORTS = [
2036
2041
  "none",
2037
- "minimal",
2038
2042
  "low",
2039
2043
  "medium",
2040
2044
  "high",
2041
2045
  "xhigh"
2042
2046
  ];
2043
- var DEFAULT_ACCOUNT_POOL_EXPOSED_FAST_MODE_REASONING_EFFORTS = [
2047
+ var LEGACY_ACCOUNT_POOL_EXPOSED_REASONING_EFFORTS_DEFAULT = [
2048
+ "none",
2049
+ "minimal",
2050
+ "low",
2051
+ "medium",
2052
+ "high",
2044
2053
  "xhigh"
2045
2054
  ];
2055
+ function migrateLegacyAccountPoolExposedModelDefaults(models) {
2056
+ return models.length === LEGACY_ACCOUNT_POOL_EXPOSED_MODELS_DEFAULT.length && models.every((model, index) => model === LEGACY_ACCOUNT_POOL_EXPOSED_MODELS_DEFAULT[index]) ? [...DEFAULT_ACCOUNT_POOL_EXPOSED_MODELS] : [...models];
2057
+ }
2058
+ function migrateLegacyAccountPoolExposedReasoningDefaults(efforts) {
2059
+ return efforts.length === LEGACY_ACCOUNT_POOL_EXPOSED_REASONING_EFFORTS_DEFAULT.length && efforts.every(
2060
+ (effort, index) => effort === LEGACY_ACCOUNT_POOL_EXPOSED_REASONING_EFFORTS_DEFAULT[index]
2061
+ ) ? [...DEFAULT_ACCOUNT_POOL_EXPOSED_REASONING_EFFORTS] : [...efforts];
2062
+ }
2046
2063
 
2047
2064
  // ../../packages/runtime-app-state/src/app/state.ts
2048
2065
  var import_node_async_hooks = require("async_hooks");
@@ -3393,6 +3410,7 @@ async function replaceAppStateSlice(key, value) {
3393
3410
  }
3394
3411
 
3395
3412
  // ../../packages/runtime-app-state/src/app/runtimeSettings.ts
3413
+ var AUTO_CONTROL_DEFAULT_OFF_MIGRATION_KEY = "officialCodexAutoControlDefaultOffMigrationApplied";
3396
3414
  function asRecord(value) {
3397
3415
  return value && typeof value === "object" ? value : {};
3398
3416
  }
@@ -3403,7 +3421,7 @@ function normalizeRelayProfileId(value) {
3403
3421
  const id = value.trim();
3404
3422
  return /^[A-Za-z0-9][A-Za-z0-9_-]{2,79}$/.test(id) ? id : null;
3405
3423
  }
3406
- function withCurrentRuntimeDefaults(settings) {
3424
+ function withCurrentRuntimeDefaults(settings, options = {}) {
3407
3425
  let changed = false;
3408
3426
  const next = { ...settings };
3409
3427
  if (!("keepAppRunningAfterWindowClose" in next)) {
@@ -3411,7 +3429,14 @@ function withCurrentRuntimeDefaults(settings) {
3411
3429
  changed = true;
3412
3430
  }
3413
3431
  if (typeof next.officialCodexAutoControlEnabled !== "boolean") {
3414
- next.officialCodexAutoControlEnabled = true;
3432
+ next.officialCodexAutoControlEnabled = false;
3433
+ changed = true;
3434
+ }
3435
+ if (next[AUTO_CONTROL_DEFAULT_OFF_MIGRATION_KEY] !== true) {
3436
+ if (options.forceAutoControlDefaultOff) {
3437
+ next.officialCodexAutoControlEnabled = false;
3438
+ }
3439
+ next[AUTO_CONTROL_DEFAULT_OFF_MIGRATION_KEY] = true;
3415
3440
  changed = true;
3416
3441
  }
3417
3442
  if (typeof next.officialCodexInCodexStatusEnabled !== "boolean") {
@@ -3444,7 +3469,9 @@ function withCurrentRuntimeDefaults(settings) {
3444
3469
  }
3445
3470
  async function readAppSettings() {
3446
3471
  const appState = await getAppState();
3447
- const next = withCurrentRuntimeDefaults(asRecord(appState.runtimeSettings));
3472
+ const next = withCurrentRuntimeDefaults(asRecord(appState.runtimeSettings), {
3473
+ forceAutoControlDefaultOff: true
3474
+ });
3448
3475
  if (next.changed) {
3449
3476
  await replaceAppStateSlice("runtimeSettings", next.settings);
3450
3477
  }
@@ -3526,6 +3553,53 @@ function parseStoredTrial(raw) {
3526
3553
  );
3527
3554
  return hasValue ? trial : null;
3528
3555
  }
3556
+ var CLOUD_SYNC_RUNTIME_SETTING_KEYS = /* @__PURE__ */ new Set([
3557
+ "keepAppRunningAfterWindowClose",
3558
+ "rateLimitPercentMode",
3559
+ "officialCodexWideViewEnabled",
3560
+ "officialCodexWideViewMaxWidth",
3561
+ "officialCodexScrollRestoreEnabled",
3562
+ "officialCodexConversationTimelineEnabled",
3563
+ "officialCodexInCodexStatusEnabled",
3564
+ "officialCodexHandoffChipEnabled",
3565
+ "officialCodexAutoControlEnabled",
3566
+ "officialCodexRelayMode",
3567
+ "officialCodexRelayProfileId",
3568
+ "officialCodexModelWhitelistUnlockEnabled",
3569
+ "officialCodexPluginMarketplaceUnlockEnabled",
3570
+ "officialCodexForcePluginInstallEnabled",
3571
+ "accountPoolEnabled",
3572
+ "accountPoolRoutingStrategy",
3573
+ "accountPoolProfilePool",
3574
+ "accountPoolExposedModels",
3575
+ "accountPoolExposedReasoningEfforts"
3576
+ ]);
3577
+ function cloneJsonValue(value) {
3578
+ if (value === void 0) {
3579
+ return void 0;
3580
+ }
3581
+ try {
3582
+ return JSON.parse(JSON.stringify(value));
3583
+ } catch {
3584
+ return void 0;
3585
+ }
3586
+ }
3587
+ function pickCloudSyncRuntimeSettings(raw) {
3588
+ if (!isRecord3(raw)) {
3589
+ return void 0;
3590
+ }
3591
+ const picked = {};
3592
+ for (const key of CLOUD_SYNC_RUNTIME_SETTING_KEYS) {
3593
+ if (!(key in raw)) {
3594
+ continue;
3595
+ }
3596
+ const value = cloneJsonValue(raw[key]);
3597
+ if (value !== void 0) {
3598
+ picked[key] = value;
3599
+ }
3600
+ }
3601
+ return Object.keys(picked).length > 0 ? picked : void 0;
3602
+ }
3529
3603
  async function getStoredTrial() {
3530
3604
  const state = await getAppState();
3531
3605
  return parseStoredTrial(state.trial);
@@ -3599,7 +3673,7 @@ async function readCodexSettingsJsonRaw() {
3599
3673
  subagentSystemNotificationsEnabled: state.preferences.subagentSystemNotificationsEnabled,
3600
3674
  folderHistory: state.preferences.folderHistory,
3601
3675
  pinnedPaths: state.preferences.pinnedPaths,
3602
- sync: state.sync
3676
+ runtimeSettings: pickCloudSyncRuntimeSettings(state.runtimeSettings) ?? {}
3603
3677
  };
3604
3678
  }
3605
3679
  async function writeCodexSettingsJsonRaw(payload) {
@@ -3608,6 +3682,7 @@ async function writeCodexSettingsJsonRaw(payload) {
3608
3682
  }
3609
3683
  const autoRoll = parseAutoRoll(payload.autoRoll ?? payload.auto_roll);
3610
3684
  const license = parseStoredLicense(payload.license);
3685
+ const runtimeSettings = pickCloudSyncRuntimeSettings(payload.runtimeSettings);
3611
3686
  await patchAppState({
3612
3687
  app: {
3613
3688
  lastProfileName: asString2(payload.lastProfileName ?? payload.last_profile_name),
@@ -3642,7 +3717,7 @@ async function writeCodexSettingsJsonRaw(payload) {
3642
3717
  folderHistory: Array.isArray(payload.folderHistory) ? payload.folderHistory : void 0,
3643
3718
  pinnedPaths: Array.isArray(payload.pinnedPaths) ? payload.pinnedPaths : void 0
3644
3719
  },
3645
- sync: isRecord3(payload.sync) ? payload.sync : void 0
3720
+ runtimeSettings
3646
3721
  });
3647
3722
  }
3648
3723
 
@@ -4925,7 +5000,6 @@ function logInfo(...args) {
4925
5000
  var RPC_TIMEOUT_MS = 1e4;
4926
5001
  var ACTIVATION_TURN_TIMEOUT_MS = 9e4;
4927
5002
  var ACTIVATION_PROMPT = "Reply with exactly: ok.";
4928
- var ACTIVATION_MODEL = "gpt-5.1-codex-mini";
4929
5003
  var MAX_STDERR_CAPTURE_CHARS = 32768;
4930
5004
  var REFRESH_TOKEN_REDEEMED_SNIPPET = "refresh token was already used";
4931
5005
  var authFileCache = /* @__PURE__ */ new Map();
@@ -5532,7 +5606,6 @@ async function activateResetWindowViaRpc(envOverride, options = {}) {
5532
5606
  method: "thread/start",
5533
5607
  params: {
5534
5608
  cwd: tempHome,
5535
- model: ACTIVATION_MODEL,
5536
5609
  approvalPolicy: "untrusted",
5537
5610
  sandbox: "read-only",
5538
5611
  experimentalRawEvents: false
@@ -5551,7 +5624,6 @@ async function activateResetWindowViaRpc(envOverride, options = {}) {
5551
5624
  method: "turn/start",
5552
5625
  params: {
5553
5626
  threadId,
5554
- model: ACTIVATION_MODEL,
5555
5627
  effort: "low",
5556
5628
  input: [
5557
5629
  {
@@ -7759,8 +7831,6 @@ Usage:
7759
7831
 
7760
7832
  codexuse account-pool status [--runtime=desktop] [--state-dir=/abs/path]
7761
7833
  codexuse account-pool quickstart
7762
- codexuse account-pool enable
7763
- codexuse account-pool disable
7764
7834
  codexuse account-pool routing <least-used|round-robin>
7765
7835
  codexuse account-pool profiles list
7766
7836
  codexuse account-pool profiles set <name> [more...]
@@ -7945,7 +8015,7 @@ function normalizeAccountPoolExposedModels(value, fallbackToDefault) {
7945
8015
  result.push(normalized);
7946
8016
  }
7947
8017
  if (result.length > 0) {
7948
- return result;
8018
+ return migrateLegacyAccountPoolExposedModelDefaults(result);
7949
8019
  }
7950
8020
  return fallbackToDefault ? [...DEFAULT_ACCOUNT_POOL_EXPOSED_MODELS] : [];
7951
8021
  }
@@ -7962,7 +8032,7 @@ function normalizeAccountPoolReasoningEfforts(value, fallback) {
7962
8032
  result.push(normalized);
7963
8033
  }
7964
8034
  if (result.length > 0 || Array.isArray(value)) {
7965
- return result;
8035
+ return migrateLegacyAccountPoolExposedReasoningDefaults(result);
7966
8036
  }
7967
8037
  return fallback ? [...fallback] : [];
7968
8038
  }
@@ -7979,10 +8049,7 @@ function normalizeAccountPoolSettings(settings) {
7979
8049
  settings.accountPoolExposedReasoningEfforts,
7980
8050
  DEFAULT_ACCOUNT_POOL_EXPOSED_REASONING_EFFORTS
7981
8051
  ),
7982
- accountPoolExposedFastModeReasoningEfforts: normalizeAccountPoolReasoningEfforts(
7983
- settings.accountPoolExposedFastModeReasoningEfforts,
7984
- DEFAULT_ACCOUNT_POOL_EXPOSED_FAST_MODE_REASONING_EFFORTS
7985
- )
8052
+ accountPoolExposedFastModeReasoningEfforts: []
7986
8053
  };
7987
8054
  }
7988
8055
  function applyAccountPoolSettings(settings, nextAccountPoolSettings) {
@@ -8003,8 +8070,6 @@ function printAccountPoolHelp(version) {
8003
8070
  Usage:
8004
8071
  codexuse account-pool status [--runtime=desktop] [--state-dir=/abs/path]
8005
8072
  codexuse account-pool quickstart [--runtime=desktop] [--state-dir=/abs/path]
8006
- codexuse account-pool enable
8007
- codexuse account-pool disable
8008
8073
  codexuse account-pool routing <least-used|round-robin>
8009
8074
 
8010
8075
  codexuse account-pool profiles list
@@ -8023,11 +8088,6 @@ Usage:
8023
8088
  codexuse account-pool reasoning remove <effort> [more...]
8024
8089
  codexuse account-pool reasoning reset
8025
8090
 
8026
- codexuse account-pool fast-mode list
8027
- codexuse account-pool fast-mode add <effort> [more...]
8028
- codexuse account-pool fast-mode remove <effort> [more...]
8029
- codexuse account-pool fast-mode reset
8030
-
8031
8091
  codexuse account-pool keys list [--runtime=desktop] [--state-dir=/abs/path]
8032
8092
  codexuse account-pool keys create [--runtime=desktop] [--state-dir=/abs/path]
8033
8093
  codexuse account-pool keys revoke <id> [--runtime=desktop] [--state-dir=/abs/path]
@@ -8056,6 +8116,7 @@ function normalizeApiKeyRecord(id, value) {
8056
8116
  id,
8057
8117
  tokenHash,
8058
8118
  tokenPreview,
8119
+ plaintextToken: asString4(record.plaintextToken),
8059
8120
  createdAt,
8060
8121
  lastUsedAt: normalizeIsoString(record.lastUsedAt),
8061
8122
  revokedAt: normalizeIsoString(record.revokedAt)
@@ -8232,6 +8293,7 @@ function accountPoolApiKeyView(record) {
8232
8293
  return {
8233
8294
  id: record.id,
8234
8295
  tokenPreview: record.tokenPreview,
8296
+ plaintextToken: record.plaintextToken,
8235
8297
  createdAt: record.createdAt,
8236
8298
  lastUsedAt: record.lastUsedAt,
8237
8299
  revokedAt: record.revokedAt
@@ -8251,6 +8313,7 @@ async function createApiKey(stateDir) {
8251
8313
  id: (0, import_node_crypto7.randomUUID)(),
8252
8314
  tokenHash: hashToken(plaintextToken),
8253
8315
  tokenPreview: `${plaintextToken.slice(0, 8)}...${plaintextToken.slice(-6)}`,
8316
+ plaintextToken,
8254
8317
  createdAt: now,
8255
8318
  lastUsedAt: null,
8256
8319
  revokedAt: null
@@ -8341,7 +8404,7 @@ async function readAccountPoolRuntimeSummary(input = {}) {
8341
8404
  runtime,
8342
8405
  stateDir,
8343
8406
  baseUrl: resolveBaseUrlFromPort(runtime, input.port ?? null),
8344
- enabled: normalized.accountPoolEnabled,
8407
+ enabled: true,
8345
8408
  hasAccountPoolAccess: license?.capabilities.accountPool === true,
8346
8409
  routingStrategy: normalized.accountPoolRoutingStrategy,
8347
8410
  activeApiKeyCount: apiKeys.length,
@@ -8373,10 +8436,7 @@ async function updateSettings(transform) {
8373
8436
  nextSettings.accountPoolExposedReasoningEfforts,
8374
8437
  null
8375
8438
  ),
8376
- accountPoolExposedFastModeReasoningEfforts: normalizeAccountPoolReasoningEfforts(
8377
- nextSettings.accountPoolExposedFastModeReasoningEfforts,
8378
- null
8379
- )
8439
+ accountPoolExposedFastModeReasoningEfforts: []
8380
8440
  };
8381
8441
  await writeAppSettings(applyAccountPoolSettings(raw, sanitizedSettings));
8382
8442
  return {
@@ -8444,11 +8504,11 @@ async function handleStatus(flags) {
8444
8504
  (profileName) => !profiles.some((profile) => profile.name === profileName)
8445
8505
  );
8446
8506
  console.log(`License: ${license ? `${license.tier} (${license.state})` : "unknown"}`);
8447
- console.log(`Enabled: ${normalized.accountPoolEnabled ? "yes" : "no"}`);
8507
+ console.log("Enabled: yes");
8448
8508
  console.log(`Runtime: ${runtime}`);
8449
8509
  console.log(`State dir: ${stateDir}`);
8450
8510
  console.log(`Routing: ${formatRoutingStrategy(normalized.accountPoolRoutingStrategy)}`);
8451
- console.log(`Public API ready: ${normalized.accountPoolEnabled && license?.capabilities.accountPool === true && apiKeys.length > 0 ? "yes" : "no"}`);
8511
+ console.log(`Public API ready: ${license?.capabilities.accountPool === true && apiKeys.length > 0 ? "yes" : "no"}`);
8452
8512
  console.log(`API keys: ${apiKeys.length}`);
8453
8513
  console.log(`Sessions: ${sessions.length}`);
8454
8514
  console.log(`Selection mode: ${explicitSelection.length > 0 ? "explicit" : "all saved profiles"}`);
@@ -8463,25 +8523,16 @@ async function handleStatus(flags) {
8463
8523
  }
8464
8524
  printStringList("Published models", normalized.accountPoolExposedModels);
8465
8525
  printStringList("Reasoning aliases", normalized.accountPoolExposedReasoningEfforts);
8466
- printStringList("Fast-mode aliases", normalized.accountPoolExposedFastModeReasoningEfforts);
8467
- if (normalized.accountPoolEnabled && license?.capabilities.accountPool !== true) {
8526
+ if (license?.capabilities.accountPool !== true) {
8468
8527
  console.log(ACCOUNT_POOL_PRO_REQUIRED_MESSAGE);
8469
8528
  }
8470
8529
  }
8471
8530
  async function handleEnable() {
8472
8531
  await requireProAccess();
8473
- const result = await updateSettings((current) => ({
8474
- ...current,
8475
- accountPoolEnabled: true
8476
- }));
8477
- console.log(result.settings.accountPoolEnabled ? "Accounts Pool enabled." : "Accounts Pool is disabled.");
8532
+ console.log("Accounts Pool is always on while CodexUse is running.");
8478
8533
  }
8479
8534
  async function handleDisable() {
8480
- const result = await updateSettings((current) => ({
8481
- ...current,
8482
- accountPoolEnabled: false
8483
- }));
8484
- console.log(result.settings.accountPoolEnabled ? "Accounts Pool is enabled." : "Accounts Pool disabled.");
8535
+ console.log("Accounts Pool is always on while CodexUse is running.");
8485
8536
  }
8486
8537
  async function handleRouting(params) {
8487
8538
  const value = parseRoutingStrategy(params[1]);
@@ -8673,15 +8724,14 @@ async function handleQuickstart(flags) {
8673
8724
  console.log(`API keys: ${summary.activeApiKeyCount}`);
8674
8725
  console.log(`Base URL: ${baseUrl}`);
8675
8726
  console.log("");
8676
- console.log("1. Enable pool:");
8677
- console.log(" codexuse account-pool enable");
8678
- console.log("2. Create key:");
8727
+ console.log("1. Create key:");
8679
8728
  console.log(` codexuse account-pool keys create --runtime=${summary.runtime}`);
8680
- console.log("3. Use OpenAI-compatible settings:");
8729
+ console.log("2. Use OpenAI-compatible settings:");
8681
8730
  console.log(` Base URL: ${baseUrl}/v1`);
8682
8731
  console.log(" API key: cux_pool_...");
8683
- console.log("4. Verify:");
8732
+ console.log("3. Verify:");
8684
8733
  console.log(` curl ${baseUrl}/v1/models -H 'Authorization: Bearer cux_pool_...'`);
8734
+ console.log(` curl ${baseUrl}/v1/chat/completions -H 'Authorization: Bearer cux_pool_...'`);
8685
8735
  }
8686
8736
  async function handleAccountPoolCommand(args, version) {
8687
8737
  const flags = args.filter((arg) => arg.startsWith("-"));
@@ -8730,16 +8780,6 @@ async function handleAccountPoolCommand(args, version) {
8730
8780
  normalizeValue: (value) => normalizeReasoningEffort(value)
8731
8781
  });
8732
8782
  return;
8733
- case "fast-mode":
8734
- await handleArraySetting({
8735
- label: "Fast-mode aliases",
8736
- actionName: "fast-mode",
8737
- params,
8738
- key: "accountPoolExposedFastModeReasoningEfforts",
8739
- defaultValues: DEFAULT_ACCOUNT_POOL_EXPOSED_FAST_MODE_REASONING_EFFORTS,
8740
- normalizeValue: (value) => normalizeReasoningEffort(value)
8741
- });
8742
- return;
8743
8783
  case "keys":
8744
8784
  await handleKeys(params, flags);
8745
8785
  return;
@@ -9539,8 +9579,10 @@ async function findOfficialCodexThreadRecord(profileHome, threadId) {
9539
9579
 
9540
9580
  // ../../packages/runtime-codex/src/codex/officialAppRestart.ts
9541
9581
  var COMMAND_TIMEOUT_MS = 3e3;
9582
+ var EXIT_WAIT_MS = 1e4;
9542
9583
  var LAUNCH_WAIT_MS = 15e3;
9543
9584
  var POLL_INTERVAL_MS = 250;
9585
+ var PROCESS_EXIT_GRACE_MS = 15e3;
9544
9586
  var APP_DISCOVERY_CACHE_TTL_MS = 6e4;
9545
9587
  var APP_DISCOVERY_MISS_CACHE_TTL_MS = 5e3;
9546
9588
  var OFFICIAL_CODEX_ACTIVITY_LIMIT = 50;
@@ -9551,6 +9593,8 @@ var CODEX_BRIDGE_LAUNCH_WAIT_MS = 3e4;
9551
9593
  var CODEXUSE_BRIDGE_BINDING_NAME = "__codexuseBridgeBinding";
9552
9594
  var CODEXUSE_BRIDGE_INSTALL_TTL_MS = 5e3;
9553
9595
  var CODEXUSE_BRIDGE_VERSION = "0.2.0";
9596
+ var CODEXUSE_STALE_LAUNCH_GRACE_MS = 45e3;
9597
+ var CODEXUSE_STALE_BRIDGE_MISS_TTL_MS = 2 * 6e4;
9554
9598
  var officialCodexBridgeActionHandler = null;
9555
9599
  var bridgeActionListeners = /* @__PURE__ */ new Map();
9556
9600
  var handledBridgeActionIds = [];
@@ -9609,6 +9653,7 @@ function sanitizeBridgeActionRoute(value) {
9609
9653
  var profileActionLock = Promise.resolve();
9610
9654
  var appDiscoveryCache = null;
9611
9655
  var bridgeInstallCache = /* @__PURE__ */ new Map();
9656
+ var staleOfficialCodexBridgeMissesByPid = /* @__PURE__ */ new Map();
9612
9657
  function hashProfileKey(profileKey) {
9613
9658
  if (!profileKey) {
9614
9659
  return null;
@@ -14159,6 +14204,26 @@ async function describeUnmanagedProfileHint(appServerPid) {
14159
14204
  }
14160
14205
  return {};
14161
14206
  }
14207
+ function getDescendantPids(rootPid, rows) {
14208
+ const descendants = [];
14209
+ const queue = [rootPid];
14210
+ const seen = /* @__PURE__ */ new Set();
14211
+ while (queue.length > 0) {
14212
+ const current = queue.shift();
14213
+ if (seen.has(current)) {
14214
+ continue;
14215
+ }
14216
+ seen.add(current);
14217
+ for (const row of rows) {
14218
+ if (row.ppid !== current || seen.has(row.pid)) {
14219
+ continue;
14220
+ }
14221
+ descendants.push(row.pid);
14222
+ queue.push(row.pid);
14223
+ }
14224
+ }
14225
+ return descendants;
14226
+ }
14162
14227
  async function waitForNewMainPid(candidate, previousPids) {
14163
14228
  const deadline = Date.now() + LAUNCH_WAIT_MS;
14164
14229
  while (Date.now() < deadline) {
@@ -14186,6 +14251,110 @@ async function waitForAppServerPid(mainPid, profileHome) {
14186
14251
  }
14187
14252
  return null;
14188
14253
  }
14254
+ async function waitForPidsExit(pids, timeoutMs) {
14255
+ const remaining = new Set(pids);
14256
+ if (remaining.size === 0) {
14257
+ return [];
14258
+ }
14259
+ const deadline = Date.now() + timeoutMs;
14260
+ while (Date.now() < deadline) {
14261
+ const rows = await readProcessRows();
14262
+ for (const pid of Array.from(remaining)) {
14263
+ if (!rows.some((row) => row.pid === pid)) {
14264
+ remaining.delete(pid);
14265
+ }
14266
+ }
14267
+ if (remaining.size === 0) {
14268
+ return [];
14269
+ }
14270
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
14271
+ }
14272
+ return Array.from(remaining);
14273
+ }
14274
+ async function stopProcessTree(rootPid, rows) {
14275
+ const tree = [rootPid, ...getDescendantPids(rootPid, rows)].filter((pid, index, all) => all.indexOf(pid) === index).sort((a, b) => b - a);
14276
+ await signalPids(tree, "SIGTERM");
14277
+ let remaining = await waitForPidsExit(tree, PROCESS_EXIT_GRACE_MS);
14278
+ if (remaining.length > 0) {
14279
+ await signalPids(remaining.sort((a, b) => b - a), "SIGKILL");
14280
+ remaining = await waitForPidsExit(remaining, EXIT_WAIT_MS);
14281
+ }
14282
+ return remaining;
14283
+ }
14284
+ async function stopUnverifiedLaunch(rootPid) {
14285
+ try {
14286
+ await stopProcessTree(rootPid, await readProcessRows());
14287
+ } catch {
14288
+ }
14289
+ }
14290
+ async function isCodexUseLaunchedProcess(pid) {
14291
+ const result = await runCommand2(
14292
+ "/bin/ps",
14293
+ ["eww", "-p", String(pid), "-o", "command="],
14294
+ 2e3
14295
+ );
14296
+ return result.code === 0 && result.stdout.includes("CODEX_TELEMETRY_LABEL=codexuse-profile-");
14297
+ }
14298
+ async function hasRecoverableOfficialCodexBridge(cdpPort) {
14299
+ try {
14300
+ const target = pickCodexCdpTarget(await readCdpTargets(cdpPort), {
14301
+ allowAnyPage: true
14302
+ });
14303
+ if (!target?.webSocketDebuggerUrl) {
14304
+ return false;
14305
+ }
14306
+ await ensureOfficialCodexBridgeInstalled(target.webSocketDebuggerUrl, false);
14307
+ const health = normalizeBridgeHealth(
14308
+ await evaluateCdpExpression(
14309
+ target.webSocketDebuggerUrl,
14310
+ createBridgeHealthExpression()
14311
+ )
14312
+ );
14313
+ return health.ok;
14314
+ } catch {
14315
+ return false;
14316
+ }
14317
+ }
14318
+ async function reapStaleOfficialCodexManagedLaunchRows(candidate, rows) {
14319
+ const now = Date.now();
14320
+ const reaped = [];
14321
+ let currentRows = rows;
14322
+ const livePids = new Set(rows.map((row) => row.pid));
14323
+ for (const pid of staleOfficialCodexBridgeMissesByPid.keys()) {
14324
+ if (!livePids.has(pid)) {
14325
+ staleOfficialCodexBridgeMissesByPid.delete(pid);
14326
+ }
14327
+ }
14328
+ for (const row of rows) {
14329
+ const cdpPort = parseRemoteDebuggingPort(row.args);
14330
+ if (!isMainProcessRow(row, candidate) || cdpPort === null || row.startedAt === null || now - row.startedAt < CODEXUSE_STALE_LAUNCH_GRACE_MS || !await isCodexUseLaunchedProcess(row.pid)) {
14331
+ continue;
14332
+ }
14333
+ const appServerPid = findAppServerPid(currentRows, row.pid);
14334
+ if (appServerPid !== null) {
14335
+ if (await hasRecoverableOfficialCodexBridge(cdpPort)) {
14336
+ staleOfficialCodexBridgeMissesByPid.delete(row.pid);
14337
+ continue;
14338
+ }
14339
+ const previousMissAt = staleOfficialCodexBridgeMissesByPid.get(row.pid);
14340
+ staleOfficialCodexBridgeMissesByPid.set(row.pid, now);
14341
+ if (previousMissAt === void 0 || now - previousMissAt > CODEXUSE_STALE_BRIDGE_MISS_TTL_MS) {
14342
+ continue;
14343
+ }
14344
+ }
14345
+ await stopProcessTree(row.pid, currentRows);
14346
+ currentRows = await readProcessRows();
14347
+ if (!currentRows.some((entry) => entry.pid === row.pid)) {
14348
+ staleOfficialCodexBridgeMissesByPid.delete(row.pid);
14349
+ reaped.push(row.pid);
14350
+ if (sharedHomeCdpWindow?.pid === row.pid) {
14351
+ sharedHomeCdpWindow = null;
14352
+ }
14353
+ }
14354
+ break;
14355
+ }
14356
+ return reaped;
14357
+ }
14189
14358
  async function focusOfficialCodexApp(candidate) {
14190
14359
  const result = await runCommand2("/usr/bin/open", [candidate.appPath], 5e3);
14191
14360
  return result.code === 0;
@@ -14488,7 +14657,19 @@ async function resolveCodexAppTarget() {
14488
14657
  const mainPids = getRunningCodexMainPidsFromRows(fallback, rows);
14489
14658
  return { candidate: fallback, runningPids, mainPids };
14490
14659
  }
14660
+ async function signalPids(pids, signal) {
14661
+ const signaled = [];
14662
+ for (const pid of pids) {
14663
+ try {
14664
+ process.kill(pid, signal);
14665
+ signaled.push(pid);
14666
+ } catch {
14667
+ }
14668
+ }
14669
+ return signaled;
14670
+ }
14491
14671
  var SHARED_CODEX_HOME = import_node_path10.default.join((0, import_node_os3.homedir)(), ".codex");
14672
+ var sharedHomeCdpWindow = null;
14492
14673
  function toIso(value) {
14493
14674
  return typeof value === "number" && Number.isFinite(value) ? new Date(value).toISOString() : null;
14494
14675
  }
@@ -14560,7 +14741,13 @@ async function getOfficialCodexProfileInstances(options = {}) {
14560
14741
  unmanaged: []
14561
14742
  };
14562
14743
  }
14563
- const [state, rows] = await Promise.all([getAppState(), readProcessRows()]);
14744
+ const [state, initialRows] = await Promise.all([getAppState(), readProcessRows()]);
14745
+ let rows = initialRows;
14746
+ let visibleMainPids = mainPids;
14747
+ if ((await reapStaleOfficialCodexManagedLaunchRows(candidate, rows)).length > 0) {
14748
+ rows = await readProcessRows();
14749
+ visibleMainPids = rows.filter((row) => isMainProcessRow(row, candidate)).map((row) => row.pid);
14750
+ }
14564
14751
  const allowedProfileNames = options.profileNames ? new Set(options.profileNames.map((name) => name.trim()).filter(Boolean)) : null;
14565
14752
  const managed = [];
14566
14753
  const managedPids = /* @__PURE__ */ new Set();
@@ -14622,7 +14809,7 @@ async function getOfficialCodexProfileInstances(options = {}) {
14622
14809
  }
14623
14810
  managed.sort((a, b) => a.profileName.localeCompare(b.profileName));
14624
14811
  const unmanaged = [];
14625
- const unmanagedPids = mainPids.filter((entry) => !managedPids.has(entry));
14812
+ const unmanagedPids = visibleMainPids.filter((entry) => !managedPids.has(entry));
14626
14813
  const allowedFallbackProfileName = allowedProfileNames?.size === 1 ? Array.from(allowedProfileNames)[0] : null;
14627
14814
  for (const pid of unmanagedPids) {
14628
14815
  const mainRow = rows.find((row) => row.pid === pid) ?? null;
@@ -14711,6 +14898,14 @@ async function launchOfficialCodexProfileInstanceOnce(options) {
14711
14898
  reason: "official-codex-app-not-found"
14712
14899
  };
14713
14900
  }
14901
+ let launchBaselineMainPids = mainPids;
14902
+ const staleLaunchPids = await reapStaleOfficialCodexManagedLaunchRows(
14903
+ candidate,
14904
+ await readProcessRows()
14905
+ );
14906
+ if (staleLaunchPids.length > 0) {
14907
+ launchBaselineMainPids = (await readProcessRows()).filter((row) => isMainProcessRow(row, candidate)).map((row) => row.pid);
14908
+ }
14714
14909
  const existing = await readManagedInstance(options.profileName);
14715
14910
  const desiredQolSettings = resolveDesiredQolSettings({
14716
14911
  requested: options.desiredQolSettings,
@@ -14795,7 +14990,7 @@ async function launchOfficialCodexProfileInstanceOnce(options) {
14795
14990
  options.profileHome,
14796
14991
  options.profileName,
14797
14992
  cdpPort,
14798
- new Set(mainPids)
14993
+ new Set(launchBaselineMainPids)
14799
14994
  );
14800
14995
  if (!launch.opened) {
14801
14996
  const reason = launch.reason ?? "open-failed";
@@ -14854,6 +15049,7 @@ async function launchOfficialCodexProfileInstanceOnce(options) {
14854
15049
  options.profileHome
14855
15050
  );
14856
15051
  if (appServerPid === null) {
15052
+ await stopUnverifiedLaunch(launchedPid);
14857
15053
  const failed = {
14858
15054
  profileName: options.profileName,
14859
15055
  profileKey: options.profileKey,
@@ -16107,6 +16303,24 @@ function buildSyncUrl(pathname) {
16107
16303
  const normalizedPath = pathname.startsWith("/") ? pathname : `/${pathname}`;
16108
16304
  return `${baseUrl}${normalizedPath}`;
16109
16305
  }
16306
+ function formatErrorResponse(raw, status) {
16307
+ const trimmed = raw.trim();
16308
+ if (trimmed) {
16309
+ try {
16310
+ const parsed = JSON.parse(trimmed);
16311
+ if (isRecord6(parsed)) {
16312
+ const message = parsed.error ?? parsed.message;
16313
+ if (typeof message === "string" && message.trim().length > 0) {
16314
+ return message.trim();
16315
+ }
16316
+ }
16317
+ } catch {
16318
+ return trimmed;
16319
+ }
16320
+ return trimmed;
16321
+ }
16322
+ return `Cloud sync request failed (${status}).`;
16323
+ }
16110
16324
  function normalizeSnapshotKind(value) {
16111
16325
  if (value === "encrypted" || value === "legacy-plaintext") {
16112
16326
  return value;
@@ -16202,7 +16416,7 @@ async function requestJson(method, pathname, access, body, rawBody) {
16202
16416
  if (!response.ok) {
16203
16417
  const message = await response.text().catch(() => "");
16204
16418
  throw new CloudSyncClientError(
16205
- message || `Cloud sync request failed (${response.status}).`,
16419
+ formatErrorResponse(message, response.status),
16206
16420
  response.status
16207
16421
  );
16208
16422
  }
@@ -17752,13 +17966,12 @@ async function pushCloudSync(options = {}) {
17752
17966
  serializedSnapshot
17753
17967
  });
17754
17968
  const remoteKind = getSnapshotKind(remote.snapshot);
17755
- await writeState({
17756
- lastPushAt: (/* @__PURE__ */ new Date()).toISOString(),
17757
- remoteUpdatedAt: remote.snapshot.updatedAt,
17758
- remoteKind,
17759
- lastError: void 0
17760
- });
17761
17969
  if (remote.status === "stale") {
17970
+ await writeState({
17971
+ remoteUpdatedAt: remote.snapshot.updatedAt,
17972
+ remoteKind,
17973
+ lastError: void 0
17974
+ });
17762
17975
  return {
17763
17976
  mode: "push",
17764
17977
  status: "stale",
@@ -17768,6 +17981,12 @@ async function pushCloudSync(options = {}) {
17768
17981
  };
17769
17982
  }
17770
17983
  await rememberPassphraseIfRequested(eligibility.access.syncKey, options, passphrase);
17984
+ await writeState({
17985
+ lastPushAt: (/* @__PURE__ */ new Date()).toISOString(),
17986
+ remoteUpdatedAt: remote.snapshot.updatedAt,
17987
+ remoteKind,
17988
+ lastError: void 0
17989
+ });
17771
17990
  return {
17772
17991
  mode: "push",
17773
17992
  status: "applied",
@@ -17937,7 +18156,7 @@ async function ensureCliStorageReady() {
17937
18156
  }
17938
18157
 
17939
18158
  // src/app/main.ts
17940
- var VERSION = true ? "5.1.8" : "0.0.0";
18159
+ var VERSION = true ? "5.2.1" : "0.0.0";
17941
18160
  async function runCli() {
17942
18161
  const args = process.argv.slice(2);
17943
18162
  if (args.length === 0) {