codexuse-cli 3.9.0 → 3.9.2

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
@@ -10610,7 +10610,7 @@ async function ensureCliStorageReady() {
10610
10610
  }
10611
10611
 
10612
10612
  // src/app/main.ts
10613
- var VERSION = true ? "3.9.0" : "0.0.0";
10613
+ var VERSION = true ? "3.9.2" : "0.0.0";
10614
10614
  async function runCli() {
10615
10615
  const args = process.argv.slice(2);
10616
10616
  if (args.length === 0) {
@@ -46821,6 +46821,7 @@ const ThreadMetaUpdateCommand = Struct({
46821
46821
  origin: optional$2(ThreadOrigin),
46822
46822
  branch: optional$2(NullOr(TrimmedNonEmptyString)),
46823
46823
  worktreePath: optional$2(NullOr(TrimmedNonEmptyString)),
46824
+ deletedAt: optional$2(NullOr(IsoDateTime)),
46824
46825
  updatedAt: optional$2(IsoDateTime)
46825
46826
  });
46826
46827
  const ThreadRuntimeModeSetCommand = Struct({
@@ -47140,6 +47141,7 @@ const ThreadMetaUpdatedPayload$1 = Struct({
47140
47141
  origin: optional$2(ThreadOrigin),
47141
47142
  branch: optional$2(NullOr(TrimmedNonEmptyString)),
47142
47143
  worktreePath: optional$2(NullOr(TrimmedNonEmptyString)),
47144
+ deletedAt: optional$2(NullOr(IsoDateTime)),
47143
47145
  updatedAt: IsoDateTime
47144
47146
  });
47145
47147
  const ThreadRuntimeModeSetPayload$1 = Struct({
@@ -47395,8 +47397,27 @@ const ProjectionPendingApprovalDecision = NullOr(ProviderApprovalDecision);
47395
47397
  const DispatchResult = Struct({ sequence: NonNegativeInt });
47396
47398
  const OrchestrationGetSnapshotInput = Struct({});
47397
47399
  const OrchestrationGetThreadSnapshotInput = Struct({ threadId: ThreadId });
47398
- const OrchestrationSyncExternalThreadsInput = Struct({});
47399
- const OrchestrationSyncExternalThreadsResult = Struct({ syncedAt: IsoDateTime });
47400
+ const OrchestrationSyncExternalThreadsInput = Struct({ projectId: optional$2(ProjectId) });
47401
+ const OrchestrationSyncExternalThreadsStats = Struct({
47402
+ bootstrappedProjectCount: NonNegativeInt,
47403
+ syncedProjectCount: NonNegativeInt,
47404
+ createdThreadCount: NonNegativeInt,
47405
+ restoredThreadCount: NonNegativeInt,
47406
+ foregroundSummaryCount: NonNegativeInt,
47407
+ foregroundHydratedThreadCount: NonNegativeInt,
47408
+ foregroundImportedMessageCount: NonNegativeInt,
47409
+ foregroundImportedActivityCount: NonNegativeInt,
47410
+ foregroundImportedPlanCount: NonNegativeInt,
47411
+ backgroundBackfillProjectCount: NonNegativeInt,
47412
+ parityWorkspaceCount: NonNegativeInt,
47413
+ hadErrors: Boolean$2
47414
+ });
47415
+ const OrchestrationSyncExternalThreadsResult = Struct({
47416
+ syncedAt: IsoDateTime,
47417
+ completed: Boolean$2,
47418
+ queued: Boolean$2,
47419
+ stats: optional$2(OrchestrationSyncExternalThreadsStats)
47420
+ });
47400
47421
  const OrchestrationGetTurnDiffInput = TurnCountRange.mapFields(assign({ threadId: ThreadId }), { unsafePreserveChecks: true });
47401
47422
  const OrchestrationGetTurnDiffResult = ThreadTurnDiff;
47402
47423
  const OrchestrationGetFullThreadDiffInput = Struct({
@@ -48774,7 +48795,8 @@ const WS_CHANNELS = {
48774
48795
  profilesSwitched: "profiles.switched",
48775
48796
  rateLimitsUpdated: "rateLimits.updated",
48776
48797
  rateLimitsState: "rateLimits.state",
48777
- cliStatusUpdated: "cli.statusUpdated"
48798
+ cliStatusUpdated: "cli.statusUpdated",
48799
+ externalThreadSyncProgress: "externalThreadSync.progress"
48778
48800
  };
48779
48801
  const tagRequestBody = (tag$1, schema) => schema.mapFields(assign({ _tag: tag(tag$1) }), { unsafePreserveChecks: true });
48780
48802
  const WebSocketRequestBody = Union([
@@ -48918,6 +48940,42 @@ const WsWelcomePayload = Struct({
48918
48940
  bootstrapProjectId: optional$2(ProjectId),
48919
48941
  bootstrapThreadId: optional$2(ThreadId)
48920
48942
  });
48943
+ const ExternalThreadSyncProjectProgress = Struct({
48944
+ projectId: ProjectId,
48945
+ workspaceRoot: TrimmedNonEmptyString,
48946
+ title: TrimmedNonEmptyString,
48947
+ scannedThreads: NonNegativeInt,
48948
+ createdThreads: NonNegativeInt,
48949
+ restoredThreads: NonNegativeInt,
48950
+ hydratedThreads: NonNegativeInt,
48951
+ importedMessages: NonNegativeInt,
48952
+ importedActivities: NonNegativeInt,
48953
+ importedPlans: NonNegativeInt
48954
+ });
48955
+ const ExternalThreadSyncProgressPayload = Struct({
48956
+ status: Literals([
48957
+ "started",
48958
+ "project",
48959
+ "completed",
48960
+ "failed"
48961
+ ]),
48962
+ runId: TrimmedNonEmptyString,
48963
+ startedAt: TrimmedNonEmptyString,
48964
+ updatedAt: TrimmedNonEmptyString,
48965
+ finishedAt: optional$2(TrimmedNonEmptyString),
48966
+ currentProjectIndex: NonNegativeInt,
48967
+ totalProjects: NonNegativeInt,
48968
+ project: optional$2(ExternalThreadSyncProjectProgress),
48969
+ projects: optional$2(Array$1(ExternalThreadSyncProjectProgress)),
48970
+ scannedThreads: NonNegativeInt,
48971
+ createdThreads: NonNegativeInt,
48972
+ restoredThreads: NonNegativeInt,
48973
+ hydratedThreads: NonNegativeInt,
48974
+ importedMessages: NonNegativeInt,
48975
+ importedActivities: NonNegativeInt,
48976
+ importedPlans: NonNegativeInt,
48977
+ hadErrors: Boolean$2
48978
+ });
48921
48979
  const makeWsPushSchema = (channel, payload) => Struct({
48922
48980
  type: Literal("push"),
48923
48981
  sequence: WsPushSequence,
@@ -48934,6 +48992,7 @@ const WsPushProfilesSwitched = makeWsPushSchema(WS_CHANNELS.profilesSwitched, Un
48934
48992
  const WsPushRateLimitsUpdated = makeWsPushSchema(WS_CHANNELS.rateLimitsUpdated, Unknown);
48935
48993
  const WsPushRateLimitsState = makeWsPushSchema(WS_CHANNELS.rateLimitsState, Unknown);
48936
48994
  const WsPushCliStatusUpdated = makeWsPushSchema(WS_CHANNELS.cliStatusUpdated, Unknown);
48995
+ const WsPushExternalThreadSyncProgress = makeWsPushSchema(WS_CHANNELS.externalThreadSyncProgress, ExternalThreadSyncProgressPayload);
48937
48996
  const WsPushOrchestrationDomainEvent = makeWsPushSchema(ORCHESTRATION_WS_CHANNELS.domainEvent, OrchestrationEvent);
48938
48997
  const WsPushChannelSchema = Literals([
48939
48998
  WS_CHANNELS.gitActionProgress,
@@ -48946,6 +49005,7 @@ const WsPushChannelSchema = Literals([
48946
49005
  WS_CHANNELS.rateLimitsUpdated,
48947
49006
  WS_CHANNELS.rateLimitsState,
48948
49007
  WS_CHANNELS.cliStatusUpdated,
49008
+ WS_CHANNELS.externalThreadSyncProgress,
48949
49009
  ORCHESTRATION_WS_CHANNELS.domainEvent
48950
49010
  ]);
48951
49011
  const WsPush = Union([
@@ -48959,6 +49019,7 @@ const WsPush = Union([
48959
49019
  WsPushRateLimitsUpdated,
48960
49020
  WsPushRateLimitsState,
48961
49021
  WsPushCliStatusUpdated,
49022
+ WsPushExternalThreadSyncProgress,
48962
49023
  WsPushOrchestrationDomainEvent
48963
49024
  ]);
48964
49025
  const WsPushEnvelopeBase = Struct({
@@ -52736,17 +52797,24 @@ const decideOrchestrationCommand = fn("decideOrchestrationCommand")(function* ({
52736
52797
  };
52737
52798
  }
52738
52799
  case "thread.meta.update": {
52739
- yield* requireThread({
52800
+ const thread = yield* requireThread({
52740
52801
  readModel,
52741
52802
  command,
52742
52803
  threadId: command.threadId
52743
52804
  });
52744
- if (command.projectId !== void 0) yield* requireThreadProject({
52745
- readModel,
52746
- command,
52747
- threadId: command.threadId,
52748
- projectId: command.projectId
52749
- });
52805
+ if (command.projectId !== void 0) {
52806
+ yield* requireProject({
52807
+ readModel,
52808
+ command,
52809
+ projectId: command.projectId
52810
+ });
52811
+ if (!(thread.deletedAt !== null && command.deletedAt === null)) yield* requireThreadProject({
52812
+ readModel,
52813
+ command,
52814
+ threadId: command.threadId,
52815
+ projectId: command.projectId
52816
+ });
52817
+ }
52750
52818
  const occurredAt = nowIso$2();
52751
52819
  return {
52752
52820
  ...withEventBase({
@@ -52764,6 +52832,7 @@ const decideOrchestrationCommand = fn("decideOrchestrationCommand")(function* ({
52764
52832
  ...command.origin !== void 0 ? { origin: command.origin } : {},
52765
52833
  ...command.branch !== void 0 ? { branch: command.branch } : {},
52766
52834
  ...command.worktreePath !== void 0 ? { worktreePath: command.worktreePath } : {},
52835
+ ...command.deletedAt !== void 0 ? { deletedAt: command.deletedAt } : {},
52767
52836
  updatedAt: command.updatedAt ?? occurredAt
52768
52837
  }
52769
52838
  };
@@ -53369,6 +53438,7 @@ function projectEvent(model, event) {
53369
53438
  } : {},
53370
53439
  ...payload.branch !== void 0 ? { branch: payload.branch } : {},
53371
53440
  ...payload.worktreePath !== void 0 ? { worktreePath: payload.worktreePath } : {},
53441
+ ...payload.deletedAt !== void 0 ? { deletedAt: payload.deletedAt } : {},
53372
53442
  updatedAt: payload.updatedAt
53373
53443
  })
53374
53444
  })));
@@ -57634,6 +57704,7 @@ const makeOrchestrationProjectionPipeline = gen(function* () {
57634
57704
  ...event.payload.origin !== void 0 ? { origin: event.payload.origin } : {},
57635
57705
  ...event.payload.branch !== void 0 ? { branch: event.payload.branch } : {},
57636
57706
  ...event.payload.worktreePath !== void 0 ? { worktreePath: event.payload.worktreePath } : {},
57707
+ ...event.payload.deletedAt !== void 0 ? { deletedAt: event.payload.deletedAt } : {},
57637
57708
  updatedAt: event.payload.updatedAt
57638
57709
  });
57639
57710
  return;
@@ -61058,6 +61129,62 @@ let externalCodexThreadSyncWatcherSettleTimer = null;
61058
61129
  let externalCodexThreadSyncWatcherPendingTrigger = null;
61059
61130
  const externalSyncAppServerLeaseCount = /* @__PURE__ */ new Map();
61060
61131
  let externalCodexThreadSyncRefreshQueue = null;
61132
+ let externalCodexThreadSyncProgressReporter = null;
61133
+ function makeEmptyExternalThreadSyncProjectStats(syncTarget) {
61134
+ return {
61135
+ projectId: syncTarget.projectId,
61136
+ workspaceRoot: syncTarget.workspace.path,
61137
+ title: syncTarget.workspace.name,
61138
+ scannedThreads: 0,
61139
+ createdThreads: 0,
61140
+ restoredThreads: 0,
61141
+ hydratedThreads: 0,
61142
+ importedMessages: 0,
61143
+ importedActivities: 0,
61144
+ importedPlans: 0
61145
+ };
61146
+ }
61147
+ function sumExternalThreadSyncProjectStats(projects) {
61148
+ return projects.reduce((total, project) => ({
61149
+ scannedThreads: total.scannedThreads + project.scannedThreads,
61150
+ createdThreads: total.createdThreads + project.createdThreads,
61151
+ restoredThreads: total.restoredThreads + project.restoredThreads,
61152
+ hydratedThreads: total.hydratedThreads + project.hydratedThreads,
61153
+ importedMessages: total.importedMessages + project.importedMessages,
61154
+ importedActivities: total.importedActivities + project.importedActivities,
61155
+ importedPlans: total.importedPlans + project.importedPlans
61156
+ }), {
61157
+ scannedThreads: 0,
61158
+ createdThreads: 0,
61159
+ restoredThreads: 0,
61160
+ hydratedThreads: 0,
61161
+ importedMessages: 0,
61162
+ importedActivities: 0,
61163
+ importedPlans: 0
61164
+ });
61165
+ }
61166
+ function makeExternalThreadSyncStats(input) {
61167
+ return {
61168
+ bootstrappedProjectCount: input?.bootstrappedProjectCount ?? 0,
61169
+ syncedProjectCount: input?.syncedProjectCount ?? 0,
61170
+ createdThreadCount: input?.createdThreadCount ?? 0,
61171
+ restoredThreadCount: input?.restoredThreadCount ?? 0,
61172
+ foregroundSummaryCount: input?.foregroundSummaryCount ?? 0,
61173
+ foregroundHydratedThreadCount: input?.foregroundHydratedThreadCount ?? 0,
61174
+ foregroundImportedMessageCount: input?.foregroundImportedMessageCount ?? 0,
61175
+ foregroundImportedActivityCount: input?.foregroundImportedActivityCount ?? 0,
61176
+ foregroundImportedPlanCount: input?.foregroundImportedPlanCount ?? 0,
61177
+ backgroundBackfillProjectCount: input?.backgroundBackfillProjectCount ?? 0,
61178
+ parityWorkspaceCount: input?.parityWorkspaceCount ?? 0,
61179
+ hadErrors: input?.hadErrors ?? false
61180
+ };
61181
+ }
61182
+ function publishExternalThreadSyncProgress(payload) {
61183
+ if (!externalCodexThreadSyncProgressReporter) return;
61184
+ Promise.resolve(externalCodexThreadSyncProgressReporter(payload)).catch((error) => {
61185
+ console.warn("[t3 external thread sync] progress publish failed", { error });
61186
+ });
61187
+ }
61061
61188
  function asRecord$3(value) {
61062
61189
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
61063
61190
  }
@@ -61146,6 +61273,9 @@ function closeExternalCodexThreadSyncWatcher() {
61146
61273
  function setExternalCodexThreadSyncRefreshQueue(queue) {
61147
61274
  externalCodexThreadSyncRefreshQueue = queue ? { offer: queue } : null;
61148
61275
  }
61276
+ function setExternalCodexThreadSyncProgressReporter(reporter) {
61277
+ externalCodexThreadSyncProgressReporter = reporter;
61278
+ }
61149
61279
  async function requestExternalCodexThreadSyncRefresh(trigger) {
61150
61280
  if (!externalCodexThreadSyncRefreshQueue) return false;
61151
61281
  try {
@@ -61973,7 +62103,7 @@ async function readLegacyThreadByCandidateIds(appServer, candidateIds) {
61973
62103
  }
61974
62104
  function shouldReadLegacyThreadForImport(input) {
61975
62105
  if (!input.existingThread) return true;
61976
- if (input.existingThread.deletedAt !== null) return false;
62106
+ if (input.existingThread.deletedAt !== null) return input.restoreDeletedImportedThread === true;
61977
62107
  if (input.forceRereadExistingThreads) return true;
61978
62108
  const legacyUpdatedAtMs = toEpochMs(input.legacyThreadSummary.updatedAt ?? input.legacyThreadSummary.createdAt, 0);
61979
62109
  if (legacyUpdatedAtMs <= 0) return false;
@@ -62004,6 +62134,9 @@ function shouldRefreshImportedMessage(input) {
62004
62134
  function hasImportedThreadArtifacts(state) {
62005
62135
  return state.messageIds.size > 0 || state.activityIds.size > 0 || state.planIds.size > 0;
62006
62136
  }
62137
+ function shouldRestoreDeletedImportedThread(input) {
62138
+ return input.existingThread !== void 0 && input.existingThread.deletedAt !== null && input.existingThread.origin === "external-import" && input.existingThread.projectId !== input.projectId;
62139
+ }
62007
62140
  function readProviderThreadIdFromResumeCursor(resumeCursor) {
62008
62141
  const cursor = asRecord$3(resumeCursor);
62009
62142
  return firstNonEmptyString(cursor?.threadId, cursor?.thread_id, cursor?.conversationId, cursor?.conversation_id) ?? null;
@@ -62053,6 +62186,7 @@ function syncExternalThreadSummary(input) {
62053
62186
  const threadIdRaw = asTrimmedString$1(input.summary.id);
62054
62187
  if (!threadIdRaw) return {
62055
62188
  createdThread: false,
62189
+ restoredThread: false,
62056
62190
  overridesChanged: false
62057
62191
  };
62058
62192
  const threadId = ThreadId.makeUnsafe(threadIdRaw);
@@ -62070,9 +62204,14 @@ function syncExternalThreadSummary(input) {
62070
62204
  orchestrationEngine: input.orchestrationEngine
62071
62205
  })) return {
62072
62206
  createdThread: false,
62207
+ restoredThread: false,
62073
62208
  overridesChanged
62074
62209
  };
62075
- const effectiveUpdatedAt = existingThread ? latestIsoTimestamp(existingThread.updatedAt, updatedAt) : updatedAt;
62210
+ const restoreDeletedImportedThread = shouldRestoreDeletedImportedThread({
62211
+ existingThread,
62212
+ projectId: input.projectId
62213
+ });
62214
+ const effectiveUpdatedAt = existingThread && existingThread.deletedAt === null ? latestIsoTimestamp(existingThread.updatedAt, updatedAt) : updatedAt;
62076
62215
  const nextBranch = input.workspace.kind === "worktree" ? firstNonEmptyString(input.workspace.worktree?.branch) : null;
62077
62216
  const nextWorktreePath = input.workspace.kind === "worktree" ? input.workspace.path : null;
62078
62217
  if (suppressed) {
@@ -62091,18 +62230,22 @@ function syncExternalThreadSummary(input) {
62091
62230
  }
62092
62231
  return {
62093
62232
  createdThread: false,
62233
+ restoredThread: false,
62094
62234
  overridesChanged
62095
62235
  };
62096
62236
  }
62097
- if (existingThread && existingThread.deletedAt !== null) return {
62237
+ if (existingThread && existingThread.deletedAt !== null && !restoreDeletedImportedThread) return {
62098
62238
  createdThread: false,
62239
+ restoredThread: false,
62099
62240
  overridesChanged
62100
62241
  };
62101
- if (existingThread && existingThread.title === title && existingThread.updatedAt === effectiveUpdatedAt && existingThread.origin === "external-import" && existingThread.branch === nextBranch && existingThread.worktreePath === nextWorktreePath) return {
62242
+ const shouldCreateThread = !input.state.threadIds.has(threadId);
62243
+ if (existingThread && existingThread.deletedAt === null && existingThread.projectId === input.projectId && existingThread.title === title && existingThread.updatedAt === effectiveUpdatedAt && existingThread.origin === "external-import" && existingThread.branch === nextBranch && existingThread.worktreePath === nextWorktreePath) return {
62102
62244
  createdThread: false,
62245
+ restoredThread: false,
62103
62246
  overridesChanged
62104
62247
  };
62105
- if (!input.state.threadIds.has(threadId)) {
62248
+ if (shouldCreateThread) {
62106
62249
  yield* input.orchestrationEngine.dispatch({
62107
62250
  type: "thread.create",
62108
62251
  commandId: CommandId.makeUnsafe(makeServerCommandId()),
@@ -62124,10 +62267,12 @@ function syncExternalThreadSummary(input) {
62124
62267
  type: "thread.meta.update",
62125
62268
  commandId: CommandId.makeUnsafe(makeServerCommandId()),
62126
62269
  threadId,
62270
+ ...existingThread?.projectId !== input.projectId ? { projectId: input.projectId } : {},
62127
62271
  title,
62128
62272
  origin: "external-import",
62129
62273
  branch: nextBranch,
62130
62274
  worktreePath: nextWorktreePath,
62275
+ ...restoreDeletedImportedThread ? { deletedAt: null } : {},
62131
62276
  updatedAt: effectiveUpdatedAt
62132
62277
  });
62133
62278
  input.state.threadById.set(threadId, {
@@ -62142,16 +62287,28 @@ function syncExternalThreadSummary(input) {
62142
62287
  });
62143
62288
  return {
62144
62289
  createdThread: !existingThread,
62290
+ restoredThread: restoreDeletedImportedThread,
62145
62291
  overridesChanged
62146
62292
  };
62147
62293
  });
62148
62294
  }
62149
62295
  function importExternalThreadArtifacts(input) {
62150
62296
  return gen(function* () {
62297
+ const existingThread = input.state.threadById.get(input.threadId);
62298
+ const restoreDeletedImportedThread = shouldRestoreDeletedImportedThread({
62299
+ existingThread,
62300
+ projectId: input.projectId
62301
+ });
62302
+ if (existingThread?.deletedAt !== null && !restoreDeletedImportedThread) return {
62303
+ createdThread: false,
62304
+ importedMessageCount: 0,
62305
+ importedActivityCount: 0,
62306
+ importedPlanCount: 0,
62307
+ overridesChanged: false
62308
+ };
62151
62309
  const isNewThread = !input.state.threadIds.has(input.threadId);
62152
62310
  const cachedThreadState = input.state.threadStateById.get(input.threadId);
62153
- const existingThreadState = !isNewThread && (!cachedThreadState || cachedThreadState.messageIds.size === 0 && cachedThreadState.activityIds.size === 0 && cachedThreadState.planIds.size === 0) ? yield* loadPersistedThreadImportState(input.importStateRepositories, input.threadId).pipe(orElseSucceed(() => createEmptyThreadImportState())) : cachedThreadState ?? createEmptyThreadImportState();
62154
- const existingThread = input.state.threadById.get(input.threadId);
62311
+ const existingThreadState = input.state.threadIds.has(input.threadId) && (!cachedThreadState || cachedThreadState.messageIds.size === 0 && cachedThreadState.activityIds.size === 0 && cachedThreadState.planIds.size === 0) ? yield* loadPersistedThreadImportState(input.importStateRepositories, input.threadId).pipe(orElseSucceed(() => createEmptyThreadImportState())) : cachedThreadState ?? createEmptyThreadImportState();
62155
62312
  const existingThreadReadModel = input.state.threadReadModelById.get(input.threadId);
62156
62313
  const localContinuationDedupState = existingThreadReadModel ? buildLocalContinuationDedupState({
62157
62314
  thread: existingThreadReadModel,
@@ -62174,7 +62331,7 @@ function importExternalThreadArtifacts(input) {
62174
62331
  importedPlanCount: 0,
62175
62332
  overridesChanged
62176
62333
  };
62177
- if (suppressed || existingThread && existingThread.deletedAt !== null) return {
62334
+ if (suppressed) return {
62178
62335
  createdThread: false,
62179
62336
  importedMessageCount: 0,
62180
62337
  importedActivityCount: 0,
@@ -62254,16 +62411,18 @@ function importExternalThreadArtifacts(input) {
62254
62411
  importedActivityCount += 1;
62255
62412
  }
62256
62413
  const importedArtifactCount = importedMessageCount + importedPlanCount + importedActivityCount;
62257
- const effectiveUpdatedAt = existingThread === void 0 ? input.importArtifacts.latestUpdatedAt : importedArtifactCount === 0 ? existingThread.updatedAt : hadImportedArtifactsBeforeSync ? latestIsoTimestamp(existingThread.updatedAt, input.importArtifacts.latestUpdatedAt) : latestIsoTimestamp(existingThread.updatedAt, input.importArtifacts.latestArtifactUpdatedAt);
62258
- if (!isNewThread && (existingThread === void 0 || existingThread.title !== effectiveTitle || existingThread.origin !== "external-import" || existingThread.branch !== input.importArtifacts.branch || existingThread.worktreePath !== input.importArtifacts.worktreePath || existingThread.updatedAt !== effectiveUpdatedAt)) yield* input.orchestrationEngine.dispatch({
62414
+ const effectiveUpdatedAt = existingThread === void 0 ? input.importArtifacts.latestUpdatedAt : existingThread.deletedAt !== null ? input.importArtifacts.latestUpdatedAt : importedArtifactCount === 0 ? existingThread.updatedAt : hadImportedArtifactsBeforeSync ? latestIsoTimestamp(existingThread.updatedAt, input.importArtifacts.latestUpdatedAt) : latestIsoTimestamp(existingThread.updatedAt, input.importArtifacts.latestArtifactUpdatedAt);
62415
+ if (!isNewThread && (existingThread === void 0 || existingThread.projectId !== input.projectId || restoreDeletedImportedThread || existingThread.title !== effectiveTitle || existingThread.origin !== "external-import" || existingThread.branch !== input.importArtifacts.branch || existingThread.worktreePath !== input.importArtifacts.worktreePath || existingThread.updatedAt !== effectiveUpdatedAt)) yield* input.orchestrationEngine.dispatch({
62259
62416
  type: "thread.meta.update",
62260
62417
  commandId: CommandId.makeUnsafe(makeServerCommandId()),
62261
62418
  threadId: input.threadId,
62419
+ ...existingThread?.projectId !== input.projectId ? { projectId: input.projectId } : {},
62262
62420
  title: effectiveTitle,
62263
62421
  modelSelection: input.importArtifacts.modelSelection,
62264
62422
  origin: "external-import",
62265
62423
  branch: input.importArtifacts.branch,
62266
62424
  worktreePath: input.importArtifacts.worktreePath,
62425
+ ...restoreDeletedImportedThread ? { deletedAt: null } : {},
62267
62426
  updatedAt: effectiveUpdatedAt
62268
62427
  });
62269
62428
  input.state.threadById.set(input.threadId, {
@@ -62413,9 +62572,9 @@ const syncPassiveImportedThreadIfNeeded = (input) => gen(function* () {
62413
62572
  })).overridesChanged) yield* tryPromise(() => writeExternalThreadOverrides(input.stateDir, overridesStore)).pipe(ignore);
62414
62573
  return "continue";
62415
62574
  });
62416
- const runExternalCodexThreadSync = gen(function* () {
62575
+ const runExternalCodexThreadSyncWithOptions = (options) => gen(function* () {
62417
62576
  const config = yield* ServerConfig$1;
62418
- if (config.mode !== "desktop") return;
62577
+ if (config.mode !== "desktop") return makeExternalThreadSyncStats();
62419
62578
  const orchestrationEngine = yield* OrchestrationEngineService;
62420
62579
  const providerRuntimeRepository = yield* ProviderSessionRuntimeRepository;
62421
62580
  const importStateRepositories = {
@@ -62457,7 +62616,7 @@ const runExternalCodexThreadSync = gen(function* () {
62457
62616
  }
62458
62617
  const syncTargets = [];
62459
62618
  for (const project of readModel.projects) {
62460
- if (project.deletedAt !== null || isGeneralChatWorkspaceRoot(project.workspaceRoot) || isAgentChatWorkspaceRoot(project.workspaceRoot)) continue;
62619
+ if (options?.projectId !== void 0 && project.id !== options.projectId || project.deletedAt !== null || isGeneralChatWorkspaceRoot(project.workspaceRoot) || isAgentChatWorkspaceRoot(project.workspaceRoot)) continue;
62461
62620
  const workspaceRoot = project.workspaceRoot;
62462
62621
  const rootKey = projectRootKey(workspaceRoot);
62463
62622
  if (projectIdByRootKey.has(rootKey)) continue;
@@ -62475,8 +62634,8 @@ const runExternalCodexThreadSync = gen(function* () {
62475
62634
  });
62476
62635
  }
62477
62636
  let bootstrappedProjectCount = 0;
62478
- let remainingBootstrapProjects = (yield* promise(() => readProjectPolicy(readModel))).remainingProjects;
62479
- for (const workspace of importableParityWorkspaces) {
62637
+ let remainingBootstrapProjects = options?.projectId === void 0 ? (yield* promise(() => readProjectPolicy(readModel))).remainingProjects : 0;
62638
+ for (const workspace of options?.projectId === void 0 ? importableParityWorkspaces : []) {
62480
62639
  const workspaceRoot = workspace.path;
62481
62640
  const workspaceRootCanonicalKey = projectRootKey(workspaceRoot);
62482
62641
  if (projectIdByRootKey.has(workspaceRootCanonicalKey)) continue;
@@ -62519,28 +62678,67 @@ const runExternalCodexThreadSync = gen(function* () {
62519
62678
  bootstrappedProjectCount += 1;
62520
62679
  if (remainingBootstrapProjects !== null && remainingBootstrapProjects > 0) remainingBootstrapProjects -= 1;
62521
62680
  }
62522
- if (syncTargets.length === 0) return;
62681
+ let hadErrors = false;
62682
+ const syncRunId = crypto.randomUUID();
62683
+ const syncStartedAt = (/* @__PURE__ */ new Date()).toISOString();
62684
+ const projectStatsByProjectId = new Map(syncTargets.map((target) => [target.projectId, makeEmptyExternalThreadSyncProjectStats(target)]));
62685
+ const publishSyncProgress = (status, input) => {
62686
+ const projects = Array.from(projectStatsByProjectId.values());
62687
+ const totals = sumExternalThreadSyncProjectStats(projects);
62688
+ publishExternalThreadSyncProgress({
62689
+ status,
62690
+ runId: syncRunId,
62691
+ startedAt: syncStartedAt,
62692
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
62693
+ ...input?.finishedAt ? { finishedAt: input.finishedAt } : {},
62694
+ currentProjectIndex: input?.currentProjectIndex ?? 0,
62695
+ totalProjects: syncTargets.length,
62696
+ ...input?.project ? { project: input.project } : {},
62697
+ ...status === "completed" || status === "failed" ? { projects } : {},
62698
+ ...totals,
62699
+ hadErrors
62700
+ });
62701
+ };
62702
+ if (syncTargets.length === 0) {
62703
+ publishSyncProgress("completed", { finishedAt: (/* @__PURE__ */ new Date()).toISOString() });
62704
+ return makeExternalThreadSyncStats({
62705
+ bootstrappedProjectCount,
62706
+ parityWorkspaceCount: importableParityWorkspaces.length
62707
+ });
62708
+ }
62709
+ publishSyncProgress("started");
62523
62710
  let createdThreadCount = 0;
62711
+ let restoredThreadCount = 0;
62524
62712
  let foregroundSummaryCount = 0;
62525
62713
  let foregroundHydratedThreadCount = 0;
62526
62714
  let foregroundImportedMessageCount = 0;
62527
62715
  let foregroundImportedActivityCount = 0;
62528
62716
  let foregroundImportedPlanCount = 0;
62529
- let hadErrors = false;
62530
62717
  const backgroundBackfillPlans = [];
62531
62718
  const lease = yield* tryPromise(() => acquireExternalSyncAppServer(runtimeContext.codexHomePath));
62532
62719
  try {
62533
62720
  const appServer = lease.appServer;
62534
- for (const syncTarget of syncTargets) {
62721
+ for (const [syncTargetIndex, syncTarget] of syncTargets.entries()) {
62535
62722
  const { projectId, workspace } = syncTarget;
62723
+ const currentProjectIndex = syncTargetIndex + 1;
62724
+ const projectStats = projectStatsByProjectId.get(projectId) ?? makeEmptyExternalThreadSyncProjectStats(syncTarget);
62725
+ projectStatsByProjectId.set(projectId, projectStats);
62726
+ publishSyncProgress("project", {
62727
+ project: projectStats,
62728
+ currentProjectIndex
62729
+ });
62536
62730
  let firstPage = null;
62537
62731
  try {
62538
62732
  firstPage = yield* tryPromise(() => listLegacyThreadPage(appServer, workspace, {
62539
- limit: EXTERNAL_SYNC_FOREGROUND_THREAD_LIMIT,
62733
+ limit: options?.projectId !== void 0 ? EXTERNAL_THREAD_PAGE_SIZE : EXTERNAL_SYNC_FOREGROUND_THREAD_LIMIT,
62540
62734
  sortKey: "updated_at"
62541
62735
  }));
62542
62736
  } catch (cause) {
62543
62737
  hadErrors = true;
62738
+ publishSyncProgress("project", {
62739
+ project: projectStats,
62740
+ currentProjectIndex
62741
+ });
62544
62742
  yield* logWarning$1("failed to list external Codex threads for project", {
62545
62743
  cause,
62546
62744
  projectId,
@@ -62550,15 +62748,25 @@ const runExternalCodexThreadSync = gen(function* () {
62550
62748
  continue;
62551
62749
  }
62552
62750
  if (!firstPage) continue;
62751
+ projectStats.scannedThreads += firstPage.threads.length;
62752
+ publishSyncProgress("project", {
62753
+ project: projectStats,
62754
+ currentProjectIndex
62755
+ });
62553
62756
  for (const summary of firstPage.threads) {
62554
62757
  const threadIdRaw = asTrimmedString$1(summary.id);
62555
62758
  const threadId = threadIdRaw ? ThreadId.makeUnsafe(threadIdRaw) : null;
62556
62759
  const existingThread = threadId ? state.threadById.get(threadId) : void 0;
62557
62760
  const existingReadModelThread = threadId ? readModelThreadById.get(threadId) : void 0;
62558
- const shouldHydrateForegroundThread = threadIdRaw.length > 0 && (existingThread === void 0 || existingThread.deletedAt === null) && (shouldReadLegacyThreadForImport({
62761
+ const restoreDeletedImportedThread = shouldRestoreDeletedImportedThread({
62762
+ existingThread,
62763
+ projectId
62764
+ });
62765
+ const shouldHydrateForegroundThread = threadIdRaw.length > 0 && (existingThread === void 0 || existingThread.deletedAt === null || restoreDeletedImportedThread) && (shouldReadLegacyThreadForImport({
62559
62766
  existingThread,
62560
62767
  legacyThreadSummary: summary,
62561
- forceRereadExistingThreads: false
62768
+ forceRereadExistingThreads: false,
62769
+ restoreDeletedImportedThread
62562
62770
  }) || (existingReadModelThread ? needsExternalThreadHydration(existingReadModelThread) : false));
62563
62771
  const summaryResult = yield* syncExternalThreadSummary({
62564
62772
  summary,
@@ -62569,9 +62777,17 @@ const runExternalCodexThreadSync = gen(function* () {
62569
62777
  orchestrationEngine
62570
62778
  });
62571
62779
  const createdThread = summaryResult.createdThread;
62780
+ const restoredThread = summaryResult.restoredThread;
62572
62781
  overridesChanged ||= summaryResult.overridesChanged;
62573
62782
  foregroundSummaryCount += 1;
62574
- if (createdThread) createdThreadCount += 1;
62783
+ if (createdThread) {
62784
+ createdThreadCount += 1;
62785
+ projectStats.createdThreads += 1;
62786
+ }
62787
+ if (restoredThread) {
62788
+ restoredThreadCount += 1;
62789
+ projectStats.restoredThreads += 1;
62790
+ }
62575
62791
  if (!shouldHydrateForegroundThread || threadIdRaw.length === 0) continue;
62576
62792
  try {
62577
62793
  const legacyThread = yield* tryPromise(() => readLegacyThread(appServer, threadIdRaw));
@@ -62596,7 +62812,15 @@ const runExternalCodexThreadSync = gen(function* () {
62596
62812
  foregroundImportedMessageCount += importResult.importedMessageCount;
62597
62813
  foregroundImportedActivityCount += importResult.importedActivityCount;
62598
62814
  foregroundImportedPlanCount += importResult.importedPlanCount;
62815
+ projectStats.hydratedThreads += 1;
62816
+ projectStats.importedMessages += importResult.importedMessageCount;
62817
+ projectStats.importedActivities += importResult.importedActivityCount;
62818
+ projectStats.importedPlans += importResult.importedPlanCount;
62599
62819
  overridesChanged ||= importResult.overridesChanged;
62820
+ publishSyncProgress("project", {
62821
+ project: projectStats,
62822
+ currentProjectIndex
62823
+ });
62600
62824
  } catch (cause) {
62601
62825
  hadErrors = true;
62602
62826
  yield* logWarning$1("failed to hydrate external Codex thread during foreground sync", {
@@ -62613,6 +62837,10 @@ const runExternalCodexThreadSync = gen(function* () {
62613
62837
  nextCursor: firstPage.nextCursor,
62614
62838
  sortKey: "updated_at"
62615
62839
  });
62840
+ publishSyncProgress("project", {
62841
+ project: projectStats,
62842
+ currentProjectIndex
62843
+ });
62616
62844
  }
62617
62845
  } finally {
62618
62846
  yield* tryPromise(() => lease.release()).pipe(ignoreCause({ log: true }));
@@ -62634,6 +62862,7 @@ const runExternalCodexThreadSync = gen(function* () {
62634
62862
  bootstrappedProjectCount,
62635
62863
  syncedProjectCount: syncTargets.length,
62636
62864
  createdThreadCount,
62865
+ restoredThreadCount,
62637
62866
  foregroundSummaryCount,
62638
62867
  foregroundHydratedThreadCount,
62639
62868
  foregroundImportedMessageCount,
@@ -62645,16 +62874,34 @@ const runExternalCodexThreadSync = gen(function* () {
62645
62874
  syncMarkerVersion: importMarker?.version ?? null,
62646
62875
  hadErrors
62647
62876
  });
62877
+ publishSyncProgress(hadErrors ? "failed" : "completed", { finishedAt: (/* @__PURE__ */ new Date()).toISOString() });
62648
62878
  if (!hadErrors) yield* tryPromise(() => writeImportMarker(config.stateDir, {
62649
62879
  version: EXTERNAL_SYNC_MARKER_VERSION,
62650
62880
  completedAt: (/* @__PURE__ */ new Date()).toISOString(),
62651
62881
  bootstrappedProjectCount,
62652
62882
  syncedProjectCount: syncTargets.length,
62653
62883
  createdThreadCount,
62884
+ restoredThreadCount,
62654
62885
  foregroundSummaryCount,
62655
62886
  backgroundBackfillProjectCount: backgroundBackfillPlans.length
62656
62887
  })).pipe(catch_((cause) => logWarning$1("failed to write external Codex thread sync marker", { cause })));
62888
+ return makeExternalThreadSyncStats({
62889
+ bootstrappedProjectCount,
62890
+ syncedProjectCount: syncTargets.length,
62891
+ createdThreadCount,
62892
+ restoredThreadCount,
62893
+ foregroundSummaryCount,
62894
+ foregroundHydratedThreadCount,
62895
+ foregroundImportedMessageCount,
62896
+ foregroundImportedActivityCount,
62897
+ foregroundImportedPlanCount,
62898
+ backgroundBackfillProjectCount: backgroundBackfillPlans.length,
62899
+ parityWorkspaceCount: importableParityWorkspaces.length,
62900
+ hadErrors
62901
+ });
62657
62902
  });
62903
+ const runExternalCodexThreadSync = runExternalCodexThreadSyncWithOptions();
62904
+ const runExternalCodexThreadSyncForProject = (projectId) => runExternalCodexThreadSyncWithOptions({ projectId });
62658
62905
  //#endregion
62659
62906
  //#region src/orchestration/Layers/ThreadSnapshotPreparation.ts
62660
62907
  function mapProviderSessionStatusToOrchestrationStatus(status) {
@@ -78149,9 +78396,25 @@ const handleOrchestrationRequest = fnUntraced(function* (body, context) {
78149
78396
  case ORCHESTRATION_WS_METHODS.getThreadSnapshot:
78150
78397
  yield* context.threadSnapshotPreparation.prepareThreadSnapshot(body.threadId);
78151
78398
  return yield* context.projectionReadModelQuery.getThreadSnapshot(stripRequestTag(body));
78152
- case ORCHESTRATION_WS_METHODS.syncExternalThreads:
78153
- if (!(yield* tryPromise(() => context.requestExternalCodexThreadSyncRefresh()).pipe(orElseSucceed(() => false)))) yield* forkDetach(context.runExternalCodexThreadSync.pipe(catch_((cause) => logWarning$1("failed to sync external Codex threads", { cause }))));
78154
- return { syncedAt: (/* @__PURE__ */ new Date()).toISOString() };
78399
+ case ORCHESTRATION_WS_METHODS.syncExternalThreads: {
78400
+ const input = stripRequestTag(body);
78401
+ if (input.projectId !== void 0) {
78402
+ const stats = yield* context.runExternalCodexThreadSyncForProject(input.projectId);
78403
+ return {
78404
+ syncedAt: (/* @__PURE__ */ new Date()).toISOString(),
78405
+ completed: true,
78406
+ queued: false,
78407
+ stats
78408
+ };
78409
+ }
78410
+ const queued = yield* tryPromise(() => context.requestExternalCodexThreadSyncRefresh()).pipe(orElseSucceed(() => false));
78411
+ if (!queued) yield* forkDetach(context.runExternalCodexThreadSync.pipe(catch_((cause) => logWarning$1("failed to sync external Codex threads", { cause }))));
78412
+ return {
78413
+ syncedAt: (/* @__PURE__ */ new Date()).toISOString(),
78414
+ completed: false,
78415
+ queued
78416
+ };
78417
+ }
78155
78418
  case ORCHESTRATION_WS_METHODS.dispatchCommand: {
78156
78419
  const normalizedCommand = yield* context.normalizeDispatchCommand({ command: body.command });
78157
78420
  const overrideIntent = yield* context.resolveExternalThreadOverrideIntent(normalizedCommand);
@@ -79315,10 +79578,22 @@ function buildCodexCommand(binaryPath, args) {
79315
79578
  };
79316
79579
  }
79317
79580
  function buildRuntimeEnv(codexHomePath) {
79318
- return {
79581
+ const env = {
79319
79582
  ...process.env,
79320
79583
  ...codexHomePath?.trim() ? { CODEX_HOME: codexHomePath.trim() } : {}
79321
79584
  };
79585
+ const homeDir = env.HOME ?? env.USERPROFILE ?? os.homedir();
79586
+ const extraPaths = [
79587
+ "/opt/homebrew/bin",
79588
+ "/usr/local/bin",
79589
+ path.join(homeDir, ".local", "bin"),
79590
+ path.join(homeDir, ".fnm", "aliases", "default", "bin"),
79591
+ path.join(homeDir, ".fnm", "current", "bin"),
79592
+ path.join(homeDir, ".volta", "bin"),
79593
+ path.join(homeDir, ".asdf", "shims")
79594
+ ];
79595
+ env.PATH = Array.from(new Set([...(env.PATH ?? "").split(path.delimiter), ...extraPaths].filter(Boolean))).join(path.delimiter);
79596
+ return env;
79322
79597
  }
79323
79598
  function createTimeoutError(command, args) {
79324
79599
  return /* @__PURE__ */ new Error(`Command timed out: ${command} ${args.join(" ")}`);
@@ -79579,7 +79854,9 @@ async function inspectAppServer(input) {
79579
79854
  }
79580
79855
  }
79581
79856
  async function inspectCodexRuntime(input) {
79582
- const binaryPath = input.binaryPath?.trim() || "codex";
79857
+ const requestedBinaryPath = input.binaryPath?.trim() || null;
79858
+ const binaryPath = requestedBinaryPath || "codex";
79859
+ const usesDefaultBinaryPath = !requestedBinaryPath || requestedBinaryPath === "codex";
79583
79860
  const args = tokenizeArgs(input.args);
79584
79861
  const env = buildRuntimeEnv(input.codexHomePath);
79585
79862
  let version = null;
@@ -79588,7 +79865,8 @@ async function inspectCodexRuntime(input) {
79588
79865
  let authMessage = null;
79589
79866
  let nodeVersion = null;
79590
79867
  let nodeDetails = null;
79591
- let nodeOk = false;
79868
+ let nodeOk;
79869
+ let codexCommandMissing = false;
79592
79870
  try {
79593
79871
  const versionCommand = buildCodexCommand(binaryPath, [...args, "--version"]);
79594
79872
  const versionResult = await runCommand$1(versionCommand.command, versionCommand.args, {
@@ -79600,9 +79878,13 @@ async function inspectCodexRuntime(input) {
79600
79878
  if (versionResult.code !== 0) details = describeCommandFailure(versionResult, "Codex CLI failed to run `--version`.");
79601
79879
  else if (parsedVersion && !isCodexCliVersionSupported(parsedVersion)) details = formatCodexCliUpgradeMessage(parsedVersion);
79602
79880
  } catch (error) {
79603
- details = error instanceof Error ? error.message : "Unable to run Codex CLI.";
79881
+ if (usesDefaultBinaryPath && error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
79882
+ codexCommandMissing = true;
79883
+ details = null;
79884
+ } else if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") details = `Configured Codex CLI path was not found: ${binaryPath}`;
79885
+ else details = error instanceof Error ? error.message : "Unable to run Codex CLI.";
79604
79886
  }
79605
- if (!details) try {
79887
+ if (!details && !codexCommandMissing) try {
79606
79888
  const authCommand = buildCodexCommand(binaryPath, [
79607
79889
  ...args,
79608
79890
  "login",
@@ -79634,7 +79916,7 @@ async function inspectCodexRuntime(input) {
79634
79916
  nodeOk = false;
79635
79917
  nodeDetails = error instanceof Error ? error.message : "Unable to run Node.";
79636
79918
  }
79637
- const appServerInspection = details === null ? await inspectAppServer({
79919
+ const appServerInspection = details === null && !codexCommandMissing ? await inspectAppServer({
79638
79920
  binaryPath,
79639
79921
  args,
79640
79922
  codexHomePath: input.codexHomePath
@@ -79654,7 +79936,7 @@ async function inspectCodexRuntime(input) {
79654
79936
  authStatus,
79655
79937
  authMessage,
79656
79938
  accountLabel: appServerInspection.accountLabel,
79657
- details: details ?? appServerInspection.details,
79939
+ details: codexCommandMissing ? null : details ?? appServerInspection.details,
79658
79940
  path: binaryPath,
79659
79941
  nodeOk,
79660
79942
  nodeVersion,
@@ -79670,6 +79952,7 @@ function compactCommandOutput(output) {
79670
79952
  return trimmed.length > 4e3 ? `${trimmed.slice(-4e3)}` : trimmed;
79671
79953
  }
79672
79954
  async function updateCodexRuntime() {
79955
+ const env = buildRuntimeEnv();
79673
79956
  const beforeVersion = (await inspectCodexRuntime({}).catch(() => null))?.doctor.version ?? null;
79674
79957
  const result = await runCommand$1("npm", [
79675
79958
  "install",
@@ -79677,7 +79960,7 @@ async function updateCodexRuntime() {
79677
79960
  CODEX_NPM_PACKAGE
79678
79961
  ], {
79679
79962
  timeoutMs: CODEX_INSTALL_TIMEOUT_MS,
79680
- env: process.env
79963
+ env
79681
79964
  }).catch((error) => ({
79682
79965
  stdout: "",
79683
79966
  stderr: error instanceof Error ? error.message : String(error),
@@ -82124,6 +82407,8 @@ const createServer = fn(function* () {
82124
82407
  clients,
82125
82408
  logOutgoingPush
82126
82409
  });
82410
+ setExternalCodexThreadSyncProgressReporter((payload) => runPromise(pushBus.publishAll(WS_CHANNELS.externalThreadSyncProgress, payload)));
82411
+ yield* addFinalizer(() => sync(() => setExternalCodexThreadSyncProgressReporter(null)));
82127
82412
  const agentChatConfig = getAgentChatConfig();
82128
82413
  const generalChatConfig = getGeneralChatConfig();
82129
82414
  yield* readiness.markPushBusReady;
@@ -82886,7 +83171,8 @@ const createServer = fn(function* () {
82886
83171
  persistExternalThreadOverrideIntent,
82887
83172
  dispatchOrchestrationCommand,
82888
83173
  requestExternalCodexThreadSyncRefresh: () => requestExternalCodexThreadSyncRefresh("renderer-ws"),
82889
- runExternalCodexThreadSync
83174
+ runExternalCodexThreadSync,
83175
+ runExternalCodexThreadSyncForProject
82890
83176
  };
82891
83177
  const routeRequest = fnUntraced(function* (request, ws) {
82892
83178
  const orchestrationResult = yield* handleOrchestrationRequest(request.body, orchestrationRequestContext);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codexuse-cli",
3
- "version": "3.9.0",
3
+ "version": "3.9.2",
4
4
  "description": "CodexUse CLI for profiles, Accounts Pool, daemon mode, licenses, and sync.",
5
5
  "author": {
6
6
  "name": "Hoang",