codexuse-cli 6.0.4 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2026,8 +2026,8 @@ var require_toml = __commonJS({
2026
2026
  });
2027
2027
 
2028
2028
  // src/commands/accountPool.ts
2029
- var import_node_crypto13 = require("crypto");
2030
- var import_node_path13 = __toESM(require("path"));
2029
+ var import_node_crypto14 = require("crypto");
2030
+ var import_node_path14 = __toESM(require("path"));
2031
2031
 
2032
2032
  // ../../packages/contracts/src/settings/types.ts
2033
2033
  var DEFAULT_ACCOUNT_POOL_EXPOSED_MODELS = [
@@ -2077,11 +2077,121 @@ function migrateLegacyAccountPoolExposedReasoningDefaults(efforts) {
2077
2077
  }
2078
2078
 
2079
2079
  // ../../packages/runtime-app-state/src/app/state.ts
2080
- var import_node_async_hooks = require("async_hooks");
2080
+ var import_node_async_hooks2 = require("async_hooks");
2081
2081
  var import_node_crypto2 = require("crypto");
2082
- var import_node_path3 = __toESM(require("path"), 1);
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/desktop/llm-compatibility.ts
2086
+ var DESKTOP_LLM_CAPABILITY_NAMES = [
2087
+ "streamingText",
2088
+ "inputImage",
2089
+ "reasoning",
2090
+ "reasoningEfforts",
2091
+ "functionTools",
2092
+ "applyPatch",
2093
+ "namespaceTools",
2094
+ "parallelTools",
2095
+ "toolChoice",
2096
+ "toolSearch",
2097
+ "standaloneWebSearch",
2098
+ "imageGeneration"
2099
+ ];
2100
+ var MAX_DESKTOP_LLM_CONTEXT_TOKENS = 1e8;
2101
+ function boundedCatalogInteger(value3, minimum, maximum) {
2102
+ return typeof value3 === "number" && Number.isInteger(value3) && value3 >= minimum && value3 <= maximum ? value3 : null;
2103
+ }
2104
+ function normalizeDesktopLlmModelCatalogMetadata(value3) {
2105
+ const record2 = value3 && typeof value3 === "object" && !Array.isArray(value3) ? value3 : {};
2106
+ const description = typeof record2.description === "string" ? record2.description.slice(0, 2e3).trim() || null : null;
2107
+ const contextWindow = boundedCatalogInteger(
2108
+ record2.contextWindow,
2109
+ 1,
2110
+ MAX_DESKTOP_LLM_CONTEXT_TOKENS
2111
+ );
2112
+ const requestedMaxContextWindow = boundedCatalogInteger(
2113
+ record2.maxContextWindow,
2114
+ 1,
2115
+ MAX_DESKTOP_LLM_CONTEXT_TOKENS
2116
+ );
2117
+ const maxContextWindow = contextWindow !== null && requestedMaxContextWindow !== null && requestedMaxContextWindow < contextWindow ? contextWindow : requestedMaxContextWindow;
2118
+ const effectiveContextWindowPercent = boundedCatalogInteger(
2119
+ record2.effectiveContextWindowPercent,
2120
+ 1,
2121
+ 100
2122
+ );
2123
+ const requestedAutoCompactTokenLimit = boundedCatalogInteger(
2124
+ record2.autoCompactTokenLimit,
2125
+ 1,
2126
+ MAX_DESKTOP_LLM_CONTEXT_TOKENS
2127
+ );
2128
+ const compactContextWindow = contextWindow ?? maxContextWindow;
2129
+ const maximumAutoCompactTokenLimit = compactContextWindow ? Math.max(
2130
+ 1,
2131
+ Math.floor(compactContextWindow * 0.9)
2132
+ ) : MAX_DESKTOP_LLM_CONTEXT_TOKENS;
2133
+ return {
2134
+ description,
2135
+ contextWindow,
2136
+ maxContextWindow,
2137
+ autoCompactTokenLimit: requestedAutoCompactTokenLimit !== null && requestedAutoCompactTokenLimit <= maximumAutoCompactTokenLimit ? requestedAutoCompactTokenLimit : null,
2138
+ effectiveContextWindowPercent
2139
+ };
2140
+ }
2141
+ var POLICY_CAPABILITIES = /* @__PURE__ */ new Set([
2142
+ "inputImage",
2143
+ "reasoning",
2144
+ "reasoningEfforts",
2145
+ "applyPatch",
2146
+ "toolSearch",
2147
+ "standaloneWebSearch",
2148
+ "imageGeneration"
2149
+ ]);
2150
+ function createDesktopLlmCapability(input) {
2151
+ return {
2152
+ nativeSupport: {
2153
+ state: input.state,
2154
+ source: input.source ?? "default"
2155
+ },
2156
+ userPolicy: input.policy ?? "auto"
2157
+ };
2158
+ }
2159
+ function migrateDesktopLlmCapabilityV3(name, value3) {
2160
+ const record2 = value3 && typeof value3 === "object" && !Array.isArray(value3) ? value3 : {};
2161
+ const enabled = record2.enabled === true;
2162
+ const legacySource = record2.source;
2163
+ const source = legacySource === "verified" ? "probe" : "default";
2164
+ return createDesktopLlmCapability({
2165
+ state: enabled ? "supported" : "unsupported",
2166
+ source,
2167
+ // Version 3 used one boolean for support and user intent. Preserve the
2168
+ // stricter behavior for semantic capabilities during the one-way migration.
2169
+ policy: POLICY_CAPABILITIES.has(name) ? enabled ? "allow" : "deny" : "auto"
2170
+ });
2171
+ }
2172
+ function normalizeDesktopLlmCapability(name, value3) {
2173
+ const record2 = value3 && typeof value3 === "object" && !Array.isArray(value3) ? value3 : null;
2174
+ const nativeSupport = record2?.nativeSupport && typeof record2.nativeSupport === "object" && !Array.isArray(record2.nativeSupport) ? record2.nativeSupport : null;
2175
+ if (nativeSupport) {
2176
+ const state = nativeSupport.state;
2177
+ const source = nativeSupport.source;
2178
+ const policy = record2?.userPolicy;
2179
+ if ((state === "unknown" || state === "supported" || state === "unsupported") && (source === "default" || source === "provider" || source === "probe" || source === "runtime" || source === "user") && !(source === "runtime" && state === "supported") && (policy === "auto" || policy === "allow" || policy === "deny")) {
2180
+ return createDesktopLlmCapability({ state, source, policy });
2181
+ }
2182
+ }
2183
+ return migrateDesktopLlmCapabilityV3(name, value3);
2184
+ }
2185
+ function normalizeDesktopLlmCapabilities(value3) {
2186
+ const record2 = value3 && typeof value3 === "object" && !Array.isArray(value3) ? value3 : {};
2187
+ return Object.fromEntries(
2188
+ DESKTOP_LLM_CAPABILITY_NAMES.map((name) => [
2189
+ name,
2190
+ normalizeDesktopLlmCapability(name, record2[name])
2191
+ ])
2192
+ );
2193
+ }
2194
+
2085
2195
  // ../../packages/contracts/src/settings/auto-roll.ts
2086
2196
  var DEFAULT_AUTO_ROLL_ENABLED = false;
2087
2197
  var DEFAULT_AUTO_ROLL_REARM_REMAINING_THRESHOLD = 15;
@@ -3173,6 +3283,78 @@ async function deleteDocument(dbPath, namespace) {
3173
3283
  );
3174
3284
  }
3175
3285
 
3286
+ // ../../packages/runtime-app-state/src/storage/cloudSyncTransaction.ts
3287
+ var import_node_async_hooks = require("async_hooks");
3288
+ var import_node_path3 = __toESM(require("path"), 1);
3289
+ var CloudSyncTransactionLockError = class extends Error {
3290
+ constructor(reason, options = {}) {
3291
+ super(
3292
+ reason === "busy" ? "Another CodexUse process is changing Cloud Sync data. Wait for it to finish, then try again." : "CodexUse could not open the Cloud Sync transaction lock.",
3293
+ options
3294
+ );
3295
+ this.reason = reason;
3296
+ this.name = "CloudSyncTransactionLockError";
3297
+ }
3298
+ };
3299
+ var TRANSACTION_LOCK_NAME = "cloud-sync-transaction";
3300
+ var heldLocks = new import_node_async_hooks.AsyncLocalStorage();
3301
+ var operationTails = /* @__PURE__ */ new Map();
3302
+ function getCloudSyncTransactionLockPath(userDataDir) {
3303
+ return import_node_path3.default.join(userDataDir, TRANSACTION_LOCK_NAME);
3304
+ }
3305
+ async function acquireTransactionLock(target, mode) {
3306
+ const acquire = mode === "write" ? acquireCrossProcessFileLock : acquireCrossProcessFileReadLock;
3307
+ let release;
3308
+ try {
3309
+ release = await acquire(target);
3310
+ } catch (error) {
3311
+ throw new CloudSyncTransactionLockError("unavailable", { cause: error });
3312
+ }
3313
+ if (release) {
3314
+ return release;
3315
+ }
3316
+ throw new CloudSyncTransactionLockError("busy");
3317
+ }
3318
+ async function withCloudSyncTransaction(userDataDir, mode, operation) {
3319
+ const target = import_node_path3.default.resolve(getCloudSyncTransactionLockPath(userDataDir));
3320
+ const held = heldLocks.getStore();
3321
+ const heldTransaction = held?.get(target);
3322
+ if (heldTransaction?.active) {
3323
+ if (heldTransaction.mode === "read" && mode === "write") {
3324
+ throw new Error("A Cloud Sync read transaction cannot be upgraded to a write transaction.");
3325
+ }
3326
+ return operation();
3327
+ }
3328
+ const previous = operationTails.get(target) ?? Promise.resolve();
3329
+ let finish;
3330
+ const turn = new Promise((resolve2) => {
3331
+ finish = resolve2;
3332
+ });
3333
+ operationTails.set(target, turn);
3334
+ await previous;
3335
+ let release = null;
3336
+ let transaction = null;
3337
+ try {
3338
+ release = await acquireTransactionLock(target, mode);
3339
+ const nextHeld = new Map(held ?? []);
3340
+ transaction = { active: true, mode };
3341
+ nextHeld.set(target, transaction);
3342
+ return await heldLocks.run(nextHeld, operation);
3343
+ } finally {
3344
+ if (transaction) {
3345
+ transaction.active = false;
3346
+ }
3347
+ try {
3348
+ await release?.();
3349
+ } finally {
3350
+ finish();
3351
+ if (operationTails.get(target) === turn) {
3352
+ operationTails.delete(target);
3353
+ }
3354
+ }
3355
+ }
3356
+ }
3357
+
3176
3358
  // ../../packages/runtime-app-state/src/app/state.ts
3177
3359
  var APP_STATE_DOCUMENT = "desktop.app-state";
3178
3360
  var APP_NAME = "codexuse-desktop";
@@ -3186,7 +3368,7 @@ var persistenceFailure = null;
3186
3368
  var pendingRendererUiPatch = null;
3187
3369
  var nextPersistenceRetryAt = 0;
3188
3370
  var writeLock = Promise.resolve();
3189
- var writeLockContext = new import_node_async_hooks.AsyncLocalStorage();
3371
+ var writeLockContext = new import_node_async_hooks2.AsyncLocalStorage();
3190
3372
  function isRecord2(value3) {
3191
3373
  return Boolean(value3) && typeof value3 === "object" && !Array.isArray(value3);
3192
3374
  }
@@ -3215,7 +3397,7 @@ function resolveDefaultUserDataDir() {
3215
3397
  if (!home) {
3216
3398
  throw new Error("Unable to resolve home directory for app state.");
3217
3399
  }
3218
- return import_node_path3.default.join(home, "Library", "Application Support", APP_NAME);
3400
+ return import_node_path4.default.join(home, "Library", "Application Support", APP_NAME);
3219
3401
  }
3220
3402
  function getUserDataDir() {
3221
3403
  return configuredUserDataDir ?? resolveDefaultUserDataDir();
@@ -3251,7 +3433,7 @@ function createDefaultAppState() {
3251
3433
  relayProfilesById: {},
3252
3434
  desktopLlmEnabled: false,
3253
3435
  desktopLlmRegistry: {
3254
- version: 3,
3436
+ version: 4,
3255
3437
  revision: (0, import_node_crypto2.createHash)("sha256").update("empty").digest("hex"),
3256
3438
  providers: [],
3257
3439
  routes: [],
@@ -3300,23 +3482,12 @@ function createDefaultAppState() {
3300
3482
  runtimeSettings: {},
3301
3483
  ui: {
3302
3484
  themeMode: null,
3303
- layout: {
3304
- sidebarCollapsed: null
3305
- },
3306
3485
  profiles: {
3307
- viewMode: null,
3308
- sortBy: null,
3309
- groupBy: null,
3310
- planFilter: null,
3311
- healthFilter: null,
3312
- customGroupFilter: null,
3313
- toolbarOpen: null,
3314
3486
  collapsedSections: {}
3315
3487
  },
3316
3488
  onboarding: {
3317
3489
  welcomeCompleted: false,
3318
3490
  welcomeCompletedAt: null,
3319
- welcomeResumeStep: null,
3320
3491
  milestones: {
3321
3492
  firstProfileAdded: false,
3322
3493
  secondProfileAdded: false
@@ -3558,12 +3729,12 @@ function migrateDesktopLlmRegistry(profiles) {
3558
3729
  ])
3559
3730
  )
3560
3731
  ).digest("hex");
3561
- const capability = (enabled, source) => ({
3562
- enabled,
3563
- source
3564
- });
3732
+ const capability = (name, enabled) => migrateDesktopLlmCapabilityV3(
3733
+ name,
3734
+ { enabled, source: enabled ? "declared" : "failed" }
3735
+ );
3565
3736
  return {
3566
- version: 3,
3737
+ version: 4,
3567
3738
  revision,
3568
3739
  providers: entries3.map((profile) => {
3569
3740
  const endpoint = profile.baseUrl.trim().replace(/\/+$/g, "");
@@ -3579,6 +3750,7 @@ function migrateDesktopLlmRegistry(profiles) {
3579
3750
  enabled: true,
3580
3751
  baseUrl: apiRoot,
3581
3752
  modelsPath: `${apiRoot}/models`,
3753
+ modelsDevId: null,
3582
3754
  authMode: "bearer",
3583
3755
  credentialRef: `CODEXUSE_RELAY_${profile.id}`,
3584
3756
  hasCredential: profile.hasApiKey,
@@ -3618,19 +3790,20 @@ function migrateDesktopLlmRegistry(profiles) {
3618
3790
  displayName: profile.model,
3619
3791
  adapter: profile.protocol === "chat-completions" ? "openai-chat" : "openai-responses",
3620
3792
  path: profile.protocol === "chat-completions" ? `${apiRoot}/chat/completions` : `${apiRoot}/responses`,
3793
+ catalogMetadata: normalizeDesktopLlmModelCatalogMetadata(null),
3621
3794
  capabilities: {
3622
- streamingText: capability(true, "declared"),
3623
- inputImage: capability(false, "failed"),
3624
- reasoning: capability(false, "failed"),
3625
- reasoningEfforts: capability(false, "failed"),
3626
- functionTools: capability(true, "declared"),
3627
- applyPatch: capability(false, "failed"),
3628
- namespaceTools: capability(false, "failed"),
3629
- parallelTools: capability(false, "failed"),
3630
- toolChoice: capability(true, "declared"),
3631
- toolSearch: capability(false, "failed"),
3632
- standaloneWebSearch: capability(false, "failed"),
3633
- imageGeneration: capability(false, "failed")
3795
+ streamingText: capability("streamingText", true),
3796
+ inputImage: capability("inputImage", false),
3797
+ reasoning: capability("reasoning", false),
3798
+ reasoningEfforts: capability("reasoningEfforts", false),
3799
+ functionTools: capability("functionTools", true),
3800
+ applyPatch: capability("applyPatch", false),
3801
+ namespaceTools: capability("namespaceTools", false),
3802
+ parallelTools: capability("parallelTools", false),
3803
+ toolChoice: capability("toolChoice", true),
3804
+ toolSearch: capability("toolSearch", false),
3805
+ standaloneWebSearch: capability("standaloneWebSearch", false),
3806
+ imageGeneration: capability("imageGeneration", false)
3634
3807
  },
3635
3808
  requestProfile: {
3636
3809
  reasoningStyle: "none",
@@ -3657,20 +3830,6 @@ function migrateDesktopLlmRegistry(profiles) {
3657
3830
  externalProfiles: []
3658
3831
  };
3659
3832
  }
3660
- var DESKTOP_LLM_CAPABILITIES = [
3661
- "streamingText",
3662
- "inputImage",
3663
- "reasoning",
3664
- "reasoningEfforts",
3665
- "functionTools",
3666
- "applyPatch",
3667
- "namespaceTools",
3668
- "parallelTools",
3669
- "toolChoice",
3670
- "toolSearch",
3671
- "standaloneWebSearch",
3672
- "imageGeneration"
3673
- ];
3674
3833
  var DESKTOP_LLM_REASONING_EFFORTS = [
3675
3834
  "minimal",
3676
3835
  "low",
@@ -3693,7 +3852,7 @@ function desktopLlmReasoningEffortsMatchStyle(adapter, style, values2) {
3693
3852
  return style !== "openrouter" || !values2.includes("max");
3694
3853
  }
3695
3854
  function normalizeDesktopLlmRegistry(value3, profiles) {
3696
- if (!isRecord2(value3) || value3.version !== 1 && value3.version !== 2 && value3.version !== 3) {
3855
+ if (!isRecord2(value3) || value3.version !== 1 && value3.version !== 2 && value3.version !== 3 && value3.version !== 4) {
3697
3856
  return migrateDesktopLlmRegistry(profiles);
3698
3857
  }
3699
3858
  const legacyProviderTransport = /* @__PURE__ */ new Map();
@@ -3724,6 +3883,7 @@ function normalizeDesktopLlmRegistry(value3, profiles) {
3724
3883
  enabled: entry.enabled === true,
3725
3884
  baseUrl,
3726
3885
  modelsPath: asString(entry.modelsPath),
3886
+ modelsDevId: typeof entry.modelsDevId === "string" && /^[a-z0-9][a-z0-9-]{0,127}$/.test(entry.modelsDevId) ? entry.modelsDevId : null,
3727
3887
  authMode,
3728
3888
  credentialRef: asString(entry.credentialRef),
3729
3889
  hasCredential: entry.hasCredential === true,
@@ -3757,17 +3917,12 @@ function normalizeDesktopLlmRegistry(value3, profiles) {
3757
3917
  if (!publicSlug || !providerId || !upstreamModelId || !displayName || !adapter || !routePath) {
3758
3918
  return [];
3759
3919
  }
3760
- const rawCapabilities = isRecord2(entry.capabilities) ? entry.capabilities : {};
3761
- const capabilities = Object.fromEntries(
3762
- DESKTOP_LLM_CAPABILITIES.map((name) => {
3763
- const rawCapability = isRecord2(rawCapabilities[name]) ? rawCapabilities[name] : {};
3764
- const source = rawCapability.source === "declared" || rawCapability.source === "verified" || rawCapability.source === "failed" || rawCapability.source === "unknown" ? rawCapability.source : "unknown";
3765
- return [name, { enabled: rawCapability.enabled === true, source }];
3766
- })
3920
+ const capabilities = normalizeDesktopLlmCapabilities(
3921
+ entry.capabilities
3767
3922
  );
3768
3923
  const rawProfile = isRecord2(entry.requestProfile) ? entry.requestProfile : {};
3769
- const reasoningStyle = rawProfile.reasoningStyle === "default" || rawProfile.reasoningStyle === "deepseek" || rawProfile.reasoningStyle === "low-high" || rawProfile.reasoningStyle === "openrouter" || rawProfile.reasoningStyle === "thinking" || rawProfile.reasoningStyle === "enable-thinking" || rawProfile.reasoningStyle === "reasoning-split" ? rawProfile.reasoningStyle : "none";
3770
3924
  const rawProbe = isRecord2(entry.lastProbeResult) ? entry.lastProbeResult : null;
3925
+ const reasoningStyle = rawProfile.reasoningStyle === "default" || rawProfile.reasoningStyle === "deepseek" || rawProfile.reasoningStyle === "low-high" || rawProfile.reasoningStyle === "openrouter" || rawProfile.reasoningStyle === "thinking" || rawProfile.reasoningStyle === "enable-thinking" || rawProfile.reasoningStyle === "reasoning-split" ? rawProfile.reasoningStyle : "none";
3771
3926
  const rawReasoningEffort = isRecord2(entry.reasoningEffort) ? entry.reasoningEffort : {};
3772
3927
  const reasoningEffortValues = Array.isArray(rawReasoningEffort.values) ? Array.from(
3773
3928
  new Set(
@@ -3777,17 +3932,20 @@ function normalizeDesktopLlmRegistry(value3, profiles) {
3777
3932
  const reasoningEffortDefault = isDesktopLlmReasoningEffort(
3778
3933
  rawReasoningEffort.defaultValue
3779
3934
  ) ? rawReasoningEffort.defaultValue : null;
3780
- const hasSelectableReasoningEffort = Boolean(
3781
- capabilities.reasoning?.enabled === true && rawReasoningEffort.mode === "selectable" && reasoningEffortValues.length > 0 && reasoningEffortDefault && reasoningEffortValues.includes(reasoningEffortDefault) && desktopLlmReasoningEffortsMatchStyle(
3935
+ const hasSelectableReasoningEffortConfig = Boolean(
3936
+ rawReasoningEffort.mode === "selectable" && reasoningEffortValues.length > 0 && reasoningEffortDefault && reasoningEffortValues.includes(reasoningEffortDefault) && desktopLlmReasoningEffortsMatchStyle(
3782
3937
  adapter,
3783
3938
  reasoningStyle,
3784
3939
  reasoningEffortValues
3785
3940
  )
3786
3941
  );
3787
- capabilities.reasoningEfforts = {
3788
- enabled: hasSelectableReasoningEffort,
3789
- source: hasSelectableReasoningEffort ? capabilities.reasoningEfforts?.source === "verified" ? "verified" : "declared" : "unknown"
3790
- };
3942
+ if (!hasSelectableReasoningEffortConfig) {
3943
+ capabilities.reasoningEfforts = createDesktopLlmCapability({
3944
+ state: "unsupported",
3945
+ source: capabilities.reasoningEfforts.nativeSupport.source,
3946
+ policy: capabilities.reasoningEfforts.userPolicy
3947
+ });
3948
+ }
3791
3949
  const reasoningEffortSource = rawReasoningEffort.source === "provider" || rawReasoningEffort.source === "models.dev" || rawReasoningEffort.source === "user" ? rawReasoningEffort.source : "unknown";
3792
3950
  const rawReasoningEffortFetchedAt = asString(
3793
3951
  rawReasoningEffort.fetchedAt
@@ -3802,13 +3960,16 @@ function normalizeDesktopLlmRegistry(value3, profiles) {
3802
3960
  displayName,
3803
3961
  adapter,
3804
3962
  path: routePath,
3963
+ catalogMetadata: normalizeDesktopLlmModelCatalogMetadata(
3964
+ entry.catalogMetadata
3965
+ ),
3805
3966
  capabilities,
3806
3967
  requestProfile: {
3807
3968
  reasoningStyle,
3808
- supportsReasoningEffort: hasSelectableReasoningEffort,
3969
+ supportsReasoningEffort: hasSelectableReasoningEffortConfig,
3809
3970
  maxOutputTokensField: rawProfile.maxOutputTokensField === "max_completion_tokens" ? "max_completion_tokens" : "max_tokens"
3810
3971
  },
3811
- reasoningEffort: hasSelectableReasoningEffort ? {
3972
+ reasoningEffort: hasSelectableReasoningEffortConfig ? {
3812
3973
  mode: "selectable",
3813
3974
  values: reasoningEffortValues,
3814
3975
  defaultValue: reasoningEffortDefault,
@@ -3830,7 +3991,7 @@ function normalizeDesktopLlmRegistry(value3, profiles) {
3830
3991
  } : null
3831
3992
  }];
3832
3993
  }) : [];
3833
- const externalProfiles = value3.version === 3 && Array.isArray(value3.externalProfiles) ? value3.externalProfiles.flatMap((entry) => {
3994
+ const externalProfiles = (value3.version === 3 || value3.version === 4) && Array.isArray(value3.externalProfiles) ? value3.externalProfiles.flatMap((entry) => {
3834
3995
  if (!isRecord2(entry)) return [];
3835
3996
  const id2 = asString(entry.id);
3836
3997
  const name = asString(entry.name);
@@ -3879,6 +4040,7 @@ function normalizeDesktopLlmRegistry(value3, profiles) {
3879
4040
  enabled: provider.enabled,
3880
4041
  baseUrl: provider.baseUrl,
3881
4042
  modelsPath: provider.modelsPath,
4043
+ modelsDevId: provider.modelsDevId,
3882
4044
  authMode: provider.authMode,
3883
4045
  credentialRef: provider.credentialRef,
3884
4046
  hasCredential: provider.hasCredential,
@@ -3895,6 +4057,7 @@ function normalizeDesktopLlmRegistry(value3, profiles) {
3895
4057
  displayName: route.displayName,
3896
4058
  adapter: route.adapter,
3897
4059
  path: route.path,
4060
+ catalogMetadata: route.catalogMetadata,
3898
4061
  capabilities: route.capabilities,
3899
4062
  requestProfile: route.requestProfile,
3900
4063
  reasoningEffort: route.reasoningEffort,
@@ -3915,7 +4078,7 @@ function normalizeDesktopLlmRegistry(value3, profiles) {
3915
4078
  })
3916
4079
  ).digest("hex");
3917
4080
  return {
3918
- version: 3,
4081
+ version: 4,
3919
4082
  revision,
3920
4083
  providers,
3921
4084
  routes,
@@ -4326,41 +4489,18 @@ function normalizeAppState(raw) {
4326
4489
  merged.ui = clone2(defaults.ui);
4327
4490
  }
4328
4491
  merged.ui.themeMode = merged.ui.themeMode === "light" || merged.ui.themeMode === "dark" ? merged.ui.themeMode : null;
4329
- if (!isRecord2(merged.ui.layout)) {
4330
- merged.ui.layout = clone2(defaults.ui.layout);
4331
- }
4332
- if (typeof merged.ui.layout.sidebarCollapsed !== "boolean") {
4333
- merged.ui.layout.sidebarCollapsed = null;
4334
- }
4335
- if (!isRecord2(merged.ui.profiles)) {
4336
- merged.ui.profiles = clone2(defaults.ui.profiles);
4337
- }
4338
- merged.ui.profiles.viewMode = merged.ui.profiles.viewMode === "cards" || merged.ui.profiles.viewMode === "compact" ? merged.ui.profiles.viewMode : null;
4339
- merged.ui.profiles.sortBy = asString(merged.ui.profiles.sortBy);
4340
- merged.ui.profiles.groupBy = asString(merged.ui.profiles.groupBy);
4341
- merged.ui.profiles.planFilter = asString(merged.ui.profiles.planFilter);
4342
- merged.ui.profiles.healthFilter = asString(merged.ui.profiles.healthFilter);
4343
- merged.ui.profiles.customGroupFilter = asString(
4344
- merged.ui.profiles.customGroupFilter
4345
- );
4346
- if (typeof merged.ui.profiles.toolbarOpen !== "boolean") {
4347
- merged.ui.profiles.toolbarOpen = null;
4348
- }
4349
- if (!isRecord2(merged.ui.profiles.collapsedSections)) {
4350
- merged.ui.profiles.collapsedSections = {};
4351
- } else {
4352
- merged.ui.profiles.collapsedSections = Object.fromEntries(
4353
- Object.entries(merged.ui.profiles.collapsedSections).flatMap(
4354
- ([key, value3]) => {
4355
- const normalizedKey = asString(key);
4356
- if (!normalizedKey || typeof value3 !== "boolean") {
4357
- return [];
4358
- }
4359
- return [[normalizedKey, value3]];
4360
- }
4361
- )
4362
- );
4363
- }
4492
+ const collapsedProfileSections = isRecord2(merged.ui.profiles) ? merged.ui.profiles.collapsedSections : null;
4493
+ merged.ui.profiles = {
4494
+ collapsedSections: isRecord2(collapsedProfileSections) ? Object.fromEntries(
4495
+ Object.entries(collapsedProfileSections).flatMap(([key, value3]) => {
4496
+ const normalizedKey = asString(key);
4497
+ if (!normalizedKey || typeof value3 !== "boolean") {
4498
+ return [];
4499
+ }
4500
+ return [[normalizedKey, value3]];
4501
+ })
4502
+ ) : {}
4503
+ };
4364
4504
  if (!isRecord2(merged.ui.onboarding)) {
4365
4505
  merged.ui.onboarding = clone2(defaults.ui.onboarding);
4366
4506
  }
@@ -4370,7 +4510,7 @@ function normalizeAppState(raw) {
4370
4510
  if (!Number.isFinite(merged.ui.onboarding.welcomeCompletedAt)) {
4371
4511
  merged.ui.onboarding.welcomeCompletedAt = null;
4372
4512
  }
4373
- merged.ui.onboarding.welcomeResumeStep = merged.ui.onboarding.welcomeResumeStep === 2 ? 2 : null;
4513
+ delete merged.ui.onboarding.welcomeResumeStep;
4374
4514
  if (!isRecord2(merged.ui.onboarding.milestones)) {
4375
4515
  merged.ui.onboarding.milestones = clone2(defaults.ui.onboarding.milestones);
4376
4516
  }
@@ -4512,10 +4652,10 @@ function normalizeAppState(raw) {
4512
4652
  ([rootPath, profileName]) => {
4513
4653
  const normalizedRoot = asString(rootPath);
4514
4654
  const normalizedProfile = asString(profileName);
4515
- if (!normalizedRoot || !import_node_path3.default.isAbsolute(normalizedRoot) || !normalizedProfile) {
4655
+ if (!normalizedRoot || !import_node_path4.default.isAbsolute(normalizedRoot) || !normalizedProfile) {
4516
4656
  return [];
4517
4657
  }
4518
- return [[import_node_path3.default.normalize(normalizedRoot), normalizedProfile]];
4658
+ return [[import_node_path4.default.normalize(normalizedRoot), normalizedProfile]];
4519
4659
  }
4520
4660
  )
4521
4661
  );
@@ -4606,7 +4746,11 @@ async function ensureInitialized() {
4606
4746
  if (memoryState && Date.now() < nextPersistenceRetryAt) {
4607
4747
  return memoryState;
4608
4748
  }
4609
- const attempt = readStoredAppStateForInit();
4749
+ const attempt = withCloudSyncTransaction(
4750
+ getUserDataDir(),
4751
+ "write",
4752
+ readStoredAppStateForInit
4753
+ );
4610
4754
  attempt.catch(() => void 0);
4611
4755
  let deadlineTimer;
4612
4756
  const deadline = new Promise((resolve2) => {
@@ -4671,56 +4815,77 @@ async function getAppState() {
4671
4815
  return state;
4672
4816
  }
4673
4817
  async function refreshAppStateCache() {
4674
- return withWriteLock(async () => {
4675
- const stored = await readStoredAppStateOrNull();
4676
- if (!stored) {
4677
- return ensureInitialized();
4818
+ try {
4819
+ return await withCloudSyncTransaction(
4820
+ getUserDataDir(),
4821
+ "write",
4822
+ () => withWriteLock(async () => {
4823
+ const stored = await readStoredAppStateOrNull();
4824
+ if (!stored) {
4825
+ return ensureInitialized();
4826
+ }
4827
+ appStateCache = freezeDeep(stored);
4828
+ ephemeralAppState = null;
4829
+ persistenceFailure = null;
4830
+ return appStateCache;
4831
+ })
4832
+ );
4833
+ } catch (error) {
4834
+ const busyLock = error instanceof CloudSyncTransactionLockError && error.reason === "busy";
4835
+ if (!busyLock) {
4836
+ const cause = error instanceof CloudSyncTransactionLockError ? error.cause ?? error : error;
4837
+ persistenceFailure = {
4838
+ kind: classifyAppStorageFailure(cause),
4839
+ message: cause instanceof Error ? cause.message : String(cause)
4840
+ };
4841
+ nextPersistenceRetryAt = Date.now() + PERSISTENCE_RETRY_COOLDOWN_MS;
4678
4842
  }
4679
- appStateCache = freezeDeep(stored);
4680
- ephemeralAppState = null;
4681
- persistenceFailure = null;
4682
- return appStateCache;
4683
- });
4843
+ return withWriteLock(() => ensureInitialized());
4844
+ }
4684
4845
  }
4685
4846
  async function updateAppState(transform3, options = {}) {
4686
4847
  const mode = options.mode ?? "patch";
4687
- return withWriteLock(async () => {
4688
- const shouldNormalize = options.normalize !== false;
4689
- const pendingUiPatch = pendingRendererUiPatch;
4690
- try {
4691
- const stored = await updateDocument({
4692
- dbPath: resolveStorageDbPath(),
4693
- namespace: APP_STATE_DOCUMENT,
4694
- normalize: normalizeAppState,
4695
- fallback: () => normalizeAppState(null),
4696
- cloneBeforeTransform: false,
4697
- normalizeResult: shouldNormalize,
4698
- cloneResult: false,
4699
- strictExisting: true,
4700
- transform: (current) => {
4701
- const transformed = transform3(
4702
- options.cloneCurrent === false ? current : clone2(current)
4703
- );
4704
- const next = mode === "replace" ? transformed : deepMerge(current, transformed);
4705
- return pendingUiPatch ? deepMerge(next, { ui: pendingUiPatch }) : next;
4848
+ return withCloudSyncTransaction(
4849
+ getUserDataDir(),
4850
+ "write",
4851
+ () => withWriteLock(async () => {
4852
+ const shouldNormalize = options.normalize !== false;
4853
+ const pendingUiPatch = pendingRendererUiPatch;
4854
+ try {
4855
+ const stored = await updateDocument({
4856
+ dbPath: resolveStorageDbPath(),
4857
+ namespace: APP_STATE_DOCUMENT,
4858
+ normalize: normalizeAppState,
4859
+ fallback: () => normalizeAppState(null),
4860
+ cloneBeforeTransform: false,
4861
+ normalizeResult: shouldNormalize,
4862
+ cloneResult: false,
4863
+ strictExisting: true,
4864
+ transform: (current) => {
4865
+ const transformed = transform3(
4866
+ options.cloneCurrent === false ? current : clone2(current)
4867
+ );
4868
+ const next = mode === "replace" ? transformed : deepMerge(current, transformed);
4869
+ return pendingUiPatch ? deepMerge(next, { ui: pendingUiPatch }) : next;
4870
+ }
4871
+ });
4872
+ if (pendingRendererUiPatch === pendingUiPatch) {
4873
+ pendingRendererUiPatch = null;
4706
4874
  }
4707
- });
4708
- if (pendingRendererUiPatch === pendingUiPatch) {
4709
- pendingRendererUiPatch = null;
4875
+ appStateCache = freezeDeep(stored);
4876
+ ephemeralAppState = null;
4877
+ persistenceFailure = null;
4878
+ return appStateCache;
4879
+ } catch (error) {
4880
+ persistenceFailure = {
4881
+ kind: classifyAppStorageFailure(error),
4882
+ message: error instanceof Error ? error.message : String(error)
4883
+ };
4884
+ nextPersistenceRetryAt = Date.now() + PERSISTENCE_RETRY_COOLDOWN_MS;
4885
+ throw error;
4710
4886
  }
4711
- appStateCache = freezeDeep(stored);
4712
- ephemeralAppState = null;
4713
- persistenceFailure = null;
4714
- return appStateCache;
4715
- } catch (error) {
4716
- persistenceFailure = {
4717
- kind: classifyAppStorageFailure(error),
4718
- message: error instanceof Error ? error.message : String(error)
4719
- };
4720
- nextPersistenceRetryAt = Date.now() + PERSISTENCE_RETRY_COOLDOWN_MS;
4721
- throw error;
4722
- }
4723
- });
4887
+ })
4888
+ );
4724
4889
  }
4725
4890
  async function patchAppState(patch) {
4726
4891
  return updateAppState(() => patch, {
@@ -4780,10 +4945,6 @@ function withCurrentRuntimeDefaults(settings, options = {}) {
4780
4945
  changed = true;
4781
4946
  }
4782
4947
  }
4783
- if (next.rateLimitPercentMode !== "remaining" && next.rateLimitPercentMode !== "used") {
4784
- next.rateLimitPercentMode = "remaining";
4785
- changed = true;
4786
- }
4787
4948
  if (next.officialCodexRelayMode !== "official" && next.officialCodexRelayMode !== "off" && next.officialCodexRelayMode !== void 0) {
4788
4949
  next.officialCodexRelayMode = "off";
4789
4950
  changed = true;
@@ -4896,7 +5057,6 @@ function parseStoredTrial(raw) {
4896
5057
  }
4897
5058
  var CLOUD_SYNC_RUNTIME_SETTING_KEYS = /* @__PURE__ */ new Set([
4898
5059
  "keepAppRunningAfterWindowClose",
4899
- "rateLimitPercentMode",
4900
5060
  "officialCodexWideViewEnabled",
4901
5061
  "officialCodexWideViewMaxWidth",
4902
5062
  "officialCodexScrollRestoreEnabled",
@@ -5408,6 +5568,9 @@ function buildTrialInfo(stored, now2) {
5408
5568
  daysLeft
5409
5569
  };
5410
5570
  }
5571
+ function lockReasonFor(info) {
5572
+ return info.expired ? "trial-ended" : null;
5573
+ }
5411
5574
  function buildLockedTrialInfo(stored) {
5412
5575
  return {
5413
5576
  active: false,
@@ -5551,7 +5714,7 @@ function readServerVerifiedTrial(now2) {
5551
5714
  }
5552
5715
  async function resolveTrialState(now2 = Date.now(), options = {}) {
5553
5716
  if (!isTrialEnforcementEnabled()) {
5554
- return { info: null, locked: false };
5717
+ return { info: null, locked: false, lockReason: null };
5555
5718
  }
5556
5719
  const allowNetwork = options.allowNetwork !== false;
5557
5720
  const secret = await getLicenseSecret();
@@ -5566,16 +5729,20 @@ async function resolveTrialState(now2 = Date.now(), options = {}) {
5566
5729
  if (hasLocalClockRollback(cached2, now2)) {
5567
5730
  const refreshed2 = allowNetwork ? await syncAndPersistTrial({ stored: cached2, secret, now: now2 }) : null;
5568
5731
  if (!refreshed2) {
5569
- return { info: buildLockedTrialInfo(cached2), locked: true };
5732
+ return {
5733
+ info: buildLockedTrialInfo(cached2),
5734
+ locked: true,
5735
+ lockReason: "unverified"
5736
+ };
5570
5737
  }
5571
5738
  const info3 = buildTrialInfo(refreshed2, trustedTrialNow(refreshed2, now2));
5572
- return { info: info3, locked: info3.expired };
5739
+ return { info: info3, locked: info3.expired, lockReason: lockReasonFor(info3) };
5573
5740
  }
5574
5741
  if (shouldRefreshInBackground(cached2, now2)) {
5575
5742
  void syncTrialWithServer({ force: true }).catch(() => void 0);
5576
5743
  }
5577
5744
  const info2 = buildTrialInfo(cached2, trustedTrialNow(cached2, now2));
5578
- return { info: info2, locked: info2.expired };
5745
+ return { info: info2, locked: info2.expired, lockReason: lockReasonFor(info2) };
5579
5746
  }
5580
5747
  }
5581
5748
  if (stored && (!currentDeviceId || !hasTrustedServerRecord(stored, secret, currentDeviceId))) {
@@ -5589,15 +5756,19 @@ async function resolveTrialState(now2 = Date.now(), options = {}) {
5589
5756
  startTrialSyncInBackground();
5590
5757
  }
5591
5758
  const info2 = buildTrialInfo(next, trustedTrialNow(next, now2));
5592
- return { info: info2, locked: info2.expired };
5759
+ return { info: info2, locked: info2.expired, lockReason: lockReasonFor(info2) };
5593
5760
  }
5594
5761
  if (options.refreshInBackground === true) {
5595
5762
  startTrialSyncInBackground();
5596
5763
  }
5597
5764
  if (!hadStoredTrial && options.refreshInBackground === true) {
5598
- return { info: null, locked: false };
5765
+ return { info: null, locked: false, lockReason: null };
5599
5766
  }
5600
- return { info: buildLockedTrialInfo(stored), locked: true };
5767
+ return {
5768
+ info: buildLockedTrialInfo(stored),
5769
+ locked: true,
5770
+ lockReason: "unverified"
5771
+ };
5601
5772
  }
5602
5773
  const refreshed = await syncAndPersistTrial({ stored, secret, now: now2 });
5603
5774
  if (!refreshed) {
@@ -5605,12 +5776,16 @@ async function resolveTrialState(now2 = Date.now(), options = {}) {
5605
5776
  const next = await persistLocalSeenIfNeeded(stored, secret, now2).catch(() => stored);
5606
5777
  rememberServerVerifiedTrial(next, now2);
5607
5778
  const info2 = buildTrialInfo(next, trustedTrialNow(next, now2));
5608
- return { info: info2, locked: info2.expired };
5779
+ return { info: info2, locked: info2.expired, lockReason: lockReasonFor(info2) };
5609
5780
  }
5610
- return { info: buildLockedTrialInfo(stored), locked: true };
5781
+ return {
5782
+ info: buildLockedTrialInfo(stored),
5783
+ locked: true,
5784
+ lockReason: "unverified"
5785
+ };
5611
5786
  }
5612
5787
  const info = buildTrialInfo(refreshed, trustedTrialNow(refreshed, now2));
5613
- return { info, locked: info.expired };
5788
+ return { info, locked: info.expired, lockReason: lockReasonFor(info) };
5614
5789
  }
5615
5790
  async function syncTrialWithServer(opts = {}) {
5616
5791
  if (!isTrialEnforcementEnabled()) {
@@ -5643,7 +5818,8 @@ var BASE_PRICE_DISPLAY = offer.basePriceDisplay;
5643
5818
  var PROMO_CODE = offer.couponCode;
5644
5819
  var PROMO_PERCENT = offer.discountPercent;
5645
5820
  var PROMO_ACTIVE = offer.isActive;
5646
- var LICENSE_MAX_USES = 5;
5821
+ var LICENSE_MAX_DEVICES = 5;
5822
+ var DEFAULT_ACTIVATION_API_URL = "https://api.codexuse.com/v1/activation";
5647
5823
  var FREE_PROFILE_LIMIT = 2;
5648
5824
  var LICENSE_REFRESH_INTERVAL_MS = 5 * 60 * 1e3;
5649
5825
  var MAX_NEXT_CHECK_MS = 60 * 60 * 1e3;
@@ -5711,7 +5887,7 @@ function isSignatureValid2(license, secret) {
5711
5887
  const expected = signLicense(license, secret);
5712
5888
  return expected === license.signature;
5713
5889
  }
5714
- async function requestGumroadVerify(licenseKey, mode) {
5890
+ async function requestGumroadVerify(licenseKey) {
5715
5891
  const controller = new AbortController();
5716
5892
  const timeout2 = setTimeout(() => controller.abort(), 1e4);
5717
5893
  try {
@@ -5719,7 +5895,7 @@ async function requestGumroadVerify(licenseKey, mode) {
5719
5895
  product_permalink: PRODUCT_PERMALINK,
5720
5896
  product_id: PRODUCT_ID,
5721
5897
  license_key: licenseKey,
5722
- increment_uses_count: mode === "activation" ? "true" : "false"
5898
+ increment_uses_count: "false"
5723
5899
  });
5724
5900
  const response = await fetch("https://api.gumroad.com/v2/licenses/verify", {
5725
5901
  method: "POST",
@@ -5751,6 +5927,41 @@ async function requestGumroadVerify(licenseKey, mode) {
5751
5927
  clearTimeout(timeout2);
5752
5928
  }
5753
5929
  }
5930
+ async function requestDeviceActivation(licenseKey) {
5931
+ const controller = new AbortController();
5932
+ const timeout2 = setTimeout(() => controller.abort(), 1e4);
5933
+ try {
5934
+ const baseUrl = (process.env.CODEXUSE_ACTIVATION_API_URL?.trim() || DEFAULT_ACTIVATION_API_URL).replace(/\/+$/, "");
5935
+ const response = await fetch(`${baseUrl}/device`, {
5936
+ method: "POST",
5937
+ headers: { "Content-Type": "application/json" },
5938
+ body: JSON.stringify({ licenseKey, deviceId: await getDeviceId() }),
5939
+ signal: controller.signal
5940
+ });
5941
+ const payload = await response.json().catch(() => null);
5942
+ if (!response.ok) {
5943
+ const message = typeof payload?.error === "string" && payload.error.trim() ? payload.error.trim() : `License activation failed (${response.status}).`;
5944
+ const code = response.status >= 500 ? "network" : isExplicitRevocationMessage(message) ? "revoked" : "invalid";
5945
+ throw new LicenseError(message, code);
5946
+ }
5947
+ return {
5948
+ email: typeof payload?.purchaseEmail === "string" ? payload.purchaseEmail.trim() || null : null
5949
+ };
5950
+ } catch (error) {
5951
+ if (error instanceof LicenseError) {
5952
+ throw error;
5953
+ }
5954
+ if (error instanceof Error && error.name === "AbortError") {
5955
+ throw new LicenseError("License activation timed out.", "network");
5956
+ }
5957
+ throw new LicenseError(
5958
+ error instanceof Error ? error.message : "Unable to reach the license server.",
5959
+ "network"
5960
+ );
5961
+ } finally {
5962
+ clearTimeout(timeout2);
5963
+ }
5964
+ }
5754
5965
  function isExplicitRevocationMessage(message) {
5755
5966
  if (!message) {
5756
5967
  return false;
@@ -5758,10 +5969,10 @@ function isExplicitRevocationMessage(message) {
5758
5969
  const normalized = message.toLowerCase();
5759
5970
  return normalized.includes("revoked") || normalized.includes("refunded") || normalized.includes("chargeback") || normalized.includes("disabled") || normalized.includes("subscription") || normalized.includes("no longer active");
5760
5971
  }
5761
- function normalizeVerificationResult(response, mode) {
5972
+ function normalizeVerificationResult(response) {
5762
5973
  if (!response.success) {
5763
5974
  const message = response.message ?? "License key is invalid.";
5764
- if (mode === "refresh" && !isExplicitRevocationMessage(message)) {
5975
+ if (!isExplicitRevocationMessage(message)) {
5765
5976
  throw new LicenseError(message, "network");
5766
5977
  }
5767
5978
  throw new LicenseError(message, "invalid");
@@ -5778,20 +5989,6 @@ function normalizeVerificationResult(response, mode) {
5778
5989
  const email = response.purchase.email ?? null;
5779
5990
  return { email };
5780
5991
  }
5781
- function ensureWithinUseLimit(response) {
5782
- if (!response.success) {
5783
- return;
5784
- }
5785
- if (typeof response.uses !== "number") {
5786
- return;
5787
- }
5788
- if (response.uses > LICENSE_MAX_USES) {
5789
- throw new LicenseError(
5790
- `This license has reached the activation limit (${LICENSE_MAX_USES}). Contact support to move it to another device.`,
5791
- "invalid"
5792
- );
5793
- }
5794
- }
5795
5992
  function computeCapabilities(opts) {
5796
5993
  return {
5797
5994
  unlimitedProfiles: opts.entitled,
@@ -5805,7 +6002,7 @@ function applyTrial(base2, trial) {
5805
6002
  if (base2.isPro) {
5806
6003
  return { ...base2, trial: null };
5807
6004
  }
5808
- const { info, locked } = trial;
6005
+ const { info, locked, lockReason } = trial;
5809
6006
  if (!info) {
5810
6007
  return base2;
5811
6008
  }
@@ -5825,6 +6022,10 @@ function applyTrial(base2, trial) {
5825
6022
  ...base2,
5826
6023
  tier: "free",
5827
6024
  state: "locked",
6025
+ // From the boundary that knows. The frontend used to read expiresAt and
6026
+ // call any lock an ended trial, but buildLockedTrialInfo keeps a stored
6027
+ // expiresAt that can be in the future.
6028
+ lockReason: lockReason ?? "unverified",
5828
6029
  capabilities: computeCapabilities({ licensed: false, entitled: false }),
5829
6030
  profileLimit: 0,
5830
6031
  profilesRemaining: 0,
@@ -5840,6 +6041,9 @@ function toLicenseStatus(stored, overrides = {}) {
5840
6041
  const base2 = {
5841
6042
  tier,
5842
6043
  state,
6044
+ // applyTrial sets this when it moves the state to "locked". Nothing else
6045
+ // locks, so nothing else has a reason.
6046
+ lockReason: null,
5843
6047
  isPro,
5844
6048
  capabilities: computeCapabilities({ licensed: isPro, entitled: isPro }),
5845
6049
  trial: null,
@@ -5859,7 +6063,7 @@ function toLicenseStatus(stored, overrides = {}) {
5859
6063
  basePriceDisplay: BASE_PRICE_DISPLAY,
5860
6064
  promoCode: PROMO_ACTIVE ? PROMO_CODE : null,
5861
6065
  promoPercent: PROMO_ACTIVE ? PROMO_PERCENT : null,
5862
- maxDevices: LICENSE_MAX_USES
6066
+ maxDevices: LICENSE_MAX_DEVICES
5863
6067
  };
5864
6068
  return { ...base2, ...overrides };
5865
6069
  }
@@ -5946,9 +6150,8 @@ var LicenseService = class {
5946
6150
  }
5947
6151
  const verify = async () => {
5948
6152
  try {
5949
- const result2 = await requestGumroadVerify(workingStored.licenseKey, "refresh");
5950
- ensureWithinUseLimit(result2);
5951
- const normalized = normalizeVerificationResult(result2, "refresh");
6153
+ const result2 = await requestGumroadVerify(workingStored.licenseKey);
6154
+ const normalized = normalizeVerificationResult(result2);
5952
6155
  const updated = {
5953
6156
  licenseKey: workingStored.licenseKey,
5954
6157
  purchaseEmail: normalized.email,
@@ -6005,9 +6208,7 @@ var LicenseService = class {
6005
6208
  }
6006
6209
  const secret = await getLicenseSecret();
6007
6210
  const digest = import_node_crypto7.default.createHash("sha256").update(trimmed).digest("hex");
6008
- const result2 = await requestGumroadVerify(trimmed, "activation");
6009
- ensureWithinUseLimit(result2);
6010
- const normalized = normalizeVerificationResult(result2, "activation");
6211
+ const normalized = await requestDeviceActivation(trimmed);
6011
6212
  const stored = {
6012
6213
  licenseKey: trimmed,
6013
6214
  purchaseEmail: normalized.email,
@@ -6067,7 +6268,7 @@ function shouldEnforceProfileLimit(status) {
6067
6268
  }
6068
6269
 
6069
6270
  // ../../packages/runtime-profiles/src/profiles/profile-manager.ts
6070
- var import_node_crypto12 = require("crypto");
6271
+ var import_node_crypto13 = require("crypto");
6071
6272
  var import_fs = require("fs");
6072
6273
  var import_node_os5 = __toESM(require("os"), 1);
6073
6274
  var import_path = __toESM(require("path"), 1);
@@ -6125,30 +6326,32 @@ function resolveProfileIdentityKeyFromProfile(profile) {
6125
6326
  }
6126
6327
 
6127
6328
  // ../../packages/runtime-codex/src/codex/rpc.ts
6128
- var import_node_child_process5 = require("child_process");
6129
- var import_node_crypto9 = require("crypto");
6329
+ var import_node_child_process6 = require("child_process");
6330
+ var import_node_crypto10 = require("crypto");
6130
6331
  var import_node_readline = __toESM(require("readline"), 1);
6131
6332
  var import_node_fs6 = require("fs");
6132
6333
  var import_node_os3 = __toESM(require("os"), 1);
6133
- var import_node_path9 = __toESM(require("path"), 1);
6334
+ var import_node_path10 = __toESM(require("path"), 1);
6134
6335
 
6135
6336
  // ../../packages/runtime-codex/src/codex/cli.ts
6337
+ var import_node_child_process3 = require("child_process");
6136
6338
  var import_node_fs4 = require("fs");
6137
- var import_node_path4 = __toESM(require("path"), 1);
6339
+ var import_node_path5 = __toESM(require("path"), 1);
6138
6340
  var STABLE_CHANNEL = "stable";
6139
6341
  var ENV_HINTS = ["CODEX_BINARY", "CODEX_CLI_PATH", "CODEX_PATH"];
6140
6342
  var cachedStatus = null;
6343
+ var cachedVersion = null;
6141
6344
  function getPathHintEntries() {
6142
6345
  const homeDir = process.env.HOME ?? "";
6143
6346
  const homeEntries = homeDir ? [
6144
- import_node_path4.default.join(homeDir, ".local", "bin"),
6145
- import_node_path4.default.join(homeDir, ".fnm", "aliases", "default", "bin"),
6146
- import_node_path4.default.join(homeDir, ".fnm", "current", "bin"),
6147
- import_node_path4.default.join(homeDir, ".volta", "bin"),
6148
- import_node_path4.default.join(homeDir, ".asdf", "shims"),
6149
- import_node_path4.default.join(homeDir, ".bun", "bin")
6347
+ import_node_path5.default.join(homeDir, ".local", "bin"),
6348
+ import_node_path5.default.join(homeDir, ".fnm", "aliases", "default", "bin"),
6349
+ import_node_path5.default.join(homeDir, ".fnm", "current", "bin"),
6350
+ import_node_path5.default.join(homeDir, ".volta", "bin"),
6351
+ import_node_path5.default.join(homeDir, ".asdf", "shims"),
6352
+ import_node_path5.default.join(homeDir, ".bun", "bin")
6150
6353
  ] : [];
6151
- const configuredHints = (process.env.CODEX_PATH_HINTS ?? "").split(import_node_path4.default.delimiter).map((entry) => entry.trim()).filter(Boolean);
6354
+ const configuredHints = (process.env.CODEX_PATH_HINTS ?? "").split(import_node_path5.default.delimiter).map((entry) => entry.trim()).filter(Boolean);
6152
6355
  return [
6153
6356
  "/opt/homebrew/bin",
6154
6357
  "/usr/local/bin",
@@ -6160,7 +6363,7 @@ function fileExists(candidate) {
6160
6363
  if (!candidate) {
6161
6364
  return null;
6162
6365
  }
6163
- const normalized = import_node_path4.default.resolve(candidate);
6366
+ const normalized = import_node_path5.default.resolve(candidate);
6164
6367
  try {
6165
6368
  const stats = (0, import_node_fs4.statSync)(normalized);
6166
6369
  if (stats.isFile()) {
@@ -6189,12 +6392,12 @@ function resolveCodexFromPath() {
6189
6392
  new Set(
6190
6393
  [
6191
6394
  ...getPathHintEntries(),
6192
- ...pathValue.split(import_node_path4.default.delimiter).map((entry) => entry.trim()).filter(Boolean)
6395
+ ...pathValue.split(import_node_path5.default.delimiter).map((entry) => entry.trim()).filter(Boolean)
6193
6396
  ].filter(Boolean)
6194
6397
  )
6195
6398
  );
6196
6399
  for (const entry of entries3) {
6197
- const candidate = fileExists(import_node_path4.default.join(entry, "codex"));
6400
+ const candidate = fileExists(import_node_path5.default.join(entry, "codex"));
6198
6401
  if (candidate) {
6199
6402
  return candidate;
6200
6403
  }
@@ -6236,8 +6439,59 @@ function evaluateExternalStatus() {
6236
6439
  function evaluateCodexCliStatus() {
6237
6440
  return evaluateExternalStatus();
6238
6441
  }
6442
+ function runVersionPreflight(cliPath) {
6443
+ return new Promise((resolve2) => {
6444
+ const useNode = /\.(?:c|m)?js$/i.test(cliPath);
6445
+ const child = (0, import_node_child_process3.spawn)(
6446
+ useNode ? process.execPath : cliPath,
6447
+ useNode ? [cliPath, "--version"] : ["--version"],
6448
+ {
6449
+ env: process.env,
6450
+ stdio: ["ignore", "pipe", "pipe"]
6451
+ }
6452
+ );
6453
+ let output = "";
6454
+ let settled = false;
6455
+ const finish = (version) => {
6456
+ if (settled) {
6457
+ return;
6458
+ }
6459
+ settled = true;
6460
+ clearTimeout(timeout2);
6461
+ resolve2(version);
6462
+ };
6463
+ const collect = (chunk) => {
6464
+ if (output.length < 1024) {
6465
+ output += chunk.toString();
6466
+ }
6467
+ };
6468
+ child.stdout?.on("data", collect);
6469
+ child.stderr?.on("data", collect);
6470
+ child.on("error", () => finish(null));
6471
+ child.on("close", (code) => {
6472
+ const trimmed = output.trim();
6473
+ const version = trimmed.match(/\b\d+\.\d+\.\d+(?:[-+][\w.-]+)?\b/)?.[0] ?? null;
6474
+ finish(code === 0 ? version : null);
6475
+ });
6476
+ const timeout2 = setTimeout(() => {
6477
+ child.kill();
6478
+ finish(null);
6479
+ }, 5e3);
6480
+ });
6481
+ }
6239
6482
  async function refreshCodexStatus() {
6240
- cachedStatus = evaluateCodexCliStatus();
6483
+ const discovered = evaluateCodexCliStatus();
6484
+ cachedVersion = null;
6485
+ if (discovered.available && discovered.path) {
6486
+ cachedVersion = await runVersionPreflight(discovered.path);
6487
+ cachedStatus = cachedVersion ? discovered : {
6488
+ ...discovered,
6489
+ available: false,
6490
+ reason: "Codex CLI was found but cannot run. Repair the Codex CLI, then try again."
6491
+ };
6492
+ } else {
6493
+ cachedStatus = discovered;
6494
+ }
6241
6495
  return { ...cachedStatus };
6242
6496
  }
6243
6497
  var CodexCliMissingError = class extends Error {
@@ -6257,8 +6511,8 @@ async function requireCodexCli() {
6257
6511
  }
6258
6512
 
6259
6513
  // ../../packages/runtime-codex/src/codex/command.ts
6260
- var import_node_child_process3 = require("child_process");
6261
- var import_node_path5 = __toESM(require("path"), 1);
6514
+ var import_node_child_process4 = require("child_process");
6515
+ var import_node_path6 = __toESM(require("path"), 1);
6262
6516
  var cachedNodeRuntime = null;
6263
6517
  function isJavaScriptEntrypoint(binaryPath) {
6264
6518
  const normalized = binaryPath.trim().toLowerCase();
@@ -6274,19 +6528,19 @@ function resolveNodeRuntime(env) {
6274
6528
  }
6275
6529
  const runtimeEnv = { ...process.env, ...env };
6276
6530
  const homeDir = runtimeEnv.HOME ?? "";
6277
- const pathHints = (runtimeEnv.CODEX_PATH_HINTS ?? process.env.CODEX_PATH_HINTS ?? "").split(import_node_path5.default.delimiter).map((entry) => entry.trim()).filter(Boolean);
6531
+ const pathHints = (runtimeEnv.CODEX_PATH_HINTS ?? process.env.CODEX_PATH_HINTS ?? "").split(import_node_path6.default.delimiter).map((entry) => entry.trim()).filter(Boolean);
6278
6532
  const extraPathEntries = [
6279
6533
  "/usr/local/bin",
6280
6534
  "/opt/homebrew/bin",
6281
- import_node_path5.default.join(homeDir, ".local", "bin"),
6282
- import_node_path5.default.join(homeDir, ".fnm", "aliases", "default", "bin"),
6283
- import_node_path5.default.join(homeDir, ".fnm", "current", "bin"),
6535
+ import_node_path6.default.join(homeDir, ".local", "bin"),
6536
+ import_node_path6.default.join(homeDir, ".fnm", "aliases", "default", "bin"),
6537
+ import_node_path6.default.join(homeDir, ".fnm", "current", "bin"),
6284
6538
  ...pathHints
6285
6539
  ].filter(Boolean);
6286
6540
  const currentPath = runtimeEnv.PATH ?? "";
6287
6541
  runtimeEnv.PATH = Array.from(
6288
- /* @__PURE__ */ new Set([...extraPathEntries, ...currentPath.split(import_node_path5.default.delimiter).filter(Boolean)])
6289
- ).join(import_node_path5.default.delimiter);
6542
+ /* @__PURE__ */ new Set([...extraPathEntries, ...currentPath.split(import_node_path6.default.delimiter).filter(Boolean)])
6543
+ ).join(import_node_path6.default.delimiter);
6290
6544
  const candidates = Array.from(
6291
6545
  new Set(
6292
6546
  [
@@ -6300,7 +6554,7 @@ function resolveNodeRuntime(env) {
6300
6554
  )
6301
6555
  );
6302
6556
  for (const candidate of candidates) {
6303
- const probe = (0, import_node_child_process3.spawnSync)(candidate, ["-v"], { env: runtimeEnv, stdio: "ignore" });
6557
+ const probe = (0, import_node_child_process4.spawnSync)(candidate, ["-v"], { env: runtimeEnv, stdio: "ignore" });
6304
6558
  if (!probe.error && probe.status === 0) {
6305
6559
  cachedNodeRuntime = candidate;
6306
6560
  return candidate;
@@ -6329,7 +6583,7 @@ var import_node_crypto8 = require("crypto");
6329
6583
  var import_node_fs5 = require("fs");
6330
6584
  var import_promises2 = require("fs/promises");
6331
6585
  var import_node_os2 = __toESM(require("os"), 1);
6332
- var import_node_path6 = __toESM(require("path"), 1);
6586
+ var import_node_path7 = __toESM(require("path"), 1);
6333
6587
  function resolveHomeDir() {
6334
6588
  return process.env.HOME || import_node_os2.default.homedir();
6335
6589
  }
@@ -6338,7 +6592,7 @@ function expandHomePrefix(input, homeDir) {
6338
6592
  return homeDir;
6339
6593
  }
6340
6594
  if (input.startsWith("~/") || input.startsWith("~\\")) {
6341
- return import_node_path6.default.join(homeDir, input.slice(2));
6595
+ return import_node_path7.default.join(homeDir, input.slice(2));
6342
6596
  }
6343
6597
  return input;
6344
6598
  }
@@ -6354,23 +6608,23 @@ function normalizeCodexHomePath(input) {
6354
6608
  if (!configured) {
6355
6609
  return null;
6356
6610
  }
6357
- return import_node_path6.default.resolve(expandHomePrefix(configured, resolveHomeDir()));
6611
+ return import_node_path7.default.resolve(expandHomePrefix(configured, resolveHomeDir()));
6358
6612
  }
6359
6613
  function resolveDefaultCodexHomeDir() {
6360
- return normalizeCodexHomePath(process.env.CODEX_HOME) ?? import_node_path6.default.join(resolveHomeDir(), ".codex");
6614
+ return normalizeCodexHomePath(process.env.CODEX_HOME) ?? import_node_path7.default.join(resolveHomeDir(), ".codex");
6361
6615
  }
6362
6616
  function resolveCodexSqliteHomeDir(codexHomePath) {
6363
6617
  return normalizeCodexHomePath(process.env.CODEX_SQLITE_HOME) ?? resolveCodexHomeDir({ codexHomePath });
6364
6618
  }
6365
6619
  function resolveCurrentProfileCodexHomeDir(profileHomeId) {
6366
- return import_node_path6.default.join(
6620
+ return import_node_path7.default.join(
6367
6621
  resolveProfileCodexHomesRoot(),
6368
6622
  (0, import_node_crypto8.createHash)("sha256").update(profileHomeId).digest("hex").slice(0, 20)
6369
6623
  );
6370
6624
  }
6371
6625
  function resolveProfileCodexHomeDir(profileHomeId) {
6372
6626
  const current = resolveCurrentProfileCodexHomeDir(profileHomeId);
6373
- const legacy = import_node_path6.default.join(resolveLegacyProfileCodexHomesRoot(), profileHomeId);
6627
+ const legacy = import_node_path7.default.join(resolveLegacyProfileCodexHomesRoot(), profileHomeId);
6374
6628
  const currentExists = (0, import_node_fs5.existsSync)(current);
6375
6629
  const legacyExists = (0, import_node_fs5.existsSync)(legacy);
6376
6630
  if (currentExists && legacyExists) {
@@ -6380,15 +6634,15 @@ function resolveProfileCodexHomeDir(profileHomeId) {
6380
6634
  }
6381
6635
  function findProfileCodexHomeLocationConflict(profileHomeId) {
6382
6636
  const current = resolveCurrentProfileCodexHomeDir(profileHomeId);
6383
- const legacy = import_node_path6.default.join(resolveLegacyProfileCodexHomesRoot(), profileHomeId);
6637
+ const legacy = import_node_path7.default.join(resolveLegacyProfileCodexHomesRoot(), profileHomeId);
6384
6638
  return (0, import_node_fs5.existsSync)(current) && (0, import_node_fs5.existsSync)(legacy) ? { current, legacy } : null;
6385
6639
  }
6386
6640
  function resolveProfileCodexHomesRoot() {
6387
- return import_node_path6.default.join(resolveHomeDir(), ".codexuse", "p");
6641
+ return import_node_path7.default.join(resolveHomeDir(), ".codexuse", "p");
6388
6642
  }
6389
6643
  async function ensureProfileCodexHomesRoot() {
6390
6644
  const root = resolveProfileCodexHomesRoot();
6391
- const parent = import_node_path6.default.dirname(root);
6645
+ const parent = import_node_path7.default.dirname(root);
6392
6646
  await (0, import_promises2.mkdir)(parent, { recursive: true, mode: 448 });
6393
6647
  await (0, import_promises2.mkdir)(root, { recursive: true, mode: 448 });
6394
6648
  if (process.platform !== "win32") {
@@ -6398,10 +6652,10 @@ async function ensureProfileCodexHomesRoot() {
6398
6652
  return root;
6399
6653
  }
6400
6654
  function resolveLegacyProfileCodexHomesRoot() {
6401
- return import_node_path6.default.join(getUserDataDir(), "profile-homes");
6655
+ return import_node_path7.default.join(getUserDataDir(), "profile-homes");
6402
6656
  }
6403
6657
  async function migrateProfileCodexHomeDir(profileHomeId) {
6404
- const legacy = import_node_path6.default.join(resolveLegacyProfileCodexHomesRoot(), profileHomeId);
6658
+ const legacy = import_node_path7.default.join(resolveLegacyProfileCodexHomesRoot(), profileHomeId);
6405
6659
  const current = resolveCurrentProfileCodexHomeDir(profileHomeId);
6406
6660
  const currentExists = (0, import_node_fs5.existsSync)(current);
6407
6661
  const legacyExists = (0, import_node_fs5.existsSync)(legacy);
@@ -6478,9 +6732,9 @@ function buildCodexChildEnv(overrides = {}) {
6478
6732
  var import_toml = __toESM(require_toml(), 1);
6479
6733
 
6480
6734
  // ../../packages/runtime-codex/src/codex/config-metadata.ts
6481
- var import_node_child_process4 = require("child_process");
6735
+ var import_node_child_process5 = require("child_process");
6482
6736
  var import_promises3 = require("fs/promises");
6483
- var import_node_path7 = __toESM(require("path"), 1);
6737
+ var import_node_path8 = __toESM(require("path"), 1);
6484
6738
  var CONFIG_SCHEMA_URL = "https://raw.githubusercontent.com/openai/codex/main/codex-rs/core/config.schema.json";
6485
6739
  var METADATA_CACHE_TTL_MS = 6e4;
6486
6740
  var FALLBACK_SCHEMA_TOP_LEVEL_KEYS = [
@@ -6590,7 +6844,7 @@ function uniqueSorted(values2) {
6590
6844
  }
6591
6845
  async function runCommand(command, args2, timeoutMs = 3e3) {
6592
6846
  return new Promise((resolve2, reject) => {
6593
- const child = (0, import_node_child_process4.spawn)(command, args2, {
6847
+ const child = (0, import_node_child_process5.spawn)(command, args2, {
6594
6848
  stdio: ["ignore", "pipe", "pipe"],
6595
6849
  env: buildCodexChildEnv()
6596
6850
  });
@@ -6666,8 +6920,8 @@ function parseSchemaKeys(schemaRaw) {
6666
6920
  async function readSchemaFromLocal() {
6667
6921
  const candidates = [
6668
6922
  process.env.CODEX_CONFIG_SCHEMA_PATH,
6669
- import_node_path7.default.join(process.cwd(), "codex-rs", "core", "config.schema.json"),
6670
- import_node_path7.default.join(process.cwd(), "node_modules", "@openai", "codex", "codex-rs", "core", "config.schema.json")
6923
+ import_node_path8.default.join(process.cwd(), "codex-rs", "core", "config.schema.json"),
6924
+ import_node_path8.default.join(process.cwd(), "node_modules", "@openai", "codex", "codex-rs", "core", "config.schema.json")
6671
6925
  ].filter((candidate) => Boolean(candidate));
6672
6926
  for (const candidate of candidates) {
6673
6927
  try {
@@ -6771,8 +7025,9 @@ async function getCodexConfigMetadata(forceRefresh = false) {
6771
7025
  }
6772
7026
 
6773
7027
  // ../../packages/runtime-codex/src/codex/config-io.ts
7028
+ var import_node_crypto9 = require("crypto");
6774
7029
  var import_promises4 = require("fs/promises");
6775
- var import_node_path8 = __toESM(require("path"), 1);
7030
+ var import_node_path9 = __toESM(require("path"), 1);
6776
7031
 
6777
7032
  // ../../packages/runtime-codex/src/codex/config-presets.ts
6778
7033
  var DEFAULT_CONFIG_TEMPLATE = [
@@ -6815,12 +7070,55 @@ var YOLO_PRESET = {
6815
7070
 
6816
7071
  // ../../packages/runtime-codex/src/codex/config-io.ts
6817
7072
  function getConfigPath(options) {
6818
- return import_node_path8.default.join(resolveCodexHomeDir(options), "config.toml");
7073
+ return import_node_path9.default.join(resolveCodexHomeDir(options), "config.toml");
6819
7074
  }
6820
7075
  async function ensureConfigDirExists(filePath) {
6821
- const dir = import_node_path8.default.dirname(filePath);
7076
+ const dir = import_node_path9.default.dirname(filePath);
6822
7077
  await (0, import_promises4.mkdir)(dir, { recursive: true });
6823
7078
  }
7079
+ async function resolveConfigWriteTarget(configPath) {
7080
+ try {
7081
+ if (!(await (0, import_promises4.lstat)(configPath)).isSymbolicLink()) {
7082
+ return configPath;
7083
+ }
7084
+ try {
7085
+ return await (0, import_promises4.realpath)(configPath);
7086
+ } catch (error) {
7087
+ if (error.code !== "ENOENT") {
7088
+ throw error;
7089
+ }
7090
+ return import_node_path9.default.resolve(import_node_path9.default.dirname(configPath), await (0, import_promises4.readlink)(configPath));
7091
+ }
7092
+ } catch (error) {
7093
+ if (error.code === "ENOENT") {
7094
+ return configPath;
7095
+ }
7096
+ throw error;
7097
+ }
7098
+ }
7099
+ async function removeStaleConfigStagingFiles(targetPath) {
7100
+ const directory = import_node_path9.default.dirname(targetPath);
7101
+ const prefix = `${import_node_path9.default.basename(targetPath)}.tmp-`;
7102
+ const entries3 = await (0, import_promises4.readdir)(directory).catch((error) => {
7103
+ if (error.code === "ENOENT") {
7104
+ return [];
7105
+ }
7106
+ throw error;
7107
+ });
7108
+ await Promise.all(
7109
+ entries3.filter((entry) => entry.startsWith(prefix)).map((entry) => (0, import_promises4.rm)(import_node_path9.default.join(directory, entry), { force: true }))
7110
+ );
7111
+ }
7112
+ async function resolveConfigWriteMode(targetPath) {
7113
+ try {
7114
+ return (await (0, import_promises4.stat)(targetPath)).mode & 511;
7115
+ } catch (error) {
7116
+ if (error.code === "ENOENT") {
7117
+ return 384;
7118
+ }
7119
+ throw error;
7120
+ }
7121
+ }
6824
7122
  function normalizeLineEndings(content) {
6825
7123
  return content.replace(/\r\n/g, "\n");
6826
7124
  }
@@ -6829,29 +7127,76 @@ function ensureTrailingNewline(content) {
6829
7127
  `;
6830
7128
  }
6831
7129
  async function readConfigContent(options) {
6832
- const configPath = getConfigPath(options);
6833
- try {
6834
- const content = await (0, import_promises4.readFile)(configPath, "utf8");
6835
- return {
6836
- exists: true,
6837
- content: normalizeLineEndings(content)
6838
- };
6839
- } catch (error) {
6840
- const nodeError = error;
6841
- if (nodeError.code === "ENOENT") {
7130
+ return withCloudSyncTransaction(getUserDataDir(), "read", async () => {
7131
+ const configPath = getConfigPath(options);
7132
+ try {
7133
+ const content = await (0, import_promises4.readFile)(configPath, "utf8");
6842
7134
  return {
6843
- exists: false,
6844
- content: DEFAULT_CONFIG_TEMPLATE
7135
+ exists: true,
7136
+ content: normalizeLineEndings(content)
6845
7137
  };
7138
+ } catch (error) {
7139
+ const nodeError = error;
7140
+ if (nodeError.code === "ENOENT") {
7141
+ return {
7142
+ exists: false,
7143
+ content: DEFAULT_CONFIG_TEMPLATE
7144
+ };
7145
+ }
7146
+ throw error;
6846
7147
  }
6847
- throw error;
6848
- }
7148
+ });
6849
7149
  }
6850
7150
  async function writeConfigContent(content, options) {
6851
- const configPath = getConfigPath(options);
6852
- await ensureConfigDirExists(configPath);
6853
- const normalized = ensureTrailingNewline(normalizeLineEndings(content));
6854
- await (0, import_promises4.writeFile)(configPath, normalized, "utf8");
7151
+ await withCloudSyncTransaction(getUserDataDir(), "write", async () => {
7152
+ const configPath = getConfigPath(options);
7153
+ await ensureConfigDirExists(configPath);
7154
+ const targetPath = await resolveConfigWriteTarget(configPath);
7155
+ await removeStaleConfigStagingFiles(targetPath);
7156
+ const mode = await resolveConfigWriteMode(targetPath);
7157
+ const normalized = ensureTrailingNewline(normalizeLineEndings(content));
7158
+ const stagingPath = `${targetPath}.tmp-${process.pid}-${(0, import_node_crypto9.randomUUID)()}`;
7159
+ try {
7160
+ const handle = await (0, import_promises4.open)(stagingPath, "wx", mode);
7161
+ try {
7162
+ await handle.writeFile(normalized, "utf8");
7163
+ await handle.sync();
7164
+ } finally {
7165
+ await handle.close();
7166
+ }
7167
+ await (0, import_promises4.rename)(stagingPath, targetPath);
7168
+ if (process.platform !== "win32") {
7169
+ await (0, import_promises4.chmod)(targetPath, mode);
7170
+ const directory = await (0, import_promises4.open)(import_node_path9.default.dirname(targetPath), "r");
7171
+ try {
7172
+ await directory.sync();
7173
+ } finally {
7174
+ await directory.close();
7175
+ }
7176
+ }
7177
+ } finally {
7178
+ await (0, import_promises4.rm)(stagingPath, { force: true });
7179
+ }
7180
+ });
7181
+ }
7182
+ async function removeConfigContent(options) {
7183
+ await withCloudSyncTransaction(getUserDataDir(), "write", async () => {
7184
+ const configPath = getConfigPath(options);
7185
+ try {
7186
+ await (0, import_promises4.unlink)(configPath);
7187
+ } catch (error) {
7188
+ if (error.code === "ENOENT") {
7189
+ return;
7190
+ }
7191
+ throw error;
7192
+ }
7193
+ const directory = await (0, import_promises4.open)(import_node_path9.default.dirname(configPath), "r");
7194
+ try {
7195
+ await directory.sync();
7196
+ } finally {
7197
+ await directory.close();
7198
+ }
7199
+ });
6855
7200
  }
6856
7201
  async function getUpdatedAt(configPath, exists) {
6857
7202
  if (!exists) {
@@ -6869,191 +7214,6 @@ async function getUpdatedAt(configPath, exists) {
6869
7214
  }
6870
7215
  }
6871
7216
 
6872
- // ../../packages/shared/src/core/errors.ts
6873
- var ANSI_PATTERN = /\u001B\[[0-9;]*m/g;
6874
- function stripAnsi(value3) {
6875
- return value3.replace(ANSI_PATTERN, "");
6876
- }
6877
- function normalizeWhitespace(value3) {
6878
- return value3.replace(/\s+/g, " ").trim();
6879
- }
6880
- function compactErrorText(value3, maxLength = 220) {
6881
- if (!value3) {
6882
- return "";
6883
- }
6884
- const cleaned = normalizeWhitespace(stripAnsi(String(value3)));
6885
- if (!cleaned) {
6886
- return "";
6887
- }
6888
- if (cleaned.length <= maxLength) {
6889
- return cleaned;
6890
- }
6891
- return `${cleaned.slice(0, maxLength).trimEnd()}\u2026`;
6892
- }
6893
- function createErrorReferenceId() {
6894
- return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`.toUpperCase();
6895
- }
6896
- function serializeUnknownError(value3) {
6897
- if (typeof value3 === "string") {
6898
- return value3;
6899
- }
6900
- if (value3 instanceof Error) {
6901
- return value3.stack ?? value3.message;
6902
- }
6903
- try {
6904
- return JSON.stringify(value3);
6905
- } catch {
6906
- return String(value3);
6907
- }
6908
- }
6909
- function extractRawMessage(error) {
6910
- if (error === null || typeof error === "undefined") {
6911
- return "";
6912
- }
6913
- if (typeof error === "string") {
6914
- return error;
6915
- }
6916
- if (error instanceof Error) {
6917
- return error.message;
6918
- }
6919
- return String(error);
6920
- }
6921
- function normalizeRawMessage(rawMessage) {
6922
- let cleaned = normalizeWhitespace(stripAnsi(rawMessage));
6923
- if (!cleaned) {
6924
- return "";
6925
- }
6926
- if (cleaned.startsWith("Error invoking remote method")) {
6927
- cleaned = cleaned.replace(/^Error invoking remote method '[^']+': Error: /, "");
6928
- }
6929
- if (cleaned.toLowerCase().includes("openai codex") && cleaned.toLowerCase().includes("workdir:")) {
6930
- const parts = cleaned.split(/error:/i);
6931
- if (parts.length > 1) {
6932
- return parts[parts.length - 1]?.trim() ?? cleaned;
6933
- }
6934
- }
6935
- return cleaned;
6936
- }
6937
- function resolveCategory(cleaned, options) {
6938
- const lower = cleaned.toLowerCase();
6939
- if (options.notFoundFallback && (lower.includes("enoent") || lower.includes("not found"))) {
6940
- return {
6941
- code: "ERR_NOT_FOUND",
6942
- title: "We couldn't find that item",
6943
- message: options.notFoundFallback,
6944
- recovery: "Check the path or selection, then try again.",
6945
- retryable: true
6946
- };
6947
- }
6948
- if (lower.includes("rate limit") || lower.includes("quota exceeded") || lower.includes("too many requests") || lower.includes("429")) {
6949
- return {
6950
- code: "ERR_RATE_LIMIT",
6951
- title: "Rate limit reached",
6952
- message: "The provider is rate limited right now.",
6953
- recovery: "Wait a moment, switch profiles, or try again.",
6954
- retryable: true
6955
- };
6956
- }
6957
- if (lower.includes("timeout") || lower.includes("timed out")) {
6958
- return {
6959
- code: "ERR_TIMEOUT",
6960
- title: "Request timed out",
6961
- message: "The operation took too long to finish.",
6962
- recovery: "Check the connection and try again.",
6963
- retryable: true
6964
- };
6965
- }
6966
- if (lower.includes("network") || lower.includes("econn") || lower.includes("networkerror") || lower.includes("connection refused") || lower.includes("socket hang up")) {
6967
- return {
6968
- code: "ERR_NETWORK",
6969
- title: "Can't reach the service",
6970
- message: "CodexUse couldn't connect to the required service.",
6971
- recovery: "Check your internet or local server connection, then retry.",
6972
- retryable: true
6973
- };
6974
- }
6975
- if (lower.includes("token_invalidated") || lower.includes("session invalidated") || lower.includes("session expired") || lower.includes("refresh token") || lower.includes("unauthorized") || lower.includes("401")) {
6976
- return {
6977
- code: "ERR_AUTH",
6978
- title: "Sign-in expired",
6979
- message: "This account needs to sign in again.",
6980
- recovery: "Reconnect the profile, then retry the action.",
6981
- retryable: true
6982
- };
6983
- }
6984
- if (lower.includes("permission") || lower.includes("eacces") || lower.includes("operation not permitted")) {
6985
- return {
6986
- code: "ERR_PERMISSION",
6987
- title: "Permission denied",
6988
- message: "CodexUse doesn't have permission to do that.",
6989
- recovery: "Check the file permissions or restart the app and try again.",
6990
- retryable: true
6991
- };
6992
- }
6993
- if (lower.includes("enospc") || lower.includes("disk full") || lower.includes("no space left")) {
6994
- return {
6995
- code: "ERR_DISK_FULL",
6996
- title: "Disk is full",
6997
- message: "CodexUse couldn't save data because the disk is full.",
6998
- recovery: "Free up disk space, then try again.",
6999
- retryable: true
7000
- };
7001
- }
7002
- if (lower.includes("codex cli") || lower.includes("command not found") || lower.includes("spawn codex") || lower.includes("could not find codex")) {
7003
- return {
7004
- code: "ERR_CLI_UNAVAILABLE",
7005
- title: "Codex CLI unavailable",
7006
- message: "CodexUse couldn't start the Codex CLI.",
7007
- recovery: "Check Runtime > Codex and confirm the CLI is installed correctly.",
7008
- retryable: true
7009
- };
7010
- }
7011
- if (lower.includes("provider") || lower.includes("model") || lower.includes("openai") || lower.includes("anthropic")) {
7012
- return {
7013
- code: "ERR_PROVIDER",
7014
- title: "Provider request failed",
7015
- message: "The AI provider rejected or failed the request.",
7016
- recovery: "Try again, or switch the active profile or model.",
7017
- retryable: true
7018
- };
7019
- }
7020
- return {
7021
- code: "ERR_UNKNOWN",
7022
- title: "That did not work",
7023
- message: options.fallback,
7024
- recovery: "Try again. If it keeps happening, report the error with the reference below.",
7025
- retryable: true
7026
- };
7027
- }
7028
- function resolveUserFacingError(error, options = {}) {
7029
- const fallback = options.fallback ?? "That action did not complete.";
7030
- const rawMessage = extractRawMessage(error);
7031
- const cleaned = normalizeRawMessage(rawMessage);
7032
- const category = resolveCategory(cleaned, {
7033
- fallback,
7034
- ...options.notFoundFallback ? { notFoundFallback: options.notFoundFallback } : {}
7035
- });
7036
- return {
7037
- ...category,
7038
- referenceId: createErrorReferenceId(),
7039
- technicalMessage: compactErrorText(cleaned || rawMessage || fallback, 400),
7040
- technicalDetails: compactErrorText(serializeUnknownError(error), 4e3)
7041
- };
7042
- }
7043
- function formatUserFacingError(error, options = {}) {
7044
- const info = resolveUserFacingError(error, options);
7045
- const maxLength = typeof options.maxLength === "number" ? options.maxLength : 220;
7046
- const withRecovery = info.recovery && !/try again/i.test(info.message) ? `${info.message} ${info.recovery}` : info.message;
7047
- if (withRecovery.length <= maxLength) {
7048
- return withRecovery;
7049
- }
7050
- let cleaned = info.message;
7051
- if (cleaned.length > maxLength) {
7052
- cleaned = `${cleaned.slice(0, maxLength).trimEnd()}\u2026`;
7053
- }
7054
- return cleaned;
7055
- }
7056
-
7057
7217
  // ../../packages/runtime-codex/src/codex/config.ts
7058
7218
  function tryParseToml(content) {
7059
7219
  try {
@@ -7061,14 +7221,10 @@ function tryParseToml(content) {
7061
7221
  return { data: parsed ?? {}, error: null };
7062
7222
  } catch (error) {
7063
7223
  const maybe = error;
7064
- const line = typeof maybe?.line === "number" ? maybe.line : null;
7065
- const column = typeof maybe?.column === "number" ? maybe.column : typeof maybe?.col === "number" ? maybe.col : null;
7224
+ const line = typeof maybe?.line === "number" ? maybe.line + 1 : null;
7225
+ const column = typeof maybe?.col === "number" ? maybe.col + 1 : null;
7066
7226
  const location = line !== null ? `line ${line}${column !== null ? `, column ${column}` : ""}` : null;
7067
- const friendly = formatUserFacingError(error, {
7068
- fallback: "Invalid config.toml syntax. Fix it and try again.",
7069
- maxLength: 180
7070
- });
7071
- const message = location ? `${friendly} (near ${location}).` : friendly;
7227
+ const message = location ? `Invalid config.toml syntax near ${location}. Fix it and try again.` : "Invalid config.toml syntax. Fix it and try again.";
7072
7228
  return { data: null, error: message };
7073
7229
  }
7074
7230
  }
@@ -7366,12 +7522,16 @@ async function getCodexConfigSnapshot(options) {
7366
7522
  const { content, exists } = await readConfigContent(options);
7367
7523
  return buildSnapshot(content, exists, options);
7368
7524
  }
7369
- async function saveCodexConfigContent(content, options) {
7525
+ function assertValidCodexConfigContent(content) {
7370
7526
  const normalized = ensureTrailingNewline(normalizeLineEndings(content));
7371
7527
  const parsed = tryParseToml(normalized);
7372
7528
  if (!parsed.data) {
7373
7529
  throw new Error(parsed.error ?? "config.toml contains invalid TOML syntax.");
7374
7530
  }
7531
+ return normalized;
7532
+ }
7533
+ async function saveCodexConfigContent(content, options) {
7534
+ const normalized = assertValidCodexConfigContent(content);
7375
7535
  await writeConfigContent(normalized, options);
7376
7536
  return buildSnapshot(normalized, true, options);
7377
7537
  }
@@ -8055,8 +8215,8 @@ var CIRCULAR = "[Circular]";
8055
8215
  function formatPropertyKey(name) {
8056
8216
  return typeof name === "string" ? JSON.stringify(name) : String(name);
8057
8217
  }
8058
- function formatPath(path19) {
8059
- return path19.map((key) => `[${formatPropertyKey(key)}]`).join("");
8218
+ function formatPath(path21) {
8219
+ return path21.map((key) => `[${formatPropertyKey(key)}]`).join("");
8060
8220
  }
8061
8221
  function formatDate(date) {
8062
8222
  try {
@@ -11567,9 +11727,9 @@ var Pointer = class extends Base {
11567
11727
  * The issue that occurred.
11568
11728
  */
11569
11729
  issue;
11570
- constructor(path19, issue) {
11730
+ constructor(path21, issue) {
11571
11731
  super();
11572
- this.path = path19;
11732
+ this.path = path21;
11573
11733
  this.issue = issue;
11574
11734
  }
11575
11735
  };
@@ -11754,43 +11914,43 @@ function getExpectedMessage(expected, issue) {
11754
11914
  const input = formatInput(issue);
11755
11915
  return input === void 0 ? `Expected ${expected}` : `Expected ${expected}, got ${input}`;
11756
11916
  }
11757
- function toDefaultIssues(issue, path19, leafHook, checkHook) {
11917
+ function toDefaultIssues(issue, path21, leafHook, checkHook) {
11758
11918
  switch (issue._tag) {
11759
11919
  case "Filter": {
11760
11920
  const message = checkHook(issue);
11761
11921
  if (message !== void 0) {
11762
11922
  return [{
11763
- path: path19,
11923
+ path: path21,
11764
11924
  message
11765
11925
  }];
11766
11926
  }
11767
11927
  if (issue.issue._tag !== "InvalidValue") {
11768
- return toDefaultIssues(issue.issue, path19, leafHook, checkHook);
11928
+ return toDefaultIssues(issue.issue, path21, leafHook, checkHook);
11769
11929
  }
11770
11930
  const expected = findExpected(issue.issue);
11771
11931
  return [{
11772
- path: path19,
11932
+ path: path21,
11773
11933
  message: expected === void 0 ? getExpectedMessage(formatCheck(issue.filter), issue) : getExpectedMessage(expected, issue.issue)
11774
11934
  }];
11775
11935
  }
11776
11936
  case "Encoding":
11777
- return toDefaultIssues(issue.issue, path19, leafHook, checkHook);
11937
+ return toDefaultIssues(issue.issue, path21, leafHook, checkHook);
11778
11938
  case "Pointer":
11779
- return toDefaultIssues(issue.issue, [...path19, ...issue.path], leafHook, checkHook);
11939
+ return toDefaultIssues(issue.issue, [...path21, ...issue.path], leafHook, checkHook);
11780
11940
  case "Composite":
11781
- return issue.issues.flatMap((issue2) => toDefaultIssues(issue2, path19, leafHook, checkHook));
11941
+ return issue.issues.flatMap((issue2) => toDefaultIssues(issue2, path21, leafHook, checkHook));
11782
11942
  case "AnyOf": {
11783
11943
  if (issue.issues.length === 0) {
11784
11944
  return [{
11785
- path: path19,
11945
+ path: path21,
11786
11946
  message: findMessage(issue) ?? getExpectedMessage(getExpected(issue.ast), issue)
11787
11947
  }];
11788
11948
  }
11789
- return issue.issues.flatMap((issue2) => toDefaultIssues(issue2, path19, leafHook, checkHook));
11949
+ return issue.issues.flatMap((issue2) => toDefaultIssues(issue2, path21, leafHook, checkHook));
11790
11950
  }
11791
11951
  default:
11792
11952
  return [{
11793
- path: path19,
11953
+ path: path21,
11794
11954
  message: leafHook(issue)
11795
11955
  }];
11796
11956
  }
@@ -11809,7 +11969,7 @@ function makeFormatterDefault() {
11809
11969
  return (issue) => formatIssue(issue, "");
11810
11970
  }
11811
11971
  var defaultFormatter = /* @__PURE__ */ makeFormatterDefault();
11812
- function formatIssue(issue, path19) {
11972
+ function formatIssue(issue, path21) {
11813
11973
  let message;
11814
11974
  switch (issue._tag) {
11815
11975
  case "Filter": {
@@ -11818,7 +11978,7 @@ function formatIssue(issue, path19) {
11818
11978
  message = annotated;
11819
11979
  } else {
11820
11980
  if (issue.issue._tag !== "InvalidValue") {
11821
- return formatIssue(issue.issue, path19);
11981
+ return formatIssue(issue.issue, path21);
11822
11982
  }
11823
11983
  const expected = findExpected(issue.issue);
11824
11984
  message = expected === void 0 ? getExpectedMessage(formatCheck(issue.filter), issue) : getExpectedMessage(expected, issue.issue);
@@ -11826,13 +11986,13 @@ function formatIssue(issue, path19) {
11826
11986
  break;
11827
11987
  }
11828
11988
  case "Encoding":
11829
- return formatIssue(issue.issue, path19);
11989
+ return formatIssue(issue.issue, path21);
11830
11990
  case "Pointer":
11831
- return formatIssue(issue.issue, path19 + formatPath(issue.path));
11991
+ return formatIssue(issue.issue, path21 + formatPath(issue.path));
11832
11992
  case "Composite":
11833
11993
  case "AnyOf": {
11834
11994
  if (issue._tag === "Composite" || issue.issues.length > 0) {
11835
- return issue.issues.map((issue2) => formatIssue(issue2, path19)).join("\n");
11995
+ return issue.issues.map((issue2) => formatIssue(issue2, path21)).join("\n");
11836
11996
  }
11837
11997
  message = findMessage(issue) ?? getExpectedMessage(getExpected(issue.ast), issue);
11838
11998
  break;
@@ -11841,8 +12001,8 @@ function formatIssue(issue, path19) {
11841
12001
  message = defaultLeafHook(issue);
11842
12002
  break;
11843
12003
  }
11844
- return path19 ? `${message}
11845
- at ${path19}` : message;
12004
+ return path21 ? `${message}
12005
+ at ${path21}` : message;
11846
12006
  }
11847
12007
  function findMessage(issue) {
11848
12008
  if (issue._tag === "Pointer") return;
@@ -16263,10 +16423,10 @@ function makeReducer2(combiner2) {
16263
16423
  }
16264
16424
 
16265
16425
  // ../../node_modules/.bun/effect@4.0.0-rc.111/node_modules/effect/dist/internal/errors.js
16266
- function errorWithPath(message, path19) {
16267
- if (path19.length > 0) {
16426
+ function errorWithPath(message, path21) {
16427
+ if (path21.length > 0) {
16268
16428
  message += `
16269
- at ${formatPath(path19)}`;
16429
+ at ${formatPath(path21)}`;
16270
16430
  }
16271
16431
  return new Error(message);
16272
16432
  }
@@ -16607,26 +16767,26 @@ function filterLayer(ast, checks, normalBase, terminalBase) {
16607
16767
  });
16608
16768
  }
16609
16769
  var memoized = /* @__PURE__ */ memoize((ast) => recur(ast, []));
16610
- function recur(ast, path19) {
16770
+ function recur(ast, path21) {
16611
16771
  const annotation = resolve(ast)?.toArbitrary;
16612
16772
  if (annotation) {
16613
- const typeParameters = isDeclaration(ast) ? ast.typeParameters.map((tp) => recur(tp, path19)) : [];
16773
+ const typeParameters = isDeclaration(ast) ? ast.typeParameters.map((tp) => recur(tp, path21)) : [];
16614
16774
  const checks = collectChecks(ast.checks);
16615
16775
  const derive = (lazyNormal) => (fc, ctx, nextCtx, recursionStack) => normalizeDerivation(annotation(makeTypeParameters(typeParameters, fc, resetContext(ctx), recursionStack, lazyNormal))(fc, nextCtx), typeParameters.length > 0)[lazyNormal ? "terminal" : "arbitrary"];
16616
16776
  return filterLayer(ast, checks, derive(false), derive(true));
16617
16777
  }
16618
16778
  if (ast.checks) {
16619
16779
  const checks = collectChecks(ast.checks);
16620
- const lawc = recur(replaceChecks(ast, void 0), path19);
16780
+ const lawc = recur(replaceChecks(ast, void 0), path21);
16621
16781
  return filterLayer(ast, checks, (fc, _ctx, nextCtx, recursionStack) => lawc(fc, nextCtx, recursionStack), (fc, _ctx, nextCtx, recursionStack) => lawc.terminal(fc, nextCtx, recursionStack));
16622
16782
  }
16623
- return base(ast, path19);
16783
+ return base(ast, path21);
16624
16784
  }
16625
- function base(ast, path19) {
16785
+ function base(ast, path21) {
16626
16786
  switch (ast._tag) {
16627
16787
  case "Never":
16628
16788
  case "Declaration":
16629
- throw errorWithPath(`Unsupported AST ${ast._tag}`, path19);
16789
+ throw errorWithPath(`Unsupported AST ${ast._tag}`, path21);
16630
16790
  case "Null":
16631
16791
  return same((fc) => fc.constant(null));
16632
16792
  case "Void":
@@ -16663,20 +16823,20 @@ function base(ast, path19) {
16663
16823
  case "ObjectKeyword":
16664
16824
  return same((fc) => fc.oneof(fc.object(), fc.array(fc.anything())));
16665
16825
  case "Enum":
16666
- return recur(enumsToLiterals(ast), path19);
16826
+ return recur(enumsToLiterals(ast), path21);
16667
16827
  case "TemplateLiteral": {
16668
- const parts = ast.parts.map((part, i) => recur(toEncoded(part), [...path19, i]));
16828
+ const parts = ast.parts.map((part, i) => recur(toEncoded(part), [...path21, i]));
16669
16829
  return same((fc, ctx, recursionStack) => fc.tuple(...parts.map((part) => part(fc, finiteNumberContext(ctx), recursionStack))).map((segments) => segments.map((segment) => globalThis.String(segment)).join("")));
16670
16830
  }
16671
16831
  case "Arrays": {
16672
16832
  const elements = ast.elements.map((ast2, i) => ({
16673
16833
  ast: ast2,
16674
- arbitrary: recur(ast2, [...path19, i])
16834
+ arbitrary: recur(ast2, [...path21, i])
16675
16835
  }));
16676
16836
  const len = ast.elements.length;
16677
16837
  const rest = ast.rest.map((ast2, i) => ({
16678
16838
  ast: ast2,
16679
- arbitrary: recur(ast2, [...path19, len + i])
16839
+ arbitrary: recur(ast2, [...path21, len + i])
16680
16840
  }));
16681
16841
  const terminal = (fc, ctx, recursionStack) => {
16682
16842
  const reset = resetContext(ctx);
@@ -16776,12 +16936,12 @@ function base(ast, path19) {
16776
16936
  case "Objects": {
16777
16937
  const propertySignatures = ast.propertySignatures.map((ps) => ({
16778
16938
  ps,
16779
- arbitrary: recur(ps.type, [...path19, ps.name])
16939
+ arbitrary: recur(ps.type, [...path21, ps.name])
16780
16940
  }));
16781
16941
  const indexSignatures = ast.indexSignatures.map((is3) => ({
16782
16942
  is: is3,
16783
- parameter: recur(is3.parameter, path19),
16784
- type: recur(is3.type, path19)
16943
+ parameter: recur(is3.parameter, path21),
16944
+ type: recur(is3.type, path21)
16785
16945
  }));
16786
16946
  const terminal = (fc, ctx, recursionStack) => {
16787
16947
  const reset = resetContext(ctx);
@@ -16884,7 +17044,7 @@ function base(ast, path19) {
16884
17044
  }, terminal);
16885
17045
  }
16886
17046
  case "Union": {
16887
- const types = ast.types.map((ast2) => recur(ast2, path19));
17047
+ const types = ast.types.map((ast2) => recur(ast2, path21));
16888
17048
  const terminal = (fc, ctx, recursionStack) => oneOf(fc, types.map((type) => type.terminal(fc, ctx, recursionStack)).filter(isNotUndefined));
16889
17049
  return makeLazy((fc, ctx, recursionStack) => {
16890
17050
  const arbitraries = types.map((type) => type(fc, ctx, recursionStack));
@@ -16904,7 +17064,7 @@ function base(ast, path19) {
16904
17064
  case "Suspend": {
16905
17065
  const memo = arbitraryMemoMap.get(ast);
16906
17066
  if (memo) return memo;
16907
- const get5 = memoizeThunk(() => recur(ast.thunk(), path19));
17067
+ const get5 = memoizeThunk(() => recur(ast.thunk(), path21));
16908
17068
  const out = makeLazy((fc, ctx, recursionStack) => {
16909
17069
  const recursion = getSuspendRecursion(fc, ast);
16910
17070
  const nextCtx = {
@@ -16914,7 +17074,7 @@ function base(ast, path19) {
16914
17074
  const nextStack = recursionStack.includes(ast) ? recursionStack : [...recursionStack, ast];
16915
17075
  const terminal = get5().terminal(fc, nextCtx, nextStack);
16916
17076
  if (terminal === void 0) {
16917
- throw errorWithPath("Unable to derive an arbitrary for a recursive schema without a finite generation path", path19);
17077
+ throw errorWithPath("Unable to derive an arbitrary for a recursive schema without a finite generation path", path21);
16918
17078
  }
16919
17079
  return fc.oneof(recursion, terminal, fc.constant(null).chain(() => get5()(fc, nextCtx, nextStack)));
16920
17080
  }, (fc, ctx, recursionStack) => {
@@ -16937,10 +17097,10 @@ function base(ast, path19) {
16937
17097
  var toEquivalence = /* @__PURE__ */ memoize((ast) => {
16938
17098
  return recur2(ast, []);
16939
17099
  });
16940
- function recur2(ast, path19) {
17100
+ function recur2(ast, path21) {
16941
17101
  const annotation = resolve(ast)?.["toEquivalence"];
16942
17102
  if (annotation) {
16943
- return annotation(isDeclaration(ast) ? ast.typeParameters.map((tp) => recur2(tp, path19)) : []);
17103
+ return annotation(isDeclaration(ast) ? ast.typeParameters.map((tp) => recur2(tp, path21)) : []);
16944
17104
  }
16945
17105
  switch (ast._tag) {
16946
17106
  case "Never":
@@ -16963,9 +17123,9 @@ function recur2(ast, path19) {
16963
17123
  case "TemplateLiteral":
16964
17124
  return equals;
16965
17125
  case "Arrays": {
16966
- const elements = ast.elements.map((e, i) => recur2(e, [...path19, i]));
17126
+ const elements = ast.elements.map((e, i) => recur2(e, [...path21, i]));
16967
17127
  const len = ast.elements.length;
16968
- const rest = ast.rest.map((r, i) => recur2(r, [...path19, len + i]));
17128
+ const rest = ast.rest.map((r, i) => recur2(r, [...path21, len + i]));
16969
17129
  return make2((a, b) => {
16970
17130
  if (!Array.isArray(a) || !Array.isArray(b)) {
16971
17131
  return false;
@@ -17000,8 +17160,8 @@ function recur2(ast, path19) {
17000
17160
  if (ast.propertySignatures.length === 0 && ast.indexSignatures.length === 0) {
17001
17161
  return equals;
17002
17162
  }
17003
- const propertySignatures = ast.propertySignatures.map((ps) => recur2(ps.type, [...path19, ps.name]));
17004
- const indexSignatures = ast.indexSignatures.map((is3) => recur2(is3.type, path19));
17163
+ const propertySignatures = ast.propertySignatures.map((ps) => recur2(ps.type, [...path21, ps.name]));
17164
+ const indexSignatures = ast.indexSignatures.map((is3) => recur2(is3.type, path21));
17005
17165
  return make2((a, b) => {
17006
17166
  if (!isObject(a) || !isObject(b)) {
17007
17167
  return false;
@@ -17037,7 +17197,7 @@ function recur2(ast, path19) {
17037
17197
  }
17038
17198
  case "Union": {
17039
17199
  const types = toType(ast).types;
17040
- const compiled = new Map(types.map((candidate, i) => [candidate, [_is(candidate), recur2(ast.types[i], path19)]]));
17200
+ const compiled = new Map(types.map((candidate, i) => [candidate, [_is(candidate), recur2(ast.types[i], path21)]]));
17041
17201
  return make2((a, b) => {
17042
17202
  const candidates = getCandidates(a, types);
17043
17203
  for (let i = 0; i < candidates.length; i++) {
@@ -17050,7 +17210,7 @@ function recur2(ast, path19) {
17050
17210
  });
17051
17211
  }
17052
17212
  case "Suspend": {
17053
- const get5 = memoizeThunk(() => recur2(ast.thunk(), path19));
17213
+ const get5 = memoizeThunk(() => recur2(ast.thunk(), path21));
17054
17214
  return make2((a, b) => get5()(a, b));
17055
17215
  }
17056
17216
  }
@@ -17336,11 +17496,11 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17336
17496
  schemas,
17337
17497
  definitions
17338
17498
  };
17339
- function compileDefinition(key, path19) {
17499
+ function compileDefinition(key, path21) {
17340
17500
  const compiled = definitionStates.get(key);
17341
17501
  if (compiled !== void 0) return typeof compiled === "string" ? compiled : key;
17342
17502
  if (!Object.hasOwn(references, key)) {
17343
- throw errorWithPath(`Invalid reference ${key}`, [...path19, "$ref"]);
17503
+ throw errorWithPath(`Invalid reference ${key}`, [...path21, "$ref"]);
17344
17504
  }
17345
17505
  definitionStates.set(key, null);
17346
17506
  const representation = references[key];
@@ -17373,14 +17533,14 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17373
17533
  const annotations = representation.checks.length === 0 ? representation.annotations : representation.checks[representation.checks.length - 1].annotations;
17374
17534
  return typeof annotations?.identifier !== "string" && typeof annotations?.[IDENTIFIER_FALLBACK_KEY] === "string" ? annotations[IDENTIFIER_FALLBACK_KEY] : void 0;
17375
17535
  }
17376
- function annotationSchemas(representation, path19) {
17377
- return representation?.schemas?.map((schema, index2) => recur3(schema, [...path19, "schemas", index2])) ?? [];
17536
+ function annotationSchemas(representation, path21) {
17537
+ return representation?.schemas?.map((schema, index2) => recur3(schema, [...path21, "schemas", index2])) ?? [];
17378
17538
  }
17379
- function compileCheck(check2, type, path19) {
17539
+ function compileCheck(check2, type, path21) {
17380
17540
  const annotations = check2.annotations;
17381
17541
  const callback2 = annotations?.toJsonSchema;
17382
17542
  if (callback2 !== void 0) {
17383
- const schemas2 = annotationSchemas(check2.representation, [...path19, "representation"]);
17543
+ const schemas2 = annotationSchemas(check2.representation, [...path21, "representation"]);
17384
17544
  const fragment = callback2({
17385
17545
  type,
17386
17546
  schemas: schemas2
@@ -17394,7 +17554,7 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17394
17554
  return check2._tag === "Filter" && hasOnlyKeywords(schema, allowed) && (ordinary2 === void 0 || hasOnlyKeywords(ordinary2, promotableAnnotationKeywords)) ? [schema, true] : [schema];
17395
17555
  }
17396
17556
  if (check2._tag === "Filter") return void 0;
17397
- const children = check2.checks.map((child, index2) => compileCheck(child, type, [...path19, "checks", index2])).filter((child) => child !== void 0);
17557
+ const children = check2.checks.map((child, index2) => compileCheck(child, type, [...path21, "checks", index2])).filter((child) => child !== void 0);
17398
17558
  if (children.length === 0) return void 0;
17399
17559
  const ordinary = collectJsonSchemaAnnotations(annotations, options);
17400
17560
  const allOf = children.map(([schema]) => schema);
@@ -17405,16 +17565,16 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17405
17565
  ...ordinary
17406
17566
  }];
17407
17567
  }
17408
- function recur3(representation, path19) {
17568
+ function recur3(representation, path21) {
17409
17569
  if (representation._tag === "Reference") {
17410
- const canonical = compileDefinition(representation.$ref, path19);
17570
+ const canonical = compileDefinition(representation.$ref, path21);
17411
17571
  return {
17412
17572
  $ref: `#/$defs/${escapeToken(canonical)}`
17413
17573
  };
17414
17574
  }
17415
17575
  const cached2 = compiledRepresentations.get(representation);
17416
17576
  if (cached2 !== void 0) return cached2;
17417
- let output = on(representation, path19);
17577
+ let output = on(representation, path21);
17418
17578
  const ordinary = collectJsonSchemaAnnotations(representation.annotations, options);
17419
17579
  if (ordinary !== void 0) {
17420
17580
  output = {
@@ -17424,7 +17584,7 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17424
17584
  }
17425
17585
  for (let index2 = 0; index2 < representation.checks.length; index2++) {
17426
17586
  const type = typeof output.type === "string" && isJsonSchemaType(output.type) ? output.type : void 0;
17427
- const check2 = compileCheck(representation.checks[index2], type, [...path19, "checks", index2]);
17587
+ const check2 = compileCheck(representation.checks[index2], type, [...path21, "checks", index2]);
17428
17588
  if (check2 !== void 0) {
17429
17589
  output = appendJsonSchema(output, ...check2);
17430
17590
  }
@@ -17432,7 +17592,7 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17432
17592
  compiledRepresentations.set(representation, output);
17433
17593
  return output;
17434
17594
  }
17435
- function on(representation, path19) {
17595
+ function on(representation, path21) {
17436
17596
  switch (representation._tag) {
17437
17597
  case "Any":
17438
17598
  case "Unknown":
@@ -17470,7 +17630,7 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17470
17630
  return {};
17471
17631
  }
17472
17632
  case "Suspend":
17473
- return recur3(representation.thunk, [...path19, "thunk"]);
17633
+ return recur3(representation.thunk, [...path21, "thunk"]);
17474
17634
  case "Never":
17475
17635
  return {
17476
17636
  not: {}
@@ -17531,7 +17691,7 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17531
17691
  };
17532
17692
  case "Arrays": {
17533
17693
  if (representation.rest.length > 1) {
17534
- throw errorWithPath("Invalid schema representation document", [...path19, "rest"]);
17694
+ throw errorWithPath("Invalid schema representation document", [...path21, "rest"]);
17535
17695
  }
17536
17696
  const out = {
17537
17697
  type: "array"
@@ -17539,7 +17699,7 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17539
17699
  let minItems = representation.elements.length;
17540
17700
  const prefixItems = representation.elements.map((element, index2) => {
17541
17701
  if (element.isOptional) minItems--;
17542
- const compiled = recur3(element.type, [...path19, "elements", index2, "type"]);
17702
+ const compiled = recur3(element.type, [...path21, "elements", index2, "type"]);
17543
17703
  const annotations = collectJsonSchemaAnnotations(element.annotations, options);
17544
17704
  return annotations === void 0 ? compiled : appendJsonSchema(compiled, annotations);
17545
17705
  });
@@ -17552,7 +17712,7 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17552
17712
  }
17553
17713
  if (representation.rest.length === 1) {
17554
17714
  delete out.maxItems;
17555
- const rest = recur3(representation.rest[0], [...path19, "rest", 0]);
17715
+ const rest = recur3(representation.rest[0], [...path21, "rest", 0]);
17556
17716
  if (Object.keys(rest).length > 0) out.items = rest;
17557
17717
  else delete out.items;
17558
17718
  }
@@ -17576,10 +17736,10 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17576
17736
  for (let index2 = 0; index2 < representation.propertySignatures.length; index2++) {
17577
17737
  const property = representation.propertySignatures[index2];
17578
17738
  if (typeof property.name !== "string") {
17579
- throw errorWithPath("Invalid schema representation document", [...path19, "propertySignatures", index2, "name"]);
17739
+ throw errorWithPath("Invalid schema representation document", [...path21, "propertySignatures", index2, "name"]);
17580
17740
  }
17581
17741
  const name = property.name;
17582
- const compiled = recur3(property.type, [...path19, "propertySignatures", index2, "type"]);
17742
+ const compiled = recur3(property.type, [...path21, "propertySignatures", index2, "type"]);
17583
17743
  const annotations = collectJsonSchemaAnnotations(property.annotations, options);
17584
17744
  assignProperty(properties, name, annotations === void 0 ? compiled : appendJsonSchema(compiled, annotations));
17585
17745
  if (!property.isOptional) required2.push(name);
@@ -17590,9 +17750,9 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17590
17750
  const additionalProperties = [];
17591
17751
  for (let index2 = 0; index2 < representation.indexSignatures.length; index2++) {
17592
17752
  const signature = representation.indexSignatures[index2];
17593
- let type = recur3(signature.type, [...path19, "indexSignatures", index2, "type"]);
17753
+ let type = recur3(signature.type, [...path21, "indexSignatures", index2, "type"]);
17594
17754
  if (Object.keys(type).length === 1 && "not" in type) type = false;
17595
- const patterns = getParameterPatterns(signature.parameter, [...path19, "indexSignatures", index2, "parameter"], /* @__PURE__ */ new Set());
17755
+ const patterns = getParameterPatterns(signature.parameter, [...path21, "indexSignatures", index2, "parameter"], /* @__PURE__ */ new Set());
17596
17756
  if (patterns.length === 0) {
17597
17757
  additionalProperties.push(type);
17598
17758
  } else {
@@ -17622,7 +17782,7 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17622
17782
  return out;
17623
17783
  }
17624
17784
  case "Union": {
17625
- const types = representation.types.map((type, index2) => recur3(type, [...path19, "types", index2]));
17785
+ const types = representation.types.map((type, index2) => recur3(type, [...path21, "types", index2]));
17626
17786
  if (types.length === 0) return {
17627
17787
  not: {}
17628
17788
  };
@@ -17638,25 +17798,25 @@ function compileJsonSchema(representations, rootPaths, references, options) {
17638
17798
  }
17639
17799
  }
17640
17800
  }
17641
- function getParameterPatterns(parameter, path19, seenReferences) {
17801
+ function getParameterPatterns(parameter, path21, seenReferences) {
17642
17802
  switch (parameter._tag) {
17643
17803
  case "Reference": {
17644
17804
  if (!Object.hasOwn(references, parameter.$ref)) {
17645
- throw errorWithPath(`Invalid reference ${parameter.$ref}`, [...path19, "$ref"]);
17805
+ throw errorWithPath(`Invalid reference ${parameter.$ref}`, [...path21, "$ref"]);
17646
17806
  }
17647
- compileDefinition(parameter.$ref, path19);
17807
+ compileDefinition(parameter.$ref, path21);
17648
17808
  if (seenReferences.has(parameter.$ref)) return [];
17649
17809
  const next = new Set(seenReferences).add(parameter.$ref);
17650
17810
  return getParameterPatterns(references[parameter.$ref], ["references", parameter.$ref], next);
17651
17811
  }
17652
17812
  case "String":
17653
- return collectPatterns(recur3(parameter, path19));
17813
+ return collectPatterns(recur3(parameter, path21));
17654
17814
  case "TemplateLiteral":
17655
17815
  return [`^${parameter.parts.map(getPartPattern).join("")}$`];
17656
17816
  case "Union":
17657
- return parameter.types.flatMap((type, index2) => getParameterPatterns(type, [...path19, "types", index2], seenReferences));
17817
+ return parameter.types.flatMap((type, index2) => getParameterPatterns(type, [...path21, "types", index2], seenReferences));
17658
17818
  default:
17659
- throw errorWithPath("Invalid schema representation document", path19);
17819
+ throw errorWithPath("Invalid schema representation document", path21);
17660
17820
  }
17661
17821
  }
17662
17822
  }
@@ -18041,25 +18201,25 @@ function get4(oldValue, newValue) {
18041
18201
  getLoop(oldValue, newValue, "", patches);
18042
18202
  return patches;
18043
18203
  }
18044
- function getLoop(oldValue, newValue, path19, patches) {
18204
+ function getLoop(oldValue, newValue, path21, patches) {
18045
18205
  if (Object.is(oldValue, newValue)) return;
18046
18206
  if (Array.isArray(oldValue) && Array.isArray(newValue)) {
18047
18207
  const len1 = oldValue.length;
18048
18208
  const len2 = newValue.length;
18049
18209
  const shared = Math.min(len1, len2);
18050
18210
  for (let i = 0; i < shared; i++) {
18051
- getLoop(oldValue[i], newValue[i], `${path19}/${i}`, patches);
18211
+ getLoop(oldValue[i], newValue[i], `${path21}/${i}`, patches);
18052
18212
  }
18053
18213
  for (let i = len1 - 1; i >= len2; i--) {
18054
18214
  patches.push({
18055
18215
  op: "remove",
18056
- path: `${path19}/${i}`
18216
+ path: `${path21}/${i}`
18057
18217
  });
18058
18218
  }
18059
18219
  for (let i = len1; i < len2; i++) {
18060
18220
  patches.push({
18061
18221
  op: "add",
18062
- path: `${path19}/${i}`,
18222
+ path: `${path21}/${i}`,
18063
18223
  value: newValue[i]
18064
18224
  });
18065
18225
  }
@@ -18070,7 +18230,7 @@ function getLoop(oldValue, newValue, path19, patches) {
18070
18230
  const keys22 = Object.keys(newValue);
18071
18231
  const allKeys = Array.from(/* @__PURE__ */ new Set([...keys1, ...keys22])).sort();
18072
18232
  for (const key of allKeys) {
18073
- const keyPath = `${path19}/${escapeToken(key)}`;
18233
+ const keyPath = `${path21}/${escapeToken(key)}`;
18074
18234
  const hasKey1 = Object.hasOwn(oldValue, key);
18075
18235
  const hasKey2 = Object.hasOwn(newValue, key);
18076
18236
  if (hasKey1 && hasKey2) {
@@ -18092,7 +18252,7 @@ function getLoop(oldValue, newValue, path19, patches) {
18092
18252
  }
18093
18253
  patches.push({
18094
18254
  op: "replace",
18095
- path: path19,
18255
+ path: path21,
18096
18256
  value: newValue
18097
18257
  });
18098
18258
  }
@@ -18242,12 +18402,12 @@ var PathNode = class {
18242
18402
  path;
18243
18403
  get;
18244
18404
  set;
18245
- constructor(path19) {
18246
- this.path = path19;
18405
+ constructor(path21) {
18406
+ this.path = path21;
18247
18407
  this.get = (s) => {
18248
18408
  let out = s;
18249
- for (let i = 0; i < path19.length; i++) {
18250
- out = out[path19[i]];
18409
+ for (let i = 0; i < path21.length; i++) {
18410
+ out = out[path21[i]];
18251
18411
  }
18252
18412
  return out;
18253
18413
  };
@@ -18255,12 +18415,12 @@ var PathNode = class {
18255
18415
  const out = cloneShallow(s);
18256
18416
  let current = out;
18257
18417
  let i = 0;
18258
- for (; i < path19.length - 1; i++) {
18259
- const key = path19[i];
18418
+ for (; i < path21.length - 1; i++) {
18419
+ const key = path21[i];
18260
18420
  assignProperty(current, key, cloneShallow(current[key]));
18261
18421
  current = current[key];
18262
18422
  }
18263
- assignProperty(current, path19[i], a);
18423
+ assignProperty(current, path21[i], a);
18264
18424
  return out;
18265
18425
  };
18266
18426
  }
@@ -23117,82 +23277,12 @@ var ProviderEvent = Schema_exports.Struct({
23117
23277
  payload: Schema_exports.optional(Schema_exports.Unknown)
23118
23278
  });
23119
23279
 
23120
- // ../../packages/contracts/src/filesystem.ts
23121
- var FILESYSTEM_PATH_MAX_LENGTH = 512;
23122
- var FilesystemBrowseInput = Schema_exports.Struct({
23123
- partialPath: TrimmedNonEmptyString.check(Schema_exports.isMaxLength(FILESYSTEM_PATH_MAX_LENGTH)),
23124
- cwd: Schema_exports.optional(TrimmedNonEmptyString.check(Schema_exports.isMaxLength(FILESYSTEM_PATH_MAX_LENGTH)))
23125
- });
23126
- var FilesystemBrowseEntry = Schema_exports.Struct({
23127
- name: TrimmedNonEmptyString,
23128
- fullPath: TrimmedNonEmptyString
23129
- });
23130
- var FilesystemBrowseResult = Schema_exports.Struct({
23131
- parentPath: TrimmedNonEmptyString,
23132
- entries: Schema_exports.Array(FilesystemBrowseEntry)
23133
- });
23134
-
23135
- // ../../packages/contracts/src/editor.ts
23136
- var EDITORS = [
23137
- { id: "cursor", label: "Cursor", commands: ["cursor"], supportsGoto: true },
23138
- { id: "vscode", label: "VS Code", commands: ["code"], supportsGoto: true },
23139
- {
23140
- id: "vscode-insiders",
23141
- label: "VS Code Insiders",
23142
- commands: ["code-insiders"],
23143
- supportsGoto: true
23144
- },
23145
- { id: "vscodium", label: "VSCodium", commands: ["codium"], supportsGoto: true },
23146
- { id: "zed", label: "Zed", commands: ["zed", "zeditor"], supportsGoto: false },
23147
- { id: "antigravity", label: "Antigravity", commands: ["agy"], supportsGoto: false },
23148
- { id: "file-manager", label: "File Manager", commands: null, supportsGoto: false }
23149
- ];
23150
- var EditorId = Schema_exports.Literals(EDITORS.map((e) => e.id));
23151
- var OpenInEditorInput = Schema_exports.Struct({
23152
- cwd: TrimmedNonEmptyString,
23153
- editor: EditorId
23154
- });
23155
-
23156
- // ../../packages/contracts/src/runtime.ts
23157
- var RuntimeConfigIssue = Schema_exports.Struct({
23158
- kind: TrimmedNonEmptyString,
23159
- message: TrimmedNonEmptyString
23160
- });
23161
- var RuntimeConfigIssues = Schema_exports.Array(RuntimeConfigIssue);
23162
- var RuntimeProviderStatusState = Schema_exports.Literals(["ready", "warning", "error"]);
23163
- var RuntimeProviderAuthStatus = Schema_exports.Literals([
23164
- "authenticated",
23165
- "unauthenticated",
23166
- "unknown"
23167
- ]);
23168
- var RuntimeProviderStatus = Schema_exports.Struct({
23169
- provider: ProviderKind,
23170
- status: RuntimeProviderStatusState,
23171
- available: Schema_exports.Boolean,
23172
- authStatus: RuntimeProviderAuthStatus,
23173
- checkedAt: IsoDateTime,
23174
- message: Schema_exports.optional(TrimmedNonEmptyString)
23175
- });
23176
- var RuntimeProviderStatuses = Schema_exports.Array(RuntimeProviderStatus);
23177
- var RuntimeConfig = Schema_exports.Struct({
23178
- cwd: TrimmedNonEmptyString,
23179
- issues: RuntimeConfigIssues,
23180
- providers: RuntimeProviderStatuses,
23181
- availableEditors: Schema_exports.Array(EditorId)
23182
- });
23183
- var RuntimeProviderUpdatedPayload = Schema_exports.Struct({
23184
- providers: RuntimeProviderStatuses
23185
- });
23186
-
23187
- // ../../packages/contracts/src/rpc.ts
23280
+ // ../../packages/contracts/src/desktop/rpc-types.ts
23188
23281
  var RPC_METHODS = {
23189
23282
  filesystemBrowse: "filesystem.browse",
23190
- // Shell methods
23191
23283
  shellOpenInEditor: "shell.openInEditor",
23192
- // Runtime meta
23193
23284
  runtimeGetConfig: "runtime.getConfig",
23194
23285
  runtimeRefreshProviders: "runtime.refreshProviders",
23195
- // Desktop dashboard/runtime methods
23196
23286
  appStateGet: "appState.get",
23197
23287
  appStatePatch: "appState.patch",
23198
23288
  appSettingsGet: "appSettings.get",
@@ -23261,11 +23351,13 @@ var RPC_METHODS = {
23261
23351
  desktopLlmSetProviderEnabled: "desktopLlm.setProviderEnabled",
23262
23352
  desktopLlmSetRoutePublished: "desktopLlm.setRoutePublished",
23263
23353
  desktopLlmProbeRoute: "desktopLlm.probeRoute",
23354
+ desktopLlmCreateGuidedProfile: "desktopLlm.createGuidedProfile",
23264
23355
  desktopLlmUpsertExternalProfile: "desktopLlm.upsertExternalProfile",
23265
23356
  desktopLlmDeleteExternalProfile: "desktopLlm.deleteExternalProfile",
23266
23357
  desktopLlmLaunchExternalProfile: "desktopLlm.launchExternalProfile",
23267
23358
  desktopLlmStopExternalProfile: "desktopLlm.stopExternalProfile",
23268
23359
  desktopLlmLifecycle: "desktopLlm.lifecycle",
23360
+ desktopLlmRuntimeControl: "desktopLlm.runtimeControl",
23269
23361
  cliInfo: "cli.info",
23270
23362
  cliStatus: "cli.status",
23271
23363
  cliCheckFreshness: "cli.checkFreshness",
@@ -23292,6 +23384,75 @@ var RPC_CHANNELS = {
23292
23384
  officialCodexActivityUpdated: "officialCodex.activityUpdated",
23293
23385
  officialCodexStatusUpdated: "officialCodex.statusUpdated"
23294
23386
  };
23387
+
23388
+ // ../../packages/contracts/src/filesystem.ts
23389
+ var FILESYSTEM_PATH_MAX_LENGTH = 512;
23390
+ var FilesystemBrowseInput = Schema_exports.Struct({
23391
+ partialPath: TrimmedNonEmptyString.check(Schema_exports.isMaxLength(FILESYSTEM_PATH_MAX_LENGTH)),
23392
+ cwd: Schema_exports.optional(TrimmedNonEmptyString.check(Schema_exports.isMaxLength(FILESYSTEM_PATH_MAX_LENGTH)))
23393
+ });
23394
+ var FilesystemBrowseEntry = Schema_exports.Struct({
23395
+ name: TrimmedNonEmptyString,
23396
+ fullPath: TrimmedNonEmptyString
23397
+ });
23398
+ var FilesystemBrowseResult = Schema_exports.Struct({
23399
+ parentPath: TrimmedNonEmptyString,
23400
+ entries: Schema_exports.Array(FilesystemBrowseEntry)
23401
+ });
23402
+
23403
+ // ../../packages/contracts/src/editor.ts
23404
+ var EDITORS = [
23405
+ { id: "cursor", label: "Cursor", commands: ["cursor"], supportsGoto: true },
23406
+ { id: "vscode", label: "VS Code", commands: ["code"], supportsGoto: true },
23407
+ {
23408
+ id: "vscode-insiders",
23409
+ label: "VS Code Insiders",
23410
+ commands: ["code-insiders"],
23411
+ supportsGoto: true
23412
+ },
23413
+ { id: "vscodium", label: "VSCodium", commands: ["codium"], supportsGoto: true },
23414
+ { id: "zed", label: "Zed", commands: ["zed", "zeditor"], supportsGoto: false },
23415
+ { id: "antigravity", label: "Antigravity", commands: ["agy"], supportsGoto: false },
23416
+ { id: "file-manager", label: "File Manager", commands: null, supportsGoto: false }
23417
+ ];
23418
+ var EditorId = Schema_exports.Literals(EDITORS.map((e) => e.id));
23419
+ var OpenInEditorInput = Schema_exports.Struct({
23420
+ cwd: TrimmedNonEmptyString,
23421
+ editor: EditorId
23422
+ });
23423
+
23424
+ // ../../packages/contracts/src/runtime.ts
23425
+ var RuntimeConfigIssue = Schema_exports.Struct({
23426
+ kind: TrimmedNonEmptyString,
23427
+ message: TrimmedNonEmptyString
23428
+ });
23429
+ var RuntimeConfigIssues = Schema_exports.Array(RuntimeConfigIssue);
23430
+ var RuntimeProviderStatusState = Schema_exports.Literals(["ready", "warning", "error"]);
23431
+ var RuntimeProviderAuthStatus = Schema_exports.Literals([
23432
+ "authenticated",
23433
+ "unauthenticated",
23434
+ "unknown"
23435
+ ]);
23436
+ var RuntimeProviderStatus = Schema_exports.Struct({
23437
+ provider: ProviderKind,
23438
+ status: RuntimeProviderStatusState,
23439
+ available: Schema_exports.Boolean,
23440
+ authStatus: RuntimeProviderAuthStatus,
23441
+ checkedAt: IsoDateTime,
23442
+ message: Schema_exports.optional(TrimmedNonEmptyString)
23443
+ });
23444
+ var RuntimeProviderStatuses = Schema_exports.Array(RuntimeProviderStatus);
23445
+ var RuntimeConfig = Schema_exports.Struct({
23446
+ cwd: TrimmedNonEmptyString,
23447
+ issues: RuntimeConfigIssues,
23448
+ providers: RuntimeProviderStatuses,
23449
+ availableEditors: Schema_exports.Array(EditorId)
23450
+ });
23451
+ var RuntimeProviderUpdatedPayload = Schema_exports.Struct({
23452
+ providers: RuntimeProviderStatuses
23453
+ });
23454
+
23455
+ // ../../packages/contracts/src/rpc.ts
23295
23456
  var tagRequestBody = (tag2, schema) => schema.mapFields(
23296
23457
  Struct_exports.assign({ _tag: Schema_exports.tag(tag2) }),
23297
23458
  // PreserveChecks is safe here. No existing schema should have checks depending on the tag
@@ -23395,6 +23556,7 @@ var DesktopRpcRequestBody = Schema_exports.Union([
23395
23556
  Schema_exports.Union([Schema_exports.Literal("manual"), Schema_exports.Literal("auto-roll")])
23396
23557
  ),
23397
23558
  carryDraft: Schema_exports.optional(Schema_exports.Boolean),
23559
+ continueThreadId: Schema_exports.optional(Schema_exports.Union([Schema_exports.String, Schema_exports.Null])),
23398
23560
  forceAdopt: Schema_exports.optional(Schema_exports.Boolean),
23399
23561
  launchIfNotRunning: Schema_exports.optional(Schema_exports.Boolean),
23400
23562
  awaitCodexFollowUp: Schema_exports.optional(Schema_exports.Boolean)
@@ -23704,6 +23866,10 @@ var DesktopRpcRequestBody = Schema_exports.Union([
23704
23866
  RPC_METHODS.desktopLlmProbeRoute,
23705
23867
  Schema_exports.Struct({ publicSlug: TrimmedNonEmptyString })
23706
23868
  ),
23869
+ tagRequestBody(
23870
+ RPC_METHODS.desktopLlmCreateGuidedProfile,
23871
+ Schema_exports.Struct({ input: Schema_exports.Unknown })
23872
+ ),
23707
23873
  tagRequestBody(
23708
23874
  RPC_METHODS.desktopLlmUpsertExternalProfile,
23709
23875
  Schema_exports.Struct({ profile: Schema_exports.Unknown })
@@ -23732,6 +23898,15 @@ var DesktopRpcRequestBody = Schema_exports.Union([
23732
23898
  ])
23733
23899
  })
23734
23900
  ),
23901
+ tagRequestBody(
23902
+ RPC_METHODS.desktopLlmRuntimeControl,
23903
+ Schema_exports.Struct({
23904
+ action: Schema_exports.Union([
23905
+ Schema_exports.Literal("drain"),
23906
+ Schema_exports.Literal("resume")
23907
+ ])
23908
+ })
23909
+ ),
23735
23910
  tagRequestBody(RPC_METHODS.cliInfo, Schema_exports.Struct({})),
23736
23911
  tagRequestBody(RPC_METHODS.cliStatus, Schema_exports.Struct({})),
23737
23912
  tagRequestBody(RPC_METHODS.cliCheckFreshness, Schema_exports.Struct({})),
@@ -24160,7 +24335,7 @@ function authWritebackPaths(filePath) {
24160
24335
  };
24161
24336
  }
24162
24337
  function fingerprintAuth(content) {
24163
- return (0, import_node_crypto9.createHash)("sha256").update(content).digest("hex");
24338
+ return (0, import_node_crypto10.createHash)("sha256").update(content).digest("hex");
24164
24339
  }
24165
24340
  async function readOptionalFile(filePath) {
24166
24341
  try {
@@ -24172,10 +24347,10 @@ async function readOptionalFile(filePath) {
24172
24347
  }
24173
24348
  }
24174
24349
  async function writeAtomicPath(filePath, content) {
24175
- const dir = import_node_path9.default.dirname(filePath);
24176
- const tempPath = import_node_path9.default.join(
24350
+ const dir = import_node_path10.default.dirname(filePath);
24351
+ const tempPath = import_node_path10.default.join(
24177
24352
  dir,
24178
- `.${import_node_path9.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto9.randomUUID)()}.tmp`
24353
+ `.${import_node_path10.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto10.randomUUID)()}.tmp`
24179
24354
  );
24180
24355
  const handle = await import_node_fs6.promises.open(tempPath, "wx", 384);
24181
24356
  try {
@@ -24199,10 +24374,10 @@ async function writeAtomicPath(filePath, content) {
24199
24374
  }
24200
24375
  }
24201
24376
  async function installAuthFileIfAbsent(filePath, content) {
24202
- const dir = import_node_path9.default.dirname(filePath);
24203
- const tempPath = import_node_path9.default.join(
24377
+ const dir = import_node_path10.default.dirname(filePath);
24378
+ const tempPath = import_node_path10.default.join(
24204
24379
  dir,
24205
- `.${import_node_path9.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto9.randomUUID)()}.install`
24380
+ `.${import_node_path10.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto10.randomUUID)()}.install`
24206
24381
  );
24207
24382
  const handle = await import_node_fs6.promises.open(tempPath, "wx", 384);
24208
24383
  try {
@@ -24273,7 +24448,7 @@ async function hasExternalOpenFileHandle(filePath) {
24273
24448
  }
24274
24449
  const lsofCommand = process.platform === "darwin" ? "/usr/sbin/lsof" : "lsof";
24275
24450
  return new Promise((resolve2) => {
24276
- const child = (0, import_node_child_process5.spawn)(lsofCommand, ["-F", "p", "--", filePath], {
24451
+ const child = (0, import_node_child_process6.spawn)(lsofCommand, ["-F", "p", "--", filePath], {
24277
24452
  stdio: ["ignore", "pipe", "ignore"]
24278
24453
  });
24279
24454
  let output = "";
@@ -24416,7 +24591,7 @@ async function acquireCodexAuthFileSystemLock(filePath) {
24416
24591
  }
24417
24592
  }
24418
24593
  async function acquireCodexAuthFileLock(filePath) {
24419
- const queueKey = import_node_path9.default.resolve(filePath);
24594
+ const queueKey = import_node_path10.default.resolve(filePath);
24420
24595
  const predecessor = authFileLockQueues.get(queueKey) ?? Promise.resolve();
24421
24596
  let finishTurn;
24422
24597
  const turn = new Promise((resolve2) => {
@@ -24449,7 +24624,7 @@ async function acquireCodexAuthFileLock(filePath) {
24449
24624
  }
24450
24625
  }
24451
24626
  async function acquireCodexAuthFileReadLock(filePath) {
24452
- const queueKey = import_node_path9.default.resolve(filePath);
24627
+ const queueKey = import_node_path10.default.resolve(filePath);
24453
24628
  await (authFileLockQueues.get(queueKey) ?? Promise.resolve());
24454
24629
  const releaseReadLock = await acquireCrossProcessFileReadLock(filePath);
24455
24630
  if (!releaseReadLock) {
@@ -24623,9 +24798,9 @@ function parseRateLimitSnapshotFromRpcMessage(message) {
24623
24798
  return snapshot2;
24624
24799
  }
24625
24800
  function resolveRpcAuthPath(envOverride, authPath) {
24626
- return authPath ?? import_node_path9.default.join(
24801
+ return authPath ?? import_node_path10.default.join(
24627
24802
  resolveCodexHomeDir({
24628
- codexHomePath: envOverride?.CODEX_HOME ?? (envOverride?.HOME ? import_node_path9.default.join(envOverride.HOME, ".codex") : void 0)
24803
+ codexHomePath: envOverride?.CODEX_HOME ?? (envOverride?.HOME ? import_node_path10.default.join(envOverride.HOME, ".codex") : void 0)
24629
24804
  }),
24630
24805
  "auth.json"
24631
24806
  );
@@ -24633,8 +24808,8 @@ function resolveRpcAuthPath(envOverride, authPath) {
24633
24808
  async function fetchRateLimitsViaRpc(envOverride, options = {}) {
24634
24809
  const binaryPath = options.codexPath ?? await requireCodexCli();
24635
24810
  const sourceAuthPath = resolveRpcAuthPath(envOverride, options.authPath);
24636
- const tempHome = await import_node_fs6.promises.mkdtemp(import_node_path9.default.join(import_node_os3.default.tmpdir(), "codex-rpc-"));
24637
- const tempAuthPath = import_node_path9.default.join(tempHome, "auth.json");
24811
+ const tempHome = await import_node_fs6.promises.mkdtemp(import_node_path10.default.join(import_node_os3.default.tmpdir(), "codex-rpc-"));
24812
+ const tempAuthPath = import_node_path10.default.join(tempHome, "auth.json");
24638
24813
  let initialSourceAuth;
24639
24814
  try {
24640
24815
  const authLock = await acquireCodexAuthFileReadLock(sourceAuthPath);
@@ -24673,7 +24848,7 @@ async function fetchRateLimitsViaRpc(envOverride, options = {}) {
24673
24848
  ["-s", "read-only", "-a", "never", "app-server"],
24674
24849
  childEnv
24675
24850
  );
24676
- const child = (0, import_node_child_process5.spawn)(command.command, command.args, {
24851
+ const child = (0, import_node_child_process6.spawn)(command.command, command.args, {
24677
24852
  stdio: ["pipe", "pipe", "pipe"],
24678
24853
  env: childEnv,
24679
24854
  shell: command.shell
@@ -24767,9 +24942,9 @@ async function activateResetWindowViaRpc(envOverride, options = {}) {
24767
24942
  async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAuthPath) {
24768
24943
  const binaryPath = options.codexPath ?? await requireCodexCli();
24769
24944
  const tempHome = await import_node_fs6.promises.mkdtemp(
24770
- import_node_path9.default.join(import_node_os3.default.tmpdir(), "codex-activation-")
24945
+ import_node_path10.default.join(import_node_os3.default.tmpdir(), "codex-activation-")
24771
24946
  );
24772
- const tempAuthPath = import_node_path9.default.join(tempHome, "auth.json");
24947
+ const tempAuthPath = import_node_path10.default.join(tempHome, "auth.json");
24773
24948
  let initialSourceAuth;
24774
24949
  try {
24775
24950
  const authLock = await acquireCodexAuthFileReadLock(sourceAuthPath);
@@ -24799,14 +24974,14 @@ async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAut
24799
24974
  let configuredModel = null;
24800
24975
  try {
24801
24976
  const snapshot2 = await getCodexConfigSnapshot({
24802
- codexHomePath: import_node_path9.default.dirname(sourceAuthPath)
24977
+ codexHomePath: import_node_path10.default.dirname(sourceAuthPath)
24803
24978
  });
24804
24979
  configuredModel = snapshot2.settings.model;
24805
24980
  } catch {
24806
24981
  }
24807
24982
  const activationModel = resolveActivationModel(configuredModel);
24808
24983
  await import_node_fs6.promises.writeFile(
24809
- import_node_path9.default.join(tempHome, "config.toml"),
24984
+ import_node_path10.default.join(tempHome, "config.toml"),
24810
24985
  `model = ${JSON.stringify(activationModel)}
24811
24986
  `,
24812
24987
  "utf8"
@@ -24825,7 +25000,7 @@ async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAut
24825
25000
  ["-s", "read-only", "-a", "never", "app-server"],
24826
25001
  childEnv
24827
25002
  );
24828
- const child = (0, import_node_child_process5.spawn)(command.command, command.args, {
25003
+ const child = (0, import_node_child_process6.spawn)(command.command, command.args, {
24829
25004
  stdio: ["pipe", "pipe", "pipe"],
24830
25005
  env: childEnv,
24831
25006
  shell: command.shell
@@ -25000,15 +25175,15 @@ async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAut
25000
25175
  }
25001
25176
 
25002
25177
  // ../../packages/runtime-codex/src/codex/officialAppRestart.ts
25003
- var import_node_child_process6 = require("child_process");
25004
- var import_node_crypto10 = require("crypto");
25178
+ var import_node_child_process7 = require("child_process");
25179
+ var import_node_crypto11 = require("crypto");
25005
25180
  var import_node_fs8 = require("fs");
25006
25181
  var import_node_os4 = require("os");
25007
- var import_node_path11 = __toESM(require("path"), 1);
25182
+ var import_node_path12 = __toESM(require("path"), 1);
25008
25183
 
25009
25184
  // ../../packages/runtime-codex/src/codex/threadUsage.ts
25010
25185
  var import_node_fs7 = require("fs");
25011
- var import_node_path10 = __toESM(require("path"), 1);
25186
+ var import_node_path11 = __toESM(require("path"), 1);
25012
25187
  var ROLLOUT_DIRS = ["sessions", "archived_sessions"];
25013
25188
  var SQLITE_EXTENSIONS = /* @__PURE__ */ new Set([".db", ".sqlite", ".sqlite3"]);
25014
25189
  var SILENT_TAKEOVER_HOT_WINDOW_MS = 6e4;
@@ -25030,7 +25205,7 @@ async function collectRolloutFiles(root) {
25030
25205
  const childVisits = [];
25031
25206
  for (const entry of entries3) {
25032
25207
  const entryName = String(entry.name);
25033
- const entryPath = import_node_path10.default.join(dir, entryName);
25208
+ const entryPath = import_node_path11.default.join(dir, entryName);
25034
25209
  if (entry.isDirectory()) {
25035
25210
  childVisits.push(visit(entryPath));
25036
25211
  continue;
@@ -25055,7 +25230,7 @@ async function collectRolloutFilesStrict(root) {
25055
25230
  await Promise.all(
25056
25231
  entries3.map(async (entry) => {
25057
25232
  const entryName = String(entry.name);
25058
- const entryPath = import_node_path10.default.join(dir, entryName);
25233
+ const entryPath = import_node_path11.default.join(dir, entryName);
25059
25234
  if (entry.isDirectory()) {
25060
25235
  await visit(entryPath);
25061
25236
  } else if (entry.isFile() && entryName.startsWith("rollout-") && entryName.endsWith(".jsonl")) {
@@ -25071,7 +25246,7 @@ async function readOfficialCodexRolloutActivityHeat(profileHome) {
25071
25246
  let latestUpdatedAtMs = null;
25072
25247
  try {
25073
25248
  for (const dirname of ROLLOUT_DIRS) {
25074
- const root = import_node_path10.default.join(profileHome, dirname);
25249
+ const root = import_node_path11.default.join(profileHome, dirname);
25075
25250
  try {
25076
25251
  await import_node_fs7.promises.access(root);
25077
25252
  } catch (error) {
@@ -25103,10 +25278,10 @@ async function findRolloutFileByScan(profileHome, threadId) {
25103
25278
  let best = null;
25104
25279
  const variants = threadIdVariants(threadId);
25105
25280
  for (const dirname of ROLLOUT_DIRS) {
25106
- const root = import_node_path10.default.join(profileHome, dirname);
25281
+ const root = import_node_path11.default.join(profileHome, dirname);
25107
25282
  const files = await collectRolloutFiles(root);
25108
25283
  for (const file of files) {
25109
- const basename = import_node_path10.default.basename(file);
25284
+ const basename = import_node_path11.default.basename(file);
25110
25285
  if (!variants.some((variant) => basename.includes(variant))) {
25111
25286
  continue;
25112
25287
  }
@@ -25182,11 +25357,11 @@ function resolveRolloutPath(profileHome, rolloutPath) {
25182
25357
  if (!rolloutPath) {
25183
25358
  return null;
25184
25359
  }
25185
- return import_node_path10.default.isAbsolute(rolloutPath) ? rolloutPath : import_node_path10.default.join(profileHome, rolloutPath);
25360
+ return import_node_path11.default.isAbsolute(rolloutPath) ? rolloutPath : import_node_path11.default.join(profileHome, rolloutPath);
25186
25361
  }
25187
25362
  async function collectSessionDatabasePaths(profileHome, sqliteHome = profileHome) {
25188
25363
  const paths = [];
25189
- const sqliteDir = import_node_path10.default.join(sqliteHome, "sqlite");
25364
+ const sqliteDir = import_node_path11.default.join(sqliteHome, "sqlite");
25190
25365
  try {
25191
25366
  const entries3 = await import_node_fs7.promises.readdir(sqliteDir, {
25192
25367
  withFileTypes: true,
@@ -25197,20 +25372,20 @@ async function collectSessionDatabasePaths(profileHome, sqliteHome = profileHome
25197
25372
  continue;
25198
25373
  }
25199
25374
  const entryName = String(entry.name);
25200
- if (SQLITE_EXTENSIONS.has(import_node_path10.default.extname(entryName))) {
25201
- paths.push(import_node_path10.default.join(sqliteDir, entryName));
25375
+ if (SQLITE_EXTENSIONS.has(import_node_path11.default.extname(entryName))) {
25376
+ paths.push(import_node_path11.default.join(sqliteDir, entryName));
25202
25377
  }
25203
25378
  }
25204
25379
  } catch {
25205
25380
  }
25206
25381
  paths.sort((left, right) => {
25207
- const leftName = import_node_path10.default.basename(left);
25208
- const rightName = import_node_path10.default.basename(right);
25382
+ const leftName = import_node_path11.default.basename(left);
25383
+ const rightName = import_node_path11.default.basename(right);
25209
25384
  if (leftName === "codex-dev.db" && rightName !== "codex-dev.db") return -1;
25210
25385
  if (rightName === "codex-dev.db" && leftName !== "codex-dev.db") return 1;
25211
25386
  return leftName.localeCompare(rightName);
25212
25387
  });
25213
- const legacy = import_node_path10.default.join(sqliteHome, "state_5.sqlite");
25388
+ const legacy = import_node_path11.default.join(sqliteHome, "state_5.sqlite");
25214
25389
  if (!paths.includes(legacy)) {
25215
25390
  paths.push(legacy);
25216
25391
  }
@@ -25690,7 +25865,7 @@ function hashProfileKey(profileKey) {
25690
25865
  if (!profileKey) {
25691
25866
  return null;
25692
25867
  }
25693
- return (0, import_node_crypto10.createHash)("sha256").update(profileKey).digest("hex").slice(0, 12);
25868
+ return (0, import_node_crypto11.createHash)("sha256").update(profileKey).digest("hex").slice(0, 12);
25694
25869
  }
25695
25870
  function sanitizeOfficialCodexOverlayActionTargetsForRenderer(targets) {
25696
25871
  const sanitized = [];
@@ -27371,7 +27546,7 @@ function createBridgeApplyQolExpression(settings) {
27371
27546
  if (customModelCount === 0) {
27372
27547
  const promo = document.createElement("p");
27373
27548
  promo.className = "codexuse-promo";
27374
- promo.textContent = "CodexUse can also run OpenRouter, DeepSeek, or a local model right here. Add one under Connect \u203A Model Providers.";
27549
+ promo.textContent = "CodexUse can also run OpenRouter, DeepSeek, or a local model right here. Add one under Settings \u203A Model Providers.";
27375
27550
  section.appendChild(promo);
27376
27551
  }
27377
27552
  const divider = mount.firstElementChild?.nextElementSibling;
@@ -29302,7 +29477,7 @@ async function runCdpCommandSequence(debuggerUrl, commands, timeoutMs = CODEX_CD
29302
29477
  });
29303
29478
  }
29304
29479
  async function verifyCdpBindingRoundTrip(debuggerUrl) {
29305
- const nonce = (0, import_node_crypto10.randomUUID)();
29480
+ const nonce = (0, import_node_crypto11.randomUUID)();
29306
29481
  const expression = `(() => {
29307
29482
  const binding = window[${JSON.stringify(CODEXUSE_BRIDGE_BINDING_NAME)}];
29308
29483
  if (typeof binding !== "function") return false;
@@ -29725,7 +29900,7 @@ async function startOfficialCodexBridgeActionListenerOnce(args2) {
29725
29900
  let closeNotified = false;
29726
29901
  let echoReceived = false;
29727
29902
  const requiredCommandIds = /* @__PURE__ */ new Set();
29728
- const echoId = (0, import_node_crypto10.randomUUID)();
29903
+ const echoId = (0, import_node_crypto11.randomUUID)();
29729
29904
  const readyTimeout = setTimeout(() => {
29730
29905
  settleReady(false);
29731
29906
  try {
@@ -29799,7 +29974,7 @@ async function startOfficialCodexBridgeActionListenerOnce(args2) {
29799
29974
  }
29800
29975
  };
29801
29976
  bridgeActionListenerVerifiers.set(args2.debuggerUrl, async () => {
29802
- const id2 = (0, import_node_crypto10.randomUUID)();
29977
+ const id2 = (0, import_node_crypto11.randomUUID)();
29803
29978
  return await new Promise((resolve2) => {
29804
29979
  const waiters = bridgeActionListenerHealthWaiters.get(args2.debuggerUrl) ?? /* @__PURE__ */ new Map();
29805
29980
  bridgeActionListenerHealthWaiters.set(args2.debuggerUrl, waiters);
@@ -29910,18 +30085,18 @@ async function startOfficialCodexBridgeActionListenerOnce(args2) {
29910
30085
  if (!requestId || !rememberBridgeActionId(requestId)) {
29911
30086
  return;
29912
30087
  }
29913
- const path19 = typeof payload.path === "string" ? payload.path.trim().slice(0, 64) : "";
30088
+ const path21 = typeof payload.path === "string" ? payload.path.trim().slice(0, 64) : "";
29914
30089
  const requestHandler = officialCodexBridgeRequestHandler;
29915
30090
  void (async () => {
29916
30091
  let result2;
29917
- if (!path19) {
30092
+ if (!path21) {
29918
30093
  result2 = { status: "failed", reason: "missing-path" };
29919
30094
  } else if (!requestHandler) {
29920
30095
  result2 = { status: "failed", reason: "no-request-handler" };
29921
30096
  } else {
29922
30097
  try {
29923
30098
  result2 = await requestHandler({
29924
- path: path19,
30099
+ path: path21,
29925
30100
  payload: payload.payload ?? null,
29926
30101
  sourceProfileName: bridgeActionListenerProfiles.get(args2.debuggerUrl) ?? profileName
29927
30102
  });
@@ -30347,7 +30522,7 @@ async function recordOfficialCodexActivity(input) {
30347
30522
  };
30348
30523
  const finite2 = (value3, min4, max4) => typeof value3 === "number" && Number.isFinite(value3) ? Math.max(min4, Math.min(max4, value3)) : null;
30349
30524
  const entry = {
30350
- id: (0, import_node_crypto10.randomUUID)(),
30525
+ id: (0, import_node_crypto11.randomUUID)(),
30351
30526
  at: now2.toISOString(),
30352
30527
  kind: input.kind,
30353
30528
  status: bounded(input.status, 80) ?? "unknown",
@@ -30417,7 +30592,7 @@ async function recordOfficialCodexActivity(input) {
30417
30592
  }
30418
30593
  function runCommand2(command, args2, timeoutMs = COMMAND_TIMEOUT_MS) {
30419
30594
  return new Promise((resolve2) => {
30420
- const child = (0, import_node_child_process6.spawn)(command, args2, {
30595
+ const child = (0, import_node_child_process7.spawn)(command, args2, {
30421
30596
  stdio: ["ignore", "pipe", "pipe"]
30422
30597
  });
30423
30598
  let stdout = "";
@@ -30496,7 +30671,7 @@ async function readProcessRows() {
30496
30671
  return rows;
30497
30672
  }
30498
30673
  function getMainExecutablePath(candidate) {
30499
- return import_node_path11.default.join(candidate.appPath, "Contents", "MacOS", candidate.executableName);
30674
+ return import_node_path12.default.join(candidate.appPath, "Contents", "MacOS", candidate.executableName);
30500
30675
  }
30501
30676
  function isMainProcessRow(row, candidate) {
30502
30677
  return row.args.includes(getMainExecutablePath(candidate));
@@ -31341,12 +31516,12 @@ async function resolveOfficialCodexBridgeTarget(args2) {
31341
31516
  }
31342
31517
  var devToolsActivePortPaths = (appUserDataDir) => {
31343
31518
  const roots = appUserDataDir ? [appUserDataDir] : [
31344
- import_node_path11.default.join((0, import_node_os4.homedir)(), "Library", "Application Support", "OpenAI", "Codex"),
31345
- import_node_path11.default.join((0, import_node_os4.homedir)(), "Library", "Application Support", "Codex"),
31346
- import_node_path11.default.join((0, import_node_os4.homedir)(), "Library", "Application Support", "com.openai.codex"),
31347
- import_node_path11.default.join((0, import_node_os4.homedir)(), "Library", "Application Support", "com.openai.chat")
31519
+ import_node_path12.default.join((0, import_node_os4.homedir)(), "Library", "Application Support", "OpenAI", "Codex"),
31520
+ import_node_path12.default.join((0, import_node_os4.homedir)(), "Library", "Application Support", "Codex"),
31521
+ import_node_path12.default.join((0, import_node_os4.homedir)(), "Library", "Application Support", "com.openai.codex"),
31522
+ import_node_path12.default.join((0, import_node_os4.homedir)(), "Library", "Application Support", "com.openai.chat")
31348
31523
  ];
31349
- return roots.map((root) => import_node_path11.default.join(root, "DevToolsActivePort"));
31524
+ return roots.map((root) => import_node_path12.default.join(root, "DevToolsActivePort"));
31350
31525
  };
31351
31526
  var readDevToolsActivePort = async (filePath) => {
31352
31527
  try {
@@ -31399,7 +31574,7 @@ async function openCodexWithProfileHome(candidate, profileHome, profileName, pre
31399
31574
  }
31400
31575
  const telemetryLabel = `codexuse-profile-${encodeURIComponent(profileName)}`;
31401
31576
  const launchHome = resolveCodexLaunchHome(profileHome);
31402
- const appUserDataDir = options.useDefaultUserData === true ? null : options.userDataDir ?? import_node_path11.default.join(profileHome, "codex-app-user-data");
31577
+ const appUserDataDir = options.useDefaultUserData === true ? null : options.userDataDir ?? import_node_path12.default.join(profileHome, "codex-app-user-data");
31403
31578
  const sqliteHome = options.sqliteHome ?? profileHome;
31404
31579
  const activePortPaths = devToolsActivePortPaths(appUserDataDir);
31405
31580
  let child;
@@ -31407,7 +31582,7 @@ async function openCodexWithProfileHome(candidate, profileHome, profileName, pre
31407
31582
  if (appUserDataDir) {
31408
31583
  (0, import_node_fs8.mkdirSync)(appUserDataDir, { recursive: true });
31409
31584
  }
31410
- child = (0, import_node_child_process6.spawn)(
31585
+ child = (0, import_node_child_process7.spawn)(
31411
31586
  "/usr/bin/open",
31412
31587
  [
31413
31588
  "-n",
@@ -31553,13 +31728,13 @@ async function openCodexWithProfileHome(candidate, profileHome, profileName, pre
31553
31728
  };
31554
31729
  }
31555
31730
  function resolveCodexLaunchHome(profileHome) {
31556
- if (Buffer.byteLength(import_node_path11.default.join(profileHome, "ipc", "ipc.sock")) >= 100) {
31731
+ if (Buffer.byteLength(import_node_path12.default.join(profileHome, "ipc", "ipc.sock")) >= 100) {
31557
31732
  throw new Error("codex-home-path-too-long");
31558
31733
  }
31559
31734
  return profileHome;
31560
31735
  }
31561
31736
  async function readBundleString(appPath, key) {
31562
- const plistPath = import_node_path11.default.join(appPath, "Contents", "Info.plist");
31737
+ const plistPath = import_node_path12.default.join(appPath, "Contents", "Info.plist");
31563
31738
  if (!(0, import_node_fs8.existsSync)(plistPath)) {
31564
31739
  return null;
31565
31740
  }
@@ -31579,18 +31754,18 @@ async function readBundleString(appPath, key) {
31579
31754
  }
31580
31755
  function addStandardOfficialCodexAppPaths(rawPaths) {
31581
31756
  for (const appName of OFFICIAL_CODEX_APP_NAMES) {
31582
- rawPaths.add(import_node_path11.default.join("/Applications", appName));
31583
- rawPaths.add(import_node_path11.default.join((0, import_node_os4.homedir)(), "Applications", appName));
31757
+ rawPaths.add(import_node_path12.default.join("/Applications", appName));
31758
+ rawPaths.add(import_node_path12.default.join((0, import_node_os4.homedir)(), "Applications", appName));
31584
31759
  }
31585
31760
  }
31586
31761
  function officialCodexAppPriority(appPath) {
31587
- const priority = OFFICIAL_CODEX_APP_NAMES.indexOf(import_node_path11.default.basename(appPath));
31762
+ const priority = OFFICIAL_CODEX_APP_NAMES.indexOf(import_node_path12.default.basename(appPath));
31588
31763
  return priority >= 0 ? priority : OFFICIAL_CODEX_APP_NAMES.length;
31589
31764
  }
31590
31765
  async function collectCodexAppCandidates(rawPaths) {
31591
31766
  const candidates = [];
31592
31767
  for (const appPath of rawPaths) {
31593
- if (!(0, import_node_fs8.existsSync)(appPath) || !OFFICIAL_CODEX_APP_NAMES.includes(import_node_path11.default.basename(appPath)) || !(0, import_node_fs8.existsSync)(import_node_path11.default.join(appPath, "Contents", "Resources", "codex"))) {
31768
+ if (!(0, import_node_fs8.existsSync)(appPath) || !OFFICIAL_CODEX_APP_NAMES.includes(import_node_path12.default.basename(appPath)) || !(0, import_node_fs8.existsSync)(import_node_path12.default.join(appPath, "Contents", "Resources", "codex"))) {
31594
31769
  continue;
31595
31770
  }
31596
31771
  const bundleId = await readBundleString(appPath, "CFBundleIdentifier");
@@ -31601,7 +31776,7 @@ async function collectCodexAppCandidates(rawPaths) {
31601
31776
  appPath,
31602
31777
  bundleId,
31603
31778
  version: await readBundleString(appPath, "CFBundleShortVersionString"),
31604
- executableName: await readBundleString(appPath, "CFBundleExecutable") ?? import_node_path11.default.basename(appPath, ".app")
31779
+ executableName: await readBundleString(appPath, "CFBundleExecutable") ?? import_node_path12.default.basename(appPath, ".app")
31605
31780
  });
31606
31781
  }
31607
31782
  return candidates.sort(
@@ -31610,7 +31785,7 @@ async function collectCodexAppCandidates(rawPaths) {
31610
31785
  }
31611
31786
  function getRunningCodexPidsFromRows(candidate, rows) {
31612
31787
  const pids = /* @__PURE__ */ new Set();
31613
- const appContentsRoot = `${import_node_path11.default.join(candidate.appPath, "Contents")}${import_node_path11.default.sep}`;
31788
+ const appContentsRoot = `${import_node_path12.default.join(candidate.appPath, "Contents")}${import_node_path12.default.sep}`;
31614
31789
  for (const row of rows) {
31615
31790
  if (row.args.includes(appContentsRoot)) {
31616
31791
  pids.add(row.pid);
@@ -31620,7 +31795,7 @@ function getRunningCodexPidsFromRows(candidate, rows) {
31620
31795
  }
31621
31796
  function getRunningCodexMainPidsFromRows(candidate, rows) {
31622
31797
  const pids = /* @__PURE__ */ new Set();
31623
- const executablePath = import_node_path11.default.join(
31798
+ const executablePath = import_node_path12.default.join(
31624
31799
  candidate.appPath,
31625
31800
  "Contents",
31626
31801
  "MacOS",
@@ -31658,7 +31833,7 @@ async function resolveCodexAppTarget() {
31658
31833
  mainPids: getRunningCodexMainPidsFromRows(candidate, rows)
31659
31834
  })).filter((entry) => entry.mainPids.length > 0);
31660
31835
  const explicit = explicitPath ? runningCandidates.find(
31661
- (entry) => import_node_path11.default.resolve(entry.candidate.appPath) === import_node_path11.default.resolve(explicitPath)
31836
+ (entry) => import_node_path12.default.resolve(entry.candidate.appPath) === import_node_path12.default.resolve(explicitPath)
31662
31837
  ) : null;
31663
31838
  if (runningCandidates.length > 1) {
31664
31839
  return {
@@ -31699,10 +31874,10 @@ function resolveOfficialCodexThreadSqliteHome(profileHome) {
31699
31874
  return profileHome === SHARED_CODEX_HOME ? resolveCodexSqliteHomeDir(profileHome) : profileHome;
31700
31875
  }
31701
31876
  function sharedCodexLaunchOptions(useDefaultUserData, profileIdentity) {
31702
- const userDataDir = !useDefaultUserData && profileIdentity ? import_node_path11.default.join(
31877
+ const userDataDir = !useDefaultUserData && profileIdentity ? import_node_path12.default.join(
31703
31878
  SHARED_CODEX_HOME,
31704
31879
  "codex-app-user-data",
31705
- (0, import_node_crypto10.createHash)("sha256").update(profileIdentity).digest("hex").slice(0, 16)
31880
+ (0, import_node_crypto11.createHash)("sha256").update(profileIdentity).digest("hex").slice(0, 16)
31706
31881
  ) : void 0;
31707
31882
  return {
31708
31883
  useDefaultUserData,
@@ -31899,7 +32074,7 @@ function isSharedHomeMainProcessRow(row, candidate) {
31899
32074
  resolveProfileCodexHomesRoot(),
31900
32075
  resolveLegacyProfileCodexHomesRoot()
31901
32076
  ];
31902
- return isMainProcessRow(row, candidate) && managedRoots.every((root) => !row.args.includes(`${root}${import_node_path11.default.sep}`));
32077
+ return isMainProcessRow(row, candidate) && managedRoots.every((root) => !row.args.includes(`${root}${import_node_path12.default.sep}`));
31903
32078
  }
31904
32079
  async function hydrateSharedHomeCdpWindow(rows, candidate) {
31905
32080
  const isRunningCandidate = async (value3) => {
@@ -34113,7 +34288,7 @@ async function attemptOfficialCodexManagedLiveLogin(args2) {
34113
34288
  }
34114
34289
  }
34115
34290
  async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTrace = {
34116
- operationId: (0, import_node_crypto10.randomUUID)(),
34291
+ operationId: (0, import_node_crypto11.randomUUID)(),
34117
34292
  attempt: 1
34118
34293
  }) {
34119
34294
  let expectedWindowPreflight = options.expectedWindowPreflight;
@@ -35181,7 +35356,7 @@ async function applyOfficialCodexLiveAccountSwitchOnce(options = {}, takeoverTra
35181
35356
  }
35182
35357
  function applyOfficialCodexLiveAccountSwitch(options = {}) {
35183
35358
  return enqueueProfileAction("shared-window", async () => {
35184
- const operationId = (0, import_node_crypto10.randomUUID)();
35359
+ const operationId = (0, import_node_crypto11.randomUUID)();
35185
35360
  let result2 = await applyOfficialCodexLiveAccountSwitchOnce(options, {
35186
35361
  operationId,
35187
35362
  attempt: 1
@@ -35906,16 +36081,16 @@ async function launchOfficialCodexProfileInstanceOnce(options) {
35906
36081
  }
35907
36082
 
35908
36083
  // ../../packages/runtime-app-state/src/app/profileHomeMutationCoordinator.ts
35909
- var import_node_crypto11 = require("crypto");
36084
+ var import_node_crypto12 = require("crypto");
35910
36085
 
35911
36086
  // ../../packages/runtime-app-state/src/app/processOwner.ts
35912
- var import_node_child_process7 = require("child_process");
36087
+ var import_node_child_process8 = require("child_process");
35913
36088
  function readProcessStartedAt(pid) {
35914
36089
  if (!Number.isSafeInteger(pid) || pid <= 0) {
35915
36090
  return null;
35916
36091
  }
35917
36092
  try {
35918
- const output = (0, import_node_child_process7.execFileSync)("/bin/ps", ["-p", String(pid), "-o", "lstart="], {
36093
+ const output = (0, import_node_child_process8.execFileSync)("/bin/ps", ["-p", String(pid), "-o", "lstart="], {
35919
36094
  encoding: "utf8",
35920
36095
  timeout: 2e3
35921
36096
  }).trim();
@@ -35944,12 +36119,12 @@ function isProcessEpochAlive(pid, expectedStartedAt) {
35944
36119
  // ../../packages/runtime-app-state/src/app/profileHomeMutationCoordinator.ts
35945
36120
  var PROFILE_HOME_MUTATION_TTL_MS = 10 * 60 * 1e3;
35946
36121
  var PROFILE_HOME_MUTATION_RENEW_MS = 30 * 1e3;
35947
- var PROCESS_OWNER_ID = (0, import_node_crypto11.randomUUID)();
36122
+ var PROCESS_OWNER_ID = (0, import_node_crypto12.randomUUID)();
35948
36123
  var PROCESS_STARTED_AT = readProcessStartedAt(process.pid);
35949
36124
  var activeRenewals = /* @__PURE__ */ new Map();
35950
36125
  async function acquireProfileHomeMutationIntent(input) {
35951
36126
  const now2 = Date.now();
35952
- const operationId = (0, import_node_crypto11.randomUUID)();
36127
+ const operationId = (0, import_node_crypto12.randomUUID)();
35953
36128
  const renewal = {
35954
36129
  timer: void 0,
35955
36130
  pending: Promise.resolve(),
@@ -36032,7 +36207,7 @@ async function releaseProfileHomeMutationIntent(homeId, operationId) {
36032
36207
 
36033
36208
  // ../../packages/runtime-profiles/src/profiles/rate-limit-cache.ts
36034
36209
  var import_node_fs9 = require("fs");
36035
- var import_node_path12 = __toESM(require("path"), 1);
36210
+ var import_node_path13 = __toESM(require("path"), 1);
36036
36211
  var memorySnapshots = /* @__PURE__ */ new Map();
36037
36212
  var persistedSnapshotWriteLock = Promise.resolve();
36038
36213
  var RATE_LIMIT_SNAPSHOT_CACHE_FILE = "rate-limit-snapshots.json";
@@ -36040,7 +36215,7 @@ function cloneSnapshot(snapshot2) {
36040
36215
  return JSON.parse(JSON.stringify(snapshot2));
36041
36216
  }
36042
36217
  function snapshotCachePath() {
36043
- return import_node_path12.default.join(getUserDataDir(), RATE_LIMIT_SNAPSHOT_CACHE_FILE);
36218
+ return import_node_path13.default.join(getUserDataDir(), RATE_LIMIT_SNAPSHOT_CACHE_FILE);
36044
36219
  }
36045
36220
  async function loadPersistedSnapshots() {
36046
36221
  let raw;
@@ -36089,7 +36264,7 @@ async function writePersistedSnapshots(snapshots) {
36089
36264
  2
36090
36265
  );
36091
36266
  try {
36092
- await import_node_fs9.promises.mkdir(import_node_path12.default.dirname(filePath), { recursive: true });
36267
+ await import_node_fs9.promises.mkdir(import_node_path13.default.dirname(filePath), { recursive: true });
36093
36268
  await import_node_fs9.promises.writeFile(tmpPath, `${payload}
36094
36269
  `, "utf8");
36095
36270
  await import_node_fs9.promises.rename(tmpPath, filePath);
@@ -36146,9 +36321,20 @@ async function pruneRateLimitSnapshots(allowedKeys) {
36146
36321
 
36147
36322
  // ../../packages/shared/src/core/profile-home-id.ts
36148
36323
  var PROFILE_HOME_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
36324
+ function isSafeProfileHomePathSegment(value3) {
36325
+ if (typeof value3 !== "string" || value3 !== value3.trim()) {
36326
+ return false;
36327
+ }
36328
+ return Boolean(
36329
+ value3 && value3 !== "." && value3 !== ".." && value3.length <= 128 && !/[\\/]/.test(value3) && !Array.from(value3).some((character) => {
36330
+ const code = character.charCodeAt(0);
36331
+ return code < 32 || code === 127;
36332
+ })
36333
+ );
36334
+ }
36149
36335
  function normalizeProfileHomeId(value3) {
36150
36336
  const candidate = typeof value3 === "string" ? value3.trim() : "";
36151
- return candidate && candidate !== "." && candidate !== ".." && candidate.length <= 128 && PROFILE_HOME_ID_PATTERN.test(candidate) ? candidate : null;
36337
+ return isSafeProfileHomePathSegment(candidate) && PROFILE_HOME_ID_PATTERN.test(candidate) ? candidate : null;
36152
36338
  }
36153
36339
 
36154
36340
  // ../../packages/runtime-profiles/src/profiles/profile-manager.ts
@@ -36160,7 +36346,7 @@ var AUTH_MUTATION_MANIFEST_NAME = ".codexuse-auth-transaction.json";
36160
36346
  var AUTH_MUTATION_BACKUP_NAME = ".codexuse-auth-transaction.backup";
36161
36347
  var AUTH_MUTATION_REPLACED_NAME = ".codexuse-auth-transaction.replaced";
36162
36348
  var PROFILE_HOME_MUTATION_MARKER_TTL_MS = 10 * 60 * 1e3;
36163
- var PROCESS_OWNER_ID2 = (0, import_node_crypto12.randomUUID)();
36349
+ var PROCESS_OWNER_ID2 = (0, import_node_crypto13.randomUUID)();
36164
36350
  var PROCESS_STARTED_AT2 = readProcessStartedAt(process.pid);
36165
36351
  var globalAuthSwapLock = Promise.resolve();
36166
36352
  var profileOperationLocks = /* @__PURE__ */ new Map();
@@ -36970,7 +37156,14 @@ var ProfileManager = class {
36970
37156
  }
36971
37157
  await this.credentialsMigrationPromise;
36972
37158
  }
36973
- async migrateCredentialsToProfileHomes() {
37159
+ migrateCredentialsToProfileHomes() {
37160
+ return withCloudSyncTransaction(
37161
+ getUserDataDir(),
37162
+ "write",
37163
+ () => this.migrateCredentialsToProfileHomesUnlocked()
37164
+ );
37165
+ }
37166
+ async migrateCredentialsToProfileHomesUnlocked() {
36974
37167
  const source = await this.readProfilesStateSource();
36975
37168
  await this.reconcileProfileHomeLocationConflicts(source);
36976
37169
  const homeIdsByProfileName = /* @__PURE__ */ new Map();
@@ -37006,7 +37199,7 @@ var ProfileManager = class {
37006
37199
  let attempt = 0;
37007
37200
  let homeId;
37008
37201
  do {
37009
- homeId = `legacy-${(0, import_node_crypto12.createHash)("sha256").update(profileName).update("\0").update(String(attempt)).digest("hex").slice(0, 32)}`;
37202
+ homeId = `legacy-${(0, import_node_crypto13.createHash)("sha256").update(profileName).update("\0").update(String(attempt)).digest("hex").slice(0, 32)}`;
37010
37203
  attempt += 1;
37011
37204
  } while (profileNamesByHomeId.has(homeId.toLowerCase()));
37012
37205
  homeIdsByProfileName.set(profileName, homeId);
@@ -37216,7 +37409,7 @@ var ProfileManager = class {
37216
37409
  const dir = import_path.default.dirname(filePath);
37217
37410
  const tempPath = import_path.default.join(
37218
37411
  dir,
37219
- `.${import_path.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto12.randomUUID)()}.tmp`
37412
+ `.${import_path.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto13.randomUUID)()}.tmp`
37220
37413
  );
37221
37414
  await import_fs.promises.mkdir(dir, { recursive: true, mode: 448 });
37222
37415
  if (process.platform !== "win32") {
@@ -37503,7 +37696,7 @@ var ProfileManager = class {
37503
37696
  if (content === null) {
37504
37697
  return null;
37505
37698
  }
37506
- return (0, import_node_crypto12.createHash)("sha256").update(content).digest("hex");
37699
+ return (0, import_node_crypto13.createHash)("sha256").update(content).digest("hex");
37507
37700
  }
37508
37701
  async readOptionalFile(filePath) {
37509
37702
  try {
@@ -37561,7 +37754,7 @@ var ProfileManager = class {
37561
37754
  const dir = import_path.default.dirname(filePath);
37562
37755
  const tempPath = import_path.default.join(
37563
37756
  dir,
37564
- `.${import_path.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto12.randomUUID)()}.install`
37757
+ `.${import_path.default.basename(filePath)}.${process.pid}.${(0, import_node_crypto13.randomUUID)()}.install`
37565
37758
  );
37566
37759
  const handle = await import_fs.promises.open(tempPath, "wx", 384);
37567
37760
  try {
@@ -37646,29 +37839,31 @@ var ProfileManager = class {
37646
37839
  );
37647
37840
  }
37648
37841
  async withAuthMutationLock(task) {
37649
- const release = await this.acquireAuthMutationLock();
37650
- let result2;
37651
- let taskError = null;
37652
- let taskFailed = false;
37653
- try {
37654
- await this.recoverAuthMutationIfNeeded();
37655
- result2 = await task();
37656
- } catch (error) {
37657
- taskFailed = true;
37658
- taskError = error;
37659
- }
37660
- try {
37661
- await release();
37662
- } catch (releaseError) {
37663
- throw errorWithCause(
37664
- "Codex auth transaction lock could not be released.",
37665
- { taskError, releaseError }
37666
- );
37667
- }
37668
- if (taskFailed) {
37669
- throw taskError;
37670
- }
37671
- return result2;
37842
+ return withCloudSyncTransaction(getUserDataDir(), "write", async () => {
37843
+ const release = await this.acquireAuthMutationLock();
37844
+ let result2;
37845
+ let taskError = null;
37846
+ let taskFailed = false;
37847
+ try {
37848
+ await this.recoverAuthMutationIfNeeded();
37849
+ result2 = await task();
37850
+ } catch (error) {
37851
+ taskFailed = true;
37852
+ taskError = error;
37853
+ }
37854
+ try {
37855
+ await release();
37856
+ } catch (releaseError) {
37857
+ throw errorWithCause(
37858
+ "Codex auth transaction lock could not be released.",
37859
+ { taskError, releaseError }
37860
+ );
37861
+ }
37862
+ if (taskFailed) {
37863
+ throw taskError;
37864
+ }
37865
+ return result2;
37866
+ });
37672
37867
  }
37673
37868
  async beginAuthMutation(operation, targetFingerprint) {
37674
37869
  const sourceRaw = await this.readOptionalFile(this.activeAuth);
@@ -37679,7 +37874,7 @@ var ProfileManager = class {
37679
37874
  });
37680
37875
  const manifest = {
37681
37876
  version: 1,
37682
- id: (0, import_node_crypto12.randomUUID)(),
37877
+ id: (0, import_node_crypto13.randomUUID)(),
37683
37878
  operation,
37684
37879
  phase: "prepared",
37685
37880
  sourceFingerprint: this.fingerprintAuthContent(sourceRaw),
@@ -38351,7 +38546,14 @@ var ProfileManager = class {
38351
38546
  normalizeWorkspaceId(value3) {
38352
38547
  return typeof value3 === "string" && value3.trim().length > 0 ? value3.trim() : DEFAULT_WORKSPACE_ID;
38353
38548
  }
38354
- async persistProfileRecord(name, data, metadata, options) {
38549
+ persistProfileRecord(name, data, metadata, options) {
38550
+ return withCloudSyncTransaction(
38551
+ getUserDataDir(),
38552
+ "write",
38553
+ () => this.persistProfileRecordUnlocked(name, data, metadata, options)
38554
+ );
38555
+ }
38556
+ async persistProfileRecordUnlocked(name, data, metadata, options) {
38355
38557
  const resolvedName = this.normalizeProfileName(name);
38356
38558
  this.assertProfileHomeUsable(resolvedName);
38357
38559
  const initialMap = await this.readProfilesStateMap();
@@ -38401,7 +38603,7 @@ var ProfileManager = class {
38401
38603
  const displayName = typeof options?.displayName === "string" && options.displayName.trim().length > 0 ? options.displayName.trim() : existingRecord?.displayName ?? resolvedName;
38402
38604
  const record2 = {
38403
38605
  name: resolvedName,
38404
- homeId: existingRecord?.homeId ?? (options?.homeId ? this.normalizeProfileHomeId(options.homeId, resolvedName) : (0, import_node_crypto12.randomUUID)()),
38606
+ homeId: existingRecord?.homeId ?? (options?.homeId ? this.normalizeProfileHomeId(options.homeId, resolvedName) : (0, import_node_crypto13.randomUUID)()),
38405
38607
  cloudHomeId: existingRecord?.cloudHomeId ?? null,
38406
38608
  displayName,
38407
38609
  data,
@@ -38506,7 +38708,7 @@ var ProfileManager = class {
38506
38708
  const safeName = record2.name.replace(/[^A-Za-z0-9._-]+/g, "-").slice(0, 48) || "profile";
38507
38709
  const destination = import_path.default.join(
38508
38710
  trashRoot,
38509
- `CodexUse-${safeName}-${(0, import_node_crypto12.randomUUID)()}`
38711
+ `CodexUse-${safeName}-${(0, import_node_crypto13.randomUUID)()}`
38510
38712
  );
38511
38713
  await import_fs.promises.rename(profileHome, destination);
38512
38714
  return destination;
@@ -38934,7 +39136,7 @@ var ProfileManager = class {
38934
39136
  async acquireProfileRuntimeLease(record2) {
38935
39137
  const leaseDir = this.getProfileRuntimeLeaseDir(record2.homeId);
38936
39138
  const deletingPath = (0, import_path2.join)(leaseDir, ".deleting");
38937
- const leaseId = (0, import_node_crypto12.randomUUID)();
39139
+ const leaseId = (0, import_node_crypto13.randomUUID)();
38938
39140
  const leasePath = (0, import_path2.join)(leaseDir, `${leaseId}.json`);
38939
39141
  const backupPath = (0, import_path2.join)(leaseDir, `${leaseId}.auth.backup`);
38940
39142
  const releaseIntent = await this.acquireProfileHomeWriteIntent(record2);
@@ -39145,7 +39347,7 @@ var ProfileManager = class {
39145
39347
  async acquireProfileHomeMutationGuard(record2) {
39146
39348
  const leaseDir = this.getProfileRuntimeLeaseDir(record2.homeId);
39147
39349
  const deletingPath = (0, import_path2.join)(leaseDir, ".deleting");
39148
- const mutationId = (0, import_node_crypto12.randomUUID)();
39350
+ const mutationId = (0, import_node_crypto13.randomUUID)();
39149
39351
  const mutationIntent = await acquireProfileHomeMutationIntent({
39150
39352
  homeId: record2.homeId,
39151
39353
  profileName: record2.name
@@ -40405,32 +40607,39 @@ var ProfileManager = class {
40405
40607
  */
40406
40608
  async exportProfilesForCloudSync() {
40407
40609
  await this.initialize();
40408
- const records = await this.listProfileRecords();
40409
- const exported = [];
40410
- for (const storedRecord of records) {
40411
- const record2 = await this.hydrateProfileRecordStrict(storedRecord);
40412
- exported.push({
40413
- name: record2.name,
40414
- homeId: record2.cloudHomeId ?? record2.homeId,
40415
- displayName: record2.displayName,
40416
- data: record2.data,
40417
- metadata: record2.metadata,
40418
- accountId: record2.accountId,
40419
- workspaceId: record2.workspaceId,
40420
- workspaceName: record2.workspaceName,
40421
- email: record2.email,
40422
- authMethod: record2.authMethod,
40423
- createdAt: record2.createdAt,
40424
- updatedAt: record2.updatedAt
40425
- });
40426
- }
40427
- return exported;
40610
+ return withCloudSyncTransaction(getUserDataDir(), "write", async () => {
40611
+ const records = await this.listProfileRecords();
40612
+ const exported = [];
40613
+ for (const storedRecord of records) {
40614
+ const record2 = await this.hydrateProfileRecordStrict(storedRecord);
40615
+ exported.push({
40616
+ name: record2.name,
40617
+ homeId: record2.cloudHomeId ?? record2.homeId,
40618
+ displayName: record2.displayName,
40619
+ data: record2.data,
40620
+ metadata: record2.metadata,
40621
+ accountId: record2.accountId,
40622
+ workspaceId: record2.workspaceId,
40623
+ workspaceName: record2.workspaceName,
40624
+ email: record2.email,
40625
+ authMethod: record2.authMethod,
40626
+ createdAt: record2.createdAt,
40627
+ updatedAt: record2.updatedAt
40628
+ });
40629
+ }
40630
+ return exported;
40631
+ });
40428
40632
  }
40429
- /**
40430
- * Replace local profiles with a full snapshot from cloud sync.
40431
- */
40432
- async replaceProfilesFromCloudSync(records) {
40633
+ /** Replaces profiles, optionally deferring stale-home removal until commit. */
40634
+ async replaceProfilesFromCloudSync(records, options = {}) {
40433
40635
  await this.initialize();
40636
+ return withCloudSyncTransaction(
40637
+ getUserDataDir(),
40638
+ "write",
40639
+ () => this.replaceProfilesFromCloudSyncUnlocked(records, options)
40640
+ );
40641
+ }
40642
+ async replaceProfilesFromCloudSyncUnlocked(records, options) {
40434
40643
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
40435
40644
  const normalized = /* @__PURE__ */ new Map();
40436
40645
  const existingMap = await this.readProfilesStateMap();
@@ -40497,8 +40706,12 @@ var ProfileManager = class {
40497
40706
  }
40498
40707
  cloudRenamesByOldName.set(renamedExisting.name, name);
40499
40708
  }
40500
- const homeId = (0, import_node_crypto12.randomUUID)();
40501
- const cloudHomeId = remoteHomeId || existing?.cloudHomeId || existing?.homeId || renamedExisting?.cloudHomeId || renamedExisting?.homeId || (0, import_node_crypto12.randomUUID)();
40709
+ const mappedHomeId = options.homeIdByProfileName?.[name];
40710
+ if (mappedHomeId !== void 0 && !isSafeProfileHomePathSegment(mappedHomeId)) {
40711
+ throw new Error(`Cloud Sync restore contains an invalid profile home id.`);
40712
+ }
40713
+ const homeId = mappedHomeId ?? (0, import_node_crypto13.randomUUID)();
40714
+ const cloudHomeId = remoteHomeId || existing?.cloudHomeId || existing?.homeId || renamedExisting?.cloudHomeId || renamedExisting?.homeId || (0, import_node_crypto13.randomUUID)();
40502
40715
  const sourceRecord = renamedExisting ?? existing;
40503
40716
  if (sourceRecord) {
40504
40717
  sourceHomeIdByTargetHomeId.set(homeId, sourceRecord.homeId);
@@ -40536,6 +40749,9 @@ var ProfileManager = class {
40536
40749
  for (const record2 of normalized.values()) {
40537
40750
  nextMap[record2.name] = this.toStateRecord(record2);
40538
40751
  }
40752
+ await options.onPreparedHomeIds?.(
40753
+ Array.from(normalized.values(), (record2) => record2.homeId)
40754
+ );
40539
40755
  const nextHomeIds = new Set(
40540
40756
  Array.from(normalized.values(), (record2) => record2.homeId)
40541
40757
  );
@@ -40549,6 +40765,7 @@ var ProfileManager = class {
40549
40765
  const preparedHomeIds = /* @__PURE__ */ new Set();
40550
40766
  let stateCommitted = false;
40551
40767
  let removed = 0;
40768
+ let pendingStaleRemovals = [];
40552
40769
  const releaseAuthMutation = await this.acquireAuthMutationLock();
40553
40770
  let cloudSyncError = null;
40554
40771
  let cloudSyncFailed = false;
@@ -40584,18 +40801,21 @@ var ProfileManager = class {
40584
40801
  }
40585
40802
  homeExisted = false;
40586
40803
  }
40587
- if (homeExisted) {
40804
+ const reusingExistingHome = options.homeIdByProfileName?.[record2.name] === record2.homeId;
40805
+ if (homeExisted && !reusingExistingHome) {
40588
40806
  throw new Error(
40589
40807
  `Generated profile home '${record2.homeId}' already exists. Retry Cloud Sync.`
40590
40808
  );
40591
40809
  }
40592
- preparedHomeIds.add(record2.homeId);
40810
+ if (!reusingExistingHome) {
40811
+ preparedHomeIds.add(record2.homeId);
40812
+ }
40593
40813
  const writtenAuth = JSON.stringify(
40594
40814
  this.convertToCodexFormat(record2.data),
40595
40815
  null,
40596
40816
  2
40597
40817
  );
40598
- const sourceHomeId = sourceHomeIdByTargetHomeId.get(record2.homeId);
40818
+ const sourceHomeId = reusingExistingHome ? null : sourceHomeIdByTargetHomeId.get(record2.homeId);
40599
40819
  if (sourceHomeId) {
40600
40820
  const sourceHome = this.getProfileHomePath(sourceHomeId);
40601
40821
  let sourceHomeExists = true;
@@ -40657,16 +40877,13 @@ var ProfileManager = class {
40657
40877
  ).catch((error) => {
40658
40878
  logWarn("Failed to prune rate-limit snapshots after Cloud Sync:", error);
40659
40879
  });
40660
- for (const record2 of existingRecords.values()) {
40661
- if (nextHomeIds.has(record2.homeId)) {
40662
- continue;
40663
- }
40664
- try {
40665
- await this.removeProfileHome(record2, true);
40666
- removed += 1;
40667
- } catch (error) {
40668
- logWarn(`Failed to move stale profile '${record2.name}' to Trash after cloud sync:`, error);
40669
- }
40880
+ const staleRecords = Array.from(existingRecords.values()).filter(
40881
+ (record2) => !nextHomeIds.has(record2.homeId)
40882
+ );
40883
+ if (options.deferStaleHomeRemoval) {
40884
+ pendingStaleRemovals = staleRecords;
40885
+ } else {
40886
+ removed = await this.removeStaleProfileHomes(staleRecords);
40670
40887
  }
40671
40888
  } catch (error) {
40672
40889
  cloudSyncFailed = true;
@@ -40720,9 +40937,61 @@ var ProfileManager = class {
40720
40937
  }
40721
40938
  return {
40722
40939
  imported: normalized.size,
40723
- removed
40940
+ removed,
40941
+ pendingStaleRemovals
40724
40942
  };
40725
40943
  }
40944
+ /** Returns the physical home currently backing each profile. */
40945
+ async getProfileHomeIdsByName() {
40946
+ await this.initialize();
40947
+ return withCloudSyncTransaction(getUserDataDir(), "write", async () => {
40948
+ const stateMap = await this.readProfilesStateMap();
40949
+ return Object.fromEntries(
40950
+ Object.entries(stateMap).flatMap(([name, raw]) => {
40951
+ const record2 = this.fromStateRecord(name, raw);
40952
+ return record2?.homeId ? [[name, record2.homeId]] : [];
40953
+ })
40954
+ );
40955
+ });
40956
+ }
40957
+ /** Permanently deletes unreferenced credential homes created by a failed pull. */
40958
+ async deleteAbandonedPullProfileHomes(homeIds) {
40959
+ if (homeIds.some((homeId) => normalizeProfileHomeId(homeId) !== homeId)) {
40960
+ throw new Error("Cloud Sync cleanup contains an invalid profile home id.");
40961
+ }
40962
+ let deleted = 0;
40963
+ for (const homeId of homeIds) {
40964
+ try {
40965
+ await import_fs.promises.rm(this.getProfileHomePath(homeId), {
40966
+ recursive: true,
40967
+ force: true
40968
+ });
40969
+ deleted += 1;
40970
+ } catch (error) {
40971
+ logWarn(
40972
+ `Failed to delete the home an abandoned cloud pull created ('${homeId}'):`,
40973
+ error
40974
+ );
40975
+ }
40976
+ }
40977
+ return deleted;
40978
+ }
40979
+ /** Moves stale user homes to Trash after every synced store commits. */
40980
+ async removeStaleProfileHomes(records) {
40981
+ let removed = 0;
40982
+ for (const record2 of records) {
40983
+ try {
40984
+ await this.removeProfileHome(record2, true);
40985
+ removed += 1;
40986
+ } catch (error) {
40987
+ logWarn(
40988
+ `Failed to move stale profile '${record2.name}' to Trash after cloud sync:`,
40989
+ error
40990
+ );
40991
+ }
40992
+ }
40993
+ return removed;
40994
+ }
40726
40995
  };
40727
40996
 
40728
40997
  // ../../packages/runtime-profiles/src/profiles/managed-profile.ts
@@ -40935,8 +41204,8 @@ Flags:
40935
41204
  --take-control Allow verified replacement of an unmanaged ChatGPT/Codex window
40936
41205
  --profile=NAME Explicitly override a workspace binding for codexuse run
40937
41206
  --strict Reject a --profile override that conflicts with a workspace binding
40938
- --runtime=NAME Accounts Pool runtime store: desktop
40939
- --state-dir=PATH Override the runtime state dir for Accounts Pool inspection
41207
+ --runtime=NAME Account Pool runtime store: desktop
41208
+ --state-dir=PATH Override the runtime state dir for Account Pool inspection
40940
41209
  --passphrase-stdin Read Cloud Sync passphrase from stdin
40941
41210
  Note: profile autoroll requires Pro or an active trial.
40942
41211
  Cloud Sync: set CODEXUSE_SYNC_PASSPHRASE or use --passphrase-stdin unless the passphrase is saved in Keychain.
@@ -41005,7 +41274,7 @@ function parseStringFlag(flags, name) {
41005
41274
 
41006
41275
  // src/commands/accountPool.ts
41007
41276
  var ACCOUNT_POOL_DOCUMENT = "desktop.account-pool.v2";
41008
- var ACCOUNT_POOL_PRO_REQUIRED_MESSAGE = "Accounts Pool requires a Pro license or an active trial.";
41277
+ var ACCOUNT_POOL_PRO_REQUIRED_MESSAGE = "Account Pool requires a Pro license or an active trial.";
41009
41278
  var DESKTOP_RPC_STATE_DIR = "desktop-rpc";
41010
41279
  var ACCOUNT_POOL_STORE_VERSION = 3;
41011
41280
  var MAX_RESPONSE_IDS_PER_SESSION = 64;
@@ -41309,7 +41578,7 @@ function normalizeAccountPoolStore(value3) {
41309
41578
  }
41310
41579
  function normalizeAccountPoolStoreStrict(value3) {
41311
41580
  if (!value3 || typeof value3 !== "object" || Array.isArray(value3)) {
41312
- throw new Error("Accounts Pool store must be a JSON object.");
41581
+ throw new Error("Account Pool store must be a JSON object.");
41313
41582
  }
41314
41583
  return normalizeAccountPoolStore(value3);
41315
41584
  }
@@ -41359,7 +41628,7 @@ function pruneStore(store) {
41359
41628
  return store;
41360
41629
  }
41361
41630
  function resolveAccountPoolDbPath(stateDir) {
41362
- return import_node_path13.default.join(stateDir, "state.sqlite");
41631
+ return import_node_path14.default.join(stateDir, "state.sqlite");
41363
41632
  }
41364
41633
  async function readStore(stateDir) {
41365
41634
  const dbPath = resolveAccountPoolDbPath(stateDir);
@@ -41399,13 +41668,13 @@ async function listApiKeys(stateDir) {
41399
41668
  return Object.values(store.apiKeysById).filter((key) => key.revokedAt === null).sort((left, right) => right.createdAt.localeCompare(left.createdAt)).map(accountPoolApiKeyView);
41400
41669
  }
41401
41670
  function hashToken(token) {
41402
- return (0, import_node_crypto13.createHash)("sha256").update(token).digest("hex");
41671
+ return (0, import_node_crypto14.createHash)("sha256").update(token).digest("hex");
41403
41672
  }
41404
41673
  async function createApiKey(stateDir) {
41405
- const plaintextToken = `cux_pool_${(0, import_node_crypto13.randomBytes)(24).toString("hex")}`;
41674
+ const plaintextToken = `cux_pool_${(0, import_node_crypto14.randomBytes)(24).toString("hex")}`;
41406
41675
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
41407
41676
  const keyRecord = {
41408
- id: (0, import_node_crypto13.randomUUID)(),
41677
+ id: (0, import_node_crypto14.randomUUID)(),
41409
41678
  tokenHash: hashToken(plaintextToken),
41410
41679
  tokenPreview: `${plaintextToken.slice(0, 8)}...${plaintextToken.slice(-6)}`,
41411
41680
  createdAt: now2,
@@ -41460,9 +41729,9 @@ async function listSessions(stateDir) {
41460
41729
  }
41461
41730
  function resolveRuntimeStateDir(runtime, explicitStateDir) {
41462
41731
  if (explicitStateDir) {
41463
- return import_node_path13.default.resolve(explicitStateDir);
41732
+ return import_node_path14.default.resolve(explicitStateDir);
41464
41733
  }
41465
- return import_node_path13.default.join(getUserDataDir(), DESKTOP_RPC_STATE_DIR);
41734
+ return import_node_path14.default.join(getUserDataDir(), DESKTOP_RPC_STATE_DIR);
41466
41735
  }
41467
41736
  function resolveStateDir(flags) {
41468
41737
  const runtimeFlag = parseStringFlag(flags, "--runtime")?.trim().toLowerCase();
@@ -41622,7 +41891,7 @@ async function handleStatus(flags) {
41622
41891
  if (baseUrl) {
41623
41892
  console.log(`Base URL: ${baseUrl}`);
41624
41893
  } else {
41625
- console.log("Base URL: check the running desktop app for the current Accounts Pool URL.");
41894
+ console.log("Base URL: check the running desktop app for the current Account Pool URL.");
41626
41895
  }
41627
41896
  printStringList("Selected profiles", selectedProfiles);
41628
41897
  if (missingSelectedProfiles.length > 0) {
@@ -41641,7 +41910,7 @@ async function handleEnable() {
41641
41910
  accountPoolEnableExistingMigrationApplied: true,
41642
41911
  accountPoolEnabled: true
41643
41912
  }));
41644
- console.log(`Accounts Pool ${result2.settings.accountPoolEnabled ? "enabled" : "disabled"}.`);
41913
+ console.log(`Account Pool ${result2.settings.accountPoolEnabled ? "enabled" : "disabled"}.`);
41645
41914
  }
41646
41915
  async function handleDisable() {
41647
41916
  const result2 = await updateSettings((current) => ({
@@ -41649,7 +41918,7 @@ async function handleDisable() {
41649
41918
  accountPoolEnableExistingMigrationApplied: true,
41650
41919
  accountPoolEnabled: false
41651
41920
  }));
41652
- console.log(`Accounts Pool ${result2.settings.accountPoolEnabled ? "enabled" : "disabled"}.`);
41921
+ console.log(`Account Pool ${result2.settings.accountPoolEnabled ? "enabled" : "disabled"}.`);
41653
41922
  }
41654
41923
  async function handleRouting(params) {
41655
41924
  const value3 = parseRoutingStrategy(params[1]);
@@ -41660,7 +41929,7 @@ async function handleRouting(params) {
41660
41929
  ...current,
41661
41930
  accountPoolRoutingStrategy: value3
41662
41931
  }));
41663
- console.log(`Accounts Pool routing set to ${formatRoutingStrategy(result2.settings.accountPoolRoutingStrategy)}.`);
41932
+ console.log(`Account Pool routing set to ${formatRoutingStrategy(result2.settings.accountPoolRoutingStrategy)}.`);
41664
41933
  }
41665
41934
  async function handleProfiles(params) {
41666
41935
  const action = params[1];
@@ -41720,10 +41989,10 @@ async function handleProfiles(params) {
41720
41989
  };
41721
41990
  });
41722
41991
  if (result2.settings.accountPoolProfilePool.length === 0) {
41723
- console.log("Accounts Pool now uses all saved profiles.");
41992
+ console.log("Account Pool now uses all saved profiles.");
41724
41993
  return;
41725
41994
  }
41726
- printStringList("Accounts Pool selected profiles", result2.settings.accountPoolProfilePool);
41995
+ printStringList("Account Pool selected profiles", result2.settings.accountPoolProfilePool);
41727
41996
  }
41728
41997
  async function handleArraySetting(input) {
41729
41998
  const action = input.params[1];
@@ -41772,7 +42041,7 @@ async function handleKeys(params, flags) {
41772
42041
  if (!action || action === "list") {
41773
42042
  const apiKeys = await listApiKeys(stateDir);
41774
42043
  if (apiKeys.length === 0) {
41775
- console.log("No active Accounts Pool API keys.");
42044
+ console.log("No active Account Pool API keys.");
41776
42045
  return;
41777
42046
  }
41778
42047
  for (const apiKey of apiKeys) {
@@ -41792,7 +42061,7 @@ async function handleKeys(params, flags) {
41792
42061
  if (baseUrl) {
41793
42062
  console.log(`Base URL: ${baseUrl}`);
41794
42063
  } else {
41795
- console.log("Base URL: use the current Accounts Pool URL shown by the running desktop app.");
42064
+ console.log("Base URL: use the current Account Pool URL shown by the running desktop app.");
41796
42065
  }
41797
42066
  console.log("This key only works for the selected runtime state dir.");
41798
42067
  console.log("Store this token now. The plaintext value is only shown once.");
@@ -41805,7 +42074,7 @@ async function handleKeys(params, flags) {
41805
42074
  }
41806
42075
  const removed = await revokeApiKey(stateDir, id2);
41807
42076
  if (!removed) {
41808
- throw new Error(`No Accounts Pool API key found for id ${id2}.`);
42077
+ throw new Error(`No Account Pool API key found for id ${id2}.`);
41809
42078
  }
41810
42079
  console.log(`Revoked key: ${id2}`);
41811
42080
  return;
@@ -41834,7 +42103,7 @@ async function handleQuickstart(flags) {
41834
42103
  const { runtime, stateDir } = resolveStateDir(flags);
41835
42104
  const summary = await readAccountPoolRuntimeSummary({ runtime, stateDir });
41836
42105
  const baseUrl = summary.baseUrl ?? "<shown-in-desktop-app>";
41837
- console.log("Accounts Pool quickstart");
42106
+ console.log("Account Pool quickstart");
41838
42107
  console.log(`Runtime: ${summary.runtime}`);
41839
42108
  console.log(`Enabled: ${summary.enabled ? "yes" : "no"}`);
41840
42109
  console.log(`Access: ${summary.hasAccountPoolAccess ? "yes" : "no"}`);
@@ -41910,7 +42179,7 @@ async function handleAccountPoolCommand(args2, version) {
41910
42179
  }
41911
42180
 
41912
42181
  // src/commands/codex.ts
41913
- var import_node_child_process9 = require("child_process");
42182
+ var import_node_child_process10 = require("child_process");
41914
42183
  var import_node_os6 = __toESM(require("os"));
41915
42184
 
41916
42185
  // ../../packages/runtime-profiles/src/profiles/rate-limit-notifier.ts
@@ -42031,9 +42300,9 @@ async function assertProfileAccessAllowed(profileManager, profileName) {
42031
42300
 
42032
42301
  // ../../packages/runtime-app-state/src/app/workspaceBindings.ts
42033
42302
  var import_node_fs10 = require("fs");
42034
- var import_node_path14 = __toESM(require("path"), 1);
42303
+ var import_node_path15 = __toESM(require("path"), 1);
42035
42304
  async function canonicalizeWorkspacePath(input, options = {}) {
42036
- const resolved = import_node_path14.default.resolve(input || process.cwd());
42305
+ const resolved = import_node_path15.default.resolve(input || process.cwd());
42037
42306
  try {
42038
42307
  const canonical = await import_node_fs10.promises.realpath(resolved);
42039
42308
  if (options.requireDirectory !== false) {
@@ -42042,10 +42311,10 @@ async function canonicalizeWorkspacePath(input, options = {}) {
42042
42311
  throw new Error(`Workspace path is not a directory: ${resolved}`);
42043
42312
  }
42044
42313
  }
42045
- return import_node_path14.default.normalize(canonical);
42314
+ return import_node_path15.default.normalize(canonical);
42046
42315
  } catch (error) {
42047
42316
  if (options.requireDirectory === false) {
42048
- return import_node_path14.default.normalize(resolved);
42317
+ return import_node_path15.default.normalize(resolved);
42049
42318
  }
42050
42319
  const message = error instanceof Error ? error.message : String(error);
42051
42320
  const symptom = new Error(
@@ -42112,7 +42381,7 @@ async function resolveWorkspaceProfileBinding(requestedPath) {
42112
42381
  inherited: candidate !== canonical
42113
42382
  };
42114
42383
  }
42115
- const parent = import_node_path14.default.dirname(candidate);
42384
+ const parent = import_node_path15.default.dirname(candidate);
42116
42385
  if (parent === candidate) {
42117
42386
  return null;
42118
42387
  }
@@ -42121,13 +42390,13 @@ async function resolveWorkspaceProfileBinding(requestedPath) {
42121
42390
  }
42122
42391
 
42123
42392
  // src/platform/codexCli.ts
42124
- var import_node_child_process8 = require("child_process");
42393
+ var import_node_child_process9 = require("child_process");
42125
42394
  var import_node_fs11 = require("fs");
42126
- var import_node_path15 = __toESM(require("path"));
42395
+ var import_node_path16 = __toESM(require("path"));
42127
42396
  var ENV_HINTS2 = ["CODEX_BINARY", "CODEX_CLI_PATH", "CODEX_PATH"];
42128
42397
  function fileExists2(candidate) {
42129
42398
  if (!candidate) return null;
42130
- const resolved = import_node_path15.default.resolve(candidate);
42399
+ const resolved = import_node_path16.default.resolve(candidate);
42131
42400
  try {
42132
42401
  const stat2 = (0, import_node_fs11.statSync)(resolved);
42133
42402
  if (stat2.isFile()) return resolved;
@@ -42147,9 +42416,9 @@ function resolveFromEnv() {
42147
42416
  }
42148
42417
  function resolveFromPath() {
42149
42418
  const pathValue = process.env.PATH ?? "";
42150
- const entries3 = pathValue.split(import_node_path15.default.delimiter).filter(Boolean);
42419
+ const entries3 = pathValue.split(import_node_path16.default.delimiter).filter(Boolean);
42151
42420
  for (const entry of entries3) {
42152
- const candidate = fileExists2(import_node_path15.default.join(entry, "codex"));
42421
+ const candidate = fileExists2(import_node_path16.default.join(entry, "codex"));
42153
42422
  if (candidate) return candidate;
42154
42423
  }
42155
42424
  return null;
@@ -42193,7 +42462,7 @@ async function runCodexLogin(mode, envOverrides = {}) {
42193
42462
  const resolvedMode = resolveLoginMode(mode ?? null);
42194
42463
  const loginArgs = resolvedMode === "device" ? ["login", "--device-auth"] : ["login"];
42195
42464
  const { command, args: args2, shell } = buildCodexCommand2(codexPath, loginArgs);
42196
- const child = (0, import_node_child_process8.spawn)(command, args2, {
42465
+ const child = (0, import_node_child_process9.spawn)(command, args2, {
42197
42466
  stdio: "inherit",
42198
42467
  env: { ...process.env, ...envOverrides },
42199
42468
  shell
@@ -42262,7 +42531,7 @@ function compareCandidates(left, right) {
42262
42531
  async function runCommand3(codexPath, args2, timeoutMs) {
42263
42532
  const command = buildCodexCommand2(codexPath, args2);
42264
42533
  return new Promise((resolve2) => {
42265
- const child = (0, import_node_child_process9.spawn)(command.command, command.args, {
42534
+ const child = (0, import_node_child_process10.spawn)(command.command, command.args, {
42266
42535
  env: process.env,
42267
42536
  shell: command.shell,
42268
42537
  stdio: ["ignore", "pipe", "pipe"]
@@ -42342,7 +42611,7 @@ async function runCodexWithProfile(manager, profileName, codexArgs) {
42342
42611
  });
42343
42612
  const command = buildCodexCommand2(codexPath, codexArgs);
42344
42613
  try {
42345
- const child = (0, import_node_child_process9.spawn)(command.command, command.args, {
42614
+ const child = (0, import_node_child_process10.spawn)(command.command, command.args, {
42346
42615
  env: runtime.env,
42347
42616
  shell: command.shell,
42348
42617
  stdio: "inherit"
@@ -42404,7 +42673,7 @@ async function handleDoctorCommand(args2) {
42404
42673
  console.log(`Usage:
42405
42674
  codexuse doctor
42406
42675
 
42407
- Checks Codex CLI, auth, saved profiles, license, and Accounts Pool readiness.`);
42676
+ Checks Codex CLI, auth, saved profiles, license, and Account Pool readiness.`);
42408
42677
  return;
42409
42678
  }
42410
42679
  const manager = new ProfileManager();
@@ -42432,10 +42701,10 @@ Checks Codex CLI, auth, saved profiles, license, and Accounts Pool readiness.`);
42432
42701
  console.log(`License: ${license ? `${license.tier} (${license.state})` : "unknown"}`);
42433
42702
  if (accountPool) {
42434
42703
  console.log(
42435
- `Accounts Pool: ${accountPool.enabled ? "on" : "off"} | keys ${accountPool.activeApiKeyCount} | sessions ${accountPool.activeSessionCount}`
42704
+ `Account Pool: ${accountPool.enabled ? "on" : "off"} | keys ${accountPool.activeApiKeyCount} | sessions ${accountPool.activeSessionCount}`
42436
42705
  );
42437
42706
  } else {
42438
- console.log("Accounts Pool: unknown");
42707
+ console.log("Account Pool: unknown");
42439
42708
  }
42440
42709
  const fixes = [];
42441
42710
  if (!codexPath) {
@@ -42590,15 +42859,15 @@ async function handleLicense(args2, version) {
42590
42859
  // src/commands/profile.ts
42591
42860
  var import_node_fs13 = require("fs");
42592
42861
  var import_node_os7 = __toESM(require("os"));
42593
- var import_node_path17 = __toESM(require("path"));
42862
+ var import_node_path18 = __toESM(require("path"));
42594
42863
 
42595
42864
  // ../../packages/runtime-app-state/src/app/officialCodexSwitchCoordinator.ts
42596
- var import_node_crypto14 = require("crypto");
42865
+ var import_node_crypto15 = require("crypto");
42597
42866
  var import_node_fs12 = require("fs");
42598
- var import_node_path16 = __toESM(require("path"), 1);
42867
+ var import_node_path17 = __toESM(require("path"), 1);
42599
42868
  var DEFAULT_SWITCH_INTENT_TTL_MS = 10 * 60 * 1e3;
42600
42869
  var SWITCH_INTENT_RENEW_MS = 30 * 1e3;
42601
- var PROCESS_OWNER_ID3 = (0, import_node_crypto14.randomUUID)();
42870
+ var PROCESS_OWNER_ID3 = (0, import_node_crypto15.randomUUID)();
42602
42871
  var PROCESS_STARTED_AT3 = readProcessStartedAt(process.pid);
42603
42872
  var localIntentDepth = /* @__PURE__ */ new Map();
42604
42873
  var pendingLocalIntentAcquisitions = /* @__PURE__ */ new Map();
@@ -42608,7 +42877,7 @@ function nextSwitchIntentGeneration(current) {
42608
42877
  }
42609
42878
  async function acquireOfficialCodexSwitchIntent(input) {
42610
42879
  const now2 = Date.now();
42611
- const operationId = input.operationId?.trim() || (0, import_node_crypto14.randomUUID)();
42880
+ const operationId = input.operationId?.trim() || (0, import_node_crypto15.randomUUID)();
42612
42881
  const targetProfileName = input.targetProfileName.trim();
42613
42882
  if (!targetProfileName) {
42614
42883
  throw new Error("Profile name is required");
@@ -42739,6 +43008,191 @@ async function releaseOfficialCodexSwitchIntent(operationId) {
42739
43008
  }
42740
43009
  }
42741
43010
 
43011
+ // ../../packages/shared/src/core/errors.ts
43012
+ var ANSI_PATTERN = /\u001B\[[0-9;]*m/g;
43013
+ function stripAnsi(value3) {
43014
+ return value3.replace(ANSI_PATTERN, "");
43015
+ }
43016
+ function normalizeWhitespace(value3) {
43017
+ return value3.replace(/\s+/g, " ").trim();
43018
+ }
43019
+ function compactErrorText(value3, maxLength = 220) {
43020
+ if (!value3) {
43021
+ return "";
43022
+ }
43023
+ const cleaned = normalizeWhitespace(stripAnsi(String(value3)));
43024
+ if (!cleaned) {
43025
+ return "";
43026
+ }
43027
+ if (cleaned.length <= maxLength) {
43028
+ return cleaned;
43029
+ }
43030
+ return `${cleaned.slice(0, maxLength).trimEnd()}\u2026`;
43031
+ }
43032
+ function createErrorReferenceId() {
43033
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`.toUpperCase();
43034
+ }
43035
+ function serializeUnknownError(value3) {
43036
+ if (typeof value3 === "string") {
43037
+ return value3;
43038
+ }
43039
+ if (value3 instanceof Error) {
43040
+ return value3.stack ?? value3.message;
43041
+ }
43042
+ try {
43043
+ return JSON.stringify(value3);
43044
+ } catch {
43045
+ return String(value3);
43046
+ }
43047
+ }
43048
+ function extractRawMessage(error) {
43049
+ if (error === null || typeof error === "undefined") {
43050
+ return "";
43051
+ }
43052
+ if (typeof error === "string") {
43053
+ return error;
43054
+ }
43055
+ if (error instanceof Error) {
43056
+ return error.message;
43057
+ }
43058
+ return String(error);
43059
+ }
43060
+ function normalizeRawMessage(rawMessage) {
43061
+ let cleaned = normalizeWhitespace(stripAnsi(rawMessage));
43062
+ if (!cleaned) {
43063
+ return "";
43064
+ }
43065
+ if (cleaned.startsWith("Error invoking remote method")) {
43066
+ cleaned = cleaned.replace(/^Error invoking remote method '[^']+': Error: /, "");
43067
+ }
43068
+ if (cleaned.toLowerCase().includes("openai codex") && cleaned.toLowerCase().includes("workdir:")) {
43069
+ const parts = cleaned.split(/error:/i);
43070
+ if (parts.length > 1) {
43071
+ return parts[parts.length - 1]?.trim() ?? cleaned;
43072
+ }
43073
+ }
43074
+ return cleaned;
43075
+ }
43076
+ function resolveCategory(cleaned, options) {
43077
+ const lower = cleaned.toLowerCase();
43078
+ if (options.notFoundFallback && (lower.includes("enoent") || lower.includes("not found"))) {
43079
+ return {
43080
+ code: "ERR_NOT_FOUND",
43081
+ title: "We couldn't find that item",
43082
+ message: options.notFoundFallback,
43083
+ recovery: "Check the path or selection, then try again.",
43084
+ retryable: true
43085
+ };
43086
+ }
43087
+ if (lower.includes("rate limit") || lower.includes("quota exceeded") || lower.includes("too many requests") || lower.includes("429")) {
43088
+ return {
43089
+ code: "ERR_RATE_LIMIT",
43090
+ title: "Rate limit reached",
43091
+ message: "The provider is rate limited right now.",
43092
+ recovery: "Wait a moment, switch profiles, or try again.",
43093
+ retryable: true
43094
+ };
43095
+ }
43096
+ if (lower.includes("timeout") || lower.includes("timed out")) {
43097
+ return {
43098
+ code: "ERR_TIMEOUT",
43099
+ title: "Request timed out",
43100
+ message: "The operation took too long to finish.",
43101
+ recovery: "Check the connection and try again.",
43102
+ retryable: true
43103
+ };
43104
+ }
43105
+ if (lower.includes("network") || lower.includes("econn") || lower.includes("networkerror") || lower.includes("connection refused") || lower.includes("socket hang up")) {
43106
+ return {
43107
+ code: "ERR_NETWORK",
43108
+ title: "Can't reach the service",
43109
+ message: "CodexUse couldn't connect to the required service.",
43110
+ recovery: "Check your internet or local server connection, then retry.",
43111
+ retryable: true
43112
+ };
43113
+ }
43114
+ if (lower.includes("token_invalidated") || lower.includes("session invalidated") || lower.includes("session expired") || lower.includes("refresh token") || lower.includes("unauthorized") || lower.includes("401")) {
43115
+ return {
43116
+ code: "ERR_AUTH",
43117
+ title: "Sign-in expired",
43118
+ message: "This account needs to sign in again.",
43119
+ recovery: "Reconnect the profile, then retry the action.",
43120
+ retryable: true
43121
+ };
43122
+ }
43123
+ if (lower.includes("permission") || lower.includes("eacces") || lower.includes("operation not permitted")) {
43124
+ return {
43125
+ code: "ERR_PERMISSION",
43126
+ title: "Permission denied",
43127
+ message: "CodexUse doesn't have permission to do that.",
43128
+ recovery: "Check the file permissions or restart the app and try again.",
43129
+ retryable: true
43130
+ };
43131
+ }
43132
+ if (lower.includes("enospc") || lower.includes("disk full") || lower.includes("no space left")) {
43133
+ return {
43134
+ code: "ERR_DISK_FULL",
43135
+ title: "Disk is full",
43136
+ message: "CodexUse couldn't save data because the disk is full.",
43137
+ recovery: "Free up disk space, then try again.",
43138
+ retryable: true
43139
+ };
43140
+ }
43141
+ if (lower.includes("codex cli") || lower.includes("command not found") || lower.includes("spawn codex") || lower.includes("could not find codex") || lower.includes("enoent") && (lower.includes("@openai/codex") || lower.includes("codex-darwin-") || lower.includes("/vendor/") || lower.includes("\\vendor\\")) || lower.includes("missing optional dependency")) {
43142
+ return {
43143
+ code: "ERR_CLI_UNAVAILABLE",
43144
+ title: "Codex CLI unavailable",
43145
+ message: "CodexUse couldn't start the Codex CLI.",
43146
+ recovery: "Run npm install -g @openai/codex@latest --include=optional --force in Terminal, then try again.",
43147
+ retryable: true
43148
+ };
43149
+ }
43150
+ if (lower.includes("provider") || lower.includes("model") || lower.includes("openai") || lower.includes("anthropic")) {
43151
+ return {
43152
+ code: "ERR_PROVIDER",
43153
+ title: "Provider request failed",
43154
+ message: "The AI provider rejected or failed the request.",
43155
+ recovery: "Try again, or switch the active profile or model.",
43156
+ retryable: true
43157
+ };
43158
+ }
43159
+ return {
43160
+ code: "ERR_UNKNOWN",
43161
+ title: "That did not work",
43162
+ message: options.fallback,
43163
+ recovery: "Try again. If it keeps happening, report the error with the reference below.",
43164
+ retryable: true
43165
+ };
43166
+ }
43167
+ function resolveUserFacingError(error, options = {}) {
43168
+ const fallback = options.fallback ?? "That action did not complete.";
43169
+ const rawMessage = extractRawMessage(error);
43170
+ const cleaned = normalizeRawMessage(rawMessage);
43171
+ const category = resolveCategory(cleaned, {
43172
+ fallback,
43173
+ ...options.notFoundFallback ? { notFoundFallback: options.notFoundFallback } : {}
43174
+ });
43175
+ return {
43176
+ ...category,
43177
+ referenceId: createErrorReferenceId(),
43178
+ technicalMessage: compactErrorText(cleaned || rawMessage || fallback, 400),
43179
+ technicalDetails: compactErrorText(serializeUnknownError(error), 4e3)
43180
+ };
43181
+ }
43182
+ function formatUserFacingError(error, options = {}) {
43183
+ const info = resolveUserFacingError(error, options);
43184
+ const maxLength = typeof options.maxLength === "number" ? options.maxLength : 220;
43185
+ const withRecovery = info.recovery && !/try again/i.test(info.message) ? `${info.message} ${info.recovery}` : info.message;
43186
+ if (withRecovery.length <= maxLength) {
43187
+ return withRecovery;
43188
+ }
43189
+ let cleaned = info.message;
43190
+ if (cleaned.length > maxLength) {
43191
+ cleaned = `${cleaned.slice(0, maxLength).trimEnd()}\u2026`;
43192
+ }
43193
+ return cleaned;
43194
+ }
43195
+
42742
43196
  // ../../packages/runtime-profiles/src/profiles/official-codex-profile-switch.ts
42743
43197
  function safeReason(error, fallback) {
42744
43198
  const message = error instanceof Error ? error.message : "";
@@ -43102,7 +43556,7 @@ function formatProfileLabel(name, displayName) {
43102
43556
  }
43103
43557
  var AUTO_ROLL_ACCESS_REQUIRED_MESSAGE = "Auto-roll requires a Pro license or an active trial.";
43104
43558
  async function withIsolatedCodexLogin(mode, action) {
43105
- const home = await import_node_fs13.promises.mkdtemp(import_node_path17.default.join(import_node_os7.default.tmpdir(), "codexuse-cli-login-"));
43559
+ const home = await import_node_fs13.promises.mkdtemp(import_node_path18.default.join(import_node_os7.default.tmpdir(), "codexuse-cli-login-"));
43106
43560
  try {
43107
43561
  await runCodexLogin(mode, {
43108
43562
  HOME: home,
@@ -43110,7 +43564,7 @@ async function withIsolatedCodexLogin(mode, action) {
43110
43564
  CODEX_SQLITE_HOME: home,
43111
43565
  ELECTRON_RUN_AS_NODE: "1"
43112
43566
  });
43113
- return await action(import_node_path17.default.join(home, "auth.json"));
43567
+ return await action(import_node_path18.default.join(home, "auth.json"));
43114
43568
  } finally {
43115
43569
  await import_node_fs13.promises.rm(home, { recursive: true, force: true }).catch(() => void 0);
43116
43570
  }
@@ -44628,9 +45082,53 @@ async function pushRemoteSnapshot(access, snapshot2, options) {
44628
45082
  };
44629
45083
  }
44630
45084
 
45085
+ // ../../packages/runtime-profiles/src/cloud-sync/journal.ts
45086
+ var import_node_fs14 = require("fs");
45087
+ var import_node_crypto16 = require("crypto");
45088
+ var import_node_path19 = __toESM(require("path"), 1);
45089
+ var JOURNAL_FILENAME = "cloud-sync-pull.journal.json";
45090
+ function getCloudSyncJournalPath() {
45091
+ return import_node_path19.default.join(getUserDataDir(), JOURNAL_FILENAME);
45092
+ }
45093
+ async function syncDirectory(dir) {
45094
+ const directory = await import_node_fs14.promises.open(dir, "r");
45095
+ try {
45096
+ await directory.sync();
45097
+ } finally {
45098
+ await directory.close();
45099
+ }
45100
+ }
45101
+ async function writeCloudSyncJournal(journal) {
45102
+ const target = getCloudSyncJournalPath();
45103
+ const dir = import_node_path19.default.dirname(target);
45104
+ await import_node_fs14.promises.mkdir(dir, { recursive: true, mode: 448 });
45105
+ await import_node_fs14.promises.chmod(dir, 448);
45106
+ const staging = `${target}.tmp-${process.pid}-${(0, import_node_crypto16.randomUUID)()}`;
45107
+ await import_node_fs14.promises.writeFile(staging, JSON.stringify(journal), {
45108
+ encoding: "utf8",
45109
+ flag: "wx",
45110
+ mode: 384,
45111
+ flush: true
45112
+ });
45113
+ await import_node_fs14.promises.rename(staging, target);
45114
+ await syncDirectory(dir);
45115
+ }
45116
+ async function clearCloudSyncJournal() {
45117
+ const target = getCloudSyncJournalPath();
45118
+ try {
45119
+ await import_node_fs14.promises.unlink(target);
45120
+ } catch (error) {
45121
+ if (error?.code === "ENOENT") {
45122
+ return;
45123
+ }
45124
+ throw error;
45125
+ }
45126
+ await syncDirectory(import_node_path19.default.dirname(target));
45127
+ }
45128
+
44631
45129
  // ../../packages/runtime-profiles/src/cloud-sync/encryption.ts
44632
- var import_node_child_process10 = require("child_process");
44633
- var import_node_crypto15 = require("crypto");
45130
+ var import_node_child_process11 = require("child_process");
45131
+ var import_node_crypto17 = require("crypto");
44634
45132
  var KEYCHAIN_SERVICE2 = "CODEXUSE_CLOUD_SYNC_PASSPHRASE";
44635
45133
  var KEYCHAIN_ACCOUNT_PREFIX2 = "license-sha256:";
44636
45134
  var ENCRYPTION_AAD = Buffer.from("codexuse-cloud-sync-v2", "utf8");
@@ -44655,7 +45153,7 @@ function requireCloudSyncPassphrase(value3) {
44655
45153
  }
44656
45154
  async function deriveKey(passphrase, salt, params = SCRYPT_PARAMS) {
44657
45155
  return new Promise((resolve2, reject) => {
44658
- (0, import_node_crypto15.scrypt)(passphrase, salt, params.keyLength, {
45156
+ (0, import_node_crypto17.scrypt)(passphrase, salt, params.keyLength, {
44659
45157
  N: params.N,
44660
45158
  r: params.r,
44661
45159
  p: params.p,
@@ -44692,10 +45190,10 @@ function normalizeDecryptedSnapshot(value3) {
44692
45190
  };
44693
45191
  }
44694
45192
  async function encryptCloudSyncSnapshot(snapshot2, passphrase) {
44695
- const salt = (0, import_node_crypto15.randomBytes)(16);
44696
- const iv = (0, import_node_crypto15.randomBytes)(12);
45193
+ const salt = (0, import_node_crypto17.randomBytes)(16);
45194
+ const iv = (0, import_node_crypto17.randomBytes)(12);
44697
45195
  const key = await deriveKey(requireCloudSyncPassphrase(passphrase), salt);
44698
- const cipher = (0, import_node_crypto15.createCipheriv)("aes-256-gcm", key, iv);
45196
+ const cipher = (0, import_node_crypto17.createCipheriv)("aes-256-gcm", key, iv);
44699
45197
  cipher.setAAD(ENCRYPTION_AAD);
44700
45198
  const plaintext = Buffer.from(JSON.stringify(snapshot2), "utf8");
44701
45199
  const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
@@ -44722,7 +45220,7 @@ async function decryptCloudSyncSnapshot(snapshot2, passphrase) {
44722
45220
  const tag2 = fromBase64(snapshot2.encryption.tag);
44723
45221
  const ciphertext = fromBase64(snapshot2.encryption.ciphertext);
44724
45222
  const key = await deriveKey(requireCloudSyncPassphrase(passphrase), salt, snapshot2.encryption.kdfParams);
44725
- const decipher = (0, import_node_crypto15.createDecipheriv)("aes-256-gcm", key, iv);
45223
+ const decipher = (0, import_node_crypto17.createDecipheriv)("aes-256-gcm", key, iv);
44726
45224
  decipher.setAAD(ENCRYPTION_AAD);
44727
45225
  decipher.setAuthTag(tag2);
44728
45226
  const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
@@ -44737,12 +45235,12 @@ async function decryptCloudSyncSnapshot(snapshot2, passphrase) {
44737
45235
  }
44738
45236
  }
44739
45237
  function keychainAccountForLicense(licenseKey) {
44740
- const digest = (0, import_node_crypto15.createHash)("sha256").update(licenseKey).digest("hex");
45238
+ const digest = (0, import_node_crypto17.createHash)("sha256").update(licenseKey).digest("hex");
44741
45239
  return KEYCHAIN_ACCOUNT_PREFIX2 + digest;
44742
45240
  }
44743
45241
  function runSecurityCommand2(args2) {
44744
45242
  return new Promise((resolve2, reject) => {
44745
- const child = (0, import_node_child_process10.spawn)("security", args2, { stdio: ["ignore", "pipe", "ignore"] });
45243
+ const child = (0, import_node_child_process11.spawn)("security", args2, { stdio: ["ignore", "pipe", "ignore"] });
44746
45244
  let stdout = "";
44747
45245
  child.stdout?.on("data", (chunk) => {
44748
45246
  stdout += String(chunk);
@@ -44972,8 +45470,7 @@ function formatMegabytes(bytes) {
44972
45470
  }
44973
45471
  async function buildLocalSnapshot(profileManager, options = {}) {
44974
45472
  const enforcePushGuards = options.enforcePushGuards !== false;
44975
- const profilesFromManager = await profileManager.exportProfilesForCloudSync();
44976
- const profiles = profilesFromManager;
45473
+ const profiles = await profileManager.exportProfilesForCloudSync();
44977
45474
  const runtimeContext = await resolveCodexRuntimeContext();
44978
45475
  const config = await getCodexConfigSnapshot({
44979
45476
  codexHomePath: runtimeContext.codexHomePath
@@ -44992,25 +45489,183 @@ async function buildLocalSnapshot(profileManager, options = {}) {
44992
45489
  configTomlContent: config.exists ? config.content : null,
44993
45490
  settingsJson
44994
45491
  };
44995
- if (!enforcePushGuards) {
44996
- return snapshot2;
44997
- }
44998
45492
  return snapshot2;
44999
45493
  }
45000
- async function applyRemoteSnapshot(profileManager, snapshot2) {
45001
- await profileManager.replaceProfilesFromCloudSync(snapshot2.profiles ?? []);
45002
- if (typeof snapshot2.configTomlContent === "string") {
45003
- const runtimeContext = await resolveCodexRuntimeContext();
45004
- await saveCodexConfigContent(snapshot2.configTomlContent, {
45005
- codexHomePath: runtimeContext.codexHomePath
45006
- });
45494
+ async function applyCloudSyncSnapshot(snapshot2, stores) {
45495
+ const staged = stageCloudSyncSnapshot(snapshot2);
45496
+ const previousSnapshot = await stores.readPrevious();
45497
+ const previous = stageCloudSyncSnapshot(previousSnapshot);
45498
+ const previousHomeIds = await stores.readPreviousHomeIds();
45499
+ await stores.writeJournal({
45500
+ version: 1,
45501
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
45502
+ phase: "restore",
45503
+ previous: previousSnapshot,
45504
+ previousHomeIds: { ...previousHomeIds },
45505
+ pendingHomeIds: []
45506
+ });
45507
+ let pendingHomeIds = [];
45508
+ let staleHomes;
45509
+ try {
45510
+ staleHomes = await writeStaged(
45511
+ staged,
45512
+ stores,
45513
+ void 0,
45514
+ async (homeIds) => {
45515
+ pendingHomeIds = [...new Set(homeIds)];
45516
+ await stores.writeJournal({
45517
+ version: 1,
45518
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
45519
+ phase: "restore",
45520
+ previous: previousSnapshot,
45521
+ previousHomeIds: { ...previousHomeIds },
45522
+ pendingHomeIds
45523
+ });
45524
+ }
45525
+ );
45526
+ } catch (error) {
45527
+ await restoreStaged(
45528
+ previousSnapshot,
45529
+ previous,
45530
+ previousHomeIds,
45531
+ pendingHomeIds,
45532
+ stores,
45533
+ error
45534
+ );
45535
+ throw error;
45007
45536
  }
45008
- if (snapshot2.settingsJson && isRecord7(snapshot2.settingsJson)) {
45009
- await writeCodexSettingsJsonRaw(snapshot2.settingsJson);
45010
- } else {
45011
- await writeCodexSettingsJsonRaw({});
45537
+ await stores.writeJournal({
45538
+ version: 1,
45539
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
45540
+ phase: "committed",
45541
+ previous: previousSnapshot,
45542
+ previousHomeIds: { ...previousHomeIds },
45543
+ pendingHomeIds: []
45544
+ });
45545
+ await stores.clearJournal();
45546
+ if (staleHomes.length > 0) {
45547
+ await stores.removeStaleHomes(staleHomes);
45548
+ }
45549
+ }
45550
+ async function writeStaged(staged, stores, homeIdByProfileName, onPreparedHomeIds) {
45551
+ const staleHomes = await stores.replaceProfiles(
45552
+ staged.profiles,
45553
+ homeIdByProfileName,
45554
+ onPreparedHomeIds
45555
+ );
45556
+ if (staged.configTomlContent !== null || homeIdByProfileName !== void 0) {
45557
+ await stores.writeConfig(staged.configTomlContent);
45558
+ }
45559
+ await stores.writeSettings(staged.settingsJson);
45560
+ return staleHomes;
45561
+ }
45562
+ async function discardAbandonedHomes(previousSnapshot, previousHomeIds, pendingHomeIds, stores) {
45563
+ if (pendingHomeIds.length === 0) {
45564
+ await stores.clearJournal();
45565
+ return;
45566
+ }
45567
+ await stores.writeJournal({
45568
+ version: 1,
45569
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
45570
+ phase: "cleanup",
45571
+ previous: previousSnapshot,
45572
+ previousHomeIds: { ...previousHomeIds },
45573
+ pendingHomeIds
45574
+ });
45575
+ try {
45576
+ const discarded = await stores.discardHomeIds(pendingHomeIds);
45577
+ if (discarded !== pendingHomeIds.length) {
45578
+ throw new Error(
45579
+ `Deleted ${discarded} of ${pendingHomeIds.length} abandoned profile homes.`
45580
+ );
45581
+ }
45582
+ } catch (cleanupError) {
45583
+ logWarn(
45584
+ "[cloud-sync] restored the previous state but could not delete the homes the failed pull created",
45585
+ {
45586
+ error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
45587
+ }
45588
+ );
45589
+ return;
45590
+ }
45591
+ await stores.clearJournal();
45592
+ }
45593
+ async function restoreStaged(previousSnapshot, previous, previousHomeIds, pendingHomeIds, stores, cause) {
45594
+ try {
45595
+ const orphanedByFailedPull = await writeStaged(
45596
+ previous,
45597
+ stores,
45598
+ previousHomeIds
45599
+ );
45600
+ const restoredHomeIds = new Set(Object.values(previousHomeIds));
45601
+ const abandonedHomeIds = [
45602
+ .../* @__PURE__ */ new Set([
45603
+ ...pendingHomeIds,
45604
+ ...stores.homeIdsOf(orphanedByFailedPull)
45605
+ ])
45606
+ ].filter((homeId) => !restoredHomeIds.has(homeId));
45607
+ await discardAbandonedHomes(
45608
+ previousSnapshot,
45609
+ previousHomeIds,
45610
+ abandonedHomeIds,
45611
+ stores
45612
+ );
45613
+ logWarn("[cloud-sync] pull failed and the previous local state was restored", {
45614
+ error: cause instanceof Error ? cause.message : String(cause)
45615
+ });
45616
+ } catch (restoreError) {
45617
+ logWarn(
45618
+ "[cloud-sync] pull failed and the previous local state could not be restored",
45619
+ {
45620
+ error: cause instanceof Error ? cause.message : String(cause),
45621
+ restoreError: restoreError instanceof Error ? restoreError.message : String(restoreError)
45622
+ }
45623
+ );
45624
+ throw new Error(
45625
+ "Cloud pull failed and the previous local state could not be fully restored. Your accounts are still on this Mac; check them before syncing again.",
45626
+ { cause: restoreError }
45627
+ );
45012
45628
  }
45013
45629
  }
45630
+ function buildCloudSyncStores(profileManager) {
45631
+ return {
45632
+ readPrevious: () => buildLocalSnapshot(profileManager, { enforcePushGuards: false }),
45633
+ readPreviousHomeIds: () => profileManager.getProfileHomeIdsByName(),
45634
+ replaceProfiles: async (profiles, homeIdByProfileName, onPreparedHomeIds) => (await profileManager.replaceProfilesFromCloudSync(profiles, {
45635
+ deferStaleHomeRemoval: true,
45636
+ homeIdByProfileName,
45637
+ onPreparedHomeIds
45638
+ })).pendingStaleRemovals,
45639
+ writeConfig: async (content) => {
45640
+ const runtimeContext = await resolveCodexRuntimeContext();
45641
+ const options = { codexHomePath: runtimeContext.codexHomePath };
45642
+ if (content === null) {
45643
+ await removeConfigContent(options);
45644
+ } else {
45645
+ await saveCodexConfigContent(content, options);
45646
+ }
45647
+ },
45648
+ writeSettings: (settings) => writeCodexSettingsJsonRaw(settings),
45649
+ removeStaleHomes: (homes) => profileManager.removeStaleProfileHomes(homes),
45650
+ homeIdsOf: (homes) => homes.map((home) => home.homeId),
45651
+ discardHomeIds: (homeIds) => profileManager.deleteAbandonedPullProfileHomes(homeIds),
45652
+ writeJournal: (journal) => writeCloudSyncJournal(journal),
45653
+ clearJournal: () => clearCloudSyncJournal()
45654
+ };
45655
+ }
45656
+ async function applyRemoteSnapshot(profileManager, snapshot2) {
45657
+ await applyCloudSyncSnapshot(
45658
+ snapshot2,
45659
+ buildCloudSyncStores(profileManager)
45660
+ );
45661
+ }
45662
+ function stageCloudSyncSnapshot(snapshot2) {
45663
+ return {
45664
+ profiles: snapshot2.profiles ?? [],
45665
+ configTomlContent: typeof snapshot2.configTomlContent === "string" ? assertValidCodexConfigContent(snapshot2.configTomlContent) : null,
45666
+ settingsJson: snapshot2.settingsJson && isRecord7(snapshot2.settingsJson) ? snapshot2.settingsJson : {}
45667
+ };
45668
+ }
45014
45669
  function getSnapshotKind(snapshot2) {
45015
45670
  if (!snapshot2) {
45016
45671
  return "none";
@@ -45105,7 +45760,11 @@ async function pushCloudSync(options = {}) {
45105
45760
  const profileManager = new ProfileManager();
45106
45761
  try {
45107
45762
  await profileManager.initialize();
45108
- const localSnapshot = await buildLocalSnapshot(profileManager, { enforcePushGuards: true });
45763
+ const localSnapshot = await withCloudSyncTransaction(
45764
+ getUserDataDir(),
45765
+ "write",
45766
+ () => buildLocalSnapshot(profileManager, { enforcePushGuards: true })
45767
+ );
45109
45768
  const passphrase = await resolvePassphrase(eligibility.access.syncKey, options);
45110
45769
  const encryptedSnapshot = await encryptCloudSyncSnapshot(localSnapshot, passphrase.value);
45111
45770
  const serializedSnapshot = JSON.stringify(encryptedSnapshot);
@@ -45197,7 +45856,11 @@ async function pullCloudSync(options = {}) {
45197
45856
  } else {
45198
45857
  plainSnapshot = remote;
45199
45858
  }
45200
- await applyRemoteSnapshot(profileManager, plainSnapshot);
45859
+ await withCloudSyncTransaction(
45860
+ getUserDataDir(),
45861
+ "write",
45862
+ () => applyRemoteSnapshot(profileManager, plainSnapshot)
45863
+ );
45201
45864
  await writeState({
45202
45865
  lastPullAt: (/* @__PURE__ */ new Date()).toISOString(),
45203
45866
  remoteUpdatedAt: remote.updatedAt,
@@ -45303,7 +45966,7 @@ async function handleSync(args2, version) {
45303
45966
  }
45304
45967
 
45305
45968
  // src/commands/workspace.ts
45306
- var import_node_fs14 = require("fs");
45969
+ var import_node_fs15 = require("fs");
45307
45970
  function printWorkspaceHelp() {
45308
45971
  console.log(`Usage:
45309
45972
  codexuse workspace bind <path> <profile>
@@ -45333,7 +45996,7 @@ async function handleWorkspaceCommand(args2) {
45333
45996
  return;
45334
45997
  }
45335
45998
  for (const binding of bindings) {
45336
- const pathState = await import_node_fs14.promises.stat(binding.rootPath).then(() => "").catch(() => " (path missing)");
45999
+ const pathState = await import_node_fs15.promises.stat(binding.rootPath).then(() => "").catch(() => " (path missing)");
45337
46000
  const profileState = profiles.has(binding.profileName) ? "" : " (profile missing)";
45338
46001
  console.log(`${binding.rootPath} -> ${binding.profileName}${pathState}${profileState}`);
45339
46002
  }
@@ -45397,7 +46060,7 @@ async function ensureCliStorageReady() {
45397
46060
  }
45398
46061
 
45399
46062
  // src/app/main.ts
45400
- var VERSION = true ? "6.0.4" : "0.0.0";
46063
+ var VERSION = true ? "6.1.0" : "0.0.0";
45401
46064
  async function runCli() {
45402
46065
  const args2 = process.argv.slice(2);
45403
46066
  if (args2.length === 0) {