codexuse-cli 6.1.1 → 6.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/dist/index.js CHANGED
@@ -2082,6 +2082,58 @@ var import_node_crypto2 = require("crypto");
2082
2082
  var import_node_path4 = __toESM(require("path"), 1);
2083
2083
  var import_node_os = __toESM(require("os"), 1);
2084
2084
 
2085
+ // ../../packages/contracts/src/license/offer-config.ts
2086
+ function getActiveOffer() {
2087
+ const basePriceUsd = 39;
2088
+ const discountPercent = 50;
2089
+ const salePriceUsd = basePriceUsd * (100 - discountPercent) / 100;
2090
+ return {
2091
+ basePriceUsd,
2092
+ basePriceDisplay: `$${basePriceUsd}`,
2093
+ couponCode: "SUMMER50",
2094
+ discountPercent,
2095
+ salePriceUsd,
2096
+ salePriceDisplay: `$${salePriceUsd.toFixed(2)}`,
2097
+ isActive: true,
2098
+ campaign: "summer-2026",
2099
+ productPermalink: "codex-use",
2100
+ checkoutBaseUrl: "https://hweihwang.gumroad.com/l/codex-use",
2101
+ trialEnabled: true,
2102
+ trialDays: 7,
2103
+ maxActivations: 5
2104
+ };
2105
+ }
2106
+ function buildCheckoutUrl(offer2, options) {
2107
+ const base2 = offer2.checkoutBaseUrl;
2108
+ const withCoupon = offer2.isActive && offer2.couponCode ? `${base2}/${offer2.couponCode}` : base2;
2109
+ const url = new URL(withCoupon);
2110
+ if (options?.directCheckout) {
2111
+ url.searchParams.set("wanted", "true");
2112
+ }
2113
+ if (!options?.source || !options?.medium) {
2114
+ return url.toString();
2115
+ }
2116
+ url.searchParams.set("utm_source", options.source);
2117
+ url.searchParams.set("utm_medium", options.medium);
2118
+ if (options.campaign) {
2119
+ url.searchParams.set("utm_campaign", options.campaign);
2120
+ } else if (offer2.campaign) {
2121
+ url.searchParams.set("utm_campaign", offer2.campaign);
2122
+ }
2123
+ return url.toString();
2124
+ }
2125
+
2126
+ // ../../packages/contracts/src/license/activation-session.ts
2127
+ var ACTIVATION_RETENTION_MS = 24 * 60 * 60 * 1e3;
2128
+ var ACTIVATION_WATCH_MS = 20 * 60 * 1e3;
2129
+ var ACTIVATION_SESSION_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
2130
+ function normalizePendingCheckout(value3) {
2131
+ if (!value3 || typeof value3 !== "object" || Array.isArray(value3)) return null;
2132
+ const { sessionId, startedAt } = value3;
2133
+ if (typeof sessionId !== "string" || !ACTIVATION_SESSION_PATTERN.test(sessionId) || typeof startedAt !== "number" || !Number.isSafeInteger(startedAt) || startedAt <= 0) return null;
2134
+ return { sessionId, startedAt };
2135
+ }
2136
+
2085
2137
  // ../../packages/contracts/src/desktop/llm-compatibility.ts
2086
2138
  var DESKTOP_LLM_CAPABILITY_NAMES = [
2087
2139
  "streamingText",
@@ -2197,7 +2249,6 @@ var DEFAULT_AUTO_ROLL_ENABLED = false;
2197
2249
  var DEFAULT_AUTO_ROLL_REARM_REMAINING_THRESHOLD = 15;
2198
2250
  var DEFAULT_AUTO_ROLL_SWITCH_REMAINING_THRESHOLD = 5;
2199
2251
  var DEFAULT_LAUNCH_OFFICIAL_CODEX_WHEN_CLOSED_ON_AUTO_ROLL = false;
2200
- var DEFAULT_HANDOFF_RUNNING_THREADS_ON_ACCOUNT_SWITCH = false;
2201
2252
  var DEFAULT_AUTO_ROLL_PRIORITY_ORDER = [];
2202
2253
  var DEFAULT_LOW_REMAINING_NOTIFICATION_ENABLED = false;
2203
2254
  var DEFAULT_LOW_REMAINING_NOTIFICATION_THRESHOLD = 1;
@@ -2305,7 +2356,6 @@ function normalizeAutoRollSettings(raw) {
2305
2356
  rearmRemainingThreshold: normalizedRearm,
2306
2357
  switchRemainingThreshold: normalizedSwitch,
2307
2358
  launchOfficialCodexWhenClosedOnAutoRoll: raw?.launchOfficialCodexWhenClosedOnAutoRoll === true ? true : DEFAULT_LAUNCH_OFFICIAL_CODEX_WHEN_CLOSED_ON_AUTO_ROLL,
2308
- handoffRunningThreadsOnAccountSwitch: raw?.handoffRunningThreadsOnAccountSwitch === true ? true : DEFAULT_HANDOFF_RUNNING_THREADS_ON_ACCOUNT_SWITCH,
2309
2359
  priorityOrder: sanitizeAutoRollPriorityOrder(raw?.priorityOrder),
2310
2360
  excludedAccountKeys: sanitizeAutoRollExcludedAccountKeys(
2311
2361
  raw?.excludedAccountKeys
@@ -2320,6 +2370,21 @@ function normalizeAutoRollSettings(raw) {
2320
2370
  return normalized;
2321
2371
  }
2322
2372
 
2373
+ // ../../packages/contracts/src/work/types.ts
2374
+ function createDefaultWorkState() {
2375
+ return {
2376
+ version: 1,
2377
+ plannerProfileName: null,
2378
+ profilePolicies: {},
2379
+ projectsByPath: {},
2380
+ jobsById: {},
2381
+ requestJobIds: {},
2382
+ plansById: {},
2383
+ configMigrationVersion: 0,
2384
+ restartRequiredProfiles: []
2385
+ };
2386
+ }
2387
+
2323
2388
  // ../../packages/runtime-app-state/src/storage/documents.ts
2324
2389
  var import_node_fs2 = require("fs");
2325
2390
  var import_node_fs3 = require("fs");
@@ -2360,12 +2425,12 @@ async function openLockDatabase(databasePath) {
2360
2425
  throw error;
2361
2426
  }
2362
2427
  }
2363
- async function acquireCrossProcessFileLockTransaction(filePath, mode) {
2428
+ async function acquireCrossProcessFileLockTransaction(filePath, mode, busyTimeoutMs = mode === "write" ? 1e3 : 0) {
2364
2429
  const databasePath = `${import_node_path.default.resolve(filePath)}.codexuse-lock.sqlite`;
2365
2430
  let database = null;
2366
2431
  try {
2367
2432
  database = await openLockDatabase(databasePath);
2368
- database.exec(`PRAGMA busy_timeout = ${mode === "write" ? 1e3 : 0};`);
2433
+ database.exec(`PRAGMA busy_timeout = ${Math.max(0, Math.trunc(busyTimeoutMs))};`);
2369
2434
  database.exec("CREATE TABLE IF NOT EXISTS codexuse_file_lock (id INTEGER PRIMARY KEY);");
2370
2435
  if (mode === "write") {
2371
2436
  database.exec("BEGIN EXCLUSIVE;");
@@ -2394,8 +2459,8 @@ async function acquireCrossProcessFileLockTransaction(filePath, mode) {
2394
2459
  }
2395
2460
  };
2396
2461
  }
2397
- async function acquireCrossProcessFileLock(filePath) {
2398
- return acquireCrossProcessFileLockTransaction(filePath, "write");
2462
+ async function acquireCrossProcessFileLock(filePath, options = {}) {
2463
+ return acquireCrossProcessFileLockTransaction(filePath, "write", options.busyTimeoutMs);
2399
2464
  }
2400
2465
  async function acquireCrossProcessFileReadLock(filePath) {
2401
2466
  return acquireCrossProcessFileLockTransaction(filePath, "read");
@@ -3408,12 +3473,12 @@ function resolveStorageDbPath() {
3408
3473
  function createDefaultAppState() {
3409
3474
  return {
3410
3475
  schemaVersion: 1,
3476
+ trialExperience: { knownLicenseHolder: false, pendingInteractiveAt: null, trial: null },
3411
3477
  autoRoll: {
3412
3478
  enabled: false,
3413
3479
  rearmRemainingThreshold: 15,
3414
3480
  switchRemainingThreshold: 5,
3415
3481
  launchOfficialCodexWhenClosedOnAutoRoll: false,
3416
- handoffRunningThreadsOnAccountSwitch: false,
3417
3482
  priorityOrder: [],
3418
3483
  excludedAccountKeys: [],
3419
3484
  lowRemainingNotificationEnabled: false,
@@ -3498,11 +3563,13 @@ function createDefaultAppState() {
3498
3563
  proUnlockedCelebrated: false
3499
3564
  },
3500
3565
  duplicateWarningDismissedKey: null,
3501
- pendingLicenseActivation: false
3566
+ pendingLicenseActivation: false,
3567
+ pendingCheckout: null
3502
3568
  },
3503
3569
  profileDashboard: {
3504
3570
  customGroupsByAccountKey: {}
3505
3571
  },
3572
+ work: createDefaultWorkState(),
3506
3573
  skills: {
3507
3574
  sources: [],
3508
3575
  installsBySlug: {}
@@ -3547,6 +3614,12 @@ function asStringArray(value3) {
3547
3614
  return [normalized];
3548
3615
  });
3549
3616
  }
3617
+ function normalizeAutoRollActivityKind(value3) {
3618
+ if (value3 === "official-codex-handoff") {
3619
+ return "official-codex-activation";
3620
+ }
3621
+ return value3 === "profile-switch" || value3 === "auth-verified" || value3 === "official-codex-activation" || value3 === "official-codex-restart" || value3 === "reset-window-activation" || value3 === "low-remaining-alert" ? value3 : "auto-roll-eval";
3622
+ }
3550
3623
  function asStringRecord(value3) {
3551
3624
  if (!isRecord2(value3)) {
3552
3625
  return {};
@@ -3605,7 +3678,6 @@ function normalizeOfficialCodexQolSettings(value3) {
3605
3678
  scrollRestoreEnabled: value3.scrollRestoreEnabled === true,
3606
3679
  conversationTimelineEnabled: value3.conversationTimelineEnabled === true,
3607
3680
  inCodexStatusEnabled: value3.inCodexStatusEnabled !== false,
3608
- handoffChipEnabled: value3.handoffChipEnabled !== false,
3609
3681
  actionTargets,
3610
3682
  providerStatus,
3611
3683
  overlayAutoRollEnabled: typeof value3.overlayAutoRollEnabled === "boolean" ? value3.overlayAutoRollEnabled : null
@@ -4110,6 +4182,35 @@ function normalizeOfficialCodexPowerStatus(value3) {
4110
4182
  appliedAt: asString(value3.appliedAt)
4111
4183
  };
4112
4184
  }
4185
+ function normalizeTrialExperience(raw) {
4186
+ const value3 = isRecord2(raw) ? raw : {};
4187
+ const trial = isRecord2(value3.trial) ? value3.trial : {};
4188
+ const startedAt = asString(trial.startedAt);
4189
+ const expiresAt = asString(trial.expiresAt);
4190
+ const start = startedAt ? Date.parse(startedAt) : NaN;
4191
+ const end = expiresAt ? Date.parse(expiresAt) : NaN;
4192
+ const observedAt = asNumberOrNull(trial.observedAt);
4193
+ const valid = startedAt && expiresAt && Number.isFinite(start) && end > start && observedAt !== null && observedAt >= start;
4194
+ const first = isRecord2(trial.firstOutcome) ? trial.firstOutcome : {};
4195
+ const completedAt = asNumberOrNull(first.completedAt);
4196
+ const kind = first.kind;
4197
+ const validKind = kind === "shared_history_switch" || kind === "shared_history_window" || kind === "matched_window" || kind === "provider_window" || kind === "pool_request";
4198
+ const interactiveAt = asNumberOrNull(trial.interactiveAt);
4199
+ const pendingInteractiveAt = asNumberOrNull(value3.pendingInteractiveAt);
4200
+ return {
4201
+ knownLicenseHolder: value3.knownLicenseHolder === true,
4202
+ pendingInteractiveAt: pendingInteractiveAt !== null && pendingInteractiveAt > 0 ? pendingInteractiveAt : null,
4203
+ trial: valid ? {
4204
+ startedAt,
4205
+ expiresAt,
4206
+ observedAt,
4207
+ priorPayment: trial.priorPayment === "known_prior_license" ? "known_prior_license" : "unknown",
4208
+ interactiveAt: interactiveAt !== null && interactiveAt > 0 && interactiveAt < end ? interactiveAt : null,
4209
+ firstOutcome: validKind && completedAt !== null && completedAt >= start && completedAt < end ? { kind, completedAt } : null,
4210
+ entitlementObservedAt: asNumberOrNull(trial.entitlementObservedAt)
4211
+ } : null
4212
+ };
4213
+ }
4113
4214
  function normalizeAppState(raw) {
4114
4215
  const defaults = createDefaultAppState();
4115
4216
  if (!isRecord2(raw)) {
@@ -4120,6 +4221,8 @@ function normalizeAppState(raw) {
4120
4221
  const next = deepMerge(defaults, raw);
4121
4222
  const merged = next;
4122
4223
  merged.schemaVersion = 1;
4224
+ merged.work = isRecord2(raw.work) ? deepMerge(createDefaultWorkState(), raw.work) : createDefaultWorkState();
4225
+ merged.trialExperience = normalizeTrialExperience(raw.trialExperience);
4123
4226
  merged.autoRoll = normalizeAutoRollSettings(rawAutoRoll);
4124
4227
  if (!isRecord2(merged.officialCodex)) {
4125
4228
  merged.officialCodex = clone2(defaults.officialCodex);
@@ -4141,10 +4244,11 @@ function normalizeAppState(raw) {
4141
4244
  );
4142
4245
  merged.officialCodex.lastActivationStatus = asString(merged.officialCodex.lastActivationStatus);
4143
4246
  merged.officialCodex.lastActivationReason = asString(merged.officialCodex.lastActivationReason);
4144
- merged.officialCodex.activity = Array.isArray(merged.officialCodex.activity) ? merged.officialCodex.activity.filter((entry) => isRecord2(entry)).map((entry) => ({
4247
+ const rawOfficialCodexActivity = Array.isArray(rawOfficialCodex?.activity) ? rawOfficialCodex.activity : [];
4248
+ merged.officialCodex.activity = rawOfficialCodexActivity.length > 0 ? rawOfficialCodexActivity.filter(isRecord2).map((entry) => ({
4145
4249
  id: asString(entry.id) ?? "",
4146
4250
  at: asString(entry.at) ?? (/* @__PURE__ */ new Date(0)).toISOString(),
4147
- kind: entry.kind === "auto-roll-eval" || entry.kind === "profile-switch" || entry.kind === "auth-verified" || entry.kind === "official-codex-activation" || entry.kind === "official-codex-restart" || entry.kind === "official-codex-handoff" || entry.kind === "reset-window-activation" || entry.kind === "low-remaining-alert" ? entry.kind : "auto-roll-eval",
4251
+ kind: normalizeAutoRollActivityKind(entry.kind),
4148
4252
  status: asString(entry.status) ?? "unknown",
4149
4253
  reason: asString(entry.reason),
4150
4254
  decisionId: asString(entry.decisionId),
@@ -4253,7 +4357,7 @@ function normalizeAppState(raw) {
4253
4357
  merged.officialCodex.relayProfilesById
4254
4358
  );
4255
4359
  merged.officialCodex.desktopLlmEnabled = rawOfficialCodex?.desktopLlmEnabled === true;
4256
- const rawActivationDebt = isRecord2(merged.officialCodex.pendingActivationDebt) ? merged.officialCodex.pendingActivationDebt : null;
4360
+ const rawActivationDebt = isRecord2(rawOfficialCodex?.pendingActivationDebt) ? rawOfficialCodex.pendingActivationDebt : null;
4257
4361
  if (rawActivationDebt) {
4258
4362
  const debt = rawActivationDebt;
4259
4363
  const targetProfileName = asString(debt.targetProfileName);
@@ -4266,23 +4370,17 @@ function normalizeAppState(raw) {
4266
4370
  decisionId: asString(debt.decisionId),
4267
4371
  attempts: asNumberOrNull(debt.attempts) ?? 0,
4268
4372
  lastReason: asString(debt.lastReason),
4269
- handoffReason: debt.handoffReason === "manual" || debt.handoffReason === "auto-roll" ? debt.handoffReason : null,
4270
- handoffThreadIds: asStringArray(debt.handoffThreadIds),
4271
- handoffSentThreadIds: asStringArray(debt.handoffSentThreadIds),
4272
- sourceActiveThreadIds: asStringArray(debt.sourceActiveThreadIds),
4273
- sourceCompletedThreadIds: asStringArray(
4274
- debt.sourceCompletedThreadIds
4373
+ activationSource: debt.activationSource === "manual" || debt.activationSource === "auto-roll" ? debt.activationSource : debt.handoffReason === "manual" ? "manual" : "auto-roll",
4374
+ blockingThreadIds: asStringArray(
4375
+ debt.blockingThreadIds ?? debt.sourceActiveThreadIds
4275
4376
  ),
4276
- sourceActiveTurnIdsByThreadId: asStringRecord(
4277
- debt.sourceActiveTurnIdsByThreadId
4377
+ completedBlockingThreadIds: asStringArray(
4378
+ debt.completedBlockingThreadIds ?? debt.sourceCompletedThreadIds
4278
4379
  ),
4279
- sourceCaptureState: debt.sourceCaptureState === "attaching" || debt.sourceCaptureState === "attached" || debt.sourceCaptureState === "failed" ? debt.sourceCaptureState : null,
4280
- handoffClientUserMessageIdsByThreadId: asStringRecord(
4281
- debt.handoffClientUserMessageIdsByThreadId
4380
+ blockingTurnIdsByThreadId: asStringRecord(
4381
+ debt.blockingTurnIdsByThreadId ?? debt.sourceActiveTurnIdsByThreadId
4282
4382
  ),
4283
- handoffTurnIdsByThreadId: asStringRecord(
4284
- debt.handoffTurnIdsByThreadId
4285
- )
4383
+ sourceListenerState: debt.sourceListenerState === "attaching" || debt.sourceListenerState === "attached" || debt.sourceListenerState === "failed" ? debt.sourceListenerState : debt.sourceCaptureState === "attaching" || debt.sourceCaptureState === "attached" || debt.sourceCaptureState === "failed" ? debt.sourceCaptureState : null
4286
4384
  } : null;
4287
4385
  } else {
4288
4386
  merged.officialCodex.pendingActivationDebt = null;
@@ -4562,6 +4660,7 @@ function normalizeAppState(raw) {
4562
4660
  if (typeof merged.ui.pendingLicenseActivation !== "boolean") {
4563
4661
  merged.ui.pendingLicenseActivation = false;
4564
4662
  }
4663
+ merged.ui.pendingCheckout = normalizePendingCheckout(merged.ui.pendingCheckout);
4565
4664
  {
4566
4665
  const allowedUiKeys = new Set(Object.keys(defaults.ui));
4567
4666
  for (const key of Object.keys(merged.ui)) {
@@ -5062,7 +5161,6 @@ var CLOUD_SYNC_RUNTIME_SETTING_KEYS = /* @__PURE__ */ new Set([
5062
5161
  "officialCodexScrollRestoreEnabled",
5063
5162
  "officialCodexConversationTimelineEnabled",
5064
5163
  "officialCodexInCodexStatusEnabled",
5065
- "officialCodexHandoffChipEnabled",
5066
5164
  "officialCodexRelayMode",
5067
5165
  "officialCodexRelayProfileId",
5068
5166
  "officialCodexModelWhitelistUnlockEnabled",
@@ -5139,27 +5237,35 @@ async function getStoredLicense() {
5139
5237
  const state = await getAppState();
5140
5238
  return parseStoredLicense(state.license);
5141
5239
  }
5142
- async function persistLicense(license) {
5240
+ async function persistLicense(license, expected) {
5143
5241
  const parsed = parseStoredLicense(license);
5144
- await patchAppState({
5145
- license: parsed ? {
5146
- licenseKey: parsed.licenseKey ?? null,
5147
- purchaseEmail: parsed.purchaseEmail ?? null,
5148
- lastVerifiedAt: parsed.lastVerifiedAt ?? null,
5149
- nextCheckAt: parsed.nextCheckAt ?? null,
5150
- lastVerificationError: parsed.lastVerificationError ?? null,
5151
- status: parsed.status ?? "inactive",
5152
- signature: parsed.signature ?? null
5153
- } : {
5154
- licenseKey: null,
5155
- purchaseEmail: null,
5156
- lastVerifiedAt: null,
5157
- nextCheckAt: null,
5158
- lastVerificationError: null,
5159
- status: "inactive",
5160
- signature: null
5242
+ let persisted = false;
5243
+ await updateAppState((current) => {
5244
+ if (expected !== void 0 && JSON.stringify(parseStoredLicense(current.license)) !== JSON.stringify(parseStoredLicense(expected))) {
5245
+ return {};
5161
5246
  }
5247
+ persisted = true;
5248
+ return {
5249
+ license: parsed ? {
5250
+ licenseKey: parsed.licenseKey ?? null,
5251
+ purchaseEmail: parsed.purchaseEmail ?? null,
5252
+ lastVerifiedAt: parsed.lastVerifiedAt ?? null,
5253
+ nextCheckAt: parsed.nextCheckAt ?? null,
5254
+ lastVerificationError: parsed.lastVerificationError ?? null,
5255
+ status: parsed.status ?? "inactive",
5256
+ signature: parsed.signature ?? null
5257
+ } : {
5258
+ licenseKey: null,
5259
+ purchaseEmail: null,
5260
+ lastVerifiedAt: null,
5261
+ nextCheckAt: null,
5262
+ lastVerificationError: null,
5263
+ status: "inactive",
5264
+ signature: null
5265
+ }
5266
+ };
5162
5267
  });
5268
+ return persisted;
5163
5269
  }
5164
5270
  async function getStoredAutoRollSettings() {
5165
5271
  const state = await getAppState();
@@ -5201,7 +5307,6 @@ async function writeCodexSettingsJsonRaw(payload) {
5201
5307
  rearmRemainingThreshold: autoRoll.rearmRemainingThreshold,
5202
5308
  switchRemainingThreshold: autoRoll.switchRemainingThreshold,
5203
5309
  launchOfficialCodexWhenClosedOnAutoRoll: autoRoll.launchOfficialCodexWhenClosedOnAutoRoll,
5204
- handoffRunningThreadsOnAccountSwitch: autoRoll.handoffRunningThreadsOnAccountSwitch,
5205
5310
  priorityOrder: autoRoll.priorityOrder,
5206
5311
  excludedAccountKeys: autoRoll.excludedAccountKeys,
5207
5312
  lowRemainingNotificationEnabled: autoRoll.lowRemainingNotificationEnabled,
@@ -5254,46 +5359,6 @@ async function getLicenseSecret() {
5254
5359
  return persistLicenseSecret(dbPath, secret);
5255
5360
  }
5256
5361
 
5257
- // ../../packages/contracts/src/license/offer-config.ts
5258
- function getActiveOffer() {
5259
- const basePriceUsd = 39;
5260
- const discountPercent = 50;
5261
- const salePriceUsd = basePriceUsd * (100 - discountPercent) / 100;
5262
- return {
5263
- basePriceUsd,
5264
- basePriceDisplay: `$${basePriceUsd}`,
5265
- couponCode: "SUMMER50",
5266
- discountPercent,
5267
- salePriceUsd,
5268
- salePriceDisplay: `$${salePriceUsd.toFixed(2)}`,
5269
- isActive: true,
5270
- campaign: "summer-2026",
5271
- productPermalink: "codex-use",
5272
- checkoutBaseUrl: "https://hweihwang.gumroad.com/l/codex-use",
5273
- trialEnabled: true,
5274
- trialDays: 7
5275
- };
5276
- }
5277
- function buildCheckoutUrl(offer2, options) {
5278
- const base2 = offer2.checkoutBaseUrl;
5279
- const withCoupon = offer2.isActive && offer2.couponCode ? `${base2}/${offer2.couponCode}` : base2;
5280
- const url = new URL(withCoupon);
5281
- if (options?.directCheckout) {
5282
- url.searchParams.set("wanted", "true");
5283
- }
5284
- if (!options?.source || !options?.medium) {
5285
- return url.toString();
5286
- }
5287
- url.searchParams.set("utm_source", options.source);
5288
- url.searchParams.set("utm_medium", options.medium);
5289
- if (options.campaign) {
5290
- url.searchParams.set("utm_campaign", options.campaign);
5291
- } else if (offer2.campaign) {
5292
- url.searchParams.set("utm_campaign", offer2.campaign);
5293
- }
5294
- return url.toString();
5295
- }
5296
-
5297
5362
  // ../../packages/runtime-profiles/src/license/trial.ts
5298
5363
  var import_node_crypto6 = __toESM(require("crypto"), 1);
5299
5364
 
@@ -5562,6 +5627,7 @@ function buildTrialInfo(stored, now2) {
5562
5627
  const expired = stored?.serverExpired === true || expiresAtMs === null || expiresAtMs <= now2;
5563
5628
  const daysLeft = expired || expiresAtMs === null ? 0 : Math.max(0, Math.ceil((expiresAtMs - now2) / DAY_MS));
5564
5629
  return {
5630
+ startedAt: stored?.startedAt ?? null,
5565
5631
  active: !expired,
5566
5632
  expired,
5567
5633
  expiresAt: stored?.expiresAt ?? null,
@@ -5573,6 +5639,7 @@ function lockReasonFor(info) {
5573
5639
  }
5574
5640
  function buildLockedTrialInfo(stored) {
5575
5641
  return {
5642
+ startedAt: null,
5576
5643
  active: false,
5577
5644
  expired: true,
5578
5645
  expiresAt: stored?.expiresAt ?? null,
@@ -6078,6 +6145,7 @@ var LicenseService = class {
6078
6145
  constructor() {
6079
6146
  this.refreshPromise = null;
6080
6147
  this.verificationPromise = null;
6148
+ this.activationTail = Promise.resolve();
6081
6149
  }
6082
6150
  async getCachedStatus() {
6083
6151
  try {
@@ -6129,8 +6197,10 @@ var LicenseService = class {
6129
6197
  nextCheckAt: new Date(cappedNextCheckTs).toISOString()
6130
6198
  };
6131
6199
  const signed = withSignature(updated, secret);
6200
+ if (!await persistLicense(signed, workingStored)) {
6201
+ return this.getStatus({ allowStale: true });
6202
+ }
6132
6203
  workingStored = signed;
6133
- await persistLicense(signed);
6134
6204
  }
6135
6205
  const tampered = Boolean(workingStored.licenseKey) && !signatureValid;
6136
6206
  const cached2 = tampered ? toLicenseStatus(null, {
@@ -6161,7 +6231,9 @@ var LicenseService = class {
6161
6231
  lastVerificationError: null
6162
6232
  };
6163
6233
  const signed = withSignature(updated, secret);
6164
- await persistLicense(signed);
6234
+ if (!await persistLicense(signed, workingStored)) {
6235
+ return this.getStatus({ allowStale: true });
6236
+ }
6165
6237
  return finalize2(toLicenseStatus(signed));
6166
6238
  } catch (error) {
6167
6239
  const message = error instanceof Error ? error.message : "License verification failed.";
@@ -6175,7 +6247,9 @@ var LicenseService = class {
6175
6247
  },
6176
6248
  secret
6177
6249
  );
6178
- await persistLicense(fallbackStored2);
6250
+ if (!await persistLicense(fallbackStored2, workingStored)) {
6251
+ return this.getStatus({ allowStale: true });
6252
+ }
6179
6253
  const fallback = toLicenseStatus(fallbackStored2, {
6180
6254
  state: fallbackStored2.status ?? "grace",
6181
6255
  error: message
@@ -6190,7 +6264,9 @@ var LicenseService = class {
6190
6264
  status: "inactive",
6191
6265
  lastVerificationError: message
6192
6266
  }, secret);
6193
- await persistLicense(fallbackStored);
6267
+ if (!await persistLicense(fallbackStored, workingStored)) {
6268
+ return this.getStatus({ allowStale: true });
6269
+ }
6194
6270
  return finalize2(toLicenseStatus(fallbackStored, { error: message }));
6195
6271
  }
6196
6272
  };
@@ -6202,6 +6278,23 @@ var LicenseService = class {
6202
6278
  }
6203
6279
  }
6204
6280
  async activate(licenseKey) {
6281
+ return (await this.queueActivation(licenseKey, false)).license;
6282
+ }
6283
+ activateFromCheckout(licenseKey) {
6284
+ return this.queueActivation(licenseKey, true);
6285
+ }
6286
+ queueActivation(licenseKey, onlyIfUnlicensed) {
6287
+ const result2 = this.activationTail.then(async () => {
6288
+ if (onlyIfUnlicensed) {
6289
+ const current = await this.getCachedStatus();
6290
+ if (current.isPro) return { license: current, activated: false };
6291
+ }
6292
+ return { license: await this.performActivation(licenseKey), activated: true };
6293
+ });
6294
+ this.activationTail = result2.then(() => void 0, () => void 0);
6295
+ return result2;
6296
+ }
6297
+ async performActivation(licenseKey) {
6205
6298
  const trimmed = licenseKey.trim();
6206
6299
  if (!trimmed) {
6207
6300
  throw new Error("License key is required.");
@@ -23636,6 +23729,7 @@ var RPC_METHODS = {
23636
23729
  runtimeRefreshProviders: "runtime.refreshProviders",
23637
23730
  appStateGet: "appState.get",
23638
23731
  appStatePatch: "appState.patch",
23732
+ trialExperienceStart: "trialExperience.start",
23639
23733
  appSettingsGet: "appSettings.get",
23640
23734
  appSettingsUpdate: "appSettings.update",
23641
23735
  officialCodexSetAutoControl: "officialCodex.setAutoControl",
@@ -23672,17 +23766,10 @@ var RPC_METHODS = {
23672
23766
  autoRollResolveDecision: "autoRoll.resolveDecision",
23673
23767
  officialCodexActivate: "officialCodex.activate",
23674
23768
  officialCodexInstances: "officialCodex.instances",
23675
- officialCodexLaunchProfile: "officialCodex.launchProfile",
23676
- officialCodexFocusProfile: "officialCodex.focusProfile",
23769
+ accountsOpen: "accounts.open",
23677
23770
  officialCodexStopProfile: "officialCodex.stopProfile",
23678
23771
  officialCodexRestartProfile: "officialCodex.restartProfile",
23679
- officialCodexUseProfile: "officialCodex.useProfile",
23680
- officialCodexLaunchProfiles: "officialCodex.launchProfiles",
23681
- officialCodexStopProfiles: "officialCodex.stopProfiles",
23682
23772
  officialCodexActivateProfiles: "officialCodex.activateProfiles",
23683
- officialCodexPrepareDraftHandoff: "officialCodex.prepareDraftHandoff",
23684
- officialCodexOpenWorkspace: "officialCodex.openWorkspace",
23685
- officialCodexOpenDevTools: "officialCodex.openDevTools",
23686
23773
  officialCodexApplyQol: "officialCodex.applyQol",
23687
23774
  officialCodexApplyPower: "officialCodex.applyPower",
23688
23775
  officialCodexRefreshBridgeCapabilities: "officialCodex.refreshBridgeCapabilities",
@@ -23722,7 +23809,27 @@ var RPC_METHODS = {
23722
23809
  accountPoolClearSession: "accountPool.clearSession",
23723
23810
  accountPoolListRecentRequests: "accountPool.listRecentRequests",
23724
23811
  accountPoolTestModels: "accountPool.testModels",
23725
- accountPoolTestResponse: "accountPool.testResponse"
23812
+ accountPoolTestResponse: "accountPool.testResponse",
23813
+ workGetSnapshot: "work.getSnapshot",
23814
+ workOpenFolder: "work.openFolder",
23815
+ workOpenWindows: "work.openWindows",
23816
+ workStartPlan: "work.startPlan",
23817
+ workOpenPlan: "work.openPlan",
23818
+ workRemovePlan: "work.removePlan",
23819
+ workSetPlanner: "work.setPlanner",
23820
+ workUpdateProfilePolicy: "work.updateProfilePolicy",
23821
+ workAuthorizeProject: "work.authorizeProject",
23822
+ workProjectPreview: "work.project.preview",
23823
+ workDelegate: "work.delegate",
23824
+ workAction: "work.action",
23825
+ workDiffReview: "work.diff.review",
23826
+ workHistoryList: "work.history.list",
23827
+ workHistoryOpen: "work.history.open",
23828
+ workConfigGet: "work.config.get",
23829
+ workConfigSaveShared: "work.config.saveShared",
23830
+ workConfigSaveOverride: "work.config.saveOverride",
23831
+ workConfigResetOverride: "work.config.resetOverride",
23832
+ workConfigReconcileExternal: "work.config.reconcileExternal"
23726
23833
  };
23727
23834
  var RPC_CHANNELS = {
23728
23835
  runtimeProvidersUpdated: "runtime.providersUpdated",
@@ -23733,7 +23840,8 @@ var RPC_CHANNELS = {
23733
23840
  autoRollDecision: "autoRoll.decision",
23734
23841
  officialCodexActivationProgress: "officialCodex.activationProgress",
23735
23842
  officialCodexActivityUpdated: "officialCodex.activityUpdated",
23736
- officialCodexStatusUpdated: "officialCodex.statusUpdated"
23843
+ officialCodexStatusUpdated: "officialCodex.statusUpdated",
23844
+ workUpdated: "work.updated"
23737
23845
  };
23738
23846
 
23739
23847
  // ../../packages/contracts/src/filesystem.ts
@@ -23818,7 +23926,14 @@ var DesktopRpcRequestBody = Schema_exports.Union([
23818
23926
  tagRequestBody(RPC_METHODS.runtimeRefreshProviders, Schema_exports.Struct({})),
23819
23927
  // Desktop dashboard/runtime methods
23820
23928
  tagRequestBody(RPC_METHODS.appStateGet, Schema_exports.Struct({})),
23821
- tagRequestBody(RPC_METHODS.appStatePatch, Schema_exports.Struct({ patch: Schema_exports.Unknown })),
23929
+ tagRequestBody(
23930
+ RPC_METHODS.appStatePatch,
23931
+ Schema_exports.Struct({ patch: Schema_exports.Unknown })
23932
+ ),
23933
+ tagRequestBody(
23934
+ RPC_METHODS.trialExperienceStart,
23935
+ Schema_exports.Struct({ interactiveAt: Schema_exports.Number })
23936
+ ),
23822
23937
  tagRequestBody(RPC_METHODS.appSettingsGet, Schema_exports.Struct({})),
23823
23938
  tagRequestBody(
23824
23939
  RPC_METHODS.appSettingsUpdate,
@@ -23839,21 +23954,27 @@ var DesktopRpcRequestBody = Schema_exports.Union([
23839
23954
  tagRequestBody(
23840
23955
  RPC_METHODS.codexConfigGet,
23841
23956
  Schema_exports.Struct({
23842
- codexHomePath: Schema_exports.optional(Schema_exports.Union([Schema_exports.String, Schema_exports.Null]))
23957
+ codexHomePath: Schema_exports.optional(
23958
+ Schema_exports.Union([Schema_exports.String, Schema_exports.Null])
23959
+ )
23843
23960
  })
23844
23961
  ),
23845
23962
  tagRequestBody(
23846
23963
  RPC_METHODS.codexConfigSaveRaw,
23847
23964
  Schema_exports.Struct({
23848
23965
  content: Schema_exports.String,
23849
- codexHomePath: Schema_exports.optional(Schema_exports.Union([Schema_exports.String, Schema_exports.Null]))
23966
+ codexHomePath: Schema_exports.optional(
23967
+ Schema_exports.Union([Schema_exports.String, Schema_exports.Null])
23968
+ )
23850
23969
  })
23851
23970
  ),
23852
23971
  tagRequestBody(
23853
23972
  RPC_METHODS.codexConfigUpdate,
23854
23973
  Schema_exports.Struct({
23855
23974
  updates: Schema_exports.Unknown,
23856
- codexHomePath: Schema_exports.optional(Schema_exports.Union([Schema_exports.String, Schema_exports.Null]))
23975
+ codexHomePath: Schema_exports.optional(
23976
+ Schema_exports.Union([Schema_exports.String, Schema_exports.Null])
23977
+ )
23857
23978
  })
23858
23979
  ),
23859
23980
  tagRequestBody(
@@ -23861,7 +23982,9 @@ var DesktopRpcRequestBody = Schema_exports.Union([
23861
23982
  Schema_exports.Struct({
23862
23983
  binaryPath: Schema_exports.optional(Schema_exports.Union([Schema_exports.String, Schema_exports.Null])),
23863
23984
  args: Schema_exports.optional(Schema_exports.Union([Schema_exports.String, Schema_exports.Null])),
23864
- codexHomePath: Schema_exports.optional(Schema_exports.Union([Schema_exports.String, Schema_exports.Null]))
23985
+ codexHomePath: Schema_exports.optional(
23986
+ Schema_exports.Union([Schema_exports.String, Schema_exports.Null])
23987
+ )
23865
23988
  })
23866
23989
  ),
23867
23990
  tagRequestBody(RPC_METHODS.codexRuntimeUpdate, Schema_exports.Struct({})),
@@ -23906,8 +24029,6 @@ var DesktopRpcRequestBody = Schema_exports.Union([
23906
24029
  reason: Schema_exports.optional(
23907
24030
  Schema_exports.Union([Schema_exports.Literal("manual"), Schema_exports.Literal("auto-roll")])
23908
24031
  ),
23909
- carryDraft: Schema_exports.optional(Schema_exports.Boolean),
23910
- continueThreadId: Schema_exports.optional(Schema_exports.Union([Schema_exports.String, Schema_exports.Null])),
23911
24032
  forceAdopt: Schema_exports.optional(Schema_exports.Boolean),
23912
24033
  launchIfNotRunning: Schema_exports.optional(Schema_exports.Boolean),
23913
24034
  awaitCodexFollowUp: Schema_exports.optional(Schema_exports.Boolean)
@@ -23989,21 +24110,16 @@ var DesktopRpcRequestBody = Schema_exports.Union([
23989
24110
  RPC_METHODS.autoRollResolveDecision,
23990
24111
  Schema_exports.Struct({
23991
24112
  id: TrimmedNonEmptyString,
23992
- action: Schema_exports.Union([Schema_exports.Literal("accept"), Schema_exports.Literal("cancel")])
24113
+ action: Schema_exports.Union([
24114
+ Schema_exports.Literal("accept"),
24115
+ Schema_exports.Literal("cancel")
24116
+ ])
23993
24117
  })
23994
24118
  ),
23995
24119
  tagRequestBody(RPC_METHODS.officialCodexActivate, Schema_exports.Struct({})),
23996
24120
  tagRequestBody(RPC_METHODS.officialCodexInstances, Schema_exports.Struct({})),
23997
24121
  tagRequestBody(
23998
- RPC_METHODS.officialCodexLaunchProfile,
23999
- Schema_exports.Struct({
24000
- name: TrimmedNonEmptyString,
24001
- desiredQolSettings: Schema_exports.optional(Schema_exports.Unknown),
24002
- desiredPowerSettings: Schema_exports.optional(Schema_exports.Unknown)
24003
- })
24004
- ),
24005
- tagRequestBody(
24006
- RPC_METHODS.officialCodexFocusProfile,
24122
+ RPC_METHODS.accountsOpen,
24007
24123
  Schema_exports.Struct({
24008
24124
  name: TrimmedNonEmptyString,
24009
24125
  desiredQolSettings: Schema_exports.optional(Schema_exports.Unknown),
@@ -24022,26 +24138,6 @@ var DesktopRpcRequestBody = Schema_exports.Union([
24022
24138
  desiredPowerSettings: Schema_exports.optional(Schema_exports.Unknown)
24023
24139
  })
24024
24140
  ),
24025
- tagRequestBody(
24026
- RPC_METHODS.officialCodexUseProfile,
24027
- Schema_exports.Struct({
24028
- name: TrimmedNonEmptyString,
24029
- desiredQolSettings: Schema_exports.optional(Schema_exports.Unknown),
24030
- desiredPowerSettings: Schema_exports.optional(Schema_exports.Unknown)
24031
- })
24032
- ),
24033
- tagRequestBody(
24034
- RPC_METHODS.officialCodexLaunchProfiles,
24035
- Schema_exports.Struct({
24036
- names: Schema_exports.Array(TrimmedNonEmptyString),
24037
- desiredQolSettings: Schema_exports.optional(Schema_exports.Unknown),
24038
- desiredPowerSettings: Schema_exports.optional(Schema_exports.Unknown)
24039
- })
24040
- ),
24041
- tagRequestBody(
24042
- RPC_METHODS.officialCodexStopProfiles,
24043
- Schema_exports.Struct({ names: Schema_exports.Array(TrimmedNonEmptyString) })
24044
- ),
24045
24141
  tagRequestBody(
24046
24142
  RPC_METHODS.officialCodexActivateProfiles,
24047
24143
  Schema_exports.Struct({
@@ -24049,28 +24145,6 @@ var DesktopRpcRequestBody = Schema_exports.Union([
24049
24145
  desiredPowerSettings: Schema_exports.optional(Schema_exports.Unknown)
24050
24146
  })
24051
24147
  ),
24052
- tagRequestBody(
24053
- RPC_METHODS.officialCodexPrepareDraftHandoff,
24054
- Schema_exports.Struct({
24055
- sourceProfileName: TrimmedNonEmptyString,
24056
- targetProfileName: TrimmedNonEmptyString,
24057
- desiredQolSettings: Schema_exports.optional(Schema_exports.Unknown),
24058
- desiredPowerSettings: Schema_exports.optional(Schema_exports.Unknown)
24059
- })
24060
- ),
24061
- tagRequestBody(
24062
- RPC_METHODS.officialCodexOpenWorkspace,
24063
- Schema_exports.Struct({
24064
- profileName: TrimmedNonEmptyString,
24065
- editor: TrimmedNonEmptyString
24066
- })
24067
- ),
24068
- tagRequestBody(
24069
- RPC_METHODS.officialCodexOpenDevTools,
24070
- Schema_exports.Struct({
24071
- profileName: TrimmedNonEmptyString
24072
- })
24073
- ),
24074
24148
  tagRequestBody(
24075
24149
  RPC_METHODS.officialCodexApplyQol,
24076
24150
  Schema_exports.Struct({
@@ -24211,7 +24285,10 @@ var DesktopRpcRequestBody = Schema_exports.Union([
24211
24285
  ),
24212
24286
  tagRequestBody(
24213
24287
  RPC_METHODS.desktopLlmSetRoutePublished,
24214
- Schema_exports.Struct({ publicSlug: TrimmedNonEmptyString, published: Schema_exports.Boolean })
24288
+ Schema_exports.Struct({
24289
+ publicSlug: TrimmedNonEmptyString,
24290
+ published: Schema_exports.Boolean
24291
+ })
24215
24292
  ),
24216
24293
  tagRequestBody(
24217
24294
  RPC_METHODS.desktopLlmProbeRoute,
@@ -24252,16 +24329,102 @@ var DesktopRpcRequestBody = Schema_exports.Union([
24252
24329
  tagRequestBody(
24253
24330
  RPC_METHODS.desktopLlmRuntimeControl,
24254
24331
  Schema_exports.Struct({
24255
- action: Schema_exports.Union([
24256
- Schema_exports.Literal("drain"),
24257
- Schema_exports.Literal("resume")
24258
- ])
24332
+ action: Schema_exports.Union([Schema_exports.Literal("drain"), Schema_exports.Literal("resume")])
24259
24333
  })
24260
24334
  ),
24261
24335
  tagRequestBody(RPC_METHODS.cliInfo, Schema_exports.Struct({})),
24262
24336
  tagRequestBody(RPC_METHODS.cliStatus, Schema_exports.Struct({})),
24263
24337
  tagRequestBody(RPC_METHODS.cliCheckFreshness, Schema_exports.Struct({})),
24264
- tagRequestBody(RPC_METHODS.cliUpdateGlobal, Schema_exports.Struct({}))
24338
+ tagRequestBody(RPC_METHODS.cliUpdateGlobal, Schema_exports.Struct({})),
24339
+ tagRequestBody(RPC_METHODS.workGetSnapshot, Schema_exports.Struct({})),
24340
+ tagRequestBody(RPC_METHODS.workStartPlan, Schema_exports.Struct({ input: Schema_exports.Unknown })),
24341
+ tagRequestBody(RPC_METHODS.workOpenPlan, Schema_exports.Struct({ planId: TrimmedNonEmptyString })),
24342
+ tagRequestBody(RPC_METHODS.workRemovePlan, Schema_exports.Struct({ planId: TrimmedNonEmptyString })),
24343
+ tagRequestBody(RPC_METHODS.workOpenWindows, Schema_exports.Struct({ jobId: TrimmedNonEmptyString })),
24344
+ tagRequestBody(RPC_METHODS.workOpenFolder, Schema_exports.Struct({
24345
+ profileName: TrimmedNonEmptyString,
24346
+ folderPath: TrimmedNonEmptyString
24347
+ })),
24348
+ tagRequestBody(
24349
+ RPC_METHODS.workSetPlanner,
24350
+ Schema_exports.Struct({ profileName: TrimmedNonEmptyString })
24351
+ ),
24352
+ tagRequestBody(
24353
+ RPC_METHODS.workUpdateProfilePolicy,
24354
+ Schema_exports.Struct({
24355
+ profileName: TrimmedNonEmptyString,
24356
+ patch: Schema_exports.Unknown
24357
+ })
24358
+ ),
24359
+ tagRequestBody(
24360
+ RPC_METHODS.workAuthorizeProject,
24361
+ Schema_exports.Struct({ permission: Schema_exports.Unknown })
24362
+ ),
24363
+ tagRequestBody(
24364
+ RPC_METHODS.workProjectPreview,
24365
+ Schema_exports.Struct({ repositoryPath: TrimmedNonEmptyString })
24366
+ ),
24367
+ tagRequestBody(
24368
+ RPC_METHODS.workDelegate,
24369
+ Schema_exports.Struct({ input: Schema_exports.Unknown })
24370
+ ),
24371
+ tagRequestBody(
24372
+ RPC_METHODS.workAction,
24373
+ Schema_exports.Struct({ input: Schema_exports.Unknown })
24374
+ ),
24375
+ tagRequestBody(
24376
+ RPC_METHODS.workDiffReview,
24377
+ Schema_exports.Struct({
24378
+ jobId: TrimmedNonEmptyString,
24379
+ offset: Schema_exports.optional(Schema_exports.Number),
24380
+ diffHash: Schema_exports.optional(Schema_exports.String)
24381
+ })
24382
+ ),
24383
+ tagRequestBody(
24384
+ RPC_METHODS.workHistoryList,
24385
+ Schema_exports.Struct({ input: Schema_exports.Unknown })
24386
+ ),
24387
+ tagRequestBody(
24388
+ RPC_METHODS.workHistoryOpen,
24389
+ Schema_exports.Struct({
24390
+ profileName: TrimmedNonEmptyString,
24391
+ threadId: TrimmedNonEmptyString
24392
+ })
24393
+ ),
24394
+ tagRequestBody(
24395
+ RPC_METHODS.workConfigGet,
24396
+ Schema_exports.Struct({
24397
+ profileName: Schema_exports.optional(Schema_exports.Union([Schema_exports.String, Schema_exports.Null]))
24398
+ })
24399
+ ),
24400
+ tagRequestBody(
24401
+ RPC_METHODS.workConfigSaveShared,
24402
+ Schema_exports.Struct({
24403
+ content: Schema_exports.String,
24404
+ expectedRevision: TrimmedNonEmptyString
24405
+ })
24406
+ ),
24407
+ tagRequestBody(
24408
+ RPC_METHODS.workConfigSaveOverride,
24409
+ Schema_exports.Struct({
24410
+ profileName: TrimmedNonEmptyString,
24411
+ content: Schema_exports.String,
24412
+ expectedRevision: Schema_exports.optional(
24413
+ Schema_exports.Union([Schema_exports.String, Schema_exports.Null])
24414
+ )
24415
+ })
24416
+ ),
24417
+ tagRequestBody(
24418
+ RPC_METHODS.workConfigResetOverride,
24419
+ Schema_exports.Struct({ profileName: TrimmedNonEmptyString })
24420
+ ),
24421
+ tagRequestBody(
24422
+ RPC_METHODS.workConfigReconcileExternal,
24423
+ Schema_exports.Struct({
24424
+ profileName: TrimmedNonEmptyString,
24425
+ expectedRevision: TrimmedNonEmptyString
24426
+ })
24427
+ )
24265
24428
  ]);
24266
24429
  var DesktopRpcRequest = Schema_exports.Struct({
24267
24430
  id: TrimmedNonEmptyString,
@@ -24319,6 +24482,10 @@ var RpcPushOfficialCodexStatusUpdated = makeRpcPushSchema(
24319
24482
  RPC_CHANNELS.officialCodexStatusUpdated,
24320
24483
  Schema_exports.Unknown
24321
24484
  );
24485
+ var RpcPushWorkUpdated = makeRpcPushSchema(
24486
+ RPC_CHANNELS.workUpdated,
24487
+ Schema_exports.Unknown
24488
+ );
24322
24489
  var RpcPushChannelSchema = Schema_exports.Literals([
24323
24490
  RPC_CHANNELS.runtimeProvidersUpdated,
24324
24491
  RPC_CHANNELS.profilesSwitched,
@@ -24328,7 +24495,8 @@ var RpcPushChannelSchema = Schema_exports.Literals([
24328
24495
  RPC_CHANNELS.autoRollDecision,
24329
24496
  RPC_CHANNELS.officialCodexActivationProgress,
24330
24497
  RPC_CHANNELS.officialCodexActivityUpdated,
24331
- RPC_CHANNELS.officialCodexStatusUpdated
24498
+ RPC_CHANNELS.officialCodexStatusUpdated,
24499
+ RPC_CHANNELS.workUpdated
24332
24500
  ]);
24333
24501
  var RpcPush = Schema_exports.Union([
24334
24502
  RpcPushRuntimeProvidersUpdated,
@@ -24339,7 +24507,8 @@ var RpcPush = Schema_exports.Union([
24339
24507
  RpcPushAutoRollDecision,
24340
24508
  RpcPushOfficialCodexActivationProgress,
24341
24509
  RpcPushOfficialCodexActivityUpdated,
24342
- RpcPushOfficialCodexStatusUpdated
24510
+ RpcPushOfficialCodexStatusUpdated,
24511
+ RpcPushWorkUpdated
24343
24512
  ]);
24344
24513
  var RpcPushEnvelopeBase = Schema_exports.Struct({
24345
24514
  type: Schema_exports.Literal("push"),
@@ -26916,7 +27085,7 @@ function createBridgeSnapshotExpression() {
26916
27085
  capabilities: {
26917
27086
  health: healthReady,
26918
27087
  snapshot: commandReady("snapshot"),
26919
- draft: commandReady("setDraft"),
27088
+ draft: false,
26920
27089
  qol: commandReady("applyQol"),
26921
27090
  power: commandReady("applyPower"),
26922
27091
  modelWhitelist: commandReady("applyPower"),
@@ -26943,114 +27112,6 @@ function createBridgeSnapshotExpression() {
26943
27112
  return snapshot;
26944
27113
  })()`;
26945
27114
  }
26946
- function createBridgeSetDraftPromptExpression(prompt) {
26947
- return `(() => {
26948
- const prompt = ${JSON.stringify(prompt)};
26949
- const visible = (element) => {
26950
- if (!element || !(element instanceof HTMLElement)) return false;
26951
- const style = window.getComputedStyle(element);
26952
- const rect = element.getBoundingClientRect();
26953
- return style.visibility !== "hidden" &&
26954
- style.display !== "none" &&
26955
- rect.width > 0 &&
26956
- rect.height > 0 &&
26957
- !element.hasAttribute("disabled") &&
26958
- element.getAttribute("aria-disabled") !== "true";
26959
- };
26960
- const dispatchInput = (element) => {
26961
- try {
26962
- element.dispatchEvent(new InputEvent("input", {
26963
- bubbles: true,
26964
- cancelable: true,
26965
- inputType: "insertText",
26966
- data: prompt
26967
- }));
26968
- } catch {
26969
- element.dispatchEvent(new Event("input", { bubbles: true }));
26970
- }
26971
- element.dispatchEvent(new Event("change", { bubbles: true }));
26972
- };
26973
- const setNativeValue = (element, value) => {
26974
- const proto = Object.getPrototypeOf(element);
26975
- const descriptor = proto ? Object.getOwnPropertyDescriptor(proto, "value") : null;
26976
- if (descriptor?.set) {
26977
- descriptor.set.call(element, value);
26978
- } else {
26979
- element.value = value;
26980
- }
26981
- };
26982
- const selectors = [
26983
- "textarea",
26984
- "input[type='text']",
26985
- "[contenteditable='true']",
26986
- "[role='textbox']"
26987
- ];
26988
- const candidates = selectors.flatMap((selector) =>
26989
- Array.from(document.querySelectorAll(selector))
26990
- ).filter(visible);
26991
- const emptyPreferred = candidates.find((element) => {
26992
- const value = element instanceof HTMLTextAreaElement || element instanceof HTMLInputElement
26993
- ? element.value
26994
- : element.textContent;
26995
- return !String(value ?? "").trim();
26996
- });
26997
- const target = emptyPreferred ?? candidates[0] ?? null;
26998
- if (!target) {
26999
- return {
27000
- status: "not-found",
27001
- reason: "composer-not-found",
27002
- route: window.location.pathname + window.location.search + window.location.hash
27003
- };
27004
- }
27005
- target.focus();
27006
- if (target instanceof HTMLTextAreaElement || target instanceof HTMLInputElement) {
27007
- setNativeValue(target, prompt);
27008
- dispatchInput(target);
27009
- return {
27010
- status: "inserted",
27011
- reason: null,
27012
- route: window.location.pathname + window.location.search + window.location.hash
27013
- };
27014
- }
27015
- const selection = window.getSelection();
27016
- if (selection) {
27017
- const range = document.createRange();
27018
- range.selectNodeContents(target);
27019
- selection.removeAllRanges();
27020
- selection.addRange(range);
27021
- }
27022
- const inserted = document.execCommand?.("insertText", false, prompt);
27023
- if (!inserted) {
27024
- target.textContent = prompt;
27025
- }
27026
- dispatchInput(target);
27027
- return {
27028
- status: "inserted",
27029
- reason: null,
27030
- route: window.location.pathname + window.location.search + window.location.hash
27031
- };
27032
- })()`;
27033
- }
27034
- function createBridgeReadComposerExpression() {
27035
- return `(() => {
27036
- const visible = (element) => {
27037
- if (!element || !(element instanceof HTMLElement)) return false;
27038
- const style = window.getComputedStyle(element);
27039
- const rect = element.getBoundingClientRect();
27040
- return style.visibility !== "hidden" && style.display !== "none" && rect.width > 0 && rect.height > 0;
27041
- };
27042
- const valueOf = (element) =>
27043
- element instanceof HTMLTextAreaElement || element instanceof HTMLInputElement
27044
- ? element.value
27045
- : element.textContent;
27046
- const candidates = ["textarea", "input[type='text']", "[contenteditable='true']", "[role='textbox']"]
27047
- .flatMap((selector) => Array.from(document.querySelectorAll(selector)))
27048
- .filter(visible);
27049
- const filled = candidates.find((element) => String(valueOf(element) ?? "").trim());
27050
- const target = filled ?? candidates[0] ?? null;
27051
- return { text: target ? String(valueOf(target) ?? "") : "" };
27052
- })()`;
27053
- }
27054
27115
  function buildInCodexStatusOverlayCssRules() {
27055
27116
  const id2 = "#codexuse-profile-menu-section";
27056
27117
  return [
@@ -27078,8 +27139,6 @@ function buildInCodexStatusOverlayCssRules() {
27078
27139
  `${id2} .codexuse-meter[data-tone="critical"] > i{background:var(--cu-crit);}`,
27079
27140
  // Hangs under the account it acts on. It used to be a full-width bold blue
27080
27141
  // row between two accounts, louder than either and owned by neither.
27081
- `${id2} button.codexuse-handoff-button{width:calc(100% - 17px);margin:1px 0 2px 17px;overflow:hidden;padding:3px 8px;color:var(--cu-muted);font-size:11px;text-overflow:ellipsis;white-space:nowrap;}`,
27082
- `${id2} button.codexuse-handoff-button:hover,${id2} button.codexuse-handoff-button:focus-visible{color:var(--cu-accent);}`,
27083
27142
  `${id2} .codexuse-decision{margin:3px 4px 5px;padding:8px;border:1px solid color-mix(in srgb,var(--cu-low) 38%,transparent);border-radius:8px;background:color-mix(in srgb,var(--cu-low) 8%,transparent);}`,
27084
27143
  `${id2} .codexuse-decision-title{font-size:12px;font-weight:600;line-height:16px;}`,
27085
27144
  `${id2} .codexuse-decision-detail{margin-top:2px;color:var(--cu-muted);font-size:11px;line-height:15px;}`,
@@ -27111,16 +27170,12 @@ function createBridgeApplyQolExpression(settings) {
27111
27170
  const scrollRestoreEnabled = ${JSON.stringify(settings.scrollRestoreEnabled === true)};
27112
27171
  const conversationTimelineEnabled = ${JSON.stringify(settings.conversationTimelineEnabled === true)};
27113
27172
  const inCodexStatusEnabled = ${JSON.stringify(settings.inCodexStatusEnabled === true)};
27114
- const handoffEnabled = ${JSON.stringify(settings.handoffChipEnabled !== false)};
27115
27173
  const accountActionMode = ${JSON.stringify(
27116
27174
  settings.overlayAccountActionMode === "shared-switch" ? "shared-switch" : "isolated-open"
27117
27175
  )};
27118
27176
  let currentAutoRollDecision = ${JSON.stringify(settings.autoRollDecision ?? null)};
27119
27177
  let currentOverlayAutoRollEnabled = ${JSON.stringify(
27120
27178
  typeof settings.overlayAutoRollEnabled === "boolean" ? settings.overlayAutoRollEnabled : null
27121
- )};
27122
- let currentOverlayRunningThreadHandoffEnabled = ${JSON.stringify(
27123
- typeof settings.overlayRunningThreadHandoffEnabled === "boolean" ? settings.overlayRunningThreadHandoffEnabled : null
27124
27179
  )};
27125
27180
  let currentWideViewEnabled = wideViewEnabled;
27126
27181
  let currentScrollRestoreEnabled = scrollRestoreEnabled;
@@ -27150,8 +27205,8 @@ function createBridgeApplyQolExpression(settings) {
27150
27205
  const profileMenuId = "codexuse-profile-menu-section";
27151
27206
  const legacySettingsId = "codexuse-settings-section";
27152
27207
  const legacyStatusId = "codexuse-status-pill";
27153
- const legacyHandoffId = "codexuse-handoff-chip";
27154
- const legacyHandoffPickerId = "codexuse-handoff-picker";
27208
+ const legacyContinuationId = "codexuse-handoff-chip";
27209
+ const legacyContinuationPickerId = "codexuse-handoff-picker";
27155
27210
  // Codex desktop is a SPA whose URL never changes per thread; key scroll
27156
27211
  // state by the open conversation id so each chat restores independently.
27157
27212
  const route = () => {
@@ -27531,7 +27586,6 @@ function createBridgeApplyQolExpression(settings) {
27531
27586
  try {
27532
27587
  const actionMessage =
27533
27588
  action === "switch" ? "Switching\u2026"
27534
- : action === "continue" ? "Moving thread\u2026"
27535
27589
  : action === "auto-roll-accept" ? "Switching\u2026"
27536
27590
  : action === "auto-roll-cancel" ? "Staying here"
27537
27591
  : action === "setting" ? "Saving\u2026"
@@ -27592,9 +27646,6 @@ function createBridgeApplyQolExpression(settings) {
27592
27646
  if (typeof result.overlayAutoRollEnabled === "boolean") {
27593
27647
  currentOverlayAutoRollEnabled = result.overlayAutoRollEnabled;
27594
27648
  }
27595
- if (typeof result.overlayRunningThreadHandoffEnabled === "boolean") {
27596
- currentOverlayRunningThreadHandoffEnabled = result.overlayRunningThreadHandoffEnabled;
27597
- }
27598
27649
  if (result.providerStatus && typeof result.providerStatus.publishedModelCount === "number") {
27599
27650
  customModelCount = Math.max(0, Math.floor(result.providerStatus.publishedModelCount));
27600
27651
  }
@@ -27614,8 +27665,8 @@ function createBridgeApplyQolExpression(settings) {
27614
27665
  };
27615
27666
  const renderProfileMenu = () => {
27616
27667
  document.getElementById(legacyStatusId)?.remove();
27617
- document.getElementById(legacyHandoffId)?.remove();
27618
- document.getElementById(legacyHandoffPickerId)?.remove();
27668
+ document.getElementById(legacyContinuationId)?.remove();
27669
+ document.getElementById(legacyContinuationPickerId)?.remove();
27619
27670
  document.getElementById(legacySettingsId)?.remove();
27620
27671
  const previous = document.getElementById(profileMenuId);
27621
27672
  const threadId = activeThreadId();
@@ -27633,12 +27684,9 @@ function createBridgeApplyQolExpression(settings) {
27633
27684
  const renderKey = JSON.stringify({
27634
27685
  targets: allTargets,
27635
27686
  canonicalSyncLine: currentCanonicalSyncLine,
27636
- handoffEnabled,
27637
- hasThread: Boolean(threadId),
27638
27687
  customModelCount,
27639
27688
  currentAutoRollDecision,
27640
27689
  currentOverlayAutoRollEnabled,
27641
- currentOverlayRunningThreadHandoffEnabled,
27642
27690
  currentWideViewEnabled,
27643
27691
  currentScrollRestoreEnabled,
27644
27692
  currentConversationTimelineEnabled,
@@ -27822,23 +27870,6 @@ function createBridgeApplyQolExpression(settings) {
27822
27870
  row.setAttribute("aria-disabled", "true");
27823
27871
  }
27824
27872
  section.appendChild(row);
27825
- if (canSwitch && handoffEnabled && threadId) {
27826
- const handoffButton = document.createElement("button");
27827
- handoffButton.type = "button";
27828
- handoffButton.className = "codexuse-handoff-button";
27829
- handoffButton.setAttribute("role", "menuitem");
27830
- // Names its own target, so a row sandwiched between two profiles can
27831
- // never be read as belonging to the wrong one.
27832
- handoffButton.textContent = "\u21B3 Continue this thread in " + label.textContent;
27833
- handoffButton.setAttribute("aria-label", "Continue this thread in " + label.textContent);
27834
- handoffButton.addEventListener("click", (event) => {
27835
- event.preventDefault();
27836
- event.stopPropagation();
27837
- setMenuButtonsDisabled(true);
27838
- requestAction("continue", target);
27839
- }, true);
27840
- section.appendChild(handoffButton);
27841
- }
27842
27873
  });
27843
27874
  const appendSettingRow = (item) => {
27844
27875
  const row = document.createElement("button");
@@ -27887,14 +27918,6 @@ function createBridgeApplyQolExpression(settings) {
27887
27918
  enabled: currentOverlayAutoRollEnabled,
27888
27919
  }]
27889
27920
  : []),
27890
- ...(typeof currentOverlayRunningThreadHandoffEnabled === "boolean"
27891
- ? [{
27892
- key: "runningThreadHandoff",
27893
- label: "Continue running threads",
27894
- detail: "Move active work after a switch",
27895
- enabled: currentOverlayRunningThreadHandoffEnabled,
27896
- }]
27897
- : []),
27898
27921
  {
27899
27922
  key: "wideView",
27900
27923
  label: "Wide conversations",
@@ -27963,11 +27986,11 @@ function createBridgeApplyQolExpression(settings) {
27963
27986
  return element?.id === profileMenuId ||
27964
27987
  element?.id === legacySettingsId ||
27965
27988
  element?.id === legacyStatusId ||
27966
- element?.id === legacyHandoffId ||
27967
- element?.id === legacyHandoffPickerId ||
27989
+ element?.id === legacyContinuationId ||
27990
+ element?.id === legacyContinuationPickerId ||
27968
27991
  element?.classList?.contains(timelineClass) ||
27969
27992
  Boolean(element?.closest?.(
27970
- "." + timelineClass + ",#" + profileMenuId + ",#" + legacySettingsId + ",#" + legacyStatusId + ",#" + legacyHandoffId + ",#" + legacyHandoffPickerId
27993
+ "." + timelineClass + ",#" + profileMenuId + ",#" + legacySettingsId + ",#" + legacyStatusId + ",#" + legacyContinuationId + ",#" + legacyContinuationPickerId
27971
27994
  ));
27972
27995
  };
27973
27996
  const isVisualOnlyMutation = (mutation) => {
@@ -27989,8 +28012,8 @@ function createBridgeApplyQolExpression(settings) {
27989
28012
  document.getElementById(profileMenuId)?.remove();
27990
28013
  document.getElementById(legacySettingsId)?.remove();
27991
28014
  document.getElementById(legacyStatusId)?.remove();
27992
- document.getElementById(legacyHandoffId)?.remove();
27993
- document.getElementById(legacyHandoffPickerId)?.remove();
28015
+ document.getElementById(legacyContinuationId)?.remove();
28016
+ document.getElementById(legacyContinuationPickerId)?.remove();
27994
28017
  };
27995
28018
  } else {
27996
28019
  document.querySelectorAll("." + timelineClass).forEach((node) => node.remove());
@@ -27998,8 +28021,8 @@ function createBridgeApplyQolExpression(settings) {
27998
28021
  document.getElementById(profileMenuId)?.remove();
27999
28022
  document.getElementById(legacySettingsId)?.remove();
28000
28023
  document.getElementById(legacyStatusId)?.remove();
28001
- document.getElementById(legacyHandoffId)?.remove();
28002
- document.getElementById(legacyHandoffPickerId)?.remove();
28024
+ document.getElementById(legacyContinuationId)?.remove();
28025
+ document.getElementById(legacyContinuationPickerId)?.remove();
28003
28026
  }
28004
28027
 
28005
28028
  state.wideViewEnabled = wideViewEnabled;
@@ -29222,22 +29245,6 @@ function normalizeBridgeSnapshot(value3) {
29222
29245
  relayStatus: normalizeRelayStatus(record2.relayStatus)
29223
29246
  };
29224
29247
  }
29225
- function normalizeDraftPromptInsertionResult(value3) {
29226
- if (!value3 || typeof value3 !== "object") {
29227
- return {
29228
- status: "failed",
29229
- reason: "invalid-bridge-result",
29230
- route: null
29231
- };
29232
- }
29233
- const record2 = value3;
29234
- const status = record2.status === "inserted" || record2.status === "not-found" || record2.status === "unavailable" || record2.status === "failed" ? record2.status : "failed";
29235
- return {
29236
- status,
29237
- reason: sanitizeUserFacingError(record2.reason),
29238
- route: typeof record2.route === "string" ? record2.route : null
29239
- };
29240
- }
29241
29248
  function normalizeQolScriptResult(value3, settings) {
29242
29249
  if (!value3 || typeof value3 !== "object") {
29243
29250
  return {
@@ -29341,18 +29348,16 @@ function normalizeOfficialCodexQolSettings2(value3) {
29341
29348
  scrollRestoreEnabled: value3.scrollRestoreEnabled === true,
29342
29349
  conversationTimelineEnabled: value3.conversationTimelineEnabled === true,
29343
29350
  inCodexStatusEnabled: value3.inCodexStatusEnabled !== false,
29344
- handoffChipEnabled: value3.handoffChipEnabled !== false,
29345
29351
  actionTargets,
29346
29352
  providerStatus,
29347
29353
  canonicalSyncLine: typeof value3.canonicalSyncLine === "string" && value3.canonicalSyncLine.trim() ? value3.canonicalSyncLine.trim().slice(0, 40) : null,
29348
29354
  autoRollDecision: normalizeOverlayAutoRollDecision(value3.autoRollDecision),
29349
29355
  overlayAutoRollEnabled: typeof value3.overlayAutoRollEnabled === "boolean" ? value3.overlayAutoRollEnabled : null,
29350
- overlayRunningThreadHandoffEnabled: typeof value3.overlayRunningThreadHandoffEnabled === "boolean" ? value3.overlayRunningThreadHandoffEnabled : null,
29351
29356
  overlayAccountActionMode: value3.overlayAccountActionMode === "shared-switch" || value3.overlayAccountActionMode === "isolated-open" ? value3.overlayAccountActionMode : null
29352
29357
  };
29353
29358
  }
29354
29359
  function hasActiveQolSettings(settings) {
29355
- return settings.wideViewEnabled || settings.scrollRestoreEnabled || settings.conversationTimelineEnabled || settings.inCodexStatusEnabled || settings.handoffChipEnabled === false;
29360
+ return settings.wideViewEnabled || settings.scrollRestoreEnabled || settings.conversationTimelineEnabled || settings.inCodexStatusEnabled;
29356
29361
  }
29357
29362
  function hasActivePowerSettings(settings) {
29358
29363
  return settings.relayMode !== "off" || settings.modelWhitelistUnlockEnabled || settings.pluginMarketplaceUnlockEnabled || settings.forcePluginInstallEnabled;
@@ -29468,7 +29473,6 @@ function createBridgeInstallExpression() {
29468
29473
  state.commands = {
29469
29474
  health: true,
29470
29475
  snapshot: true,
29471
- setDraft: true,
29472
29476
  sendMessage: true,
29473
29477
  applyQol: true,
29474
29478
  applyPower: true
@@ -30528,11 +30532,11 @@ async function startOfficialCodexBridgeActionListenerOnce(args2) {
30528
30532
  if (!id2 || !rememberBridgeActionId(id2)) {
30529
30533
  return;
30530
30534
  }
30531
- const action = payload.action === "continue" || payload.action === "switch" || payload.action === "auto-roll" || payload.action === "auto-roll-accept" || payload.action === "auto-roll-cancel" || payload.action === "restart" || payload.action === "setting" ? payload.action : null;
30535
+ const action = payload.action === "switch" || payload.action === "auto-roll" || payload.action === "auto-roll-accept" || payload.action === "auto-roll-cancel" || payload.action === "restart" || payload.action === "setting" ? payload.action : null;
30532
30536
  if (!action) {
30533
30537
  return;
30534
30538
  }
30535
- const settingKey = payload.settingKey === "autoRoll" || payload.settingKey === "runningThreadHandoff" || payload.settingKey === "wideView" || payload.settingKey === "scrollRestore" || payload.settingKey === "conversationTimeline" || payload.settingKey === "handoffChip" ? payload.settingKey : null;
30539
+ const settingKey = payload.settingKey === "autoRoll" || payload.settingKey === "wideView" || payload.settingKey === "scrollRestore" || payload.settingKey === "conversationTimeline" ? payload.settingKey : null;
30536
30540
  const settingValue = typeof payload.settingValue === "boolean" ? payload.settingValue : null;
30537
30541
  if (action === "setting" && (!settingKey || settingValue === null)) {
30538
30542
  return;
@@ -31023,6 +31027,25 @@ function enqueueProfileAction(profileName, work) {
31023
31027
  });
31024
31028
  return run2;
31025
31029
  }
31030
+ var LAUNCH_LOCK_NAME = ".codexuse-launch.lock";
31031
+ var LAUNCH_LOCK_WAIT_MS = 6e4;
31032
+ async function withProfileLaunchFileLock(profileHome, work, options) {
31033
+ const accountKey = options.profileKey?.trim();
31034
+ const lockPath = accountKey ? import_node_path12.default.join(resolveProfileCodexHomesRoot(), ".launch-locks", (0, import_node_crypto11.createHash)("sha256").update(accountKey).digest("hex")) : import_node_path12.default.join(profileHome, LAUNCH_LOCK_NAME);
31035
+ const deadline = Date.now() + (options.waitMs ?? LAUNCH_LOCK_WAIT_MS);
31036
+ for (; ; ) {
31037
+ const release = await acquireCrossProcessFileLock(lockPath, { busyTimeoutMs: 0 });
31038
+ if (release) {
31039
+ try {
31040
+ return await work();
31041
+ } finally {
31042
+ await release();
31043
+ }
31044
+ }
31045
+ if (Date.now() >= deadline) return options.onBusy();
31046
+ await sleep3(250);
31047
+ }
31048
+ }
31026
31049
  async function readProcessRows() {
31027
31050
  const result2 = await runCommand2(
31028
31051
  "/bin/ps",
@@ -31783,128 +31806,6 @@ async function verifyCurrentManagedProfileProof(instance, runtime, candidate, op
31783
31806
  });
31784
31807
  return migrated;
31785
31808
  }
31786
- async function resolveOfficialCodexBridgeTarget(args2) {
31787
- const existing = args2.state.officialCodex.instancesByProfileName[args2.profileName] ?? null;
31788
- if (existing) {
31789
- const runtime = await resolveInstanceRuntimeState({
31790
- instance: existing,
31791
- candidate: args2.candidate,
31792
- rows: args2.rows
31793
- });
31794
- const verified = await verifyCurrentManagedProfileProof(
31795
- existing,
31796
- runtime,
31797
- args2.candidate,
31798
- { requireCdpBrowser: true }
31799
- );
31800
- if (verified) {
31801
- return { instance: verified, runtime, managed: true };
31802
- }
31803
- }
31804
- const runningManagedPids = /* @__PURE__ */ new Set();
31805
- for (const instance of Object.values(
31806
- args2.state.officialCodex.instancesByProfileName
31807
- )) {
31808
- if (instance.profileName === args2.profileName) {
31809
- continue;
31810
- }
31811
- const runtime = await resolveInstanceRuntimeState({
31812
- instance,
31813
- candidate: args2.candidate,
31814
- rows: args2.rows
31815
- });
31816
- const verified = runtime.running ? await verifyCurrentManagedProfileProof(
31817
- instance,
31818
- runtime,
31819
- args2.candidate,
31820
- { requireCdpBrowser: true }
31821
- ) : null;
31822
- if (verified?.pid) {
31823
- runningManagedPids.add(verified.pid);
31824
- }
31825
- }
31826
- const candidates = [];
31827
- for (const row of args2.rows) {
31828
- if (!isMainProcessRow(row, args2.candidate) || runningManagedPids.has(row.pid)) {
31829
- continue;
31830
- }
31831
- const cdpPort = parseRemoteDebuggingPort(row.args);
31832
- if (!cdpPort) {
31833
- continue;
31834
- }
31835
- const appServerPid = findAppServerPid(args2.rows, row.pid);
31836
- candidates.push({
31837
- row,
31838
- cdpPort,
31839
- appServerPid,
31840
- hint: await describeUnmanagedProfileHint(appServerPid)
31841
- });
31842
- }
31843
- const target = candidates.find(
31844
- (entry) => entry.hint.profileName === args2.profileName && entry.hint.profileMatchSource === "profile-home"
31845
- ) ?? null;
31846
- if (!target) {
31847
- return null;
31848
- }
31849
- if (!target.appServerPid || !target.row.startedAt || !await attestOfficialCodexProcessEpoch({
31850
- candidate: args2.candidate,
31851
- pid: target.row.pid,
31852
- appServerPid: target.appServerPid,
31853
- startedAt: target.row.startedAt,
31854
- cdpPort: target.cdpPort
31855
- })) {
31856
- return null;
31857
- }
31858
- const now2 = Date.now();
31859
- const bridge = bridgeStateUnattached(target.cdpPort, now2);
31860
- const observed = {
31861
- profileName: args2.profileName,
31862
- profileKey: existing?.profileKey ?? null,
31863
- profileMatchSource: target.hint.profileMatchSource,
31864
- processProofVersion: MANAGED_PROCESS_PROOF_VERSION,
31865
- profileHome: existing?.profileHome ?? null,
31866
- appPath: args2.candidate.appPath,
31867
- bundleId: args2.candidate.bundleId,
31868
- pid: target.row.pid,
31869
- appServerPid: target.appServerPid,
31870
- launchedAt: target.row.startedAt,
31871
- lastVerifiedAt: now2,
31872
- lastStatus: "observed-unmanaged",
31873
- lastError: null,
31874
- ...bridge,
31875
- bridgeStatus: existing?.bridgeStatus ?? bridge.bridgeStatus,
31876
- bridgeLastCheckedAt: existing?.bridgeLastCheckedAt ?? bridge.bridgeLastCheckedAt,
31877
- bridgeError: existing?.bridgeError ?? bridge.bridgeError,
31878
- bridgeVersion: existing?.bridgeVersion ?? bridge.bridgeVersion,
31879
- bridgeRoute: existing?.bridgeRoute ?? bridge.bridgeRoute,
31880
- bridgeDevToolsUrl: existing?.bridgeDevToolsUrl ?? bridge.bridgeDevToolsUrl,
31881
- bridgeCapabilities: existing?.bridgeCapabilities ?? bridge.bridgeCapabilities,
31882
- bridgeActiveThreadId: existing?.bridgeActiveThreadId ?? bridge.bridgeActiveThreadId,
31883
- bridgeActiveThreadTitle: existing?.bridgeActiveThreadTitle ?? bridge.bridgeActiveThreadTitle,
31884
- bridgeActiveThreadUpdatedAt: existing?.bridgeActiveThreadUpdatedAt ?? bridge.bridgeActiveThreadUpdatedAt,
31885
- bridgeComposerText: existing?.bridgeComposerText ?? bridge.bridgeComposerText,
31886
- bridgeWorkspacePath: existing?.bridgeWorkspacePath ?? bridge.bridgeWorkspacePath,
31887
- bridgeModel: existing?.bridgeModel ?? bridge.bridgeModel,
31888
- bridgeActivityState: existing?.bridgeActivityState ?? bridge.bridgeActivityState,
31889
- bridgeQol: existing?.bridgeQol ?? bridge.bridgeQol,
31890
- bridgePower: existing?.bridgePower ?? bridge.bridgePower,
31891
- bridgeRelayStatus: existing?.bridgeRelayStatus ?? bridge.bridgeRelayStatus,
31892
- desiredQolSettings: existing?.desiredQolSettings ?? null,
31893
- desiredPowerSettings: existing?.desiredPowerSettings ?? null
31894
- };
31895
- if (!existing || existing.pid !== observed.pid || existing.appServerPid !== observed.appServerPid || existing.cdpPort !== observed.cdpPort || existing.lastStatus !== observed.lastStatus) {
31896
- await patchManagedInstance(observed);
31897
- }
31898
- return {
31899
- managed: false,
31900
- runtime: {
31901
- running: true,
31902
- appServerPid: target.appServerPid,
31903
- startedAt: target.row.startedAt
31904
- },
31905
- instance: observed
31906
- };
31907
- }
31908
31809
  var devToolsActivePortPaths = (appUserDataDir) => {
31909
31810
  const roots = appUserDataDir ? [appUserDataDir] : [
31910
31811
  import_node_path12.default.join((0, import_node_os4.homedir)(), "Library", "Application Support", "OpenAI", "Codex"),
@@ -31991,6 +31892,10 @@ async function openCodexWithProfileHome(candidate, profileHome, profileName, pre
31991
31892
  `CODEX_SQLITE_HOME=${sqliteHome}`,
31992
31893
  "--env",
31993
31894
  `CODEX_TELEMETRY_LABEL=${telemetryLabel}`,
31895
+ ...Object.entries(options.environment ?? {}).flatMap(([key, value3]) => [
31896
+ "--env",
31897
+ `${key}=${value3}`
31898
+ ]),
31994
31899
  "--args",
31995
31900
  ...appUserDataDir ? [`--user-data-dir=${appUserDataDir}`] : [],
31996
31901
  "--remote-debugging-port=0",
@@ -32277,7 +32182,7 @@ function resolveOfficialCodexLaunchConfiguration(profileHome, options = {}) {
32277
32182
  };
32278
32183
  }
32279
32184
  function resolveOfficialCodexThreadSqliteHome(profileHome) {
32280
- return profileHome === SHARED_CODEX_HOME ? resolveCodexSqliteHomeDir(profileHome) : profileHome;
32185
+ return profileHome;
32281
32186
  }
32282
32187
  function sharedCodexLaunchOptions(useDefaultUserData, profileIdentity) {
32283
32188
  const userDataDir = !useDefaultUserData && profileIdentity ? import_node_path12.default.join(
@@ -32442,39 +32347,6 @@ async function reconcileSharedManagedWindowAfterLaunch(args2) {
32442
32347
  }
32443
32348
  return null;
32444
32349
  }
32445
- async function readSharedComposerDraft(debuggerUrl) {
32446
- try {
32447
- const value3 = await evaluateCdpExpression(
32448
- debuggerUrl,
32449
- createBridgeReadComposerExpression()
32450
- );
32451
- const text = value3 && typeof value3 === "object" && "text" in value3 ? value3.text : null;
32452
- return typeof text === "string" ? text : "";
32453
- } catch {
32454
- return "";
32455
- }
32456
- }
32457
- async function restoreSharedComposerDraft(debuggerUrl, prompt) {
32458
- if (!prompt.trim()) {
32459
- return;
32460
- }
32461
- for (let attempt = 0; attempt < 8; attempt += 1) {
32462
- await new Promise((resolve2) => setTimeout(resolve2, 400));
32463
- try {
32464
- const result2 = await evaluateOfficialCodexBridgeCommand(
32465
- debuggerUrl,
32466
- "setDraft",
32467
- createBridgeSetDraftPromptExpression(prompt),
32468
- false
32469
- );
32470
- const status = result2 && typeof result2 === "object" && "status" in result2 ? result2.status : null;
32471
- if (status === "inserted") {
32472
- return;
32473
- }
32474
- } catch {
32475
- }
32476
- }
32477
- }
32478
32350
  function isSharedHomeMainProcessRow(row, candidate) {
32479
32351
  const managedRoots = [
32480
32352
  resolveProfileCodexHomesRoot(),
@@ -34437,15 +34309,11 @@ async function applySharedLaunchFollowUp(args2) {
34437
34309
  ].filter((key) => renderer[key] !== true).join(",")}`
34438
34310
  };
34439
34311
  }
34440
- if (args2.carryDraft && args2.carriedDraft.trim()) {
34441
- await restoreSharedComposerDraft(debuggerUrl, args2.carriedDraft);
34442
- }
34443
34312
  const [finalAccount, snapshot2] = await Promise.all([
34444
34313
  readTargetAccount(),
34445
34314
  readSharedBridgeSnapshot(debuggerUrl)
34446
34315
  ]);
34447
- const expectedDraft = args2.carryDraft && args2.carriedDraft.trim() ? args2.carriedDraft : "";
34448
- if (!finalAccount || !officialCodexExpectedAccountMatches(args2.expectedAccount, finalAccount) || !snapshot2 || snapshot2.activeThreadId !== null || (snapshot2.composerText ?? "") !== expectedDraft) {
34316
+ if (!finalAccount || !officialCodexExpectedAccountMatches(args2.expectedAccount, finalAccount) || !snapshot2 || snapshot2.activeThreadId !== null || (snapshot2.composerText ?? "") !== "") {
34449
34317
  return { verified: false, reason: "renderer-postcondition-unverified" };
34450
34318
  }
34451
34319
  return { verified: true, reason: null };
@@ -34488,9 +34356,8 @@ function liveRendererEvidenceVerified(args2) {
34488
34356
  }
34489
34357
  const evidence = args2.value && typeof args2.value === "object" ? args2.value : {};
34490
34358
  const sourceThreadEvicted = evidence.sourceThreadEvicted === true && evidence.activeThreadId === null && args2.snapshot.activeThreadId === null && (!args2.sourceThreadId || args2.snapshot.activeThreadId !== args2.sourceThreadId);
34491
- const composerSafe = args2.carryDraft ? !args2.sourceDraft || args2.snapshot.composerText !== args2.sourceDraft : !args2.snapshot.composerText;
34492
34359
  return Boolean(
34493
- evidence.status === "observed" && evidence.displayedAccountMatched === true && evidence.workspaceMatched === true && evidence.threadSurfaceReady === true && evidence.rateSurfaceReady === true && evidence.composerReady === true && sourceThreadEvicted && composerSafe
34360
+ evidence.status === "observed" && evidence.displayedAccountMatched === true && evidence.workspaceMatched === true && evidence.threadSurfaceReady === true && evidence.rateSurfaceReady === true && evidence.composerReady === true && sourceThreadEvicted && !args2.snapshot.composerText
34494
34361
  );
34495
34362
  }
34496
34363
  async function attemptOfficialCodexManagedLiveLogin(args2) {
@@ -34594,7 +34461,7 @@ async function attemptOfficialCodexManagedLiveLogin(args2) {
34594
34461
  sourceAccountThreadIds: sourceSurface.accountThreadIds,
34595
34462
  sourceRateResponseSignature: sourceSurface.accountRateSignature,
34596
34463
  sourceRateSurfaceSignature: sourceSurface.rateSignature,
34597
- clearComposer: args2.options.carryDraft !== true
34464
+ clearComposer: true
34598
34465
  }),
34599
34466
  false
34600
34467
  );
@@ -34603,9 +34470,7 @@ async function attemptOfficialCodexManagedLiveLogin(args2) {
34603
34470
  verified: liveRendererEvidenceVerified({
34604
34471
  value: value3,
34605
34472
  snapshot: snapshot2,
34606
- sourceThreadId: sourceSnapshot.activeThreadId,
34607
- sourceDraft: args2.sourceDraft,
34608
- carryDraft: args2.options.carryDraft === true
34473
+ sourceThreadId: sourceSnapshot.activeThreadId
34609
34474
  }),
34610
34475
  snapshot: snapshot2
34611
34476
  };
@@ -34638,13 +34503,6 @@ async function attemptOfficialCodexManagedLiveLogin(args2) {
34638
34503
  })) {
34639
34504
  return null;
34640
34505
  }
34641
- if (args2.options.carryDraft && args2.sourceDraft.trim()) {
34642
- await restoreSharedComposerDraft(args2.debuggerUrl, args2.sourceDraft);
34643
- const restoredSnapshot = await readSharedBridgeSnapshot(args2.debuggerUrl);
34644
- if (restoredSnapshot?.composerText !== args2.sourceDraft) {
34645
- return null;
34646
- }
34647
- }
34648
34506
  const bridge = await refreshAdoptedSharedWindow(profileName);
34649
34507
  if (bridge?.bridgeStatus !== "healthy") {
34650
34508
  return null;
@@ -34717,6 +34575,22 @@ async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTra
34717
34575
  };
34718
34576
  }
34719
34577
  let rows = await readProcessRows();
34578
+ const instances = (await updateAppState((current) => current, {
34579
+ mode: "replace",
34580
+ cloneCurrent: false
34581
+ })).officialCodex.instancesByProfileName;
34582
+ for (const instance of Object.values(instances)) {
34583
+ if (instance.profileName !== options.profileName && (!options.profileKey || instance.profileKey !== options.profileKey)) continue;
34584
+ const row = rows.find((entry) => entry.pid === instance.pid);
34585
+ if (!row || isSharedHomeMainProcessRow(row, candidate)) continue;
34586
+ if ((await resolveInstanceRuntimeState({ instance, candidate, rows })).running) {
34587
+ return {
34588
+ status: "failed",
34589
+ reason: `This account already has an isolated Codex window under profile '${instance.profileName}'. Open that window instead.`,
34590
+ pid: instance.pid
34591
+ };
34592
+ }
34593
+ }
34720
34594
  await hydrateSharedHomeCdpWindow(rows, candidate);
34721
34595
  if (expectedWindowPreflight && !sharedWindowTopologyMatches(
34722
34596
  expectedWindowPreflight,
@@ -34758,8 +34632,6 @@ async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTra
34758
34632
  pid: null
34759
34633
  };
34760
34634
  }
34761
- let carriedDraft = "";
34762
- const needsBridgeAutomation = options.carryDraft === true;
34763
34635
  if (driveTarget) {
34764
34636
  const managedTarget = driveTarget;
34765
34637
  const mainRow = rows.find((row) => row.pid === managedTarget.pid) ?? null;
@@ -34876,11 +34748,6 @@ async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTra
34876
34748
  } catch {
34877
34749
  }
34878
34750
  }
34879
- if (liveAutomationEligible && options.carryDraft && target?.webSocketDebuggerUrl) {
34880
- carriedDraft = await readSharedComposerDraft(
34881
- target.webSocketDebuggerUrl
34882
- );
34883
- }
34884
34751
  if (liveAutomationEligible && target?.webSocketDebuggerUrl && options.liveLoginCredentials) {
34885
34752
  const live = await attemptOfficialCodexManagedLiveLogin({
34886
34753
  candidate,
@@ -34889,7 +34756,6 @@ async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTra
34889
34756
  startedAt: mainRow.startedAt,
34890
34757
  debuggerUrl: target.webSocketDebuggerUrl,
34891
34758
  sourceSnapshot: snapshot2,
34892
- sourceDraft: carriedDraft,
34893
34759
  options
34894
34760
  });
34895
34761
  if (live) {
@@ -34970,7 +34836,7 @@ async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTra
34970
34836
  if (!driveTarget && plainSharedRows.length > 0 && options.forceAdopt !== true) {
34971
34837
  return {
34972
34838
  status: "skipped",
34973
- reason: options.accountChanged === true || needsBridgeAutomation ? "plain-window-requires-take-control" : "same-account-plain-window",
34839
+ reason: options.accountChanged === true ? "plain-window-requires-take-control" : "same-account-plain-window",
34974
34840
  pid: plainSharedRows[0]?.pid ?? null,
34975
34841
  closedPreviousWindow,
34976
34842
  suppressPlainReopen: closedPreviousWindow
@@ -35403,8 +35269,6 @@ async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTra
35403
35269
  }
35404
35270
  const followUp = await applySharedLaunchFollowUp({
35405
35271
  cdpPort: finalCdpPort,
35406
- carriedDraft,
35407
- carryDraft: options.carryDraft === true,
35408
35272
  expectedAccount: options.expectedAccount ?? null,
35409
35273
  allowOnboardingOverride: true
35410
35274
  });
@@ -35670,8 +35534,6 @@ async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTra
35670
35534
  }
35671
35535
  const followUp = await applySharedLaunchFollowUp({
35672
35536
  cdpPort,
35673
- carriedDraft,
35674
- carryDraft: options.carryDraft === true,
35675
35537
  expectedAccount: options.expectedAccount ?? null,
35676
35538
  allowOnboardingOverride: false
35677
35539
  });
@@ -35758,7 +35620,7 @@ async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTra
35758
35620
  }
35759
35621
  }
35760
35622
  function applyOfficialCodexLiveAccountSwitch(options = {}) {
35761
- return enqueueProfileAction("shared-window", async () => {
35623
+ return enqueueProfileAction("shared-window", () => withProfileLaunchFileLock(resolveDefaultCodexHomeDir(), async () => {
35762
35624
  const operationId = (0, import_node_crypto11.randomUUID)();
35763
35625
  let result2 = await applyOfficialCodexLiveAccountSwitchOnce(options, {
35764
35626
  operationId,
@@ -35792,7 +35654,10 @@ function applyOfficialCodexLiveAccountSwitch(options = {}) {
35792
35654
  });
35793
35655
  }
35794
35656
  return { ...result2, closedPreviousWindow };
35795
- });
35657
+ }, {
35658
+ profileKey: options.profileKey,
35659
+ onBusy: () => ({ status: "failed", reason: "launch-in-progress", pid: null, closedPreviousWindow: false })
35660
+ }));
35796
35661
  }
35797
35662
  function toIso2(value3) {
35798
35663
  return typeof value3 === "number" && Number.isFinite(value3) ? new Date(value3).toISOString() : null;
@@ -36036,93 +35901,28 @@ async function getOfficialCodexProfileInstances(options = {}) {
36036
35901
  unmanaged
36037
35902
  };
36038
35903
  }
36039
- async function setOfficialCodexProfileDraftPrompt(profileName, prompt) {
36040
- const normalizedProfileName = profileName.trim();
36041
- const normalizedPrompt = prompt.trim();
36042
- if (!normalizedProfileName || !normalizedPrompt) {
36043
- return {
36044
- status: "unavailable",
36045
- reason: "missing-profile-or-prompt",
36046
- route: null
36047
- };
36048
- }
36049
- if (process.platform !== "darwin") {
36050
- return {
36051
- status: "unavailable",
36052
- reason: "unsupported-platform",
36053
- route: null
36054
- };
36055
- }
36056
- try {
36057
- const [state, { candidate }, rows] = await Promise.all([
36058
- getAppState(),
36059
- resolveCodexAppTarget(),
36060
- readProcessRows()
36061
- ]);
36062
- if (!candidate) {
36063
- return {
36064
- status: "unavailable",
36065
- reason: "codex-app-not-found",
36066
- route: null
36067
- };
36068
- }
36069
- const bridgeTarget = await resolveOfficialCodexBridgeTarget({
36070
- profileName: normalizedProfileName,
36071
- state,
36072
- candidate,
36073
- rows
36074
- });
36075
- if (!bridgeTarget?.instance.cdpPort) {
36076
- return {
36077
- status: "unavailable",
36078
- reason: "target-instance-not-running",
36079
- route: null
36080
- };
36081
- }
36082
- const targets = await readCdpTargets(bridgeTarget.instance.cdpPort);
36083
- const target = pickCodexCdpTarget(targets);
36084
- if (!target?.webSocketDebuggerUrl) {
36085
- return {
36086
- status: "unavailable",
36087
- reason: "cdp-target-not-found",
36088
- route: null
36089
- };
36090
- }
36091
- const listenerAttached = await startOfficialCodexBridgeActionListener({
36092
- profileName: normalizedProfileName,
36093
- cdpPort: bridgeTarget.instance.cdpPort,
36094
- debuggerUrl: target.webSocketDebuggerUrl,
36095
- processEpoch: notificationProcessEpochFromInstance(bridgeTarget.instance)
36096
- });
36097
- if (!listenerAttached) {
36098
- return {
36099
- status: "failed",
36100
- reason: "bridge-listener-attach-failed",
36101
- route: null
36102
- };
36103
- }
36104
- const result2 = await evaluateOfficialCodexBridgeCommand(
36105
- target.webSocketDebuggerUrl,
36106
- "setDraft",
36107
- createBridgeSetDraftPromptExpression(normalizedPrompt),
36108
- false
36109
- );
36110
- return normalizeDraftPromptInsertionResult(result2);
36111
- } catch (error) {
36112
- return {
36113
- status: "failed",
36114
- reason: sanitizeUserFacingError(error) ?? "draft-insertion-failed",
36115
- route: null
36116
- };
36117
- }
36118
- }
36119
35904
  function launchOfficialCodexProfileInstance(options) {
36120
35905
  return enqueueProfileAction(
36121
35906
  options.profileName,
36122
35907
  () => launchOfficialCodexProfileInstanceWithRetries(options)
36123
35908
  );
36124
35909
  }
36125
- async function launchOfficialCodexProfileInstanceWithRetries(options) {
35910
+ function launchOfficialCodexProfileInstanceWithRetries(options) {
35911
+ return withProfileLaunchFileLock(
35912
+ options.profileHome,
35913
+ () => launchOfficialCodexProfileInstanceUnlocked(options),
35914
+ {
35915
+ profileKey: options.profileKey,
35916
+ onBusy: () => ({
35917
+ status: "failed",
35918
+ profileName: options.profileName,
35919
+ instance: null,
35920
+ reason: "launch-in-progress"
35921
+ })
35922
+ }
35923
+ );
35924
+ }
35925
+ async function launchOfficialCodexProfileInstanceUnlocked(options) {
36126
35926
  let launched = await launchOfficialCodexProfileInstanceOnce(options);
36127
35927
  for (let attempt = 1; attempt < LAUNCH_VERIFY_RETRIES; attempt += 1) {
36128
35928
  if (launched.status !== "failed" || launched.reason !== "app-server-not-verified") {
@@ -36167,7 +35967,25 @@ async function launchOfficialCodexProfileInstanceOnce(options) {
36167
35967
  if (staleLaunchPids.length > 0) {
36168
35968
  launchBaselineMainPids = (await readProcessRows()).filter((row) => isMainProcessRow(row, candidate)).map((row) => row.pid);
36169
35969
  }
36170
- const existing = await readManagedInstance(options.profileName);
35970
+ const instances = (await updateAppState((current) => current, {
35971
+ mode: "replace",
35972
+ cloneCurrent: false
35973
+ })).officialCodex.instancesByProfileName;
35974
+ if (options.profileKey) {
35975
+ for (const instance of Object.values(instances)) {
35976
+ if (instance.profileName === options.profileName || instance.profileKey !== options.profileKey) continue;
35977
+ const runtime = await resolveInstanceRuntimeState({ instance, candidate, rows: await readProcessRows() });
35978
+ if (runtime.running) {
35979
+ return {
35980
+ status: "failed",
35981
+ profileName: options.profileName,
35982
+ instance: managedInstanceToPayload(instance, true, runtime.appServerPid, runtime.startedAt),
35983
+ reason: `This account already has a Codex window under profile '${instance.profileName}'. Open that profile instead.`
35984
+ };
35985
+ }
35986
+ }
35987
+ }
35988
+ const existing = instances[options.profileName] ?? null;
36171
35989
  const desiredQolSettings = resolveDesiredQolSettings({
36172
35990
  requested: options.desiredQolSettings,
36173
35991
  existing: existing?.desiredQolSettings
@@ -36260,7 +36078,10 @@ async function launchOfficialCodexProfileInstanceOnce(options) {
36260
36078
  candidate,
36261
36079
  options.profileHome,
36262
36080
  options.profileName,
36263
- new Set(launchBaselineMainPids)
36081
+ new Set(launchBaselineMainPids),
36082
+ {
36083
+ environment: options.environment
36084
+ }
36264
36085
  );
36265
36086
  if (launch.pid !== null && launch.startedAt !== null && launch.cdpPort !== null) {
36266
36087
  launchedProcess = {
@@ -38982,6 +38803,19 @@ var ProfileManager = class {
38982
38803
  const workspace = this.resolveWorkspaceIdentity(data, resolvedMetadata);
38983
38804
  const workspaceId = workspace.id || DEFAULT_WORKSPACE_ID;
38984
38805
  const workspaceName = workspace.name ?? null;
38806
+ const identityKey = this.resolveProfileIdentityFromData(null, data, resolvedMetadata);
38807
+ if (identityKey && (!existingRecord || identityKey !== this.resolveProfileIdentityFromRecord(existingRecord) || workspaceId !== this.normalizeWorkspaceId(existingRecord.workspaceId) || this.resolveAuthMethod(data) !== this.resolveAuthMethod(existingRecord.data))) {
38808
+ const duplicate = await this.getProfileRowByIdentityAndWorkspace(
38809
+ identityKey,
38810
+ workspaceId,
38811
+ { authMethod: this.resolveAuthMethod(data) }
38812
+ );
38813
+ if (duplicate && duplicate.name !== resolvedName) {
38814
+ throw new Error(
38815
+ `Account is already saved as profile '${duplicate.name}'. Switch to or delete that profile before creating another.`
38816
+ );
38817
+ }
38818
+ }
38985
38819
  if (!data.workspace_id) {
38986
38820
  data.workspace_id = workspaceId;
38987
38821
  }
@@ -40385,27 +40219,6 @@ var ProfileManager = class {
40385
40219
  const description = this.describeActiveAuth(authData);
40386
40220
  const normalizedProfile = description.normalized;
40387
40221
  normalizedProfile.created_at = normalizedProfile.created_at ?? (/* @__PURE__ */ new Date()).toISOString();
40388
- const identityKey = this.resolveProfileIdentityFromData(
40389
- null,
40390
- normalizedProfile,
40391
- description.metadata
40392
- );
40393
- const workspace = this.resolveWorkspaceIdentity(
40394
- normalizedProfile,
40395
- description.metadata
40396
- );
40397
- if (identityKey) {
40398
- const duplicate = await this.getProfileRowByIdentityAndWorkspace(
40399
- identityKey,
40400
- workspace.id ?? DEFAULT_WORKSPACE_ID,
40401
- { authMethod: this.resolveAuthMethod(normalizedProfile) }
40402
- );
40403
- if (duplicate && duplicate.name !== profileName) {
40404
- throw new Error(
40405
- `Account is already saved as profile '${duplicate.name}'. Switch to or delete that profile before creating another.`
40406
- );
40407
- }
40408
- }
40409
40222
  await this.persistProfileRecord(
40410
40223
  profileName,
40411
40224
  normalizedProfile,
@@ -40478,20 +40291,6 @@ var ProfileManager = class {
40478
40291
  `Active Codex login is for a different OpenAI identity than profile '${profileName}'. Create a new profile for that login instead.`
40479
40292
  );
40480
40293
  }
40481
- if (existingIdentity && normalized.workspace_id) {
40482
- const targetWorkspaceId = normalized.workspace_id;
40483
- const currentWorkspaceId = currentWorkspace.id ?? DEFAULT_WORKSPACE_ID;
40484
- if (targetWorkspaceId !== currentWorkspaceId) {
40485
- const duplicate = await this.getProfileRowByIdentityAndWorkspace(existingIdentity, targetWorkspaceId, {
40486
- authMethod: this.resolveAuthMethod(existing)
40487
- });
40488
- if (duplicate && duplicate.name !== profileName) {
40489
- throw new Error(
40490
- `Account is already saved as profile '${duplicate.name}'. Switch to or delete that profile before creating another.`
40491
- );
40492
- }
40493
- }
40494
- }
40495
40294
  const { profile: merged, metadata } = this.mergeProfileRecords(existing, normalized);
40496
40295
  delete merged.tokenAlert;
40497
40296
  await this.persistProfileRecord(profileName, merged, metadata);
@@ -43471,8 +43270,137 @@ function normalizeRawMessage(rawMessage) {
43471
43270
  }
43472
43271
  return cleaned;
43473
43272
  }
43273
+ var KNOWN_ERRORS = {
43274
+ "desktop-llm-route-bound-running": {
43275
+ message: "This model is used by an open Codex window.",
43276
+ recovery: "Close that window, then save again."
43277
+ },
43278
+ "desktop-llm-route-bound": {
43279
+ message: "This model is used by an account.",
43280
+ recovery: "Change that account's model first."
43281
+ },
43282
+ "desktop-llm-provider-bound": {
43283
+ message: "This provider is used by an account.",
43284
+ recovery: "Remove or change that account first."
43285
+ },
43286
+ "desktop-llm-route-slug-collision": {
43287
+ message: "Another model already uses that name.",
43288
+ recovery: "Choose a different name."
43289
+ },
43290
+ "desktop-llm-route-not-verified": {
43291
+ message: "This model has not been tested yet.",
43292
+ recovery: "Test the model, then use it."
43293
+ },
43294
+ "desktop-llm-credential-missing": {
43295
+ message: "This provider has no API key.",
43296
+ recovery: "Add the key under Settings, Model Providers."
43297
+ },
43298
+ "desktop-llm-provider-credential-missing": {
43299
+ message: "This provider has no API key.",
43300
+ recovery: "Add the key under Settings, Model Providers."
43301
+ },
43302
+ "external-profile-not-ready": {
43303
+ message: "This account's model is not ready.",
43304
+ recovery: "Finish its setup under Settings, Model Providers."
43305
+ },
43306
+ "external-profile-route-not-ready": {
43307
+ message: "This account's model is not ready.",
43308
+ recovery: "Finish its setup under Settings, Model Providers."
43309
+ },
43310
+ "quit-custom-provider-profile-before-change": {
43311
+ message: "This account's Codex window is open.",
43312
+ recovery: "Close the window, then make the change."
43313
+ },
43314
+ "quit-managed-profile-before-native-restore": {
43315
+ message: "This account's Codex window is open.",
43316
+ recovery: "Close the window, then restore its settings."
43317
+ },
43318
+ "profile-name-already-used": {
43319
+ message: "Another account already uses that name.",
43320
+ recovery: "Choose a different name."
43321
+ },
43322
+ "unverified-official-codex-window": {
43323
+ message: "A Codex window is open that CodexUse cannot confirm belongs to this account.",
43324
+ recovery: "Close that window, then open the account again."
43325
+ },
43326
+ "multiple-official-app-variants-running": {
43327
+ message: "More than one version of the Codex app is running.",
43328
+ recovery: "Quit the extra one, then try again."
43329
+ },
43330
+ "previous-instance-still-running": {
43331
+ message: "The previous Codex window is still closing.",
43332
+ recovery: "Wait a moment, then try again."
43333
+ },
43334
+ "launch-in-progress": {
43335
+ message: "This account is already opening.",
43336
+ recovery: "Wait for its window to appear."
43337
+ },
43338
+ "official-codex-app-not-found": {
43339
+ message: "The Codex app is not installed on this Mac.",
43340
+ recovery: "Install Codex, then try again."
43341
+ },
43342
+ "work-config-invalid-toml": {
43343
+ message: "The settings are not valid TOML. Nothing was changed.",
43344
+ recovery: "Fix the syntax, then save again."
43345
+ },
43346
+ "work-config-secret": {
43347
+ message: "Settings cannot contain API keys, tokens, or passwords.",
43348
+ recovery: "Remove the secret, then save again."
43349
+ },
43350
+ "work-config-planner-tools-managed": {
43351
+ message: "CodexUse manages the codexuse_work tool entry.",
43352
+ recovery: "Remove that entry, then save again."
43353
+ },
43354
+ "work-config-shared-stale": {
43355
+ message: "The shared settings changed after you opened them.",
43356
+ recovery: "Reload, then apply your change again."
43357
+ },
43358
+ "work-config-override-stale": {
43359
+ message: "This account's settings changed after you opened them.",
43360
+ recovery: "Reload, then apply your change again."
43361
+ },
43362
+ "work-config-external-changed": {
43363
+ message: "This account's Codex settings were changed outside CodexUse.",
43364
+ recovery: "Open the account, review the outside changes, and import them first."
43365
+ },
43366
+ "work-config-external-review-stale": {
43367
+ message: "The outside settings changed after you reviewed them.",
43368
+ recovery: "Reload and review them again."
43369
+ },
43370
+ "work-config-changed-during-save": {
43371
+ message: "The settings changed while saving. Nothing was applied.",
43372
+ recovery: "Reload, then save again."
43373
+ },
43374
+ "work-config-write-not-confirmed": {
43375
+ message: "CodexUse wrote the settings but could not read them back.",
43376
+ recovery: "Reload to check what was saved."
43377
+ },
43378
+ "Enable third-party providers before authorizing a custom-provider worker.": {
43379
+ message: "Allow third-party providers for this folder before using a custom-model worker.",
43380
+ recovery: "Turn on the allowance in the folder's options, then start again."
43381
+ }
43382
+ };
43383
+ function findKnownError(cleaned) {
43384
+ for (const [key, entry] of Object.entries(KNOWN_ERRORS)) {
43385
+ const matches = key.includes(" ") ? cleaned.includes(key) : new RegExp(`(^|[^a-z0-9-])${key}([^a-z0-9-]|$)`).test(cleaned);
43386
+ if (matches) {
43387
+ return entry;
43388
+ }
43389
+ }
43390
+ return null;
43391
+ }
43474
43392
  function resolveCategory(cleaned, options) {
43475
43393
  const lower = cleaned.toLowerCase();
43394
+ const known = findKnownError(cleaned);
43395
+ if (known) {
43396
+ return {
43397
+ code: "ERR_ACTION_REQUIRED",
43398
+ title: "Something needs to change first",
43399
+ message: known.message,
43400
+ recovery: known.recovery,
43401
+ retryable: true
43402
+ };
43403
+ }
43476
43404
  if (options.notFoundFallback && (lower.includes("enoent") || lower.includes("not found"))) {
43477
43405
  return {
43478
43406
  code: "ERR_NOT_FOUND",
@@ -43487,7 +43415,7 @@ function resolveCategory(cleaned, options) {
43487
43415
  code: "ERR_RATE_LIMIT",
43488
43416
  title: "Rate limit reached",
43489
43417
  message: "The provider is rate limited right now.",
43490
- recovery: "Wait a moment, switch profiles, or try again.",
43418
+ recovery: "Wait a moment, open another account, or try again.",
43491
43419
  retryable: true
43492
43420
  };
43493
43421
  }
@@ -43514,7 +43442,7 @@ function resolveCategory(cleaned, options) {
43514
43442
  code: "ERR_AUTH",
43515
43443
  title: "Sign-in expired",
43516
43444
  message: "This account needs to sign in again.",
43517
- recovery: "Reconnect the profile, then retry the action.",
43445
+ recovery: "Reconnect the account, then retry the action.",
43518
43446
  retryable: true
43519
43447
  };
43520
43448
  }
@@ -43550,7 +43478,7 @@ function resolveCategory(cleaned, options) {
43550
43478
  code: "ERR_PROVIDER",
43551
43479
  title: "Provider request failed",
43552
43480
  message: "The AI provider rejected or failed the request.",
43553
- recovery: "Try again, or switch the active profile or model.",
43481
+ recovery: "Try again, open another account, or change the model.",
43554
43482
  retryable: true
43555
43483
  };
43556
43484
  }
@@ -43820,7 +43748,6 @@ async function coordinateOfficialCodexProfileSwitch(options) {
43820
43748
  }
43821
43749
  }
43822
43750
  const transition = await applyOfficialCodexLiveAccountSwitch({
43823
- carryDraft: options.carryDraft === true,
43824
43751
  profileName: targetProfileName,
43825
43752
  profileKey: options.targetProfileKey ?? null,
43826
43753
  desiredQolSettings: options.desiredQolSettings,
@@ -44568,7 +44495,7 @@ async function coordinateCliOfficialCodexProfileSwitch(options) {
44568
44495
  actor: "cli",
44569
44496
  expectedSourceProfileName,
44570
44497
  standingTakeControlConsent: await readStandingTakeControlConsent(),
44571
- // ceiling: CLI cannot own persisted live-login expiry maintenance; upgrade when a resident backend handoff is available.
44498
+ // ceiling: CLI cannot own persisted live-login expiry maintenance; upgrade when a resident backend recovery process is available.
44572
44499
  allowLiveLogin: false
44573
44500
  })
44574
44501
  );
@@ -44628,42 +44555,6 @@ async function coordinateCliOfficialCodexProfileSwitch(options) {
44628
44555
  configureOfficialCodexBridgeNotificationHandler(null);
44629
44556
  }
44630
44557
  }
44631
- async function prepareCliManagedDraftHandoff(manager, sourceProfileName, targetProfile) {
44632
- const sourceProfile = await getManagedProfileByName(
44633
- manager,
44634
- sourceProfileName
44635
- );
44636
- if (!sourceProfile) {
44637
- return;
44638
- }
44639
- const sourceRuntimeName = managedProfileRuntimeName(sourceProfile);
44640
- const targetRuntimeName = managedProfileRuntimeName(targetProfile);
44641
- const instances = await getOfficialCodexProfileInstances({
44642
- profileNames: [sourceRuntimeName, targetRuntimeName]
44643
- });
44644
- const source = instances.instances.find(
44645
- (instance) => instance.profileName === sourceRuntimeName && instance.running
44646
- );
44647
- if (!source) {
44648
- return;
44649
- }
44650
- const sourceContext = [
44651
- source.bridgeActiveThreadTitle ? `Source task: ${source.bridgeActiveThreadTitle}` : null,
44652
- source.bridgeActiveThreadId ? `Source task ID: ${source.bridgeActiveThreadId}` : null,
44653
- source.bridgeComposerText?.trim() ? `Visible draft:
44654
- ${source.bridgeComposerText.trim()}` : null
44655
- ].filter((line) => Boolean(line));
44656
- if (sourceContext.length === 0) {
44657
- return;
44658
- }
44659
- await setOfficialCodexProfileDraftPrompt(
44660
- targetRuntimeName,
44661
- [
44662
- "Continue the same Codex task after this profile switch.",
44663
- ...sourceContext
44664
- ].join("\n\n").slice(0, 2e4)
44665
- );
44666
- }
44667
44558
  async function coordinateCliManagedProfileSwitch(options) {
44668
44559
  const targetProfile = await getManagedProfileByName(
44669
44560
  options.profileManager,
@@ -44722,17 +44613,6 @@ async function coordinateCliManagedProfileSwitch(options) {
44722
44613
  mechanism = "relaunch";
44723
44614
  }
44724
44615
  await persistLastProfileName(targetProfile.name);
44725
- if (options.carryDraft && current.name && current.name !== targetProfile.name) {
44726
- await prepareCliManagedDraftHandoff(
44727
- options.profileManager,
44728
- current.name,
44729
- targetProfile
44730
- ).catch((error) => {
44731
- console.warn(
44732
- `Could not prepare profile handoff: ${error instanceof Error ? error.message : String(error)}`
44733
- );
44734
- });
44735
- }
44736
44616
  return {
44737
44617
  sourceProfileName: current.name,
44738
44618
  targetProfileName: targetProfile.name,
@@ -44755,17 +44635,6 @@ async function coordinateCliManagedProfileSwitch(options) {
44755
44635
  const managedOutcome = { ...outcome, sourceProfileName: current.name };
44756
44636
  if (managedOutcome.authStatus !== "not-started") {
44757
44637
  await persistLastProfileName(targetProfile.name);
44758
- if (options.carryDraft && currentProfile?.kind === "custom" && current.name && current.name !== targetProfile.name) {
44759
- await prepareCliManagedDraftHandoff(
44760
- options.profileManager,
44761
- current.name,
44762
- targetProfile
44763
- ).catch((error) => {
44764
- console.warn(
44765
- `Could not prepare profile handoff: ${error instanceof Error ? error.message : String(error)}`
44766
- );
44767
- });
44768
- }
44769
44638
  }
44770
44639
  return managedOutcome;
44771
44640
  }
@@ -44956,8 +44825,7 @@ async function runAutoRollPass(manager, options) {
44956
44825
  synchronizeApp: options.synchronizeOfficialCodex,
44957
44826
  launchIfNotRunning: options.launchOfficialCodexWhenClosed === true,
44958
44827
  explicitTakeControl: options.takeControl === true,
44959
- readStandingTakeControlConsent: async () => (await readAppSettings()).officialCodexAutoControlEnabled === true,
44960
- carryDraft: true
44828
+ readStandingTakeControlConsent: async () => (await readAppSettings()).officialCodexAutoControlEnabled === true
44961
44829
  });
44962
44830
  await recordCliCoordinatedOutcome(
44963
44831
  outcome,
@@ -45117,8 +44985,7 @@ async function handleProfileCommand(args2, version) {
45117
44985
  synchronizeApp: activation.synchronize,
45118
44986
  launchIfNotRunning: activation.launch,
45119
44987
  explicitTakeControl: takeControl,
45120
- readStandingTakeControlConsent: async () => (await readAppSettings()).officialCodexAutoControlEnabled === true,
45121
- carryDraft: true
44988
+ readStandingTakeControlConsent: async () => (await readAppSettings()).officialCodexAutoControlEnabled === true
45122
44989
  });
45123
44990
  await recordCliCoordinatedOutcome(
45124
44991
  outcome,
@@ -46458,7 +46325,7 @@ async function ensureCliStorageReady() {
46458
46325
  }
46459
46326
 
46460
46327
  // src/app/main.ts
46461
- var VERSION = true ? "6.1.1" : "0.0.0";
46328
+ var VERSION = true ? "6.2.1" : "0.0.0";
46462
46329
  async function runCli() {
46463
46330
  const args2 = process.argv.slice(2);
46464
46331
  if (args2.length === 0) {